|
1 /** |
|
2 * XML Security Library (http://www.aleksey.com/xmlsec). |
|
3 * |
|
4 * XPath transform |
|
5 * |
|
6 * This is free software; see Copyright file in the source |
|
7 * distribution for preciese wording. |
|
8 * |
|
9 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> |
|
10 * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. |
|
11 */ |
|
12 #include "xmlsec_globals.h" |
|
13 |
|
14 #include <stdlib.h> |
|
15 #include <string.h> |
|
16 |
|
17 #include <libxml2_tree.h> |
|
18 #include <libxml2_xpath.h> |
|
19 #include <libxml2_xpathinternals.h> |
|
20 #include <libxml2_xpointer.h> |
|
21 #include <libxml2_valid.h> |
|
22 #include <libxml2_globals.h> |
|
23 |
|
24 #include "xmlsec_xmlsec.h" |
|
25 #include "xmlsec_xmltree.h" |
|
26 #include "xmlsec_keys.h" |
|
27 #include "xmlsec_list.h" |
|
28 #include "xmlsec_transforms.h" |
|
29 #include "xmlsec_errors.h" |
|
30 |
|
31 |
|
32 /************************************************************************** |
|
33 * |
|
34 * xmlSecXPathHereFunction: |
|
35 * @ctxt: the ponter to XPath context. |
|
36 * @nargs: the arguments nubmer. |
|
37 * |
|
38 * The implementation of XPath "here()" function. |
|
39 * See xmlXPtrHereFunction() in xpointer.c. the only change is that |
|
40 * we return NodeSet instead of NodeInterval. |
|
41 * |
|
42 *****************************************************************************/ |
|
43 static void |
|
44 xmlSecXPathHereFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
|
45 CHECK_ARITY(0); |
|
46 |
|
47 if((ctxt == NULL) || (ctxt->context == NULL) || (ctxt->context->here == NULL)) { |
|
48 XP_ERROR(XPTR_SYNTAX_ERROR); |
|
49 } |
|
50 valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->here)); |
|
51 } |
|
52 |
|
53 /************************************************************************** |
|
54 * |
|
55 * XPath/XPointer data |
|
56 * |
|
57 *****************************************************************************/ |
|
58 typedef struct _xmlSecXPathData xmlSecXPathData, |
|
59 *xmlSecXPathDataPtr; |
|
60 typedef enum { |
|
61 xmlSecXPathDataTypeXPath, |
|
62 xmlSecXPathDataTypeXPath2, |
|
63 xmlSecXPathDataTypeXPointer |
|
64 } xmlSecXPathDataType; |
|
65 |
|
66 struct _xmlSecXPathData { |
|
67 xmlSecXPathDataType type; |
|
68 xmlXPathContextPtr ctx; |
|
69 xmlChar* expr; |
|
70 xmlSecNodeSetOp nodeSetOp; |
|
71 xmlSecNodeSetType nodeSetType; |
|
72 }; |
|
73 |
|
74 static xmlSecXPathDataPtr xmlSecXPathDataCreate (xmlSecXPathDataType type); |
|
75 static void xmlSecXPathDataDestroy (xmlSecXPathDataPtr data); |
|
76 static int xmlSecXPathDataSetExpr (xmlSecXPathDataPtr data, |
|
77 const xmlChar* expr); |
|
78 static int xmlSecXPathDataRegisterNamespaces(xmlSecXPathDataPtr data, |
|
79 xmlNodePtr node); |
|
80 static int xmlSecXPathDataNodeRead (xmlSecXPathDataPtr data, |
|
81 xmlNodePtr node); |
|
82 static xmlSecNodeSetPtr xmlSecXPathDataExecute (xmlSecXPathDataPtr data, |
|
83 xmlDocPtr doc, |
|
84 xmlNodePtr hereNode); |
|
85 |
|
86 static xmlSecXPathDataPtr |
|
87 xmlSecXPathDataCreate(xmlSecXPathDataType type) { |
|
88 xmlSecXPathDataPtr data; |
|
89 |
|
90 data = (xmlSecXPathDataPtr) xmlMalloc(sizeof(xmlSecXPathData)); |
|
91 if(data == NULL) { |
|
92 xmlSecError(XMLSEC_ERRORS_HERE, |
|
93 NULL, |
|
94 NULL, |
|
95 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
96 "sizeof(xmlSecXPathData)=%d", |
|
97 sizeof(xmlSecXPathData)); |
|
98 return(NULL); |
|
99 } |
|
100 memset(data, 0, sizeof(xmlSecXPathData)); |
|
101 |
|
102 data->type = type; |
|
103 data->nodeSetType = xmlSecNodeSetTree; |
|
104 |
|
105 /* create xpath or xpointer context */ |
|
106 switch(data->type) { |
|
107 case xmlSecXPathDataTypeXPath: |
|
108 case xmlSecXPathDataTypeXPath2: |
|
109 data->ctx = xmlXPathNewContext(NULL); /* we'll set doc in the context later */ |
|
110 if(data->ctx == NULL) { |
|
111 xmlSecError(XMLSEC_ERRORS_HERE, |
|
112 NULL, |
|
113 "xmlXPathNewContext", |
|
114 XMLSEC_ERRORS_R_XML_FAILED, |
|
115 XMLSEC_ERRORS_NO_MESSAGE); |
|
116 xmlSecXPathDataDestroy(data); |
|
117 return(NULL); |
|
118 } |
|
119 break; |
|
120 case xmlSecXPathDataTypeXPointer: |
|
121 data->ctx = xmlXPtrNewContext(NULL, NULL, NULL); /* we'll set doc in the context later */ |
|
122 if(data->ctx == NULL) { |
|
123 xmlSecError(XMLSEC_ERRORS_HERE, |
|
124 NULL, |
|
125 "xmlXPtrNewContext", |
|
126 XMLSEC_ERRORS_R_XML_FAILED, |
|
127 XMLSEC_ERRORS_NO_MESSAGE); |
|
128 xmlSecXPathDataDestroy(data); |
|
129 return(NULL); |
|
130 } |
|
131 break; |
|
132 } |
|
133 |
|
134 return(data); |
|
135 } |
|
136 |
|
137 static void |
|
138 xmlSecXPathDataDestroy(xmlSecXPathDataPtr data) { |
|
139 xmlSecAssert(data != NULL); |
|
140 |
|
141 if(data->expr != NULL) { |
|
142 xmlFree(data->expr); |
|
143 } |
|
144 if(data->ctx != NULL) { |
|
145 xmlXPathFreeContext(data->ctx); |
|
146 } |
|
147 memset(data, 0, sizeof(xmlSecXPathData)); |
|
148 xmlFree(data); |
|
149 } |
|
150 |
|
151 static int |
|
152 xmlSecXPathDataSetExpr(xmlSecXPathDataPtr data, const xmlChar* expr) { |
|
153 xmlSecAssert2(data != NULL, -1); |
|
154 xmlSecAssert2(data->expr == NULL, -1); |
|
155 xmlSecAssert2(data->ctx != NULL, -1); |
|
156 xmlSecAssert2(expr != NULL, -1); |
|
157 |
|
158 data->expr = xmlStrdup(expr); |
|
159 if(data->expr == NULL) { |
|
160 xmlSecError(XMLSEC_ERRORS_HERE, |
|
161 NULL, |
|
162 NULL, |
|
163 XMLSEC_ERRORS_R_STRDUP_FAILED, |
|
164 XMLSEC_ERRORS_NO_MESSAGE); |
|
165 return(-1); |
|
166 } |
|
167 return(0); |
|
168 } |
|
169 |
|
170 |
|
171 static int |
|
172 xmlSecXPathDataRegisterNamespaces(xmlSecXPathDataPtr data, xmlNodePtr node) { |
|
173 xmlNodePtr cur; |
|
174 xmlNsPtr ns; |
|
175 int ret; |
|
176 |
|
177 xmlSecAssert2(data != NULL, -1); |
|
178 xmlSecAssert2(data->ctx != NULL, -1); |
|
179 xmlSecAssert2(node != NULL, -1); |
|
180 |
|
181 /* register namespaces */ |
|
182 for(cur = node; cur != NULL; cur = cur->parent) { |
|
183 for(ns = cur->nsDef; ns != NULL; ns = ns->next) { |
|
184 /* check that we have no other namespace with same prefix already */ |
|
185 if((ns->prefix != NULL) && (xmlXPathNsLookup(data->ctx, ns->prefix) == NULL)){ |
|
186 ret = xmlXPathRegisterNs(data->ctx, ns->prefix, ns->href); |
|
187 if(ret != 0) { |
|
188 xmlSecError(XMLSEC_ERRORS_HERE, |
|
189 NULL, |
|
190 "xmlXPathRegisterNs", |
|
191 XMLSEC_ERRORS_R_XML_FAILED, |
|
192 "href=%s;prefix=%s", |
|
193 xmlSecErrorsSafeString(ns->href), |
|
194 xmlSecErrorsSafeString(ns->prefix)); |
|
195 return(-1); |
|
196 } |
|
197 } |
|
198 } |
|
199 } |
|
200 |
|
201 return(0); |
|
202 } |
|
203 |
|
204 static int |
|
205 xmlSecXPathDataNodeRead(xmlSecXPathDataPtr data, xmlNodePtr node) { |
|
206 int ret; |
|
207 |
|
208 xmlSecAssert2(data != NULL, -1); |
|
209 xmlSecAssert2(data->expr == NULL, -1); |
|
210 xmlSecAssert2(data->ctx != NULL, -1); |
|
211 xmlSecAssert2(node != NULL, -1); |
|
212 |
|
213 ret = xmlSecXPathDataRegisterNamespaces (data, node); |
|
214 if(ret < 0) { |
|
215 xmlSecError(XMLSEC_ERRORS_HERE, |
|
216 NULL, |
|
217 "xmlSecXPathDataRegisterNamespaces", |
|
218 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
219 XMLSEC_ERRORS_NO_MESSAGE); |
|
220 return(-1); |
|
221 } |
|
222 |
|
223 /* read node content and set expr */ |
|
224 data->expr = xmlNodeGetContent(node); |
|
225 if(data->expr == NULL) { |
|
226 xmlSecError(XMLSEC_ERRORS_HERE, |
|
227 NULL, |
|
228 xmlSecErrorsSafeString(xmlSecNodeGetName(node)), |
|
229 XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, |
|
230 XMLSEC_ERRORS_NO_MESSAGE); |
|
231 return(-1); |
|
232 } |
|
233 |
|
234 return(0); |
|
235 } |
|
236 |
|
237 static xmlSecNodeSetPtr |
|
238 xmlSecXPathDataExecute(xmlSecXPathDataPtr data, xmlDocPtr doc, xmlNodePtr hereNode) { |
|
239 xmlXPathObjectPtr xpathObj = NULL; |
|
240 xmlSecNodeSetPtr nodes = NULL; |
|
241 |
|
242 xmlSecAssert2(data != NULL, NULL); |
|
243 xmlSecAssert2(data->expr != NULL, NULL); |
|
244 xmlSecAssert2(data->ctx != NULL, NULL); |
|
245 xmlSecAssert2(doc != NULL, NULL); |
|
246 xmlSecAssert2(hereNode != NULL, NULL); |
|
247 |
|
248 /* do not forget to set the doc */ |
|
249 data->ctx->doc = doc; |
|
250 |
|
251 /* here function works only on the same document */ |
|
252 if(hereNode->doc == doc) { |
|
253 xmlXPathRegisterFunc(data->ctx, (xmlChar *)"here", xmlSecXPathHereFunction); |
|
254 data->ctx->here = hereNode; |
|
255 data->ctx->xptr = 1; |
|
256 } |
|
257 |
|
258 /* execute xpath or xpointer expression */ |
|
259 switch(data->type) { |
|
260 case xmlSecXPathDataTypeXPath: |
|
261 case xmlSecXPathDataTypeXPath2: |
|
262 xpathObj = xmlXPathEvalExpression(data->expr, data->ctx); |
|
263 if(xpathObj == NULL) { |
|
264 xmlSecError(XMLSEC_ERRORS_HERE, |
|
265 NULL, |
|
266 "xmlXPathEvalExpression", |
|
267 XMLSEC_ERRORS_R_XML_FAILED, |
|
268 "expr=%s", |
|
269 xmlSecErrorsSafeString(data->expr)); |
|
270 return(NULL); |
|
271 } |
|
272 break; |
|
273 case xmlSecXPathDataTypeXPointer: |
|
274 xpathObj = xmlXPtrEval(data->expr, data->ctx); |
|
275 if(xpathObj == NULL) { |
|
276 xmlSecError(XMLSEC_ERRORS_HERE, |
|
277 NULL, |
|
278 "xmlXPtrEval", |
|
279 XMLSEC_ERRORS_R_XML_FAILED, |
|
280 "expr=%s", |
|
281 xmlSecErrorsSafeString(data->expr)); |
|
282 return(NULL); |
|
283 } |
|
284 break; |
|
285 } |
|
286 |
|
287 if (xpathObj != NULL) { |
|
288 nodes = xmlSecNodeSetCreate(doc, xpathObj->nodesetval, data->nodeSetType); |
|
289 } |
|
290 if(nodes == NULL) { |
|
291 xmlSecError(XMLSEC_ERRORS_HERE, |
|
292 NULL, |
|
293 "xmlSecNodeSetCreate", |
|
294 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
295 "type=%d", data->nodeSetType); |
|
296 xmlXPathFreeObject(xpathObj); |
|
297 return(NULL); |
|
298 } |
|
299 xpathObj->nodesetval = NULL; |
|
300 xmlXPathFreeObject(xpathObj); |
|
301 |
|
302 return(nodes); |
|
303 } |
|
304 |
|
305 |
|
306 /************************************************************************** |
|
307 * |
|
308 * XPath data list |
|
309 * |
|
310 *****************************************************************************/ |
|
311 #define xmlSecXPathDataListId \ |
|
312 xmlSecXPathDataListGetKlass() |
|
313 static xmlSecPtrListId xmlSecXPathDataListGetKlass (void); |
|
314 static xmlSecNodeSetPtr xmlSecXPathDataListExecute (xmlSecPtrListPtr dataList, |
|
315 xmlDocPtr doc, |
|
316 xmlNodePtr hereNode, |
|
317 xmlSecNodeSetPtr nodes); |
|
318 |
|
319 static xmlSecPtrListKlass xmlSecXPathDataListKlass = { |
|
320 BAD_CAST "xpath-data-list", |
|
321 NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */ |
|
322 (xmlSecPtrDestroyItemMethod)xmlSecXPathDataDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */ |
|
323 NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */ |
|
324 NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */ |
|
325 }; |
|
326 |
|
327 static xmlSecPtrListId |
|
328 xmlSecXPathDataListGetKlass(void) { |
|
329 return(&xmlSecXPathDataListKlass); |
|
330 } |
|
331 |
|
332 static xmlSecNodeSetPtr |
|
333 xmlSecXPathDataListExecute(xmlSecPtrListPtr dataList, xmlDocPtr doc, |
|
334 xmlNodePtr hereNode, xmlSecNodeSetPtr nodes) { |
|
335 xmlSecXPathDataPtr data; |
|
336 xmlSecNodeSetPtr res, tmp, tmp2; |
|
337 xmlSecSize pos; |
|
338 |
|
339 xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), NULL); |
|
340 xmlSecAssert2(xmlSecPtrListGetSize(dataList) > 0, NULL); |
|
341 xmlSecAssert2(doc != NULL, NULL); |
|
342 xmlSecAssert2(hereNode != NULL, NULL); |
|
343 |
|
344 res = nodes; |
|
345 for(pos = 0; pos < xmlSecPtrListGetSize(dataList); ++pos) { |
|
346 data = (xmlSecXPathDataPtr)xmlSecPtrListGetItem(dataList, pos); |
|
347 if(data == NULL) { |
|
348 xmlSecError(XMLSEC_ERRORS_HERE, |
|
349 NULL, |
|
350 "xmlSecPtrListGetItem", |
|
351 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
352 "pos=%d", pos); |
|
353 if((res != NULL) && (res != nodes)) { |
|
354 xmlSecNodeSetDestroy(res); |
|
355 } |
|
356 return(NULL); |
|
357 } |
|
358 |
|
359 tmp = xmlSecXPathDataExecute(data, doc, hereNode); |
|
360 if(tmp == NULL) { |
|
361 xmlSecError(XMLSEC_ERRORS_HERE, |
|
362 NULL, |
|
363 "xmlSecXPathDataExecute", |
|
364 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
365 XMLSEC_ERRORS_NO_MESSAGE); |
|
366 if((res != NULL) && (res != nodes)) { |
|
367 xmlSecNodeSetDestroy(res); |
|
368 } |
|
369 return(NULL); |
|
370 } |
|
371 |
|
372 tmp2 = xmlSecNodeSetAdd(res, tmp, data->nodeSetOp); |
|
373 if(tmp2 == NULL) { |
|
374 xmlSecError(XMLSEC_ERRORS_HERE, |
|
375 NULL, |
|
376 "xmlSecNodeSetAdd", |
|
377 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
378 "xmlSecNodeSetIntersection"); |
|
379 if((res != NULL) && (res != nodes)) { |
|
380 xmlSecNodeSetDestroy(res); |
|
381 } |
|
382 xmlSecNodeSetDestroy(tmp); |
|
383 return(NULL); |
|
384 } |
|
385 res = tmp2; |
|
386 } |
|
387 |
|
388 return(res); |
|
389 } |
|
390 |
|
391 /****************************************************************************** |
|
392 * |
|
393 * XPath/XPointer transforms |
|
394 * |
|
395 * xmlSecXPathDataList is located after xmlSecTransform structure |
|
396 * |
|
397 *****************************************************************************/ |
|
398 #define xmlSecXPathTransformSize \ |
|
399 (sizeof(xmlSecTransform) + sizeof(xmlSecPtrList)) |
|
400 #define xmlSecXPathTransformGetDataList(transform) \ |
|
401 ((xmlSecTransformCheckSize((transform), xmlSecXPathTransformSize)) ? \ |
|
402 (xmlSecPtrListPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \ |
|
403 (xmlSecPtrListPtr)NULL) |
|
404 #define xmlSecTransformXPathCheckId(transform) \ |
|
405 (xmlSecTransformCheckId((transform), xmlSecTransformXPathId) || \ |
|
406 xmlSecTransformCheckId((transform), xmlSecTransformXPath2Id) || \ |
|
407 xmlSecTransformCheckId((transform), xmlSecTransformXPointerId)) |
|
408 |
|
409 static int xmlSecTransformXPathInitialize (xmlSecTransformPtr transform); |
|
410 static void xmlSecTransformXPathFinalize (xmlSecTransformPtr transform); |
|
411 static int xmlSecTransformXPathExecute (xmlSecTransformPtr transform, |
|
412 int last, |
|
413 xmlSecTransformCtxPtr transformCtx); |
|
414 |
|
415 static int |
|
416 xmlSecTransformXPathInitialize(xmlSecTransformPtr transform) { |
|
417 xmlSecPtrListPtr dataList; |
|
418 int ret; |
|
419 |
|
420 xmlSecAssert2(xmlSecTransformXPathCheckId(transform), -1); |
|
421 |
|
422 dataList = xmlSecXPathTransformGetDataList(transform); |
|
423 xmlSecAssert2(dataList != NULL, -1); |
|
424 |
|
425 ret = xmlSecPtrListInitialize(dataList, xmlSecXPathDataListId); |
|
426 if(ret < 0) { |
|
427 xmlSecError(XMLSEC_ERRORS_HERE, |
|
428 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
429 "xmlSecPtrListInitialize", |
|
430 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
431 XMLSEC_ERRORS_NO_MESSAGE); |
|
432 return(-1); |
|
433 } |
|
434 return(0); |
|
435 } |
|
436 |
|
437 static void |
|
438 xmlSecTransformXPathFinalize(xmlSecTransformPtr transform) { |
|
439 xmlSecPtrListPtr dataList; |
|
440 |
|
441 xmlSecAssert(xmlSecTransformXPathCheckId(transform)); |
|
442 |
|
443 dataList = xmlSecXPathTransformGetDataList(transform); |
|
444 xmlSecAssert(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId)); |
|
445 |
|
446 xmlSecPtrListFinalize(dataList); |
|
447 } |
|
448 |
|
449 static int |
|
450 xmlSecTransformXPathExecute(xmlSecTransformPtr transform, int last, |
|
451 xmlSecTransformCtxPtr transformCtx) { |
|
452 xmlSecPtrListPtr dataList; |
|
453 xmlDocPtr doc; |
|
454 |
|
455 xmlSecAssert2(xmlSecTransformXPathCheckId(transform), -1); |
|
456 xmlSecAssert2(transform->hereNode != NULL, -1); |
|
457 xmlSecAssert2(transform->outNodes == NULL, -1); |
|
458 xmlSecAssert2(last != 0, -1); |
|
459 xmlSecAssert2(transformCtx != NULL, -1); |
|
460 |
|
461 dataList = xmlSecXPathTransformGetDataList(transform); |
|
462 xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1); |
|
463 xmlSecAssert2(xmlSecPtrListGetSize(dataList) > 0, -1); |
|
464 |
|
465 doc = (transform->inNodes != NULL) ? transform->inNodes->doc : transform->hereNode->doc; |
|
466 xmlSecAssert2(doc != NULL, -1); |
|
467 |
|
468 transform->outNodes = xmlSecXPathDataListExecute(dataList, doc, |
|
469 transform->hereNode, transform->inNodes); |
|
470 if(transform->outNodes == NULL) { |
|
471 xmlSecError(XMLSEC_ERRORS_HERE, |
|
472 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
473 "xmlSecXPathDataExecute", |
|
474 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
475 XMLSEC_ERRORS_NO_MESSAGE); |
|
476 return(-1); |
|
477 } |
|
478 return(0); |
|
479 } |
|
480 |
|
481 /****************************************************************************** |
|
482 * |
|
483 * XPath transform |
|
484 * |
|
485 *****************************************************************************/ |
|
486 static int xmlSecTransformXPathNodeRead (xmlSecTransformPtr transform, |
|
487 xmlNodePtr node, |
|
488 xmlSecTransformCtxPtr transformCtx); |
|
489 |
|
490 static xmlSecTransformKlass xmlSecTransformXPathKlass = { |
|
491 /* klass/object sizes */ |
|
492 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
|
493 xmlSecXPathTransformSize, /* xmlSecSize objSize */ |
|
494 |
|
495 xmlSecNameXPath, /* const xmlChar* name; */ |
|
496 xmlSecXPathNs, /* const xmlChar* href; */ |
|
497 xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */ |
|
498 |
|
499 xmlSecTransformXPathInitialize, /* xmlSecTransformInitializeMethod initialize; */ |
|
500 xmlSecTransformXPathFinalize, /* xmlSecTransformFinalizeMethod finalize; */ |
|
501 xmlSecTransformXPathNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ |
|
502 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
|
503 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ |
|
504 NULL, /* xmlSecTransformSetKeyMethod setKey; */ |
|
505 NULL, /* xmlSecTransformValidateMethod validate; */ |
|
506 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
|
507 NULL, /* xmlSecTransformPushBinMethod pushBin; */ |
|
508 NULL, /* xmlSecTransformPopBinMethod popBin; */ |
|
509 xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */ |
|
510 xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */ |
|
511 xmlSecTransformXPathExecute, /* xmlSecTransformExecuteMethod execute; */ |
|
512 |
|
513 NULL, /* void* reserved0; */ |
|
514 NULL, /* void* reserved1; */ |
|
515 }; |
|
516 |
|
517 /** |
|
518 * xmlSecTransformXPathGetKlass: |
|
519 * |
|
520 * The XPath transform evaluates given XPath expression and |
|
521 * intersects the result with the previous nodes set. See |
|
522 * http://www.w3.org/TR/xmldsig-core/#sec-XPath for more details. |
|
523 * |
|
524 * Returns XPath transform id. |
|
525 */ |
|
526 EXPORT_C |
|
527 xmlSecTransformId |
|
528 xmlSecTransformXPathGetKlass(void) { |
|
529 return(&xmlSecTransformXPathKlass); |
|
530 } |
|
531 |
|
532 static const char xpathPattern[] = "(//. | //@* | //namespace::*)[%s]"; |
|
533 static int |
|
534 xmlSecTransformXPathNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) { |
|
535 xmlSecPtrListPtr dataList; |
|
536 xmlSecXPathDataPtr data; |
|
537 xmlNodePtr cur; |
|
538 xmlChar* tmp; |
|
539 int ret; |
|
540 |
|
541 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPathId), -1); |
|
542 xmlSecAssert2(node != NULL, -1); |
|
543 xmlSecAssert2(transformCtx != NULL, -1); |
|
544 |
|
545 dataList = xmlSecXPathTransformGetDataList(transform); |
|
546 xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1); |
|
547 xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1); |
|
548 |
|
549 /* there is only one required node */ |
|
550 cur = xmlSecGetNextElementNode(node->children); |
|
551 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeXPath, xmlSecDSigNs))) { |
|
552 xmlSecError(XMLSEC_ERRORS_HERE, |
|
553 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
554 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), |
|
555 XMLSEC_ERRORS_R_INVALID_NODE, |
|
556 "expected=%s", |
|
557 xmlSecErrorsSafeString(xmlSecNodeXPath)); |
|
558 return(-1); |
|
559 } |
|
560 |
|
561 /* read information from the node */ |
|
562 data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPath); |
|
563 if(data == NULL) { |
|
564 xmlSecError(XMLSEC_ERRORS_HERE, |
|
565 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
566 "xmlSecXPathDataCreate", |
|
567 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
568 XMLSEC_ERRORS_NO_MESSAGE); |
|
569 return(-1); |
|
570 } |
|
571 |
|
572 ret = xmlSecXPathDataNodeRead(data, cur); |
|
573 if(ret < 0) { |
|
574 xmlSecError(XMLSEC_ERRORS_HERE, |
|
575 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
576 "xmlSecXPathDataNodeRead", |
|
577 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
578 XMLSEC_ERRORS_NO_MESSAGE); |
|
579 xmlSecXPathDataDestroy(data); |
|
580 return(-1); |
|
581 } |
|
582 |
|
583 /* append it to the list */ |
|
584 ret = xmlSecPtrListAdd(dataList, data); |
|
585 if(ret < 0) { |
|
586 xmlSecError(XMLSEC_ERRORS_HERE, |
|
587 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
588 "xmlSecPtrListAdd", |
|
589 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
590 XMLSEC_ERRORS_NO_MESSAGE); |
|
591 xmlSecXPathDataDestroy(data); |
|
592 return(-1); |
|
593 } |
|
594 |
|
595 /* create full XPath expression */ |
|
596 xmlSecAssert2(data->expr != NULL, -1); |
|
597 tmp = (xmlChar*) xmlMalloc(sizeof(xmlChar) * (xmlStrlen(data->expr) + |
|
598 strlen(xpathPattern) + 1)); |
|
599 if(tmp == NULL) { |
|
600 xmlSecError(XMLSEC_ERRORS_HERE, |
|
601 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
602 NULL, |
|
603 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
604 "size=%d", |
|
605 xmlStrlen(data->expr) + strlen(xpathPattern) + 1); |
|
606 return(-1); |
|
607 } |
|
608 sprintf((char*)tmp, xpathPattern, (char*)data->expr); |
|
609 xmlFree(data->expr); |
|
610 data->expr = tmp; |
|
611 |
|
612 /* set correct node set type and operation */ |
|
613 data->nodeSetOp = xmlSecNodeSetIntersection; |
|
614 data->nodeSetType = xmlSecNodeSetNormal; |
|
615 |
|
616 /* check that we have nothing else */ |
|
617 cur = xmlSecGetNextElementNode(cur->next); |
|
618 if(cur != NULL) { |
|
619 xmlSecError(XMLSEC_ERRORS_HERE, |
|
620 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
621 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), |
|
622 XMLSEC_ERRORS_R_UNEXPECTED_NODE, |
|
623 XMLSEC_ERRORS_NO_MESSAGE); |
|
624 return(-1); |
|
625 } |
|
626 return(0); |
|
627 } |
|
628 |
|
629 /****************************************************************************** |
|
630 * |
|
631 * XPath2 transform |
|
632 * |
|
633 *****************************************************************************/ |
|
634 static int xmlSecTransformXPath2NodeRead (xmlSecTransformPtr transform, |
|
635 xmlNodePtr node, |
|
636 xmlSecTransformCtxPtr transformCtx); |
|
637 static xmlSecTransformKlass xmlSecTransformXPath2Klass = { |
|
638 /* klass/object sizes */ |
|
639 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
|
640 xmlSecXPathTransformSize, /* xmlSecSize objSize */ |
|
641 |
|
642 xmlSecNameXPath2, /* const xmlChar* name; */ |
|
643 xmlSecXPath2Ns, /* const xmlChar* href; */ |
|
644 xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */ |
|
645 |
|
646 xmlSecTransformXPathInitialize, /* xmlSecTransformInitializeMethod initialize; */ |
|
647 xmlSecTransformXPathFinalize, /* xmlSecTransformFinalizeMethod finalize; */ |
|
648 xmlSecTransformXPath2NodeRead, /* xmlSecTransformNodeReadMethod readNode; */ |
|
649 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
|
650 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ |
|
651 NULL, /* xmlSecTransformSetKeyMethod setKey; */ |
|
652 NULL, /* xmlSecTransformValidateMethod validate; */ |
|
653 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
|
654 NULL, /* xmlSecTransformPushBinMethod pushBin; */ |
|
655 NULL, /* xmlSecTransformPopBinMethod popBin; */ |
|
656 xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */ |
|
657 xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */ |
|
658 xmlSecTransformXPathExecute, /* xmlSecTransformExecuteMethod execute; */ |
|
659 |
|
660 NULL, /* void* reserved0; */ |
|
661 NULL, /* void* reserved1; */ |
|
662 }; |
|
663 |
|
664 /** |
|
665 * xmlSecTransformXPath2GetKlass: |
|
666 * |
|
667 * The XPath2 transform (http://www.w3.org/TR/xmldsig-filter2/). |
|
668 * |
|
669 * Returns XPath2 transform klass. |
|
670 */ |
|
671 EXPORT_C |
|
672 xmlSecTransformId |
|
673 xmlSecTransformXPath2GetKlass(void) { |
|
674 return(&xmlSecTransformXPath2Klass); |
|
675 } |
|
676 |
|
677 static int |
|
678 xmlSecTransformXPath2NodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) { |
|
679 xmlSecPtrListPtr dataList; |
|
680 xmlSecXPathDataPtr data; |
|
681 xmlNodePtr cur; |
|
682 xmlChar* op; |
|
683 int ret; |
|
684 |
|
685 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPath2Id), -1); |
|
686 xmlSecAssert2(node != NULL, -1); |
|
687 xmlSecAssert2(transformCtx != NULL, -1); |
|
688 |
|
689 dataList = xmlSecXPathTransformGetDataList(transform); |
|
690 xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1); |
|
691 xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1); |
|
692 |
|
693 /* There are only xpath nodes */ |
|
694 cur = xmlSecGetNextElementNode(node->children); |
|
695 while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeXPath2, xmlSecXPath2Ns)) { |
|
696 /* read information from the node */ |
|
697 data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPath2); |
|
698 if(data == NULL) { |
|
699 xmlSecError(XMLSEC_ERRORS_HERE, |
|
700 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
701 "xmlSecXPathDataCreate", |
|
702 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
703 XMLSEC_ERRORS_NO_MESSAGE); |
|
704 return(-1); |
|
705 } |
|
706 |
|
707 ret = xmlSecXPathDataNodeRead(data, cur); |
|
708 if(ret < 0) { |
|
709 xmlSecError(XMLSEC_ERRORS_HERE, |
|
710 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
711 "xmlSecXPathDataNodeRead", |
|
712 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
713 XMLSEC_ERRORS_NO_MESSAGE); |
|
714 xmlSecXPathDataDestroy(data); |
|
715 return(-1); |
|
716 } |
|
717 |
|
718 /* append it to the list */ |
|
719 ret = xmlSecPtrListAdd(dataList, data); |
|
720 if(ret < 0) { |
|
721 xmlSecError(XMLSEC_ERRORS_HERE, |
|
722 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
723 "xmlSecPtrListAdd", |
|
724 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
725 XMLSEC_ERRORS_NO_MESSAGE); |
|
726 xmlSecXPathDataDestroy(data); |
|
727 return(-1); |
|
728 } |
|
729 |
|
730 /* set correct node set type and operation */ |
|
731 data->nodeSetType = xmlSecNodeSetTree; |
|
732 op = xmlGetProp(cur, xmlSecAttrFilter); |
|
733 if(op == NULL) { |
|
734 xmlSecError(XMLSEC_ERRORS_HERE, |
|
735 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
736 xmlSecErrorsSafeString(xmlSecAttrFilter), |
|
737 XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, |
|
738 "node=%s", |
|
739 xmlSecErrorsSafeString(xmlSecNodeGetName(cur))); |
|
740 return(-1); |
|
741 } |
|
742 if(xmlStrEqual(op, xmlSecXPath2FilterIntersect)) { |
|
743 data->nodeSetOp = xmlSecNodeSetIntersection; |
|
744 } else if(xmlStrEqual(op, xmlSecXPath2FilterSubtract)) { |
|
745 data->nodeSetOp = xmlSecNodeSetSubtraction; |
|
746 } else if(xmlStrEqual(op, xmlSecXPath2FilterUnion)) { |
|
747 data->nodeSetOp = xmlSecNodeSetUnion; |
|
748 } else { |
|
749 xmlSecError(XMLSEC_ERRORS_HERE, |
|
750 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
751 xmlSecErrorsSafeString(xmlSecAttrFilter), |
|
752 XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, |
|
753 "filter=%s", |
|
754 xmlSecErrorsSafeString(op)); |
|
755 xmlFree(op); |
|
756 return(-1); |
|
757 } |
|
758 xmlFree(op); |
|
759 |
|
760 cur = xmlSecGetNextElementNode(cur->next); |
|
761 } |
|
762 |
|
763 /* check that we have nothing else */ |
|
764 if(cur != NULL) { |
|
765 xmlSecError(XMLSEC_ERRORS_HERE, |
|
766 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
767 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), |
|
768 XMLSEC_ERRORS_R_UNEXPECTED_NODE, |
|
769 XMLSEC_ERRORS_NO_MESSAGE); |
|
770 return(-1); |
|
771 } |
|
772 return(0); |
|
773 } |
|
774 |
|
775 /****************************************************************************** |
|
776 * |
|
777 * XPointer transform |
|
778 * |
|
779 *****************************************************************************/ |
|
780 static int xmlSecTransformXPointerNodeRead (xmlSecTransformPtr transform, |
|
781 xmlNodePtr node, |
|
782 xmlSecTransformCtxPtr transformCtx); |
|
783 static xmlSecTransformKlass xmlSecTransformXPointerKlass = { |
|
784 /* klass/object sizes */ |
|
785 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
|
786 xmlSecXPathTransformSize, /* xmlSecSize objSize */ |
|
787 |
|
788 xmlSecNameXPointer, /* const xmlChar* name; */ |
|
789 xmlSecXPointerNs, /* const xmlChar* href; */ |
|
790 xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */ |
|
791 |
|
792 xmlSecTransformXPathInitialize, /* xmlSecTransformInitializeMethod initialize; */ |
|
793 xmlSecTransformXPathFinalize, /* xmlSecTransformFinalizeMethod finalize; */ |
|
794 xmlSecTransformXPointerNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ |
|
795 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
|
796 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ |
|
797 NULL, /* xmlSecTransformSetKeyMethod setKey; */ |
|
798 NULL, /* xmlSecTransformValidateMethod validate; */ |
|
799 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
|
800 NULL, /* xmlSecTransformPushBinMethod pushBin; */ |
|
801 NULL, /* xmlSecTransformPopBinMethod popBin; */ |
|
802 xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */ |
|
803 xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */ |
|
804 xmlSecTransformXPathExecute, /* xmlSecTransformExecuteMethod execute; */ |
|
805 |
|
806 NULL, /* void* reserved0; */ |
|
807 NULL, /* void* reserved1; */ |
|
808 }; |
|
809 |
|
810 /** |
|
811 * xmlSecTransformXPointerGetKlass: |
|
812 * |
|
813 * The XPointer transform klass |
|
814 * (http://www.ietf.org/internet-drafts/draft-eastlake-xmldsig-uri-02.txt). |
|
815 * |
|
816 * Returns XPointer transform klass. |
|
817 */ |
|
818 EXPORT_C |
|
819 xmlSecTransformId |
|
820 xmlSecTransformXPointerGetKlass(void) { |
|
821 return(&xmlSecTransformXPointerKlass); |
|
822 } |
|
823 |
|
824 /** |
|
825 * xmlSecTransformXPointerSetExpr: |
|
826 * @transform: the pointer to XPointer transform. |
|
827 * @expr: the XPointer expression. |
|
828 * @nodeSetType: the type of evaluated XPointer expression. |
|
829 * @hereNode: the pointer to "here" node. |
|
830 * |
|
831 * Sets the XPointer expression for an XPointer @transform. |
|
832 * |
|
833 * Returns 0 on success or a negative value if an error occurs. |
|
834 */ |
|
835 EXPORT_C |
|
836 int |
|
837 xmlSecTransformXPointerSetExpr(xmlSecTransformPtr transform, const xmlChar* expr, |
|
838 xmlSecNodeSetType nodeSetType, xmlNodePtr hereNode) { |
|
839 xmlSecPtrListPtr dataList; |
|
840 xmlSecXPathDataPtr data; |
|
841 int ret; |
|
842 |
|
843 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPointerId), -1); |
|
844 xmlSecAssert2(transform->hereNode == NULL, -1); |
|
845 xmlSecAssert2(expr != NULL, -1); |
|
846 xmlSecAssert2(hereNode != NULL, -1); |
|
847 |
|
848 transform->hereNode = hereNode; |
|
849 |
|
850 dataList = xmlSecXPathTransformGetDataList(transform); |
|
851 xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1); |
|
852 xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1); |
|
853 |
|
854 data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPointer); |
|
855 if(data == NULL) { |
|
856 xmlSecError(XMLSEC_ERRORS_HERE, |
|
857 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
858 "xmlSecXPathDataCreate", |
|
859 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
860 XMLSEC_ERRORS_NO_MESSAGE); |
|
861 return(-1); |
|
862 } |
|
863 |
|
864 ret = xmlSecXPathDataRegisterNamespaces(data, hereNode); |
|
865 if(ret < 0) { |
|
866 xmlSecError(XMLSEC_ERRORS_HERE, |
|
867 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
868 "xmlSecXPathDataRegisterNamespaces", |
|
869 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
870 XMLSEC_ERRORS_NO_MESSAGE); |
|
871 xmlSecXPathDataDestroy(data); |
|
872 return(-1); |
|
873 } |
|
874 |
|
875 ret = xmlSecXPathDataSetExpr(data, expr); |
|
876 if(ret < 0) { |
|
877 xmlSecError(XMLSEC_ERRORS_HERE, |
|
878 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
879 "xmlSecXPathDataSetExpr", |
|
880 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
881 XMLSEC_ERRORS_NO_MESSAGE); |
|
882 xmlSecXPathDataDestroy(data); |
|
883 return(-1); |
|
884 } |
|
885 |
|
886 /* append it to the list */ |
|
887 ret = xmlSecPtrListAdd(dataList, data); |
|
888 if(ret < 0) { |
|
889 xmlSecError(XMLSEC_ERRORS_HERE, |
|
890 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
891 "xmlSecPtrListAdd", |
|
892 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
893 XMLSEC_ERRORS_NO_MESSAGE); |
|
894 xmlSecXPathDataDestroy(data); |
|
895 return(-1); |
|
896 } |
|
897 |
|
898 /* set correct node set type and operation */ |
|
899 data->nodeSetOp = xmlSecNodeSetIntersection; |
|
900 data->nodeSetType = nodeSetType; |
|
901 |
|
902 return(0); |
|
903 } |
|
904 |
|
905 static int |
|
906 xmlSecTransformXPointerNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) { |
|
907 xmlSecPtrListPtr dataList; |
|
908 xmlSecXPathDataPtr data; |
|
909 xmlNodePtr cur; |
|
910 int ret; |
|
911 |
|
912 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPointerId), -1); |
|
913 xmlSecAssert2(node != NULL, -1); |
|
914 xmlSecAssert2(transformCtx != NULL, -1); |
|
915 |
|
916 dataList = xmlSecXPathTransformGetDataList(transform); |
|
917 xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1); |
|
918 xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1); |
|
919 |
|
920 /* there is only one required node */ |
|
921 cur = xmlSecGetNextElementNode(node->children); |
|
922 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeXPointer, xmlSecXPointerNs))) { |
|
923 xmlSecError(XMLSEC_ERRORS_HERE, |
|
924 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
925 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), |
|
926 XMLSEC_ERRORS_R_INVALID_NODE, |
|
927 "expected=%s", |
|
928 xmlSecErrorsSafeString(xmlSecNodeXPath)); |
|
929 return(-1); |
|
930 } |
|
931 |
|
932 /* read information from the node */ |
|
933 data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPointer); |
|
934 if(data == NULL) { |
|
935 xmlSecError(XMLSEC_ERRORS_HERE, |
|
936 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
937 "xmlSecXPathDataCreate", |
|
938 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
939 XMLSEC_ERRORS_NO_MESSAGE); |
|
940 return(-1); |
|
941 } |
|
942 |
|
943 ret = xmlSecXPathDataNodeRead(data, cur); |
|
944 if(ret < 0) { |
|
945 xmlSecError(XMLSEC_ERRORS_HERE, |
|
946 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
947 "xmlSecXPathDataNodeRead", |
|
948 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
949 XMLSEC_ERRORS_NO_MESSAGE); |
|
950 xmlSecXPathDataDestroy(data); |
|
951 return(-1); |
|
952 } |
|
953 |
|
954 /* append it to the list */ |
|
955 ret = xmlSecPtrListAdd(dataList, data); |
|
956 if(ret < 0) { |
|
957 xmlSecError(XMLSEC_ERRORS_HERE, |
|
958 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
959 "xmlSecPtrListAdd", |
|
960 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
961 XMLSEC_ERRORS_NO_MESSAGE); |
|
962 xmlSecXPathDataDestroy(data); |
|
963 return(-1); |
|
964 } |
|
965 |
|
966 /* set correct node set type and operation */ |
|
967 data->nodeSetOp = xmlSecNodeSetIntersection; |
|
968 data->nodeSetType = xmlSecNodeSetTree; |
|
969 |
|
970 /* check that we have nothing else */ |
|
971 cur = xmlSecGetNextElementNode(cur->next); |
|
972 if(cur != NULL) { |
|
973 xmlSecError(XMLSEC_ERRORS_HERE, |
|
974 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
975 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), |
|
976 XMLSEC_ERRORS_R_UNEXPECTED_NODE, |
|
977 XMLSEC_ERRORS_NO_MESSAGE); |
|
978 return(-1); |
|
979 } |
|
980 return(0); |
|
981 } |
|
982 |
|
983 |
|
984 /****************************************************************************** |
|
985 * |
|
986 * Visa3DHack transform |
|
987 * |
|
988 *****************************************************************************/ |
|
989 #define xmlSecVisa3DHackTransformSize \ |
|
990 (sizeof(xmlSecTransform) + sizeof(xmlChar*)) |
|
991 #define xmlSecVisa3DHackTransformGetIDPtr(transform) \ |
|
992 ((xmlSecTransformCheckSize((transform), xmlSecVisa3DHackTransformSize)) ? \ |
|
993 (xmlChar**)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \ |
|
994 (xmlChar**)NULL) |
|
995 #define xmlSecTransformVisa3DHackCheckId(transform) \ |
|
996 (xmlSecTransformCheckId((transform), xmlSecTransformVisa3DHackId)) |
|
997 |
|
998 static int xmlSecTransformVisa3DHackInitialize (xmlSecTransformPtr transform); |
|
999 static void xmlSecTransformVisa3DHackFinalize (xmlSecTransformPtr transform); |
|
1000 static int xmlSecTransformVisa3DHackExecute (xmlSecTransformPtr transform, |
|
1001 int last, |
|
1002 xmlSecTransformCtxPtr transformCtx); |
|
1003 |
|
1004 static xmlSecTransformKlass xmlSecTransformVisa3DHackKlass = { |
|
1005 /* klass/object sizes */ |
|
1006 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
|
1007 xmlSecVisa3DHackTransformSize, /* xmlSecSize objSize */ |
|
1008 |
|
1009 BAD_CAST "Visa3DHackTransform", /* const xmlChar* name; */ |
|
1010 NULL, /* const xmlChar* href; */ |
|
1011 xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */ |
|
1012 |
|
1013 xmlSecTransformVisa3DHackInitialize, /* xmlSecTransformInitializeMethod initialize; */ |
|
1014 xmlSecTransformVisa3DHackFinalize, /* xmlSecTransformFinalizeMethod finalize; */ |
|
1015 NULL, /* xmlSecTransformNodeReadMethod readNode; */ |
|
1016 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
|
1017 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ |
|
1018 NULL, /* xmlSecTransformSetKeyMethod setKey; */ |
|
1019 NULL, /* xmlSecTransformValidateMethod validate; */ |
|
1020 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
|
1021 NULL, /* xmlSecTransformPushBinMethod pushBin; */ |
|
1022 NULL, /* xmlSecTransformPopBinMethod popBin; */ |
|
1023 xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */ |
|
1024 xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */ |
|
1025 xmlSecTransformVisa3DHackExecute, /* xmlSecTransformExecuteMethod execute; */ |
|
1026 |
|
1027 NULL, /* void* reserved0; */ |
|
1028 NULL, /* void* reserved1; */ |
|
1029 }; |
|
1030 |
|
1031 /** |
|
1032 * xmlSecTransformVisa3DHackGetKlass: |
|
1033 * |
|
1034 * The Visa3DHack transform klass. The only reason why we need this |
|
1035 * is Visa3D protocol. It doesn't follow XML/XPointer/XMLDSig specs and allows |
|
1036 * something like "#12345" in the URI attribute. |
|
1037 * |
|
1038 * Returns Visa3DHack transform klass. |
|
1039 */ |
|
1040 EXPORT_C |
|
1041 xmlSecTransformId |
|
1042 xmlSecTransformVisa3DHackGetKlass(void) { |
|
1043 return(&xmlSecTransformVisa3DHackKlass); |
|
1044 } |
|
1045 |
|
1046 /** |
|
1047 * xmlSecTransformVisa3DHackSetID: |
|
1048 * @transform: the pointer to Visa3DHack transform. |
|
1049 * @id: the ID value. |
|
1050 * |
|
1051 * Sets the ID value for an Visa3DHack @transform. |
|
1052 * |
|
1053 * Returns 0 on success or a negative value if an error occurs. |
|
1054 */ |
|
1055 EXPORT_C |
|
1056 int |
|
1057 xmlSecTransformVisa3DHackSetID(xmlSecTransformPtr transform, const xmlChar* id) { |
|
1058 xmlChar** idPtr; |
|
1059 |
|
1060 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformVisa3DHackId), -1); |
|
1061 xmlSecAssert2(id != NULL, -1); |
|
1062 |
|
1063 idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform); |
|
1064 xmlSecAssert2(idPtr != NULL, -1); |
|
1065 xmlSecAssert2((*idPtr) == NULL, -1); |
|
1066 |
|
1067 (*idPtr) = xmlStrdup(id); |
|
1068 if((*idPtr) == NULL) { |
|
1069 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1070 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
1071 "xmlStrdup", |
|
1072 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
1073 XMLSEC_ERRORS_NO_MESSAGE); |
|
1074 return(-1); |
|
1075 } |
|
1076 |
|
1077 return(0); |
|
1078 } |
|
1079 |
|
1080 static int |
|
1081 xmlSecTransformVisa3DHackInitialize(xmlSecTransformPtr transform) { |
|
1082 xmlSecAssert2(xmlSecTransformVisa3DHackCheckId(transform), -1); |
|
1083 |
|
1084 return(0); |
|
1085 } |
|
1086 |
|
1087 static void |
|
1088 xmlSecTransformVisa3DHackFinalize(xmlSecTransformPtr transform) { |
|
1089 xmlChar** idPtr; |
|
1090 |
|
1091 xmlSecAssert(xmlSecTransformVisa3DHackCheckId(transform)); |
|
1092 |
|
1093 idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform); |
|
1094 xmlSecAssert(idPtr != NULL); |
|
1095 |
|
1096 if((*idPtr) != NULL) { |
|
1097 xmlFree((*idPtr)); |
|
1098 } |
|
1099 (*idPtr) = NULL; |
|
1100 } |
|
1101 |
|
1102 static int |
|
1103 xmlSecTransformVisa3DHackExecute(xmlSecTransformPtr transform, int last, |
|
1104 xmlSecTransformCtxPtr transformCtx) { |
|
1105 xmlChar** idPtr; |
|
1106 xmlDocPtr doc; |
|
1107 xmlAttrPtr attr; |
|
1108 xmlNodeSetPtr nodeSet; |
|
1109 |
|
1110 xmlSecAssert2(xmlSecTransformVisa3DHackCheckId(transform), -1); |
|
1111 xmlSecAssert2(transform->outNodes == NULL, -1); |
|
1112 xmlSecAssert2(last != 0, -1); |
|
1113 xmlSecAssert2(transformCtx != NULL, -1); |
|
1114 |
|
1115 idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform); |
|
1116 xmlSecAssert2(idPtr != NULL, -1); |
|
1117 xmlSecAssert2((*idPtr) != NULL, -1); |
|
1118 |
|
1119 doc = (transform->inNodes != NULL) ? transform->inNodes->doc : transform->hereNode->doc; |
|
1120 xmlSecAssert2(doc != NULL, -1); |
|
1121 |
|
1122 attr = xmlGetID(doc, (*idPtr)); |
|
1123 if((attr == NULL) || (attr->parent == NULL)) { |
|
1124 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1125 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
1126 "xmlGetID", |
|
1127 XMLSEC_ERRORS_R_XML_FAILED, |
|
1128 "id=\"%s\"", |
|
1129 xmlSecErrorsSafeString((*idPtr))); |
|
1130 return(-1); |
|
1131 } |
|
1132 |
|
1133 nodeSet = xmlXPathNodeSetCreate(attr->parent); |
|
1134 if(nodeSet == NULL) { |
|
1135 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1136 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
1137 "xmlXPathNodeSetCreate", |
|
1138 XMLSEC_ERRORS_R_XML_FAILED, |
|
1139 "id=\"%s\"", |
|
1140 xmlSecErrorsSafeString((*idPtr))); |
|
1141 return(-1); |
|
1142 } |
|
1143 |
|
1144 transform->outNodes = xmlSecNodeSetCreate(doc, nodeSet, xmlSecNodeSetTreeWithoutComments); |
|
1145 if(transform->outNodes == NULL) { |
|
1146 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1147 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
1148 "xmlSecNodeSetCreate", |
|
1149 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1150 XMLSEC_ERRORS_NO_MESSAGE); |
|
1151 xmlXPathFreeNodeSet(nodeSet); |
|
1152 return(-1); |
|
1153 } |
|
1154 return(0); |
|
1155 } |
|
1156 |
|
1157 |
|
1158 |