|
1 /** |
|
2 * XML Security Library (http://www.aleksey.com/xmlsec). |
|
3 * |
|
4 * The Transforms Element (http://www.w3.org/TR/xmldsig-core/#sec-Transforms) |
|
5 * |
|
6 * The optional Transforms element contains an ordered list of Transform |
|
7 * elements; these describe how the signer obtained the data object that |
|
8 * was digested. |
|
9 * |
|
10 * Schema Definition: |
|
11 * |
|
12 * <element name="Transforms" type="ds:TransformsType"/> |
|
13 * <complexType name="TransformsType"> |
|
14 * <sequence> |
|
15 * <element ref="ds:Transform" maxOccurs="unbounded"/> |
|
16 * </sequence> |
|
17 * </complexType> |
|
18 * |
|
19 * <element name="Transform" type="ds:TransformType"/> |
|
20 * <complexType name="TransformType" mixed="true"> |
|
21 * <choice minOccurs="0" maxOccurs="unbounded"> |
|
22 * <any namespace="##other" processContents="lax"/> |
|
23 * <!-- (1,1) elements from (0,unbounded) namespaces --> |
|
24 * <element name="XPath" type="string"/> |
|
25 * </choice> |
|
26 * <attribute name="Algorithm" type="anyURI" use="required"/> |
|
27 * </complexType> |
|
28 * |
|
29 * DTD: |
|
30 * |
|
31 * <!ELEMENT Transforms (Transform+)> |
|
32 * <!ELEMENT Transform (#PCDATA|XPath %Transform.ANY;)* > |
|
33 * <!ATTLIST Transform Algorithm CDATA #REQUIRED > |
|
34 * <!ELEMENT XPath (#PCDATA) > |
|
35 * |
|
36 * This is free software; see Copyright file in the source |
|
37 * distribution for preciese wording. |
|
38 * |
|
39 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> |
|
40 * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. |
|
41 */ |
|
42 |
|
43 #include "xmlsec_globals.h" |
|
44 |
|
45 #include <stdlib.h> |
|
46 #include <stdio.h> |
|
47 #include <string.h> |
|
48 |
|
49 #include <libxml2_tree.h> |
|
50 #include <libxml2_xpath.h> |
|
51 #include <libxml2_xpointer.h> |
|
52 #include <libxml2_globals.h> |
|
53 |
|
54 #include "xmlsec_xmlsec.h" |
|
55 #include "xmlsec_buffer.h" |
|
56 #include "xmlsec_xmltree.h" |
|
57 #include "xmlsec_keysdata.h" |
|
58 #include "xmlsec_keys.h" |
|
59 #include "xmlsec_keyinfo.h" |
|
60 #include "xmlsec_transforms.h" |
|
61 #include "xmlsec_base64.h" |
|
62 #include "xmlsec_io.h" |
|
63 #include "xmlsec_membuf.h" |
|
64 #include "xmlsec_parser.h" |
|
65 #include "xmlsec_errors.h" |
|
66 |
|
67 /************************************************************************** |
|
68 * |
|
69 * Global xmlSecTransformIds list functions |
|
70 * |
|
71 *************************************************************************/ |
|
72 static xmlSecPtrList xmlSecAllTransformIds; |
|
73 |
|
74 |
|
75 /** |
|
76 * xmlSecTransformIdsGet: |
|
77 * |
|
78 * Gets global registered transform klasses list. |
|
79 * |
|
80 * Returns the pointer to list of all registered transform klasses. |
|
81 */ |
|
82 EXPORT_C |
|
83 xmlSecPtrListPtr |
|
84 xmlSecTransformIdsGet(void) { |
|
85 return(&xmlSecAllTransformIds); |
|
86 } |
|
87 |
|
88 /** |
|
89 * xmlSecTransformIdsInit: |
|
90 * |
|
91 * Initializes the transform klasses. This function is called from the |
|
92 * #xmlSecInit function and the application should not call it directly. |
|
93 * |
|
94 * Returns 0 on success or a negative value if an error occurs. |
|
95 */ |
|
96 EXPORT_C |
|
97 int |
|
98 xmlSecTransformIdsInit(void) { |
|
99 int ret; |
|
100 |
|
101 ret = xmlSecPtrListInitialize(xmlSecTransformIdsGet(), xmlSecTransformIdListId); |
|
102 if(ret < 0) { |
|
103 xmlSecError(XMLSEC_ERRORS_HERE, |
|
104 NULL, |
|
105 "xmlSecPtrListPtrInitialize", |
|
106 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
107 "xmlSecTransformIdListId"); |
|
108 return(-1); |
|
109 } |
|
110 |
|
111 ret = xmlSecTransformIdsRegisterDefault(); |
|
112 if(ret < 0) { |
|
113 xmlSecError(XMLSEC_ERRORS_HERE, |
|
114 NULL, |
|
115 "xmlSecTransformIdsRegisterDefault", |
|
116 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
117 XMLSEC_ERRORS_NO_MESSAGE); |
|
118 return(-1); |
|
119 } |
|
120 |
|
121 return(0); |
|
122 } |
|
123 |
|
124 /** |
|
125 * xmlSecTransformIdsShutdown: |
|
126 * |
|
127 * Shuts down the keys data klasses. This function is called from the |
|
128 * #xmlSecShutdown function and the application should not call it directly. |
|
129 */ |
|
130 EXPORT_C |
|
131 void |
|
132 xmlSecTransformIdsShutdown(void) { |
|
133 xmlSecPtrListFinalize(xmlSecTransformIdsGet()); |
|
134 } |
|
135 |
|
136 /** |
|
137 * xmlSecTransformIdsRegister: |
|
138 * @id: the transform klass. |
|
139 * |
|
140 * Registers @id in the global list of transform klasses. |
|
141 * |
|
142 * Returns 0 on success or a negative value if an error occurs. |
|
143 */ |
|
144 EXPORT_C |
|
145 int |
|
146 xmlSecTransformIdsRegister(xmlSecTransformId id) { |
|
147 int ret; |
|
148 |
|
149 xmlSecAssert2(id != xmlSecTransformIdUnknown, -1); |
|
150 |
|
151 ret = xmlSecPtrListAdd(xmlSecTransformIdsGet(), (xmlSecPtr)id); |
|
152 if(ret < 0) { |
|
153 xmlSecError(XMLSEC_ERRORS_HERE, |
|
154 NULL, |
|
155 "xmlSecPtrListAdd", |
|
156 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
157 "transform=%s", |
|
158 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id))); |
|
159 return(-1); |
|
160 } |
|
161 |
|
162 return(0); |
|
163 } |
|
164 |
|
165 /** |
|
166 * xmlSecTransformIdsRegisterDefault: |
|
167 * |
|
168 * Registers default (implemented by XML Security Library) |
|
169 * transform klasses: XPath transform, Base64 transform, ... |
|
170 * |
|
171 * Returns 0 on success or a negative value if an error occurs. |
|
172 */ |
|
173 EXPORT_C |
|
174 int |
|
175 xmlSecTransformIdsRegisterDefault(void) { |
|
176 if(xmlSecTransformIdsRegister(xmlSecTransformBase64Id) < 0) { |
|
177 xmlSecError(XMLSEC_ERRORS_HERE, |
|
178 NULL, |
|
179 "xmlSecTransformIdsRegister", |
|
180 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
181 "name=%s", |
|
182 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformBase64Id))); |
|
183 return(-1); |
|
184 } |
|
185 |
|
186 if(xmlSecTransformIdsRegister(xmlSecTransformEnvelopedId) < 0) { |
|
187 xmlSecError(XMLSEC_ERRORS_HERE, |
|
188 NULL, |
|
189 "xmlSecTransformIdsRegister", |
|
190 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
191 "name=%s", |
|
192 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformEnvelopedId))); |
|
193 return(-1); |
|
194 } |
|
195 |
|
196 /* c14n methods */ |
|
197 if(xmlSecTransformIdsRegister(xmlSecTransformInclC14NId) < 0) { |
|
198 xmlSecError(XMLSEC_ERRORS_HERE, |
|
199 NULL, |
|
200 "xmlSecTransformIdsRegister", |
|
201 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
202 "name=%s", |
|
203 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NId))); |
|
204 return(-1); |
|
205 } |
|
206 if(xmlSecTransformIdsRegister(xmlSecTransformInclC14NWithCommentsId) < 0) { |
|
207 xmlSecError(XMLSEC_ERRORS_HERE, |
|
208 NULL, |
|
209 "xmlSecTransformIdsRegister", |
|
210 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
211 "name=%s", |
|
212 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NWithCommentsId))); |
|
213 return(-1); |
|
214 } |
|
215 if(xmlSecTransformIdsRegister(xmlSecTransformExclC14NId) < 0) { |
|
216 xmlSecError(XMLSEC_ERRORS_HERE, |
|
217 NULL, |
|
218 "xmlSecTransformIdsRegister", |
|
219 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
220 "name=%s", |
|
221 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformExclC14NId))); |
|
222 return(-1); |
|
223 } |
|
224 if(xmlSecTransformIdsRegister(xmlSecTransformExclC14NWithCommentsId) < 0) { |
|
225 xmlSecError(XMLSEC_ERRORS_HERE, |
|
226 NULL, |
|
227 "xmlSecTransformIdsRegister", |
|
228 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
229 "name=%s", |
|
230 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformExclC14NWithCommentsId))); |
|
231 return(-1); |
|
232 } |
|
233 |
|
234 if(xmlSecTransformIdsRegister(xmlSecTransformXPathId) < 0) { |
|
235 xmlSecError(XMLSEC_ERRORS_HERE, |
|
236 NULL, |
|
237 "xmlSecTransformIdsRegister", |
|
238 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
239 "name=%s", |
|
240 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPathId))); |
|
241 return(-1); |
|
242 } |
|
243 |
|
244 if(xmlSecTransformIdsRegister(xmlSecTransformXPath2Id) < 0) { |
|
245 xmlSecError(XMLSEC_ERRORS_HERE, |
|
246 NULL, |
|
247 "xmlSecTransformIdsRegister", |
|
248 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
249 "name=%s", |
|
250 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPath2Id))); |
|
251 return(-1); |
|
252 } |
|
253 |
|
254 if(xmlSecTransformIdsRegister(xmlSecTransformXPointerId) < 0) { |
|
255 xmlSecError(XMLSEC_ERRORS_HERE, |
|
256 NULL, |
|
257 "xmlSecTransformIdsRegister", |
|
258 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
259 "name=%s", |
|
260 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPointerId))); |
|
261 return(-1); |
|
262 } |
|
263 |
|
264 #ifndef XMLSEC_NO_XSLT |
|
265 if(xmlSecTransformIdsRegister(xmlSecTransformXsltId) < 0) { |
|
266 xmlSecError(XMLSEC_ERRORS_HERE, |
|
267 NULL, |
|
268 "xmlSecTransformIdsRegister", |
|
269 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
270 "name=%s", |
|
271 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXsltId))); |
|
272 return(-1); |
|
273 } |
|
274 #endif /* XMLSEC_NO_XSLT */ |
|
275 |
|
276 return(0); |
|
277 } |
|
278 |
|
279 /************************************************************************** |
|
280 * |
|
281 * utils |
|
282 * |
|
283 *************************************************************************/ |
|
284 /** |
|
285 * xmlSecTransformUriTypeCheck: |
|
286 * @type: the expected URI type. |
|
287 * @uri: the uri for checking. |
|
288 * |
|
289 * Checks if @uri matches expected type @type. |
|
290 * |
|
291 * Returns 1 if @uri matches @type, 0 if not or a negative value |
|
292 * if an error occurs. |
|
293 */ |
|
294 EXPORT_C |
|
295 int |
|
296 xmlSecTransformUriTypeCheck(xmlSecTransformUriType type, const xmlChar* uri) { |
|
297 xmlSecTransformUriType uriType = 0; |
|
298 |
|
299 if((uri == NULL) || (xmlStrlen(uri) == 0)) { |
|
300 uriType = xmlSecTransformUriTypeEmpty; |
|
301 } else if(uri[0] == '#') { |
|
302 uriType = xmlSecTransformUriTypeSameDocument; |
|
303 } else if(xmlStrncmp(uri, BAD_CAST "file://", 7) == 0) { |
|
304 uriType = xmlSecTransformUriTypeLocal; |
|
305 } else { |
|
306 uriType = xmlSecTransformUriTypeRemote; |
|
307 } |
|
308 return(((uriType & type) != 0) ? 1 : 0); |
|
309 } |
|
310 |
|
311 /************************************************************************** |
|
312 * |
|
313 * xmlSecTransformCtx |
|
314 * |
|
315 *************************************************************************/ |
|
316 |
|
317 /** |
|
318 * xmlSecTransformCtxCreate: |
|
319 * |
|
320 * Creates transforms chain processing context. |
|
321 * The caller is responsible for destroying returend object by calling |
|
322 * #xmlSecTransformCtxDestroy function. |
|
323 * |
|
324 * Returns pointer to newly allocated context object or NULL if an error |
|
325 * occurs. |
|
326 */ |
|
327 EXPORT_C |
|
328 xmlSecTransformCtxPtr |
|
329 xmlSecTransformCtxCreate(void) { |
|
330 xmlSecTransformCtxPtr ctx; |
|
331 int ret; |
|
332 |
|
333 /* Allocate a new xmlSecTransform and fill the fields. */ |
|
334 ctx = (xmlSecTransformCtxPtr)xmlMalloc(sizeof(xmlSecTransformCtx)); |
|
335 if(ctx == NULL) { |
|
336 xmlSecError(XMLSEC_ERRORS_HERE, |
|
337 NULL, |
|
338 NULL, |
|
339 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
340 "size=%d", sizeof(xmlSecTransformCtx)); |
|
341 return(NULL); |
|
342 } |
|
343 |
|
344 ret = xmlSecTransformCtxInitialize(ctx); |
|
345 if(ret < 0) { |
|
346 xmlSecError(XMLSEC_ERRORS_HERE, |
|
347 NULL, |
|
348 "xmlSecTransformCtxInitialize", |
|
349 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
350 XMLSEC_ERRORS_NO_MESSAGE); |
|
351 xmlSecTransformCtxDestroy(ctx); |
|
352 return(NULL); |
|
353 } |
|
354 |
|
355 return(ctx); |
|
356 } |
|
357 |
|
358 /** |
|
359 * xmlSecTransformCtxDestroy: |
|
360 * @ctx: the pointer to transforms chain processing context. |
|
361 * |
|
362 * Destroy context object created with #xmlSecTransformCtxCreate function. |
|
363 */ |
|
364 EXPORT_C |
|
365 void |
|
366 xmlSecTransformCtxDestroy(xmlSecTransformCtxPtr ctx) { |
|
367 xmlSecAssert(ctx != NULL); |
|
368 |
|
369 xmlSecTransformCtxFinalize(ctx); |
|
370 xmlFree(ctx); |
|
371 } |
|
372 |
|
373 /** |
|
374 * xmlSecTransformCtxInitialize: |
|
375 * @ctx: the pointer to transforms chain processing context. |
|
376 * |
|
377 * Initializes transforms chain processing context. |
|
378 * The caller is responsible for cleaing up returend object by calling |
|
379 * #xmlSecTransformCtxFinalize function. |
|
380 * |
|
381 * Returns 0 on success or a negative value if an error occurs. |
|
382 */ |
|
383 EXPORT_C |
|
384 int |
|
385 xmlSecTransformCtxInitialize(xmlSecTransformCtxPtr ctx) { |
|
386 int ret; |
|
387 |
|
388 xmlSecAssert2(ctx != NULL, -1); |
|
389 |
|
390 memset(ctx, 0, sizeof(xmlSecTransformCtx)); |
|
391 |
|
392 ret = xmlSecPtrListInitialize(&(ctx->enabledTransforms), xmlSecTransformIdListId); |
|
393 if(ret < 0) { |
|
394 xmlSecError(XMLSEC_ERRORS_HERE, |
|
395 NULL, |
|
396 "xmlSecPtrListInitialize", |
|
397 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
398 XMLSEC_ERRORS_NO_MESSAGE); |
|
399 return(-1); |
|
400 } |
|
401 |
|
402 ctx->enabledUris = xmlSecTransformUriTypeAny; |
|
403 return(0); |
|
404 } |
|
405 |
|
406 /** |
|
407 * xmlSecTransformCtxFinalize: |
|
408 * @ctx: the pointer to transforms chain processing context. |
|
409 * |
|
410 * Cleans up @ctx object initialized with #xmlSecTransformCtxInitialize function. |
|
411 */ |
|
412 EXPORT_C |
|
413 void |
|
414 xmlSecTransformCtxFinalize(xmlSecTransformCtxPtr ctx) { |
|
415 xmlSecAssert(ctx != NULL); |
|
416 |
|
417 xmlSecTransformCtxReset(ctx); |
|
418 xmlSecPtrListFinalize(&(ctx->enabledTransforms)); |
|
419 memset(ctx, 0, sizeof(xmlSecTransformCtx)); |
|
420 } |
|
421 |
|
422 /** |
|
423 * xmlSecTransformCtxReset: |
|
424 * @ctx: the pointer to transforms chain processing context. |
|
425 * |
|
426 * Resets transfroms context for new processing. |
|
427 */ |
|
428 EXPORT_C |
|
429 void |
|
430 xmlSecTransformCtxReset(xmlSecTransformCtxPtr ctx) { |
|
431 xmlSecTransformPtr transform, tmp; |
|
432 |
|
433 xmlSecAssert(ctx != NULL); |
|
434 |
|
435 ctx->result = NULL; |
|
436 ctx->status = xmlSecTransformStatusNone; |
|
437 |
|
438 /* destroy uri */ |
|
439 if(ctx->uri != NULL) { |
|
440 xmlFree(ctx->uri); |
|
441 ctx->uri = NULL; |
|
442 } |
|
443 if(ctx->xptrExpr != NULL) { |
|
444 xmlFree(ctx->xptrExpr); |
|
445 ctx->xptrExpr = NULL; |
|
446 } |
|
447 |
|
448 /* destroy transforms chain */ |
|
449 for(transform = ctx->first; transform != NULL; transform = tmp) { |
|
450 tmp = transform->next; |
|
451 xmlSecTransformDestroy(transform); |
|
452 } |
|
453 ctx->first = ctx->last = NULL; |
|
454 } |
|
455 |
|
456 /** |
|
457 * xmlSecTransformCtxCopyUserPref: |
|
458 * @dst: the pointer to destination transforms chain processing context. |
|
459 * @src: the pointer to source transforms chain processing context. |
|
460 * |
|
461 * Copies user settings from @src context to @dst. |
|
462 * |
|
463 * Returns 0 on success or a negative value otherwise. |
|
464 */ |
|
465 EXPORT_C |
|
466 int |
|
467 xmlSecTransformCtxCopyUserPref(xmlSecTransformCtxPtr dst, xmlSecTransformCtxPtr src) { |
|
468 int ret; |
|
469 |
|
470 xmlSecAssert2(dst != NULL, -1); |
|
471 xmlSecAssert2(src != NULL, -1); |
|
472 |
|
473 dst->userData = src->userData; |
|
474 dst->flags = src->flags; |
|
475 dst->flags2 = src->flags2; |
|
476 dst->enabledUris = src->enabledUris; |
|
477 dst->preExecCallback = src->preExecCallback; |
|
478 |
|
479 ret = xmlSecPtrListCopy(&(dst->enabledTransforms), &(src->enabledTransforms)); |
|
480 if(ret < 0) { |
|
481 xmlSecError(XMLSEC_ERRORS_HERE, |
|
482 NULL, |
|
483 "xmlSecPtrListCopy", |
|
484 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
485 XMLSEC_ERRORS_NO_MESSAGE); |
|
486 return(-1); |
|
487 } |
|
488 |
|
489 return(0); |
|
490 } |
|
491 |
|
492 /** |
|
493 * xmlSecTransformCtxAppend: |
|
494 * @ctx: the pointer to transforms chain processing context. |
|
495 * @transform: the pointer to new transform. |
|
496 * |
|
497 * Connects the @transform to the end of the chain of transforms in the @ctx |
|
498 * (see #xmlSecTransformConnect function for details). |
|
499 * |
|
500 * Returns 0 on success or a negative value otherwise. |
|
501 */ |
|
502 EXPORT_C |
|
503 int |
|
504 xmlSecTransformCtxAppend(xmlSecTransformCtxPtr ctx, xmlSecTransformPtr transform) { |
|
505 int ret; |
|
506 |
|
507 xmlSecAssert2(ctx != NULL, -1); |
|
508 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1); |
|
509 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
510 |
|
511 if(ctx->last != NULL) { |
|
512 ret = xmlSecTransformConnect(ctx->last, transform, ctx); |
|
513 if(ret < 0) { |
|
514 xmlSecError(XMLSEC_ERRORS_HERE, |
|
515 NULL, |
|
516 "xmlSecTransformConnect", |
|
517 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
518 "name=%s", |
|
519 xmlSecErrorsSafeString(xmlSecTransformGetName(transform))); |
|
520 return(-1); |
|
521 } |
|
522 } else { |
|
523 xmlSecAssert2(ctx->first == NULL, -1); |
|
524 ctx->first = transform; |
|
525 } |
|
526 ctx->last = transform; |
|
527 |
|
528 return(0); |
|
529 } |
|
530 |
|
531 /** |
|
532 * xmlSecTransformCtxPrepend: |
|
533 * @ctx: the pointer to transforms chain processing context. |
|
534 * @transform: the pointer to new transform. |
|
535 * |
|
536 * Connects the @transform to the beggining of the chain of transforms in the @ctx |
|
537 * (see #xmlSecTransformConnect function for details). |
|
538 * |
|
539 * Returns 0 on success or a negative value otherwise. |
|
540 */ |
|
541 EXPORT_C |
|
542 int |
|
543 xmlSecTransformCtxPrepend(xmlSecTransformCtxPtr ctx, xmlSecTransformPtr transform) { |
|
544 int ret; |
|
545 |
|
546 xmlSecAssert2(ctx != NULL, -1); |
|
547 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1); |
|
548 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
549 |
|
550 if(ctx->first != NULL) { |
|
551 ret = xmlSecTransformConnect(transform, ctx->first, ctx); |
|
552 if(ret < 0) { |
|
553 xmlSecError(XMLSEC_ERRORS_HERE, |
|
554 NULL, |
|
555 "xmlSecTransformConnect", |
|
556 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
557 "name=%s", |
|
558 xmlSecErrorsSafeString(xmlSecTransformGetName(transform))); |
|
559 return(-1); |
|
560 } |
|
561 } else { |
|
562 xmlSecAssert2(ctx->last == NULL, -1); |
|
563 ctx->last = transform; |
|
564 } |
|
565 ctx->first = transform; |
|
566 |
|
567 return(0); |
|
568 } |
|
569 |
|
570 /** |
|
571 * xmlSecTransformCtxCreateAndAppend: |
|
572 * @ctx: the pointer to transforms chain processing context. |
|
573 * @id: the new transform klass. |
|
574 * |
|
575 * Creaeates new transform and connects it to the end of the chain of |
|
576 * transforms in the @ctx (see #xmlSecTransformConnect function for details). |
|
577 * |
|
578 * Returns pointer to newly created transform or NULL if an error occurs. |
|
579 */ |
|
580 EXPORT_C |
|
581 xmlSecTransformPtr |
|
582 xmlSecTransformCtxCreateAndAppend(xmlSecTransformCtxPtr ctx, xmlSecTransformId id) { |
|
583 xmlSecTransformPtr transform; |
|
584 int ret; |
|
585 |
|
586 xmlSecAssert2(ctx != NULL, NULL); |
|
587 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL); |
|
588 xmlSecAssert2(id != xmlSecTransformIdUnknown, NULL); |
|
589 |
|
590 transform = xmlSecTransformCreate(id); |
|
591 if(!xmlSecTransformIsValid(transform)) { |
|
592 xmlSecError(XMLSEC_ERRORS_HERE, |
|
593 NULL, |
|
594 "xmlSecTransformCreate", |
|
595 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
596 "transform=%s", |
|
597 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id))); |
|
598 return(NULL); |
|
599 } |
|
600 |
|
601 ret = xmlSecTransformCtxAppend(ctx, transform); |
|
602 if(ret < 0) { |
|
603 xmlSecError(XMLSEC_ERRORS_HERE, |
|
604 NULL, |
|
605 "xmlSecTransformCtxAppend", |
|
606 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
607 "name=%s", |
|
608 xmlSecErrorsSafeString(xmlSecTransformGetName(transform))); |
|
609 xmlSecTransformDestroy(transform); |
|
610 return(NULL); |
|
611 } |
|
612 |
|
613 return(transform); |
|
614 } |
|
615 |
|
616 /** |
|
617 * xmlSecTransformCtxCreateAndPrepend: |
|
618 * @ctx: the pointer to transforms chain processing context. |
|
619 * @id: the new transform klass. |
|
620 * |
|
621 * Creaeates new transform and connects it to the end of the chain of |
|
622 * transforms in the @ctx (see #xmlSecTransformConnect function for details). |
|
623 * |
|
624 * Returns pointer to newly created transform or NULL if an error occurs. |
|
625 */ |
|
626 EXPORT_C |
|
627 xmlSecTransformPtr |
|
628 xmlSecTransformCtxCreateAndPrepend(xmlSecTransformCtxPtr ctx, xmlSecTransformId id) { |
|
629 xmlSecTransformPtr transform; |
|
630 int ret; |
|
631 |
|
632 xmlSecAssert2(ctx != NULL, NULL); |
|
633 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL); |
|
634 xmlSecAssert2(id != xmlSecTransformIdUnknown, NULL); |
|
635 |
|
636 transform = xmlSecTransformCreate(id); |
|
637 if(!xmlSecTransformIsValid(transform)) { |
|
638 xmlSecError(XMLSEC_ERRORS_HERE, |
|
639 NULL, |
|
640 "xmlSecTransformCreate", |
|
641 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
642 "transform=%s", |
|
643 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id))); |
|
644 return(NULL); |
|
645 } |
|
646 |
|
647 ret = xmlSecTransformCtxPrepend(ctx, transform); |
|
648 if(ret < 0) { |
|
649 xmlSecError(XMLSEC_ERRORS_HERE, |
|
650 NULL, |
|
651 "xmlSecTransformCtxPrepend", |
|
652 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
653 "name=%s", |
|
654 xmlSecErrorsSafeString(xmlSecTransformGetName(transform))); |
|
655 xmlSecTransformDestroy(transform); |
|
656 return(NULL); |
|
657 } |
|
658 |
|
659 return(transform); |
|
660 } |
|
661 |
|
662 /** |
|
663 * xmlSecTransformCtxNodeRead: |
|
664 * @ctx: the pointer to transforms chain processing context. |
|
665 * @node: the pointer to transform's node. |
|
666 * @usage: the transform's usage (signature, encryption, etc.). |
|
667 * |
|
668 * Reads the transform from the @node and appends it to the current chain |
|
669 * of transforms in @ctx. |
|
670 * |
|
671 * Returns pointer to newly created transform or NULL if an error occurs. |
|
672 */ |
|
673 EXPORT_C |
|
674 xmlSecTransformPtr |
|
675 xmlSecTransformCtxNodeRead(xmlSecTransformCtxPtr ctx, xmlNodePtr node, |
|
676 xmlSecTransformUsage usage) { |
|
677 xmlSecTransformPtr transform; |
|
678 int ret; |
|
679 |
|
680 xmlSecAssert2(ctx != NULL, NULL); |
|
681 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL); |
|
682 xmlSecAssert2(node != NULL, NULL); |
|
683 |
|
684 transform = xmlSecTransformNodeRead(node, usage, ctx); |
|
685 if(transform == NULL) { |
|
686 xmlSecError(XMLSEC_ERRORS_HERE, |
|
687 NULL, |
|
688 "xmlSecTransformNodeRead", |
|
689 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
690 "name=%s", |
|
691 xmlSecErrorsSafeString(xmlSecNodeGetName(node))); |
|
692 return(NULL); |
|
693 } |
|
694 |
|
695 ret = xmlSecTransformCtxAppend(ctx, transform); |
|
696 if(ret < 0) { |
|
697 xmlSecError(XMLSEC_ERRORS_HERE, |
|
698 NULL, |
|
699 "xmlSecTransformCtxAppend", |
|
700 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
701 "name=%s", |
|
702 xmlSecErrorsSafeString(xmlSecTransformGetName(transform))); |
|
703 xmlSecTransformDestroy(transform); |
|
704 return(NULL); |
|
705 } |
|
706 |
|
707 return(transform); |
|
708 } |
|
709 |
|
710 /** |
|
711 * xmlSecTransformCtxNodesListRead: |
|
712 * @ctx: the pointer to transforms chain processing context. |
|
713 * @node: the pointer to <dsig:Transform/> nodes parent node. |
|
714 * @usage: the transform's usage (signature, encryption, etc.). |
|
715 * |
|
716 * Reads transforms from the <dsig:Transform/> children of the @node and |
|
717 * appends them to the current transforms chain in @ctx object. |
|
718 * |
|
719 * Returns 0 on success or a negative value otherwise. |
|
720 */ |
|
721 EXPORT_C |
|
722 int |
|
723 xmlSecTransformCtxNodesListRead(xmlSecTransformCtxPtr ctx, xmlNodePtr node, xmlSecTransformUsage usage) { |
|
724 xmlSecTransformPtr transform; |
|
725 xmlNodePtr cur; |
|
726 int ret; |
|
727 |
|
728 xmlSecAssert2(ctx != NULL, -1); |
|
729 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1); |
|
730 xmlSecAssert2(node != NULL, -1); |
|
731 |
|
732 cur = xmlSecGetNextElementNode(node->children); |
|
733 while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeTransform, xmlSecDSigNs)) { |
|
734 transform = xmlSecTransformNodeRead(cur, usage, ctx); |
|
735 if(transform == NULL) { |
|
736 xmlSecError(XMLSEC_ERRORS_HERE, |
|
737 NULL, |
|
738 "xmlSecTransformNodeRead", |
|
739 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
740 "node=%s", |
|
741 xmlSecErrorsSafeString(xmlSecNodeGetName(cur))); |
|
742 return(-1); |
|
743 } |
|
744 |
|
745 ret = xmlSecTransformCtxAppend(ctx, transform); |
|
746 if(ret < 0) { |
|
747 xmlSecError(XMLSEC_ERRORS_HERE, |
|
748 NULL, |
|
749 "xmlSecTransformCtxAppend", |
|
750 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
751 "node=%s", |
|
752 xmlSecErrorsSafeString(xmlSecNodeGetName(cur))); |
|
753 xmlSecTransformDestroy(transform); |
|
754 return(-1); |
|
755 } |
|
756 cur = xmlSecGetNextElementNode(cur->next); |
|
757 } |
|
758 |
|
759 if(cur != NULL) { |
|
760 xmlSecError(XMLSEC_ERRORS_HERE, |
|
761 NULL, |
|
762 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), |
|
763 XMLSEC_ERRORS_R_UNEXPECTED_NODE, |
|
764 XMLSEC_ERRORS_NO_MESSAGE); |
|
765 return(-1); |
|
766 } |
|
767 return(0); |
|
768 } |
|
769 |
|
770 /** |
|
771 * xmlSecTransformCtxSetUri: |
|
772 * @ctx: the pointer to transforms chain processing context. |
|
773 * @uri: the URI. |
|
774 * @hereNode: the pointer to "here" node required by some |
|
775 * XML transforms (may be NULL). |
|
776 * |
|
777 * Parses uri and adds xpointer transforms if required. |
|
778 * |
|
779 * The following examples demonstrate what the URI attribute identifies and |
|
780 * how it is dereferenced |
|
781 * (http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel): |
|
782 * |
|
783 * - URI="http://example.com/bar.xml" |
|
784 * identifies the octets that represent the external resource |
|
785 * 'http://example.com/bar.xml', that is probably an XML document given |
|
786 * its file extension. |
|
787 * |
|
788 * - URI="http://example.com/bar.xml#chapter1" |
|
789 * identifies the element with ID attribute value 'chapter1' of the |
|
790 * external XML resource 'http://example.com/bar.xml', provided as an |
|
791 * octet stream. Again, for the sake of interoperability, the element |
|
792 * identified as 'chapter1' should be obtained using an XPath transform |
|
793 * rather than a URI fragment (barename XPointer resolution in external |
|
794 * resources is not REQUIRED in this specification). |
|
795 * |
|
796 * - URI="" |
|
797 * identifies the node-set (minus any comment nodes) of the XML resource |
|
798 * containing the signature |
|
799 * |
|
800 * - URI="#chapter1" |
|
801 * identifies a node-set containing the element with ID attribute value |
|
802 * 'chapter1' of the XML resource containing the signature. XML Signature |
|
803 * (and its applications) modify this node-set to include the element plus |
|
804 * all descendents including namespaces and attributes -- but not comments. |
|
805 * |
|
806 * Returns 0 on success or a negative value otherwise. |
|
807 */ |
|
808 EXPORT_C |
|
809 int |
|
810 xmlSecTransformCtxSetUri(xmlSecTransformCtxPtr ctx, const xmlChar* uri, xmlNodePtr hereNode) { |
|
811 xmlSecNodeSetType nodeSetType = xmlSecNodeSetTree; |
|
812 const xmlChar* xptr; |
|
813 xmlChar* buf = NULL; |
|
814 int useVisa3DHack = 0; |
|
815 int ret; |
|
816 |
|
817 xmlSecAssert2(ctx != NULL, -1); |
|
818 xmlSecAssert2(ctx->uri == NULL, -1); |
|
819 xmlSecAssert2(ctx->xptrExpr == NULL, -1); |
|
820 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1); |
|
821 xmlSecAssert2(hereNode != NULL, -1); |
|
822 |
|
823 /* check uri */ |
|
824 if(xmlSecTransformUriTypeCheck(ctx->enabledUris, uri) != 1) { |
|
825 xmlSecError(XMLSEC_ERRORS_HERE, |
|
826 NULL, |
|
827 NULL, |
|
828 XMLSEC_ERRORS_R_INVALID_URI_TYPE, |
|
829 "uri=%s", |
|
830 xmlSecErrorsSafeString(uri)); |
|
831 return(-1); |
|
832 } |
|
833 |
|
834 /* is it an empty uri? */ |
|
835 if((uri == NULL) || (xmlStrlen(uri) == 0)) { |
|
836 return(0); |
|
837 } |
|
838 |
|
839 /* do we have barename or full xpointer? */ |
|
840 xptr = xmlStrchr(uri, '#'); |
|
841 if(xptr == NULL){ |
|
842 ctx->uri = xmlStrdup(uri); |
|
843 if(ctx->uri == NULL) { |
|
844 xmlSecError(XMLSEC_ERRORS_HERE, |
|
845 NULL, |
|
846 NULL, |
|
847 XMLSEC_ERRORS_R_STRDUP_FAILED, |
|
848 "size=%d", xmlStrlen(uri)); |
|
849 return(-1); |
|
850 } |
|
851 /* we are done */ |
|
852 return(0); |
|
853 } else if(xmlStrcmp(uri, BAD_CAST "#xpointer(/)") == 0) { |
|
854 ctx->xptrExpr = xmlStrdup(uri); |
|
855 if(ctx->xptrExpr == NULL) { |
|
856 xmlSecError(XMLSEC_ERRORS_HERE, |
|
857 NULL, |
|
858 NULL, |
|
859 XMLSEC_ERRORS_R_STRDUP_FAILED, |
|
860 "size=%d", xmlStrlen(uri)); |
|
861 return(-1); |
|
862 } |
|
863 /* we are done */ |
|
864 return(0); |
|
865 } |
|
866 |
|
867 ctx->uri = xmlStrndup(uri, xptr - uri); |
|
868 if(ctx->uri == NULL) { |
|
869 xmlSecError(XMLSEC_ERRORS_HERE, |
|
870 NULL, |
|
871 NULL, |
|
872 XMLSEC_ERRORS_R_STRDUP_FAILED, |
|
873 "size=%d", xptr - uri); |
|
874 return(-1); |
|
875 } |
|
876 |
|
877 ctx->xptrExpr = xmlStrdup(xptr); |
|
878 if(ctx->xptrExpr == NULL) { |
|
879 xmlSecError(XMLSEC_ERRORS_HERE, |
|
880 NULL, |
|
881 NULL, |
|
882 XMLSEC_ERRORS_R_STRDUP_FAILED, |
|
883 "size=%d", xmlStrlen(xptr)); |
|
884 return(-1); |
|
885 } |
|
886 |
|
887 /* do we have barename or full xpointer? */ |
|
888 xmlSecAssert2(xptr != NULL, -1); |
|
889 if((xmlStrncmp(xptr, BAD_CAST "#xpointer(", 10) == 0) || (xmlStrncmp(xptr, BAD_CAST "#xmlns(", 7) == 0)) { |
|
890 ++xptr; |
|
891 nodeSetType = xmlSecNodeSetTree; |
|
892 } else if((ctx->flags & XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK) != 0) { |
|
893 ++xptr; |
|
894 nodeSetType = xmlSecNodeSetTreeWithoutComments; |
|
895 useVisa3DHack = 1; |
|
896 } else { |
|
897 static const char tmpl[] = "xpointer(id(\'%s\'))"; |
|
898 xmlSecSize size; |
|
899 |
|
900 /* we need to add "xpointer(id('..')) because otherwise we have |
|
901 * problems with numeric ("111" and so on) and other "strange" ids */ |
|
902 size = xmlStrlen(BAD_CAST tmpl) + xmlStrlen(xptr) + 2; |
|
903 buf = (xmlChar*)xmlMalloc(size * sizeof(xmlChar)); |
|
904 if(buf == NULL) { |
|
905 xmlSecError(XMLSEC_ERRORS_HERE, |
|
906 NULL, |
|
907 NULL, |
|
908 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
909 "size=%d", size); |
|
910 return(-1); |
|
911 } |
|
912 sprintf((char*)buf, tmpl, xptr + 1); |
|
913 xptr = buf; |
|
914 nodeSetType = xmlSecNodeSetTreeWithoutComments; |
|
915 } |
|
916 |
|
917 if(useVisa3DHack == 0) { |
|
918 xmlSecTransformPtr transform; |
|
919 |
|
920 /* we need to create XPonter transform to execute expr */ |
|
921 transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformXPointerId); |
|
922 if(!xmlSecTransformIsValid(transform)) { |
|
923 xmlSecError(XMLSEC_ERRORS_HERE, |
|
924 NULL, |
|
925 "xmlSecTransformCtxCreateAndPrepend", |
|
926 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
927 "transform=%s", |
|
928 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPointerId))); |
|
929 xmlFree( buf ); //buf == xptr |
|
930 return(-1); |
|
931 } |
|
932 |
|
933 ret = xmlSecTransformXPointerSetExpr(transform, xptr, nodeSetType, hereNode); |
|
934 if(ret < 0) { |
|
935 xmlSecError(XMLSEC_ERRORS_HERE, |
|
936 NULL, |
|
937 "xmlSecTransformXPointerSetExpr", |
|
938 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
939 "name=%s", |
|
940 xmlSecErrorsSafeString(xmlSecTransformGetName(transform))); |
|
941 if( buf != NULL) { |
|
942 xmlFree( buf ); //buf == xptr |
|
943 } |
|
944 return(-1); |
|
945 } |
|
946 } else { |
|
947 /* Visa3D protocol doesn't follow XML/XPointer/XMLDSig specs |
|
948 * and allows something like "#12345" in the URI attribute. |
|
949 */ |
|
950 xmlSecTransformPtr transform; |
|
951 |
|
952 transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformVisa3DHackId); |
|
953 if(!xmlSecTransformIsValid(transform)) { |
|
954 xmlSecError(XMLSEC_ERRORS_HERE, |
|
955 NULL, |
|
956 "xmlSecTransformCtxCreateAndPrepend", |
|
957 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
958 "transform=%s", |
|
959 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformVisa3DHackId))); |
|
960 return(-1); |
|
961 } |
|
962 |
|
963 ret = xmlSecTransformVisa3DHackSetID(transform, xptr); |
|
964 if(ret < 0) { |
|
965 xmlSecError(XMLSEC_ERRORS_HERE, |
|
966 NULL, |
|
967 "xmlSecTransformVisa3DHackSetID", |
|
968 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
969 "name=%s", |
|
970 xmlSecErrorsSafeString(xmlSecTransformGetName(transform))); |
|
971 if(buf != NULL) { |
|
972 xmlFree(buf); |
|
973 } |
|
974 return(-1); |
|
975 } |
|
976 } |
|
977 if(buf != NULL) { |
|
978 xmlFree(buf); |
|
979 } |
|
980 |
|
981 return(0); |
|
982 } |
|
983 |
|
984 /** |
|
985 * xmlSecTransformCtxPrepare: |
|
986 * @ctx: the pointer to transforms chain processing context. |
|
987 * @inputDataType: the expected input type. |
|
988 * |
|
989 * Prepares the transform context for processing data of @inputDataType. |
|
990 * |
|
991 * Returns 0 on success or a negative value otherwise. |
|
992 */ |
|
993 EXPORT_C |
|
994 int |
|
995 xmlSecTransformCtxPrepare(xmlSecTransformCtxPtr ctx, xmlSecTransformDataType inputDataType) { |
|
996 xmlSecTransformDataType firstType; |
|
997 xmlSecTransformPtr transform; |
|
998 int ret; |
|
999 |
|
1000 xmlSecAssert2(ctx != NULL, -1); |
|
1001 xmlSecAssert2(ctx->result == NULL, -1); |
|
1002 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1); |
|
1003 |
|
1004 /* add binary buffer to store result */ |
|
1005 transform = xmlSecTransformCtxCreateAndAppend(ctx, xmlSecTransformMemBufId); |
|
1006 if(!xmlSecTransformIsValid(transform)) { |
|
1007 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1008 NULL, |
|
1009 "xmlSecTransformCreate", |
|
1010 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1011 "transform=%s", |
|
1012 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId))); |
|
1013 return(-1); |
|
1014 } |
|
1015 ctx->result = xmlSecTransformMemBufGetBuffer(transform); |
|
1016 if(ctx->result == NULL) { |
|
1017 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1018 NULL, |
|
1019 "xmlSecTransformMemBufGetBuffer", |
|
1020 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1021 "transform=%s", |
|
1022 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId))); |
|
1023 return(-1); |
|
1024 } |
|
1025 |
|
1026 firstType = xmlSecTransformGetDataType(ctx->first, xmlSecTransformModePush, ctx); |
|
1027 if(((firstType & xmlSecTransformDataTypeBin) == 0) && |
|
1028 ((inputDataType & xmlSecTransformDataTypeBin) != 0)) { |
|
1029 |
|
1030 /* need to add parser transform */ |
|
1031 transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformXmlParserId); |
|
1032 if(transform == NULL) { |
|
1033 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1034 NULL, |
|
1035 "xmlSecTransformCtxCreateAndPrepend", |
|
1036 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1037 "transform=%s", |
|
1038 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXmlParserId))); |
|
1039 return(-1); |
|
1040 } |
|
1041 } else if(((firstType & xmlSecTransformDataTypeXml) == 0) && |
|
1042 ((inputDataType & xmlSecTransformDataTypeXml) != 0)) { |
|
1043 |
|
1044 /* need to add c14n transform */ |
|
1045 transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformInclC14NId); |
|
1046 if(transform == NULL) { |
|
1047 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1048 NULL, |
|
1049 "xmlSecTransformCtxCreateAndPrepend", |
|
1050 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1051 "transform=%s", |
|
1052 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NId))); |
|
1053 return(-1); |
|
1054 } |
|
1055 } |
|
1056 |
|
1057 /* finally let application a chance to verify that it's ok to execte |
|
1058 * this transforms chain */ |
|
1059 if(ctx->preExecCallback != NULL) { |
|
1060 ret = (ctx->preExecCallback)(ctx); |
|
1061 if(ret < 0) { |
|
1062 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1063 NULL, |
|
1064 "ctx->preExecCallback", |
|
1065 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1066 XMLSEC_ERRORS_NO_MESSAGE); |
|
1067 return(-1); |
|
1068 } |
|
1069 } |
|
1070 |
|
1071 ctx->status = xmlSecTransformStatusWorking; |
|
1072 return(0); |
|
1073 } |
|
1074 |
|
1075 /** |
|
1076 * xmlSecTransformCtxBinaryExecute: |
|
1077 * @ctx: the pointer to transforms chain processing context. |
|
1078 * @data: the input binary data buffer. |
|
1079 * @dataSize: the input data size. |
|
1080 * |
|
1081 * Processes binary data using transforms chain in the @ctx. |
|
1082 * |
|
1083 * Returns 0 on success or a negative value otherwise. |
|
1084 */ |
|
1085 EXPORT_C |
|
1086 int |
|
1087 xmlSecTransformCtxBinaryExecute(xmlSecTransformCtxPtr ctx, |
|
1088 const xmlSecByte* data, xmlSecSize dataSize) { |
|
1089 int ret; |
|
1090 |
|
1091 xmlSecAssert2(ctx != NULL, -1); |
|
1092 xmlSecAssert2(ctx->result == NULL, -1); |
|
1093 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1); |
|
1094 xmlSecAssert2(data != NULL, -1); |
|
1095 xmlSecAssert2(dataSize > 0, -1); |
|
1096 |
|
1097 /* we should not have uri stored in ctx */ |
|
1098 xmlSecAssert2(ctx->uri == NULL, -1); |
|
1099 |
|
1100 ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeBin); |
|
1101 if(ret < 0) { |
|
1102 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1103 NULL, |
|
1104 "xmlSecTransformCtxPrepare", |
|
1105 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1106 "type=bin"); |
|
1107 return(-1); |
|
1108 } |
|
1109 |
|
1110 ret = xmlSecTransformPushBin(ctx->first, data, dataSize, 1, ctx); |
|
1111 if(ret < 0) { |
|
1112 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1113 NULL, |
|
1114 "xmlSecTransformCtxPushBin", |
|
1115 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1116 "dataSize=%d", dataSize); |
|
1117 return(-1); |
|
1118 } |
|
1119 |
|
1120 ctx->status = xmlSecTransformStatusFinished; |
|
1121 return(0); |
|
1122 } |
|
1123 |
|
1124 /** |
|
1125 * xmlSecTransformCtxUriExecute: |
|
1126 * @ctx: the pointer to transforms chain processing context. |
|
1127 * @uri: the URI. |
|
1128 * |
|
1129 * Process binary data from the URI using transforms chain in @ctx. |
|
1130 * |
|
1131 * Returns 0 on success or a negative value otherwise. |
|
1132 */ |
|
1133 EXPORT_C |
|
1134 int |
|
1135 xmlSecTransformCtxUriExecute(xmlSecTransformCtxPtr ctx, const xmlChar* uri) { |
|
1136 xmlSecTransformPtr uriTransform; |
|
1137 int ret; |
|
1138 |
|
1139 xmlSecAssert2(ctx != NULL, -1); |
|
1140 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1); |
|
1141 xmlSecAssert2(uri != NULL, -1); |
|
1142 |
|
1143 /* we should not execute transform for a different uri */ |
|
1144 xmlSecAssert2((ctx->uri == NULL) || (uri == ctx->uri) || xmlStrEqual(uri, ctx->uri), -1); |
|
1145 |
|
1146 uriTransform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformInputURIId); |
|
1147 if(uriTransform == NULL) { |
|
1148 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1149 NULL, |
|
1150 "xmlSecTransformCtxCreateAndPrepend", |
|
1151 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1152 "transform=%s", |
|
1153 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInputURIId))); |
|
1154 return(-1); |
|
1155 } |
|
1156 |
|
1157 ret = xmlSecTransformInputURIOpen(uriTransform, uri); |
|
1158 if(ret < 0) { |
|
1159 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1160 NULL, |
|
1161 "xmlSecTransformInputURIOpen", |
|
1162 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1163 "uri=%s", |
|
1164 xmlSecErrorsSafeString(uri)); |
|
1165 return(-1); |
|
1166 } |
|
1167 |
|
1168 /* we do not need to do something special for this transform */ |
|
1169 ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeUnknown); |
|
1170 if(ret < 0) { |
|
1171 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1172 NULL, |
|
1173 "xmlSecTransformCtxPrepare", |
|
1174 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1175 "type=bin"); |
|
1176 return(-1); |
|
1177 } |
|
1178 |
|
1179 /* Now we have a choice: we either can push from first transform or pop |
|
1180 * from last. Our C14N transforms prefers push, so push data! |
|
1181 */ |
|
1182 ret = xmlSecTransformPump(uriTransform, uriTransform->next, ctx); |
|
1183 if(ret < 0) { |
|
1184 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1185 NULL, |
|
1186 "xmlSecTransformPump", |
|
1187 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1188 "uri=%s", |
|
1189 xmlSecErrorsSafeString(uri)); |
|
1190 return(-1); |
|
1191 } |
|
1192 |
|
1193 ctx->status = xmlSecTransformStatusFinished; |
|
1194 return(0); |
|
1195 } |
|
1196 |
|
1197 /** |
|
1198 * xmlSecTransformCtxXmlExecute: |
|
1199 * @ctx: the pointer to transforms chain processing context. |
|
1200 * @nodes: the input node set. |
|
1201 * |
|
1202 * Process @nodes using transforms in the transforms chain in @ctx. |
|
1203 * |
|
1204 * Returns 0 on success or a negative value otherwise. |
|
1205 */ |
|
1206 EXPORT_C |
|
1207 int |
|
1208 xmlSecTransformCtxXmlExecute(xmlSecTransformCtxPtr ctx, xmlSecNodeSetPtr nodes) { |
|
1209 int ret; |
|
1210 |
|
1211 xmlSecAssert2(ctx != NULL, -1); |
|
1212 xmlSecAssert2(ctx->result == NULL, -1); |
|
1213 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1); |
|
1214 xmlSecAssert2(nodes != NULL, -1); |
|
1215 |
|
1216 xmlSecAssert2((ctx->uri == NULL) || (xmlStrlen(ctx->uri) == 0), -1); |
|
1217 |
|
1218 ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeXml); |
|
1219 if(ret < 0) { |
|
1220 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1221 NULL, |
|
1222 "xmlSecTransformCtxPrepare", |
|
1223 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1224 "type=xml"); |
|
1225 return(-1); |
|
1226 } |
|
1227 |
|
1228 /* it's better to do push than pop because all XML transform |
|
1229 * just don't care and c14n likes push more than pop */ |
|
1230 ret = xmlSecTransformPushXml(ctx->first, nodes, ctx); |
|
1231 if(ret < 0) { |
|
1232 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1233 NULL, |
|
1234 "xmlSecTransformPushXml", |
|
1235 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1236 "transform=%s", |
|
1237 xmlSecErrorsSafeString(xmlSecTransformGetName(ctx->first))); |
|
1238 return(-1); |
|
1239 } |
|
1240 |
|
1241 ctx->status = xmlSecTransformStatusFinished; |
|
1242 return(0); |
|
1243 } |
|
1244 |
|
1245 /** |
|
1246 * xmlSecTransformCtxExecute: |
|
1247 * @ctx: the pointer to transforms chain processing context. |
|
1248 * @doc: the pointer to input document. |
|
1249 * |
|
1250 * Executes transforms chain in @ctx. |
|
1251 * |
|
1252 * Returns 0 on success or a negative value otherwise. |
|
1253 */ |
|
1254 EXPORT_C |
|
1255 int |
|
1256 xmlSecTransformCtxExecute(xmlSecTransformCtxPtr ctx, xmlDocPtr doc) { |
|
1257 int ret; |
|
1258 |
|
1259 xmlSecAssert2(ctx != NULL, -1); |
|
1260 xmlSecAssert2(ctx->result == NULL, -1); |
|
1261 xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1); |
|
1262 xmlSecAssert2(doc != NULL, -1); |
|
1263 |
|
1264 if((ctx->uri == NULL) || (xmlStrlen(ctx->uri) == 0)) { |
|
1265 xmlSecNodeSetPtr nodes; |
|
1266 |
|
1267 if((ctx->xptrExpr != NULL) && (xmlStrlen(ctx->xptrExpr) > 0)){ |
|
1268 /* our xpointer transform takes care of providing correct nodes set */ |
|
1269 nodes = xmlSecNodeSetCreate(doc, NULL, xmlSecNodeSetNormal); |
|
1270 if(nodes == NULL) { |
|
1271 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1272 NULL, |
|
1273 "xmlSecNodeSetCreate", |
|
1274 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1275 XMLSEC_ERRORS_NO_MESSAGE); |
|
1276 return(-1); |
|
1277 } |
|
1278 |
|
1279 } else { |
|
1280 /* we do not want to have comments for empty URI */ |
|
1281 nodes = xmlSecNodeSetGetChildren(doc, NULL, 0, 0); |
|
1282 if(nodes == NULL) { |
|
1283 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1284 NULL, |
|
1285 "xmlSecNodeSetGetChildren", |
|
1286 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1287 XMLSEC_ERRORS_NO_MESSAGE); |
|
1288 return(-1); |
|
1289 } |
|
1290 } |
|
1291 ret = xmlSecTransformCtxXmlExecute(ctx, nodes); |
|
1292 if(ret < 0) { |
|
1293 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1294 NULL, |
|
1295 "xmlSecTransformCtxXmlExecute", |
|
1296 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1297 XMLSEC_ERRORS_NO_MESSAGE); |
|
1298 xmlSecNodeSetDestroy(nodes); |
|
1299 return(-1); |
|
1300 } |
|
1301 xmlSecNodeSetDestroy(nodes); |
|
1302 } else { |
|
1303 ret = xmlSecTransformCtxUriExecute(ctx, ctx->uri); |
|
1304 if(ret < 0) { |
|
1305 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1306 NULL, |
|
1307 "xmlSecTransformCtxUriExecute", |
|
1308 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1309 XMLSEC_ERRORS_NO_MESSAGE); |
|
1310 return(-1); |
|
1311 } |
|
1312 } |
|
1313 |
|
1314 return(0); |
|
1315 } |
|
1316 |
|
1317 /** |
|
1318 * xmlSecTransformCtxDebugDump: |
|
1319 * @ctx: the pointer to transforms chain processing context. |
|
1320 * @output: the pointer to output FILE. |
|
1321 * |
|
1322 * Prints transforms context debug information to @output. |
|
1323 */ |
|
1324 EXPORT_C |
|
1325 void |
|
1326 xmlSecTransformCtxDebugDump(xmlSecTransformCtxPtr ctx, FILE* output) { |
|
1327 xmlSecTransformPtr transform; |
|
1328 |
|
1329 xmlSecAssert(ctx != NULL); |
|
1330 xmlSecAssert(output != NULL); |
|
1331 |
|
1332 fprintf(output, "== TRANSFORMS CTX (status=%d)\n", ctx->status); |
|
1333 |
|
1334 fprintf(output, "== flags: 0x%08x\n", ctx->flags); |
|
1335 fprintf(output, "== flags2: 0x%08x\n", ctx->flags2); |
|
1336 if(xmlSecPtrListGetSize(&(ctx->enabledTransforms)) > 0) { |
|
1337 fprintf(output, "== enabled transforms: "); |
|
1338 xmlSecTransformIdListDebugDump(&(ctx->enabledTransforms), output); |
|
1339 } else { |
|
1340 fprintf(output, "== enabled transforms: all\n"); |
|
1341 } |
|
1342 |
|
1343 fprintf(output, "=== uri: %s\n", |
|
1344 (ctx->uri != NULL) ? ctx->uri : BAD_CAST "NULL"); |
|
1345 fprintf(output, "=== uri xpointer expr: %s\n", |
|
1346 (ctx->xptrExpr != NULL) ? ctx->xptrExpr : BAD_CAST "NULL"); |
|
1347 for(transform = ctx->first; transform != NULL; transform = transform->next) { |
|
1348 xmlSecTransformDebugDump(transform, output); |
|
1349 } |
|
1350 } |
|
1351 |
|
1352 /** |
|
1353 * xmlSecTransformCtxDebugXmlDump: |
|
1354 * @ctx: the pointer to transforms chain processing context. |
|
1355 * @output: the pointer to output FILE. |
|
1356 * |
|
1357 * Prints transforms context debug information to @output in XML format. |
|
1358 */ |
|
1359 EXPORT_C |
|
1360 void |
|
1361 xmlSecTransformCtxDebugXmlDump(xmlSecTransformCtxPtr ctx, FILE* output) { |
|
1362 xmlSecTransformPtr transform; |
|
1363 |
|
1364 xmlSecAssert(ctx != NULL); |
|
1365 xmlSecAssert(output != NULL); |
|
1366 |
|
1367 fprintf(output, "<TransformCtx status=\"%d\">\n", ctx->status); |
|
1368 |
|
1369 fprintf(output, "<Flags>%08x</Flags>\n", ctx->flags); |
|
1370 fprintf(output, "<Flags2>%08x</Flags2>\n", ctx->flags2); |
|
1371 if(xmlSecPtrListGetSize(&(ctx->enabledTransforms)) > 0) { |
|
1372 fprintf(output, "<EnabledTransforms>\n"); |
|
1373 xmlSecTransformIdListDebugXmlDump(&(ctx->enabledTransforms), output); |
|
1374 fprintf(output, "</EnabledTransforms>\n"); |
|
1375 } else { |
|
1376 fprintf(output, "<EnabledTransforms>all</EnabledTransforms>\n"); |
|
1377 } |
|
1378 |
|
1379 |
|
1380 fprintf(output, "<Uri>%s</Uri>\n", |
|
1381 (ctx->uri != NULL) ? ctx->uri : BAD_CAST "NULL"); |
|
1382 fprintf(output, "<UriXPointer>%s</UriXPointer>\n", |
|
1383 (ctx->xptrExpr != NULL) ? ctx->xptrExpr : BAD_CAST "NULL"); |
|
1384 |
|
1385 for(transform = ctx->first; transform != NULL; transform = transform->next) { |
|
1386 xmlSecTransformDebugXmlDump(transform, output); |
|
1387 } |
|
1388 fprintf(output, "</TransformCtx>\n"); |
|
1389 } |
|
1390 |
|
1391 /************************************************************************** |
|
1392 * |
|
1393 * xmlSecTransform |
|
1394 * |
|
1395 *************************************************************************/ |
|
1396 /** |
|
1397 * xmlSecTransformCreate: |
|
1398 * @id: the transform id to create. |
|
1399 * |
|
1400 * Creates new transform of the @id klass. The caller is responsible for |
|
1401 * destroying returned tansform using #xmlSecTransformDestroy function. |
|
1402 * |
|
1403 * Returns pointer to newly created transform or NULL if an error occurs. |
|
1404 */ |
|
1405 EXPORT_C |
|
1406 xmlSecTransformPtr |
|
1407 xmlSecTransformCreate(xmlSecTransformId id) { |
|
1408 xmlSecTransformPtr transform; |
|
1409 int ret; |
|
1410 |
|
1411 xmlSecAssert2(id != NULL, NULL); |
|
1412 xmlSecAssert2(id->klassSize >= sizeof(xmlSecTransformKlass), NULL); |
|
1413 xmlSecAssert2(id->objSize >= sizeof(xmlSecTransform), NULL); |
|
1414 xmlSecAssert2(id->name != NULL, NULL); |
|
1415 |
|
1416 /* Allocate a new xmlSecTransform and fill the fields. */ |
|
1417 transform = (xmlSecTransformPtr)xmlMalloc(id->objSize); |
|
1418 if(transform == NULL) { |
|
1419 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1420 NULL, |
|
1421 NULL, |
|
1422 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
1423 "size=%d", id->objSize); |
|
1424 return(NULL); |
|
1425 } |
|
1426 memset(transform, 0, id->objSize); |
|
1427 transform->id = id; |
|
1428 |
|
1429 if(id->initialize != NULL) { |
|
1430 ret = (id->initialize)(transform); |
|
1431 if(ret < 0) { |
|
1432 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1433 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
1434 "id->initialize", |
|
1435 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1436 XMLSEC_ERRORS_NO_MESSAGE); |
|
1437 xmlSecTransformDestroy(transform); |
|
1438 return(NULL); |
|
1439 } |
|
1440 } |
|
1441 |
|
1442 ret = xmlSecBufferInitialize(&(transform->inBuf), 0); |
|
1443 if(ret < 0) { |
|
1444 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1445 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
1446 "xmlSecBufferInitialize", |
|
1447 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1448 "size=%d", 0); |
|
1449 xmlSecTransformDestroy(transform); |
|
1450 return(NULL); |
|
1451 } |
|
1452 |
|
1453 ret = xmlSecBufferInitialize(&(transform->outBuf), 0); |
|
1454 if(ret < 0) { |
|
1455 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1456 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
1457 "xmlSecBufferInitialize", |
|
1458 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1459 "size=%d", 0); |
|
1460 xmlSecTransformDestroy(transform); |
|
1461 return(NULL); |
|
1462 } |
|
1463 |
|
1464 return(transform); |
|
1465 } |
|
1466 |
|
1467 /** |
|
1468 * xmlSecTransformDestroy: |
|
1469 * @transform: the pointer to transform. |
|
1470 * |
|
1471 * Destroys transform created with #xmlSecTransformCreate function. |
|
1472 */ |
|
1473 EXPORT_C |
|
1474 void |
|
1475 xmlSecTransformDestroy(xmlSecTransformPtr transform) { |
|
1476 xmlSecAssert(xmlSecTransformIsValid(transform)); |
|
1477 xmlSecAssert(transform->id->objSize > 0); |
|
1478 |
|
1479 /* first need to remove ourselves from chain */ |
|
1480 xmlSecTransformRemove(transform); |
|
1481 |
|
1482 xmlSecBufferFinalize(&(transform->inBuf)); |
|
1483 xmlSecBufferFinalize(&(transform->outBuf)); |
|
1484 |
|
1485 /* we never destroy input nodes, output nodes |
|
1486 * are destroyed if and only if they are different |
|
1487 * from input nodes |
|
1488 */ |
|
1489 if((transform->outNodes != NULL) && (transform->outNodes != transform->inNodes)) { |
|
1490 xmlSecNodeSetDestroy(transform->outNodes); |
|
1491 } |
|
1492 if(transform->id->finalize != NULL) { |
|
1493 (transform->id->finalize)(transform); |
|
1494 } |
|
1495 memset(transform, 0, transform->id->objSize); |
|
1496 xmlFree(transform); |
|
1497 } |
|
1498 |
|
1499 /** |
|
1500 * xmlSecTransformNodeRead: |
|
1501 * @node: the pointer to the transform's node. |
|
1502 * @usage: the transform usage (signature, encryption, ...). |
|
1503 * @transformCtx: the transform's chaing processing context. |
|
1504 * |
|
1505 * Reads transform from the @node as follows: |
|
1506 * |
|
1507 * 1) reads "Algorithm" attribute; |
|
1508 * |
|
1509 * 2) checks the lists of known and allowed transforms; |
|
1510 * |
|
1511 * 3) calls transform's create method; |
|
1512 * |
|
1513 * 4) calls transform's read transform node method. |
|
1514 * |
|
1515 * Returns pointer to newly created transform or NULL if an error occurs. |
|
1516 */ |
|
1517 EXPORT_C |
|
1518 xmlSecTransformPtr |
|
1519 xmlSecTransformNodeRead(xmlNodePtr node, xmlSecTransformUsage usage, xmlSecTransformCtxPtr transformCtx) { |
|
1520 xmlSecTransformPtr transform; |
|
1521 xmlSecTransformId id; |
|
1522 xmlChar *href; |
|
1523 int ret; |
|
1524 |
|
1525 xmlSecAssert2(node != NULL, NULL); |
|
1526 xmlSecAssert2(transformCtx != NULL, NULL); |
|
1527 |
|
1528 href = xmlGetProp(node, xmlSecAttrAlgorithm); |
|
1529 if(href == NULL) { |
|
1530 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1531 NULL, |
|
1532 xmlSecErrorsSafeString(xmlSecAttrAlgorithm), |
|
1533 XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, |
|
1534 "node=%s", |
|
1535 xmlSecErrorsSafeString(xmlSecNodeGetName(node))); |
|
1536 return(NULL); |
|
1537 } |
|
1538 |
|
1539 id = xmlSecTransformIdListFindByHref(xmlSecTransformIdsGet(), href, usage); |
|
1540 if(id == xmlSecTransformIdUnknown) { |
|
1541 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1542 NULL, |
|
1543 "xmlSecTransformIdsListFindByHref", |
|
1544 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1545 "href=%s", |
|
1546 xmlSecErrorsSafeString(href)); |
|
1547 xmlFree(href); |
|
1548 return(NULL); |
|
1549 } |
|
1550 |
|
1551 /* check with enabled transforms list */ |
|
1552 if((xmlSecPtrListGetSize(&(transformCtx->enabledTransforms)) > 0) && |
|
1553 (xmlSecTransformIdListFind(&(transformCtx->enabledTransforms), id) != 1)) { |
|
1554 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1555 NULL, |
|
1556 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)), |
|
1557 XMLSEC_ERRORS_R_TRANSFORM_DISABLED, |
|
1558 "href=%s", |
|
1559 xmlSecErrorsSafeString(href)); |
|
1560 xmlFree(href); |
|
1561 return(NULL); |
|
1562 } |
|
1563 |
|
1564 transform = xmlSecTransformCreate(id); |
|
1565 if(!xmlSecTransformIsValid(transform)) { |
|
1566 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1567 NULL, |
|
1568 "xmlSecTransformCreate", |
|
1569 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1570 "transform=%s", |
|
1571 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id))); |
|
1572 xmlFree(href); |
|
1573 return(NULL); |
|
1574 } |
|
1575 |
|
1576 if(transform->id->readNode != NULL) { |
|
1577 ret = transform->id->readNode(transform, node, transformCtx); |
|
1578 if(ret < 0) { |
|
1579 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1580 NULL, |
|
1581 "id->readNode", |
|
1582 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1583 "transform=%s", |
|
1584 xmlSecErrorsSafeString(xmlSecTransformGetName(transform))); |
|
1585 xmlSecTransformDestroy(transform); |
|
1586 xmlFree(href); |
|
1587 return(NULL); |
|
1588 } |
|
1589 } |
|
1590 |
|
1591 /* finally remember the transform node */ |
|
1592 transform->hereNode = node; |
|
1593 xmlFree(href); |
|
1594 return(transform); |
|
1595 } |
|
1596 |
|
1597 /** |
|
1598 * xmlSecTransformPump: |
|
1599 * @left: the source pumping transform. |
|
1600 * @right: the destination pumping transform. |
|
1601 * @transformCtx: the transform's chaing processing context. |
|
1602 * |
|
1603 * Pops data from @left transform and pushes to @right transform until |
|
1604 * no more data is available. |
|
1605 * |
|
1606 * Returns 0 on success or a negative value if an error occurs. |
|
1607 */ |
|
1608 EXPORT_C |
|
1609 int |
|
1610 xmlSecTransformPump(xmlSecTransformPtr left, xmlSecTransformPtr right, xmlSecTransformCtxPtr transformCtx) { |
|
1611 xmlSecTransformDataType leftType; |
|
1612 xmlSecTransformDataType rightType; |
|
1613 int ret; |
|
1614 |
|
1615 xmlSecAssert2(xmlSecTransformIsValid(left), -1); |
|
1616 xmlSecAssert2(xmlSecTransformIsValid(right), -1); |
|
1617 xmlSecAssert2(transformCtx != NULL, -1); |
|
1618 |
|
1619 leftType = xmlSecTransformGetDataType(left, xmlSecTransformModePop, transformCtx); |
|
1620 rightType = xmlSecTransformGetDataType(right, xmlSecTransformModePush, transformCtx); |
|
1621 |
|
1622 if(((leftType & xmlSecTransformDataTypeXml) != 0) && |
|
1623 ((rightType & xmlSecTransformDataTypeXml) != 0)) { |
|
1624 |
|
1625 xmlSecNodeSetPtr nodes = NULL; |
|
1626 |
|
1627 ret = xmlSecTransformPopXml(left, &nodes, transformCtx); |
|
1628 if(ret < 0) { |
|
1629 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1630 xmlSecErrorsSafeString(xmlSecTransformGetName(left)), |
|
1631 "xmlSecTransformPopXml", |
|
1632 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1633 XMLSEC_ERRORS_NO_MESSAGE); |
|
1634 return(-1); |
|
1635 } |
|
1636 |
|
1637 ret = xmlSecTransformPushXml(right, nodes, transformCtx); |
|
1638 if(ret < 0) { |
|
1639 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1640 xmlSecErrorsSafeString(xmlSecTransformGetName(right)), |
|
1641 "xmlSecTransformPushXml", |
|
1642 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1643 XMLSEC_ERRORS_NO_MESSAGE); |
|
1644 return(-1); |
|
1645 } |
|
1646 } else if(((leftType & xmlSecTransformDataTypeBin) != 0) && |
|
1647 ((rightType & xmlSecTransformDataTypeBin) != 0)) { |
|
1648 xmlSecByte buf[XMLSEC_TRANSFORM_BINARY_CHUNK]; |
|
1649 xmlSecSize bufSize; |
|
1650 int final; |
|
1651 |
|
1652 do { |
|
1653 ret = xmlSecTransformPopBin(left, buf, sizeof(buf), &bufSize, transformCtx); |
|
1654 if(ret < 0) { |
|
1655 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1656 xmlSecErrorsSafeString(xmlSecTransformGetName(left)), |
|
1657 "xmlSecTransformPopBin", |
|
1658 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1659 XMLSEC_ERRORS_NO_MESSAGE); |
|
1660 return(-1); |
|
1661 } |
|
1662 final = (bufSize == 0) ? 1 : 0; |
|
1663 ret = xmlSecTransformPushBin(right, buf, bufSize, final, transformCtx); |
|
1664 if(ret < 0) { |
|
1665 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1666 xmlSecErrorsSafeString(xmlSecTransformGetName(right)), |
|
1667 "xmlSecTransformPushBin", |
|
1668 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1669 XMLSEC_ERRORS_NO_MESSAGE); |
|
1670 return(-1); |
|
1671 } |
|
1672 } while(final == 0); |
|
1673 } else { |
|
1674 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1675 xmlSecErrorsSafeString(xmlSecTransformGetName(left)), |
|
1676 xmlSecErrorsSafeString(xmlSecTransformGetName(right)), |
|
1677 XMLSEC_ERRORS_R_INVALID_TRANSFORM, |
|
1678 "transforms input/output data formats do not match"); |
|
1679 } |
|
1680 return(0); |
|
1681 } |
|
1682 |
|
1683 |
|
1684 /** |
|
1685 * xmlSecTransformSetKey: |
|
1686 * @transform: the pointer to transform. |
|
1687 * @key: the pointer to key. |
|
1688 * |
|
1689 * Sets the transform's key. |
|
1690 * |
|
1691 * Returns 0 on success or a negative value otherwise. |
|
1692 */ |
|
1693 EXPORT_C |
|
1694 int |
|
1695 xmlSecTransformSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { |
|
1696 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
1697 xmlSecAssert2(key != NULL, -1); |
|
1698 |
|
1699 if(transform->id->setKey != NULL) { |
|
1700 return((transform->id->setKey)(transform, key)); |
|
1701 } |
|
1702 return(0); |
|
1703 } |
|
1704 |
|
1705 /** |
|
1706 * xmlSecTransformSetKeyReq: |
|
1707 * @transform: the pointer to transform. |
|
1708 * @keyReq: the pointer to keys requirements object. |
|
1709 * |
|
1710 * Sets the key requirements for @transform in the @keyReq. |
|
1711 * |
|
1712 * Returns 0 on success or a negative value otherwise. |
|
1713 */ |
|
1714 EXPORT_C |
|
1715 int |
|
1716 xmlSecTransformSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { |
|
1717 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
1718 xmlSecAssert2(keyReq != NULL, -1); |
|
1719 |
|
1720 keyReq->keyId = xmlSecKeyDataIdUnknown; |
|
1721 keyReq->keyType = xmlSecKeyDataTypeUnknown; |
|
1722 keyReq->keyUsage = xmlSecKeyUsageAny; |
|
1723 keyReq->keyBitsSize = 0; |
|
1724 |
|
1725 if(transform->id->setKeyReq != NULL) { |
|
1726 return((transform->id->setKeyReq)(transform, keyReq)); |
|
1727 } |
|
1728 return(0); |
|
1729 } |
|
1730 |
|
1731 /** |
|
1732 * xmlSecTransformVerify: |
|
1733 * @transform: the pointer to transform. |
|
1734 * @data: the binary data for verification. |
|
1735 * @dataSize: the data size. |
|
1736 * @transformCtx: the transform's chaing processing context. |
|
1737 * |
|
1738 * Verifies the data with transform's processing results |
|
1739 * (for digest, HMAC and signature transforms). The verification |
|
1740 * result is stored in the #status member of #xmlSecTransform object. |
|
1741 * |
|
1742 * Returns 0 on success or a negative value if an error occurs. |
|
1743 */ |
|
1744 EXPORT_C |
|
1745 int |
|
1746 xmlSecTransformVerify(xmlSecTransformPtr transform, const xmlSecByte* data, |
|
1747 xmlSecSize dataSize, xmlSecTransformCtxPtr transformCtx) { |
|
1748 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
1749 xmlSecAssert2(transform->id->verify != NULL, -1); |
|
1750 xmlSecAssert2(transformCtx != NULL, -1); |
|
1751 |
|
1752 return((transform->id->verify)(transform, data, dataSize, transformCtx)); |
|
1753 } |
|
1754 |
|
1755 /** |
|
1756 * xmlSecTransformVerifyNodeContent: |
|
1757 * @transform: the pointer to transform. |
|
1758 * @node: the pointer to node. |
|
1759 * @transformCtx: the transform's chaing processing context. |
|
1760 * |
|
1761 * Gets the @node content, base64 decodes it and calls #xmlSecTransformVerify |
|
1762 * function to verify binary results. |
|
1763 * |
|
1764 * Returns 0 on success or a negative value if an error occurs. |
|
1765 */ |
|
1766 EXPORT_C |
|
1767 int |
|
1768 xmlSecTransformVerifyNodeContent(xmlSecTransformPtr transform, xmlNodePtr node, |
|
1769 xmlSecTransformCtxPtr transformCtx) { |
|
1770 xmlSecBuffer buffer; |
|
1771 int ret; |
|
1772 |
|
1773 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
1774 xmlSecAssert2(node != NULL, -1); |
|
1775 xmlSecAssert2(transformCtx != NULL, -1); |
|
1776 |
|
1777 ret = xmlSecBufferInitialize(&buffer, 0); |
|
1778 if(ret < 0) { |
|
1779 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1780 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
1781 "xmlSecBufferInitialize", |
|
1782 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1783 XMLSEC_ERRORS_NO_MESSAGE); |
|
1784 return(-1); |
|
1785 } |
|
1786 |
|
1787 ret = xmlSecBufferBase64NodeContentRead(&buffer, node); |
|
1788 if((ret < 0) || (xmlSecBufferGetData(&buffer) == NULL)) { |
|
1789 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1790 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
1791 "xmlSecBufferBase64NodeContentRead", |
|
1792 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1793 XMLSEC_ERRORS_NO_MESSAGE); |
|
1794 xmlSecBufferFinalize(&buffer); |
|
1795 return(-1); |
|
1796 } |
|
1797 |
|
1798 ret = xmlSecTransformVerify(transform, xmlSecBufferGetData(&buffer), |
|
1799 xmlSecBufferGetSize(&buffer), transformCtx); |
|
1800 if(ret < 0) { |
|
1801 xmlSecError(XMLSEC_ERRORS_HERE, |
|
1802 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
1803 "xmlSecTransformVerify", |
|
1804 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
1805 XMLSEC_ERRORS_NO_MESSAGE); |
|
1806 xmlSecBufferFinalize(&buffer); |
|
1807 return(-1); |
|
1808 } |
|
1809 |
|
1810 xmlSecBufferFinalize(&buffer); |
|
1811 return(0); |
|
1812 } |
|
1813 |
|
1814 /** |
|
1815 * xmlSecTransformGetDataType: |
|
1816 * @transform: the pointer to transform. |
|
1817 * @mode: the data mode (push or pop). |
|
1818 * @transformCtx: the transform's chaing processing context. |
|
1819 * |
|
1820 * Gets transform input (@mode is "push") or output (@mode is "pop") data |
|
1821 * type (binary or XML). |
|
1822 * |
|
1823 * Returns the transform's data type for the @mode operation. |
|
1824 */ |
|
1825 EXPORT_C |
|
1826 xmlSecTransformDataType |
|
1827 xmlSecTransformGetDataType(xmlSecTransformPtr transform, xmlSecTransformMode mode, |
|
1828 xmlSecTransformCtxPtr transformCtx) { |
|
1829 xmlSecAssert2(xmlSecTransformIsValid(transform), xmlSecTransformDataTypeUnknown); |
|
1830 xmlSecAssert2(transform->id->getDataType != NULL, xmlSecTransformDataTypeUnknown); |
|
1831 |
|
1832 return((transform->id->getDataType)(transform, mode, transformCtx)); |
|
1833 } |
|
1834 |
|
1835 /** |
|
1836 * xmlSecTransformPushBin: |
|
1837 * @transform: the pointer to transform object. |
|
1838 * @data: the input binary data, |
|
1839 * @dataSize: the input data size. |
|
1840 * @final: the flag: if set to 1 then it's the last |
|
1841 * data chunk. |
|
1842 * @transformCtx: the pointer to transform context object. |
|
1843 * |
|
1844 * Process binary @data and pushes results to next transform. |
|
1845 * |
|
1846 * Returns 0 on success or a negative value if an error occurs. |
|
1847 */ |
|
1848 EXPORT_C |
|
1849 int |
|
1850 xmlSecTransformPushBin(xmlSecTransformPtr transform, const xmlSecByte* data, |
|
1851 xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) { |
|
1852 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
1853 xmlSecAssert2(transform->id->pushBin != NULL, -1); |
|
1854 xmlSecAssert2(transformCtx != NULL, -1); |
|
1855 |
|
1856 return((transform->id->pushBin)(transform, data, dataSize, final, transformCtx)); |
|
1857 } |
|
1858 |
|
1859 /** |
|
1860 * xmlSecTransformPopBin: |
|
1861 * @transform: the pointer to transform object. |
|
1862 * @data: the buffer to store result data. |
|
1863 * @maxDataSize: the size of the buffer #data. |
|
1864 * @dataSize: the pointer to returned data size. |
|
1865 * @transformCtx: the pointer to transform context object. |
|
1866 * |
|
1867 * Pops data from previous transform in the chain, processes data and |
|
1868 * returns result in the @data buffer. The size of returned data is |
|
1869 * placed in the @dataSize. |
|
1870 * |
|
1871 * Returns 0 on success or a negative value if an error occurs. |
|
1872 */ |
|
1873 EXPORT_C |
|
1874 int |
|
1875 xmlSecTransformPopBin(xmlSecTransformPtr transform, xmlSecByte* data, |
|
1876 xmlSecSize maxDataSize, xmlSecSize* dataSize, xmlSecTransformCtxPtr transformCtx) { |
|
1877 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
1878 xmlSecAssert2(transform->id->popBin != NULL, -1); |
|
1879 xmlSecAssert2(data != NULL, -1); |
|
1880 xmlSecAssert2(dataSize != NULL, -1); |
|
1881 xmlSecAssert2(transformCtx != NULL, -1); |
|
1882 |
|
1883 return((transform->id->popBin)(transform, data, maxDataSize, dataSize, transformCtx)); |
|
1884 } |
|
1885 |
|
1886 /** |
|
1887 * xmlSecTransformPushXml: |
|
1888 * @transform: the pointer to transform object. |
|
1889 * @nodes: the input nodes. |
|
1890 * @transformCtx: the pointer to transform context object. |
|
1891 * |
|
1892 * Processes @nodes and pushes result to the next transform in the chain. |
|
1893 * |
|
1894 * Returns 0 on success or a negative value if an error occurs. |
|
1895 */ |
|
1896 EXPORT_C |
|
1897 int |
|
1898 xmlSecTransformPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes, |
|
1899 xmlSecTransformCtxPtr transformCtx) { |
|
1900 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
1901 xmlSecAssert2(transform->id->pushXml != NULL, -1); |
|
1902 xmlSecAssert2(transformCtx != NULL, -1); |
|
1903 |
|
1904 return((transform->id->pushXml)(transform, nodes, transformCtx)); |
|
1905 } |
|
1906 |
|
1907 /** |
|
1908 * xmlSecTransformPopXml: |
|
1909 * @transform: the pointer to transform object. |
|
1910 * @nodes: the pointer to store popinter to result nodes. |
|
1911 * @transformCtx: the pointer to transform context object. |
|
1912 * |
|
1913 * Pops data from previous transform in the chain, processes the data and |
|
1914 * returns result in @nodes. |
|
1915 * |
|
1916 * Returns 0 on success or a negative value if an error occurs. |
|
1917 */ |
|
1918 EXPORT_C |
|
1919 int |
|
1920 xmlSecTransformPopXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr* nodes, |
|
1921 xmlSecTransformCtxPtr transformCtx) { |
|
1922 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
1923 xmlSecAssert2(transform->id->popXml != NULL, -1); |
|
1924 xmlSecAssert2(transformCtx != NULL, -1); |
|
1925 |
|
1926 return((transform->id->popXml)(transform, nodes, transformCtx)); |
|
1927 } |
|
1928 |
|
1929 /** |
|
1930 * xmlSecTransformExecute: |
|
1931 * @transform: the pointer to transform. |
|
1932 * @last: the flag: if set to 1 then it's the last data chunk. |
|
1933 * @transformCtx: the transform's chaing processing context. |
|
1934 * |
|
1935 * Executes transform (used by default popBin/pushBin/popXml/pushXml methods). |
|
1936 * |
|
1937 * Returns 0 on success or a negative value if an error occurs. |
|
1938 */ |
|
1939 EXPORT_C |
|
1940 int |
|
1941 xmlSecTransformExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { |
|
1942 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
1943 xmlSecAssert2(transform->id->execute != NULL, -1); |
|
1944 xmlSecAssert2(transformCtx != NULL, -1); |
|
1945 |
|
1946 return((transform->id->execute)(transform, last, transformCtx)); |
|
1947 } |
|
1948 |
|
1949 /** |
|
1950 * xmlSecTransformDebugDump: |
|
1951 * @transform: the pointer to transform. |
|
1952 * @output: the pointer to output FILE. |
|
1953 * |
|
1954 * Prints transform's debug information to @output. |
|
1955 */ |
|
1956 EXPORT_C |
|
1957 void |
|
1958 xmlSecTransformDebugDump(xmlSecTransformPtr transform, FILE* output) { |
|
1959 xmlSecAssert(xmlSecTransformIsValid(transform)); |
|
1960 xmlSecAssert(output != NULL); |
|
1961 |
|
1962 fprintf(output, "=== Transform: %s (href=%s)\n", |
|
1963 xmlSecErrorsSafeString(transform->id->name), |
|
1964 xmlSecErrorsSafeString(transform->id->href)); |
|
1965 } |
|
1966 |
|
1967 /** |
|
1968 * xmlSecTransformDebugXmlDump: |
|
1969 * @transform: the pointer to transform. |
|
1970 * @output: the pointer to output FILE. |
|
1971 * |
|
1972 * Prints transform's debug information to @output in XML format. |
|
1973 */ |
|
1974 EXPORT_C |
|
1975 void |
|
1976 xmlSecTransformDebugXmlDump(xmlSecTransformPtr transform, FILE* output) { |
|
1977 xmlSecAssert(xmlSecTransformIsValid(transform)); |
|
1978 xmlSecAssert(output != NULL); |
|
1979 |
|
1980 fprintf(output, "<Transform name=\"%s\" href=\"%s\" />\n", |
|
1981 xmlSecErrorsSafeString(transform->id->name), |
|
1982 xmlSecErrorsSafeString(transform->id->href)); |
|
1983 } |
|
1984 |
|
1985 /************************************************************************ |
|
1986 * |
|
1987 * Operations on transforms chain |
|
1988 * |
|
1989 ************************************************************************/ |
|
1990 /** |
|
1991 * xmlSecTransformConnect: |
|
1992 * @left: the pointer to left (prev) transform. |
|
1993 * @right: the pointer to right (next) transform. |
|
1994 * @transformCtx: the transform's chaing processing context. |
|
1995 * |
|
1996 * If the data object is a node-set and the next transform requires octets, |
|
1997 * the signature application MUST attempt to convert the node-set to an octet |
|
1998 * stream using Canonical XML [XML-C14N]. |
|
1999 * |
|
2000 * The story is different if the right transform is base64 decode |
|
2001 * (http://www.w3.org/TR/xmldsig-core/#sec-Base-64): |
|
2002 * |
|
2003 * This transform requires an octet stream for input. If an XPath node-set |
|
2004 * (or sufficiently functional alternative) is given as input, then it is |
|
2005 * converted to an octet stream by performing operations logically equivalent |
|
2006 * to 1) applying an XPath transform with expression self::text(), then 2) |
|
2007 * taking the string-value of the node-set. Thus, if an XML element is |
|
2008 * identified by a barename XPointer in the Reference URI, and its content |
|
2009 * consists solely of base64 encoded character data, then this transform |
|
2010 * automatically strips away the start and end tags of the identified element |
|
2011 * and any of its descendant elements as well as any descendant comments and |
|
2012 * processing instructions. The output of this transform is an octet stream. |
|
2013 * |
|
2014 * Returns 0 on success or a negative value if an error occurs. |
|
2015 */ |
|
2016 EXPORT_C |
|
2017 int |
|
2018 xmlSecTransformConnect(xmlSecTransformPtr left, xmlSecTransformPtr right, |
|
2019 xmlSecTransformCtxPtr transformCtx) { |
|
2020 xmlSecTransformDataType leftType; |
|
2021 xmlSecTransformDataType rightType; |
|
2022 xmlSecTransformId middleId; |
|
2023 xmlSecTransformPtr middle; |
|
2024 |
|
2025 xmlSecAssert2(xmlSecTransformIsValid(left), -1); |
|
2026 xmlSecAssert2(xmlSecTransformIsValid(right), -1); |
|
2027 xmlSecAssert2(transformCtx != NULL, -1); |
|
2028 |
|
2029 leftType = xmlSecTransformGetDataType(left, xmlSecTransformModePop, transformCtx); |
|
2030 rightType = xmlSecTransformGetDataType(right, xmlSecTransformModePush, transformCtx); |
|
2031 |
|
2032 if((((leftType & xmlSecTransformDataTypeBin) != 0) && |
|
2033 ((rightType & xmlSecTransformDataTypeBin) != 0)) || |
|
2034 (((leftType & xmlSecTransformDataTypeXml) != 0) && |
|
2035 ((rightType & xmlSecTransformDataTypeXml) != 0))) { |
|
2036 |
|
2037 left->next = right; |
|
2038 right->prev = left; |
|
2039 return(0); |
|
2040 } |
|
2041 |
|
2042 if(((leftType & xmlSecTransformDataTypeBin) != 0) && |
|
2043 ((rightType & xmlSecTransformDataTypeXml) != 0)) { |
|
2044 |
|
2045 /* need to insert parser */ |
|
2046 middleId = xmlSecTransformXmlParserId; |
|
2047 } else if(((leftType & xmlSecTransformDataTypeXml) != 0) && |
|
2048 ((rightType & xmlSecTransformDataTypeBin) != 0)) { |
|
2049 |
|
2050 /* need to insert c14n or special pre-base64 transform */ |
|
2051 if(xmlSecTransformCheckId(right, xmlSecTransformBase64Id)) { |
|
2052 middleId = xmlSecTransformRemoveXmlTagsC14NId; |
|
2053 } else { |
|
2054 middleId = xmlSecTransformInclC14NId; |
|
2055 } |
|
2056 } else { |
|
2057 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2058 xmlSecErrorsSafeString(xmlSecTransformGetName(left)), |
|
2059 xmlSecErrorsSafeString(xmlSecTransformGetName(right)), |
|
2060 XMLSEC_ERRORS_R_INVALID_TRANSFORM, |
|
2061 "leftType=%d;rightType=%d", |
|
2062 leftType, rightType); |
|
2063 return(-1); |
|
2064 } |
|
2065 |
|
2066 /* insert transform */ |
|
2067 middle = xmlSecTransformCreate(middleId); |
|
2068 if(middle == NULL) { |
|
2069 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2070 xmlSecErrorsSafeString(xmlSecTransformGetName(left)), |
|
2071 "xmlSecTransformCreate", |
|
2072 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2073 "transform=%s", |
|
2074 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(middleId))); |
|
2075 return(-1); |
|
2076 } |
|
2077 left->next = middle; |
|
2078 middle->prev = left; |
|
2079 middle->next = right; |
|
2080 right->prev = middle; |
|
2081 return(0); |
|
2082 } |
|
2083 |
|
2084 /** |
|
2085 * xmlSecTransformRemove: |
|
2086 * @transform: the pointer to #xmlSecTransform structure. |
|
2087 * |
|
2088 * Removes @transform from the chain. |
|
2089 */ |
|
2090 EXPORT_C |
|
2091 void |
|
2092 xmlSecTransformRemove(xmlSecTransformPtr transform) { |
|
2093 xmlSecAssert(xmlSecTransformIsValid(transform)); |
|
2094 |
|
2095 if(transform->next != NULL) { |
|
2096 transform->next->prev = transform->prev; |
|
2097 } |
|
2098 if(transform->prev != NULL) { |
|
2099 transform->prev->next = transform->next; |
|
2100 } |
|
2101 transform->next = transform->prev = NULL; |
|
2102 } |
|
2103 |
|
2104 |
|
2105 /************************************************************************ |
|
2106 * |
|
2107 * Default callbacks, most of the transforms can use them |
|
2108 * |
|
2109 ************************************************************************/ |
|
2110 /** |
|
2111 * xmlSecTransformDefaultGetDataType: |
|
2112 * @transform: the pointer to transform. |
|
2113 * @mode: the data mode (push or pop). |
|
2114 * @transformCtx: the transform's chaing processing context. |
|
2115 * |
|
2116 * Gets transform input (@mode is "push") or output (@mode is "pop") data |
|
2117 * type (binary or XML) by analyzing available pushBin/popBin/pushXml/popXml |
|
2118 * methods. |
|
2119 * |
|
2120 * Returns the transform's data type for the @mode operation. |
|
2121 */ |
|
2122 EXPORT_C |
|
2123 xmlSecTransformDataType |
|
2124 xmlSecTransformDefaultGetDataType(xmlSecTransformPtr transform, xmlSecTransformMode mode, |
|
2125 xmlSecTransformCtxPtr transformCtx) { |
|
2126 xmlSecTransformDataType type = xmlSecTransformDataTypeUnknown; |
|
2127 |
|
2128 xmlSecAssert2(xmlSecTransformIsValid(transform), xmlSecTransformDataTypeUnknown); |
|
2129 xmlSecAssert2(transformCtx != NULL, xmlSecTransformDataTypeUnknown); |
|
2130 |
|
2131 /* we'll try to guess the data type based on the handlers we have */ |
|
2132 switch(mode) { |
|
2133 case xmlSecTransformModePush: |
|
2134 if(transform->id->pushBin != NULL) { |
|
2135 type |= xmlSecTransformDataTypeBin; |
|
2136 } |
|
2137 if(transform->id->pushXml != NULL) { |
|
2138 type |= xmlSecTransformDataTypeXml; |
|
2139 } |
|
2140 break; |
|
2141 case xmlSecTransformModePop: |
|
2142 if(transform->id->popBin != NULL) { |
|
2143 type |= xmlSecTransformDataTypeBin; |
|
2144 } |
|
2145 if(transform->id->popXml != NULL) { |
|
2146 type |= xmlSecTransformDataTypeXml; |
|
2147 } |
|
2148 break; |
|
2149 default: |
|
2150 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2151 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2152 NULL, |
|
2153 XMLSEC_ERRORS_R_INVALID_DATA, |
|
2154 "mode=%d", mode); |
|
2155 return(xmlSecTransformDataTypeUnknown); |
|
2156 } |
|
2157 |
|
2158 return(type); |
|
2159 } |
|
2160 |
|
2161 /** |
|
2162 * xmlSecTransformDefaultPushBin: |
|
2163 * @transform: the pointer to transform object. |
|
2164 * @data: the input binary data, |
|
2165 * @dataSize: the input data size. |
|
2166 * @final: the flag: if set to 1 then it's the last |
|
2167 * data chunk. |
|
2168 * @transformCtx: the pointer to transform context object. |
|
2169 * |
|
2170 * Process binary @data by calling transform's execute method and pushes |
|
2171 * results to next transform. |
|
2172 * |
|
2173 * Returns 0 on success or a negative value if an error occurs. |
|
2174 */ |
|
2175 EXPORT_C |
|
2176 int |
|
2177 xmlSecTransformDefaultPushBin(xmlSecTransformPtr transform, const xmlSecByte* data, |
|
2178 xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) { |
|
2179 xmlSecSize inSize = 0; |
|
2180 xmlSecSize outSize = 0; |
|
2181 int finalData = 0; |
|
2182 int ret; |
|
2183 |
|
2184 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
2185 xmlSecAssert2(transformCtx != NULL, -1); |
|
2186 |
|
2187 do { |
|
2188 /* append data to input buffer */ |
|
2189 if(dataSize > 0) { |
|
2190 xmlSecSize chunkSize; |
|
2191 |
|
2192 xmlSecAssert2(data != NULL, -1); |
|
2193 |
|
2194 chunkSize = dataSize; |
|
2195 if(chunkSize > XMLSEC_TRANSFORM_BINARY_CHUNK) { |
|
2196 chunkSize = XMLSEC_TRANSFORM_BINARY_CHUNK; |
|
2197 } |
|
2198 |
|
2199 ret = xmlSecBufferAppend(&(transform->inBuf), data, chunkSize); |
|
2200 if(ret < 0) { |
|
2201 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2202 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2203 "xmlSecBufferAppend", |
|
2204 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2205 "size=%d", chunkSize); |
|
2206 return(-1); |
|
2207 } |
|
2208 |
|
2209 dataSize -= chunkSize; |
|
2210 data += chunkSize; |
|
2211 } |
|
2212 |
|
2213 /* process data */ |
|
2214 inSize = xmlSecBufferGetSize(&(transform->inBuf)); |
|
2215 outSize = xmlSecBufferGetSize(&(transform->outBuf)); |
|
2216 finalData = (((dataSize == 0) && (final != 0)) ? 1 : 0); |
|
2217 ret = xmlSecTransformExecute(transform, finalData, transformCtx); |
|
2218 if(ret < 0) { |
|
2219 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2220 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2221 "xmlSecTransformExecute", |
|
2222 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2223 "final=%d", final); |
|
2224 return(-1); |
|
2225 } |
|
2226 |
|
2227 /* push data to the next transform */ |
|
2228 inSize = xmlSecBufferGetSize(&(transform->inBuf)); |
|
2229 outSize = xmlSecBufferGetSize(&(transform->outBuf)); |
|
2230 if(inSize > 0) { |
|
2231 finalData = 0; |
|
2232 } |
|
2233 |
|
2234 /* we don't want to puch too much */ |
|
2235 if(outSize > XMLSEC_TRANSFORM_BINARY_CHUNK) { |
|
2236 outSize = XMLSEC_TRANSFORM_BINARY_CHUNK; |
|
2237 finalData = 0; |
|
2238 } |
|
2239 if((transform->next != NULL) && ((outSize > 0) || (finalData != 0))) { |
|
2240 ret = xmlSecTransformPushBin(transform->next, |
|
2241 xmlSecBufferGetData(&(transform->outBuf)), |
|
2242 outSize, |
|
2243 finalData, |
|
2244 transformCtx); |
|
2245 if(ret < 0) { |
|
2246 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2247 xmlSecErrorsSafeString(xmlSecTransformGetName(transform->next)), |
|
2248 "xmlSecTransformPushBin", |
|
2249 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2250 "final=%d;outSize=%d", final, outSize); |
|
2251 return(-1); |
|
2252 } |
|
2253 } |
|
2254 |
|
2255 /* remove data anyway */ |
|
2256 if(outSize > 0) { |
|
2257 ret = xmlSecBufferRemoveHead(&(transform->outBuf), outSize); |
|
2258 if(ret < 0) { |
|
2259 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2260 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2261 "xmlSecBufferAppend", |
|
2262 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2263 "size=%d", outSize); |
|
2264 return(-1); |
|
2265 } |
|
2266 } |
|
2267 } while((dataSize > 0) || (outSize > 0)); |
|
2268 |
|
2269 return(0); |
|
2270 } |
|
2271 |
|
2272 /** |
|
2273 * xmlSecTransformDefaultPopBin: |
|
2274 * @transform: the pointer to transform object. |
|
2275 * @data: the buffer to store result data. |
|
2276 * @maxDataSize: the size of the buffer #data. |
|
2277 * @dataSize: the pointer to returned data size. |
|
2278 * @transformCtx: the pointer to transform context object. |
|
2279 * |
|
2280 * Pops data from previous transform in the chain, processes data by calling |
|
2281 * transform's execute method and returns result in the @data buffer. The |
|
2282 * size of returned data is placed in the @dataSize. |
|
2283 * |
|
2284 * Returns 0 on success or a negative value if an error occurs. |
|
2285 */ |
|
2286 EXPORT_C |
|
2287 int |
|
2288 xmlSecTransformDefaultPopBin(xmlSecTransformPtr transform, xmlSecByte* data, |
|
2289 xmlSecSize maxDataSize, xmlSecSize* dataSize, xmlSecTransformCtxPtr transformCtx) { |
|
2290 xmlSecSize outSize; |
|
2291 int final = 0; |
|
2292 int ret; |
|
2293 |
|
2294 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
2295 xmlSecAssert2(data != NULL, -1); |
|
2296 xmlSecAssert2(dataSize != NULL, -1); |
|
2297 xmlSecAssert2(transformCtx != NULL, -1); |
|
2298 |
|
2299 while((xmlSecBufferGetSize(&(transform->outBuf)) == 0) && (final == 0)) { |
|
2300 /* read data from previous transform if exist */ |
|
2301 if(transform->prev != NULL) { |
|
2302 xmlSecSize inSize, chunkSize; |
|
2303 |
|
2304 inSize = xmlSecBufferGetSize(&(transform->inBuf)); |
|
2305 chunkSize = XMLSEC_TRANSFORM_BINARY_CHUNK; |
|
2306 |
|
2307 /* ensure that we have space for at least one data chunk */ |
|
2308 ret = xmlSecBufferSetMaxSize(&(transform->inBuf), inSize + chunkSize); |
|
2309 if(ret < 0) { |
|
2310 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2311 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2312 "xmlSecBufferSetMaxSize", |
|
2313 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2314 "size=%d", inSize + chunkSize); |
|
2315 return(-1); |
|
2316 } |
|
2317 |
|
2318 /* get data from previous transform */ |
|
2319 ret = xmlSecTransformPopBin(transform->prev, |
|
2320 xmlSecBufferGetData(&(transform->inBuf)) + inSize, |
|
2321 chunkSize, &chunkSize, transformCtx); |
|
2322 if(ret < 0) { |
|
2323 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2324 xmlSecErrorsSafeString(xmlSecTransformGetName(transform->prev)), |
|
2325 "xmlSecTransformPopBin", |
|
2326 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2327 XMLSEC_ERRORS_NO_MESSAGE); |
|
2328 return(-1); |
|
2329 } |
|
2330 |
|
2331 /* adjust our size if needed */ |
|
2332 if(chunkSize > 0) { |
|
2333 ret = xmlSecBufferSetSize(&(transform->inBuf), inSize + chunkSize); |
|
2334 if(ret < 0) { |
|
2335 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2336 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2337 "xmlSecBufferSetSize", |
|
2338 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2339 "size=%d", inSize + chunkSize); |
|
2340 return(-1); |
|
2341 } |
|
2342 final = 0; /* the previous transform returned some data..*/ |
|
2343 } else { |
|
2344 final = 1; /* no data returned from previous transform, we are done */ |
|
2345 } |
|
2346 } else { |
|
2347 final = 1; /* no previous transform, we are "permanently final" */ |
|
2348 } |
|
2349 |
|
2350 /* execute our transform */ |
|
2351 ret = xmlSecTransformExecute(transform, final, transformCtx); |
|
2352 if(ret < 0) { |
|
2353 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2354 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2355 "xmlSecTransformExecute", |
|
2356 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2357 XMLSEC_ERRORS_NO_MESSAGE); |
|
2358 return(-1); |
|
2359 } |
|
2360 } |
|
2361 |
|
2362 /* copy result (if any) */ |
|
2363 outSize = xmlSecBufferGetSize(&(transform->outBuf)); |
|
2364 if(outSize > maxDataSize) { |
|
2365 outSize = maxDataSize; |
|
2366 } |
|
2367 |
|
2368 /* we don't want to put too much */ |
|
2369 if(outSize > XMLSEC_TRANSFORM_BINARY_CHUNK) { |
|
2370 outSize = XMLSEC_TRANSFORM_BINARY_CHUNK; |
|
2371 } |
|
2372 if(outSize > 0) { |
|
2373 xmlSecAssert2(xmlSecBufferGetData(&(transform->outBuf)), -1); |
|
2374 |
|
2375 memcpy(data, xmlSecBufferGetData(&(transform->outBuf)), outSize); |
|
2376 |
|
2377 ret = xmlSecBufferRemoveHead(&(transform->outBuf), outSize); |
|
2378 if(ret < 0) { |
|
2379 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2380 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2381 "xmlSecBufferRemoveHead", |
|
2382 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2383 "size=%d", outSize); |
|
2384 return(-1); |
|
2385 } |
|
2386 } |
|
2387 |
|
2388 /* set the result size */ |
|
2389 (*dataSize) = outSize; |
|
2390 return(0); |
|
2391 } |
|
2392 |
|
2393 /** |
|
2394 * xmlSecTransformDefaultPushXml: |
|
2395 * @transform: the pointer to transform object. |
|
2396 * @nodes: the input nodes. |
|
2397 * @transformCtx: the pointer to transform context object. |
|
2398 * |
|
2399 * Processes @nodes by calling transform's execute method and pushes |
|
2400 * result to the next transform in the chain. |
|
2401 * |
|
2402 * Returns 0 on success or a negative value if an error occurs. |
|
2403 */ |
|
2404 EXPORT_C |
|
2405 int |
|
2406 xmlSecTransformDefaultPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes, |
|
2407 xmlSecTransformCtxPtr transformCtx) { |
|
2408 int ret; |
|
2409 |
|
2410 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
2411 xmlSecAssert2(transform->inNodes == NULL, -1); |
|
2412 xmlSecAssert2(transform->outNodes == NULL, -1); |
|
2413 xmlSecAssert2(transformCtx != NULL, -1); |
|
2414 |
|
2415 /* execute our transform */ |
|
2416 transform->inNodes = nodes; |
|
2417 ret = xmlSecTransformExecute(transform, 1, transformCtx); |
|
2418 if(ret < 0) { |
|
2419 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2420 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2421 "xmlSecTransformExecute", |
|
2422 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2423 XMLSEC_ERRORS_NO_MESSAGE); |
|
2424 return(-1); |
|
2425 } |
|
2426 |
|
2427 /* push result to the next transform (if exist) */ |
|
2428 if(transform->next != NULL) { |
|
2429 ret = xmlSecTransformPushXml(transform->next, transform->outNodes, transformCtx); |
|
2430 if(ret < 0) { |
|
2431 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2432 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2433 "xmlSecTransformPushXml", |
|
2434 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2435 XMLSEC_ERRORS_NO_MESSAGE); |
|
2436 return(-1); |
|
2437 } |
|
2438 } |
|
2439 return(0); |
|
2440 } |
|
2441 |
|
2442 /** |
|
2443 * xmlSecTransformDefaultPopXml: |
|
2444 * @transform: the pointer to transform object. |
|
2445 * @nodes: the pointer to store popinter to result nodes. |
|
2446 * @transformCtx: the pointer to transform context object. |
|
2447 * |
|
2448 * Pops data from previous transform in the chain, processes the data |
|
2449 * by calling transform's execute method and returns result in @nodes. |
|
2450 * |
|
2451 * Returns 0 on success or a negative value if an error occurs. |
|
2452 */ |
|
2453 EXPORT_C |
|
2454 int |
|
2455 xmlSecTransformDefaultPopXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr* nodes, |
|
2456 xmlSecTransformCtxPtr transformCtx) { |
|
2457 int ret; |
|
2458 |
|
2459 xmlSecAssert2(xmlSecTransformIsValid(transform), -1); |
|
2460 xmlSecAssert2(transform->inNodes == NULL, -1); |
|
2461 xmlSecAssert2(transform->outNodes == NULL, -1); |
|
2462 xmlSecAssert2(transformCtx != NULL, -1); |
|
2463 |
|
2464 /* pop result from the prev transform (if exist) */ |
|
2465 if(transform->prev != NULL) { |
|
2466 ret = xmlSecTransformPopXml(transform->prev, &(transform->inNodes), transformCtx); |
|
2467 if(ret < 0) { |
|
2468 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2469 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2470 "xmlSecTransformPopXml", |
|
2471 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2472 XMLSEC_ERRORS_NO_MESSAGE); |
|
2473 return(-1); |
|
2474 } |
|
2475 } |
|
2476 |
|
2477 /* execute our transform */ |
|
2478 ret = xmlSecTransformExecute(transform, 1, transformCtx); |
|
2479 if(ret < 0) { |
|
2480 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2481 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2482 "xmlSecTransformExecute", |
|
2483 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2484 XMLSEC_ERRORS_NO_MESSAGE); |
|
2485 return(-1); |
|
2486 } |
|
2487 |
|
2488 /* return result if requested */ |
|
2489 if(nodes != NULL) { |
|
2490 (*nodes) = transform->outNodes; |
|
2491 } |
|
2492 |
|
2493 return(0); |
|
2494 } |
|
2495 |
|
2496 /*********************************************************************** |
|
2497 * |
|
2498 * Transform Ids list |
|
2499 * |
|
2500 **********************************************************************/ |
|
2501 static xmlSecPtrListKlass xmlSecTransformIdListKlass = { |
|
2502 BAD_CAST "transform-ids-list", |
|
2503 NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */ |
|
2504 NULL, /* xmlSecPtrDestroyItemMethod destroyItem; */ |
|
2505 NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */ |
|
2506 NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */ |
|
2507 }; |
|
2508 |
|
2509 /** |
|
2510 * xmlSecTransformIdListGetKlass: |
|
2511 * |
|
2512 * The transform id list klass. |
|
2513 * |
|
2514 * Returns pointer to the transform id list klass. |
|
2515 */ |
|
2516 EXPORT_C |
|
2517 xmlSecPtrListId |
|
2518 xmlSecTransformIdListGetKlass(void) { |
|
2519 return(&xmlSecTransformIdListKlass); |
|
2520 } |
|
2521 |
|
2522 /** |
|
2523 * xmlSecTransformIdListFind: |
|
2524 * @list: the pointer to transform ids list. |
|
2525 * @transformId: the transform klass. |
|
2526 * |
|
2527 * Lookups @dataId in @list. |
|
2528 * |
|
2529 * Returns 1 if @dataId is found in the @list, 0 if not and a negative |
|
2530 * value if an error occurs. |
|
2531 */ |
|
2532 EXPORT_C |
|
2533 int |
|
2534 xmlSecTransformIdListFind(xmlSecPtrListPtr list, xmlSecTransformId transformId) { |
|
2535 xmlSecSize i, size; |
|
2536 |
|
2537 xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), -1); |
|
2538 xmlSecAssert2(transformId != NULL, -1); |
|
2539 |
|
2540 size = xmlSecPtrListGetSize(list); |
|
2541 for(i = 0; i < size; ++i) { |
|
2542 if((xmlSecTransformId)xmlSecPtrListGetItem(list, i) == transformId) { |
|
2543 return(1); |
|
2544 } |
|
2545 } |
|
2546 return(0); |
|
2547 } |
|
2548 |
|
2549 /** |
|
2550 * xmlSecTransformIdListFindByHref: |
|
2551 * @list: the pointer to transform ids list. |
|
2552 * @href: the desired transform klass href. |
|
2553 * @usage: the desired transform usage. |
|
2554 * |
|
2555 * Lookups data klass in the list with given @href and @usage in @list. |
|
2556 * |
|
2557 * Returns transform klass is found and NULL otherwise. |
|
2558 */ |
|
2559 EXPORT_C |
|
2560 xmlSecTransformId |
|
2561 xmlSecTransformIdListFindByHref(xmlSecPtrListPtr list, const xmlChar* href, |
|
2562 xmlSecTransformUsage usage) { |
|
2563 xmlSecTransformId transformId; |
|
2564 xmlSecSize i, size; |
|
2565 |
|
2566 xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), xmlSecTransformIdUnknown); |
|
2567 xmlSecAssert2(href != NULL, xmlSecTransformIdUnknown); |
|
2568 |
|
2569 size = xmlSecPtrListGetSize(list); |
|
2570 for(i = 0; i < size; ++i) { |
|
2571 transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i); |
|
2572 xmlSecAssert2(transformId != xmlSecTransformIdUnknown, xmlSecTransformIdUnknown); |
|
2573 |
|
2574 if(((usage & transformId->usage) != 0) && (transformId->href != NULL) && |
|
2575 xmlStrEqual(href, transformId->href)) { |
|
2576 |
|
2577 return(transformId); |
|
2578 } |
|
2579 } |
|
2580 return(xmlSecTransformIdUnknown); |
|
2581 } |
|
2582 |
|
2583 /** |
|
2584 * xmlSecTransformIdListFindByName: |
|
2585 * @list: the pointer to transform ids list. |
|
2586 * @name: the desired transform klass name. |
|
2587 * @usage: the desired transform usage. |
|
2588 * |
|
2589 * Lookups data klass in the list with given @name and @usage in @list. |
|
2590 * |
|
2591 * Returns transform klass is found and NULL otherwise. |
|
2592 */ |
|
2593 EXPORT_C |
|
2594 xmlSecTransformId |
|
2595 xmlSecTransformIdListFindByName(xmlSecPtrListPtr list, const xmlChar* name, |
|
2596 xmlSecTransformUsage usage) { |
|
2597 xmlSecTransformId transformId; |
|
2598 xmlSecSize i, size; |
|
2599 |
|
2600 xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), xmlSecTransformIdUnknown); |
|
2601 xmlSecAssert2(name != NULL, xmlSecTransformIdUnknown); |
|
2602 |
|
2603 size = xmlSecPtrListGetSize(list); |
|
2604 for(i = 0; i < size; ++i) { |
|
2605 transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i); |
|
2606 xmlSecAssert2(transformId != xmlSecTransformIdUnknown, xmlSecTransformIdUnknown); |
|
2607 |
|
2608 if(((usage & transformId->usage) != 0) && (transformId->name != NULL) && |
|
2609 xmlStrEqual(name, BAD_CAST transformId->name)) { |
|
2610 |
|
2611 return(transformId); |
|
2612 } |
|
2613 } |
|
2614 return(xmlSecTransformIdUnknown); |
|
2615 } |
|
2616 |
|
2617 /** |
|
2618 * xmlSecTransformIdListDebugDump: |
|
2619 * @list: the pointer to transform ids list. |
|
2620 * @output: the pointer to output FILE. |
|
2621 * |
|
2622 * Prints binary transform debug information to @output. |
|
2623 */ |
|
2624 EXPORT_C |
|
2625 void |
|
2626 xmlSecTransformIdListDebugDump(xmlSecPtrListPtr list, FILE* output) { |
|
2627 xmlSecTransformId transformId; |
|
2628 xmlSecSize i, size; |
|
2629 |
|
2630 xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecTransformIdListId)); |
|
2631 xmlSecAssert(output != NULL); |
|
2632 |
|
2633 size = xmlSecPtrListGetSize(list); |
|
2634 for(i = 0; i < size; ++i) { |
|
2635 transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i); |
|
2636 xmlSecAssert(transformId != NULL); |
|
2637 xmlSecAssert(transformId->name != NULL); |
|
2638 |
|
2639 if(i > 0) { |
|
2640 fprintf(output, ",\"%s\"", transformId->name); |
|
2641 } else { |
|
2642 fprintf(output, "\"%s\"", transformId->name); |
|
2643 } |
|
2644 } |
|
2645 fprintf(output, "\n"); |
|
2646 } |
|
2647 |
|
2648 /** |
|
2649 * xmlSecTransformIdListDebugXmlDump: |
|
2650 * @list: the pointer to transform ids list. |
|
2651 * @output: the pointer to output FILE. |
|
2652 * |
|
2653 * Prints binary transform debug information to @output in XML format. |
|
2654 */ |
|
2655 EXPORT_C |
|
2656 void |
|
2657 xmlSecTransformIdListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) { |
|
2658 xmlSecTransformId transformId; |
|
2659 xmlSecSize i, size; |
|
2660 |
|
2661 xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecTransformIdListId)); |
|
2662 xmlSecAssert(output != NULL); |
|
2663 |
|
2664 fprintf(output, "<TransformIdsList>\n"); |
|
2665 size = xmlSecPtrListGetSize(list); |
|
2666 for(i = 0; i < size; ++i) { |
|
2667 transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i); |
|
2668 xmlSecAssert(transformId != NULL); |
|
2669 xmlSecAssert(transformId->name != NULL); |
|
2670 |
|
2671 fprintf(output, "<TransformId name=\"%s\" />", transformId->name); |
|
2672 } |
|
2673 fprintf(output, "</TransformIdsList>\n"); |
|
2674 } |
|
2675 |
|
2676 /************************************************************************ |
|
2677 * |
|
2678 * IO buffers for transforms |
|
2679 * |
|
2680 ************************************************************************/ |
|
2681 typedef struct _xmlSecTransformIOBuffer xmlSecTransformIOBuffer, |
|
2682 *xmlSecTransformIOBufferPtr; |
|
2683 typedef enum { |
|
2684 xmlSecTransformIOBufferModeRead, |
|
2685 xmlSecTransformIOBufferModeWrite |
|
2686 } xmlSecTransformIOBufferMode; |
|
2687 |
|
2688 struct _xmlSecTransformIOBuffer { |
|
2689 xmlSecTransformIOBufferMode mode; |
|
2690 xmlSecTransformPtr transform; |
|
2691 xmlSecTransformCtxPtr transformCtx; |
|
2692 }; |
|
2693 |
|
2694 static xmlSecTransformIOBufferPtr xmlSecTransformIOBufferCreate (xmlSecTransformIOBufferMode mode, |
|
2695 xmlSecTransformPtr transform, |
|
2696 xmlSecTransformCtxPtr transformCtx); |
|
2697 static void xmlSecTransformIOBufferDestroy (xmlSecTransformIOBufferPtr buffer); |
|
2698 static int xmlSecTransformIOBufferRead (xmlSecTransformIOBufferPtr buffer, |
|
2699 xmlSecByte *buf, |
|
2700 xmlSecSize size); |
|
2701 static int xmlSecTransformIOBufferWrite (xmlSecTransformIOBufferPtr buffer, |
|
2702 const xmlSecByte *buf, |
|
2703 xmlSecSize size); |
|
2704 static int xmlSecTransformIOBufferClose (xmlSecTransformIOBufferPtr buffer); |
|
2705 |
|
2706 |
|
2707 /** |
|
2708 * xmlSecTransformCreateOutputBuffer: |
|
2709 * @transform: the pointer to transform. |
|
2710 * @transformCtx: the pointer to transform context object. |
|
2711 * |
|
2712 * Creates output buffer to write data to @transform. |
|
2713 * |
|
2714 * Returns pointer to new output buffer or NULL if an error occurs. |
|
2715 */ |
|
2716 EXPORT_C |
|
2717 xmlOutputBufferPtr |
|
2718 xmlSecTransformCreateOutputBuffer(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) { |
|
2719 xmlSecTransformIOBufferPtr buffer; |
|
2720 xmlSecTransformDataType type; |
|
2721 xmlOutputBufferPtr output; |
|
2722 |
|
2723 xmlSecAssert2(xmlSecTransformIsValid(transform), NULL); |
|
2724 xmlSecAssert2(transformCtx != NULL, NULL); |
|
2725 |
|
2726 /* check that we have binary push method for this transform */ |
|
2727 type = xmlSecTransformDefaultGetDataType(transform, xmlSecTransformModePush, transformCtx); |
|
2728 if((type & xmlSecTransformDataTypeBin) == 0) { |
|
2729 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2730 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2731 NULL, |
|
2732 XMLSEC_ERRORS_R_INVALID_TRANSFORM, |
|
2733 "push binary data not supported"); |
|
2734 return(NULL); |
|
2735 } |
|
2736 |
|
2737 buffer = xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferModeWrite, transform, transformCtx); |
|
2738 if(buffer == NULL) { |
|
2739 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2740 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2741 "xmlSecTransformIOBufferCreate", |
|
2742 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2743 XMLSEC_ERRORS_NO_MESSAGE); |
|
2744 return(NULL); |
|
2745 } |
|
2746 |
|
2747 output = xmlOutputBufferCreateIO((xmlOutputWriteCallback)xmlSecTransformIOBufferWrite, |
|
2748 (xmlOutputCloseCallback)xmlSecTransformIOBufferClose, |
|
2749 buffer, |
|
2750 NULL); |
|
2751 if(output == NULL) { |
|
2752 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2753 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2754 "xmlOutputBufferCreateIO", |
|
2755 XMLSEC_ERRORS_R_XML_FAILED, |
|
2756 XMLSEC_ERRORS_NO_MESSAGE); |
|
2757 xmlSecTransformIOBufferDestroy(buffer); |
|
2758 return(NULL); |
|
2759 } |
|
2760 |
|
2761 return(output); |
|
2762 } |
|
2763 |
|
2764 /** |
|
2765 * xmlSecTransformCreateInputBuffer: |
|
2766 * @transform: the pointer to transform. |
|
2767 * @transformCtx: the pointer to transform context object. |
|
2768 * |
|
2769 * Creates input buffer to read data from @transform. |
|
2770 * |
|
2771 * Returns pointer to new input buffer or NULL if an error occurs. |
|
2772 */ |
|
2773 EXPORT_C |
|
2774 xmlParserInputBufferPtr |
|
2775 xmlSecTransformCreateInputBuffer(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) { |
|
2776 xmlSecTransformIOBufferPtr buffer; |
|
2777 xmlSecTransformDataType type; |
|
2778 xmlParserInputBufferPtr input; |
|
2779 |
|
2780 xmlSecAssert2(xmlSecTransformIsValid(transform), NULL); |
|
2781 xmlSecAssert2(transformCtx != NULL, NULL); |
|
2782 |
|
2783 /* check that we have binary pop method for this transform */ |
|
2784 type = xmlSecTransformDefaultGetDataType(transform, xmlSecTransformModePop, transformCtx); |
|
2785 if((type & xmlSecTransformDataTypeBin) == 0) { |
|
2786 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2787 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2788 NULL, |
|
2789 XMLSEC_ERRORS_R_INVALID_TRANSFORM, |
|
2790 "pop binary data not supported"); |
|
2791 return(NULL); |
|
2792 } |
|
2793 |
|
2794 buffer = xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferModeRead, transform, transformCtx); |
|
2795 if(buffer == NULL) { |
|
2796 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2797 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2798 "xmlSecTransformIOBufferCreate", |
|
2799 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2800 XMLSEC_ERRORS_NO_MESSAGE); |
|
2801 return(NULL); |
|
2802 } |
|
2803 |
|
2804 input = xmlParserInputBufferCreateIO((xmlInputReadCallback)xmlSecTransformIOBufferRead, |
|
2805 (xmlInputCloseCallback)xmlSecTransformIOBufferClose, |
|
2806 buffer, |
|
2807 XML_CHAR_ENCODING_NONE); |
|
2808 if(input == NULL) { |
|
2809 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2810 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
2811 "xmlParserInputBufferCreateIO", |
|
2812 XMLSEC_ERRORS_R_XML_FAILED, |
|
2813 XMLSEC_ERRORS_NO_MESSAGE); |
|
2814 xmlSecTransformIOBufferDestroy(buffer); |
|
2815 return(NULL); |
|
2816 } |
|
2817 |
|
2818 return(input); |
|
2819 } |
|
2820 |
|
2821 static xmlSecTransformIOBufferPtr |
|
2822 xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferMode mode, xmlSecTransformPtr transform, |
|
2823 xmlSecTransformCtxPtr transformCtx) { |
|
2824 xmlSecTransformIOBufferPtr buffer; |
|
2825 |
|
2826 xmlSecAssert2(xmlSecTransformIsValid(transform), NULL); |
|
2827 xmlSecAssert2(transformCtx != NULL, NULL); |
|
2828 |
|
2829 buffer = (xmlSecTransformIOBufferPtr)xmlMalloc(sizeof(xmlSecTransformIOBuffer)); |
|
2830 if(buffer == NULL) { |
|
2831 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2832 NULL, |
|
2833 NULL, |
|
2834 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
2835 "size=%d", sizeof(xmlSecTransformIOBuffer)); |
|
2836 return(NULL); |
|
2837 } |
|
2838 memset(buffer, 0, sizeof(xmlSecTransformIOBuffer)); |
|
2839 |
|
2840 buffer->mode = mode; |
|
2841 buffer->transform = transform; |
|
2842 buffer->transformCtx = transformCtx; |
|
2843 |
|
2844 return(buffer); |
|
2845 } |
|
2846 |
|
2847 static void |
|
2848 xmlSecTransformIOBufferDestroy(xmlSecTransformIOBufferPtr buffer) { |
|
2849 xmlSecAssert(buffer != NULL); |
|
2850 |
|
2851 memset(buffer, 0, sizeof(xmlSecTransformIOBuffer)); |
|
2852 xmlFree(buffer); |
|
2853 } |
|
2854 |
|
2855 static int |
|
2856 xmlSecTransformIOBufferRead(xmlSecTransformIOBufferPtr buffer, |
|
2857 xmlSecByte *buf, xmlSecSize size) { |
|
2858 int ret; |
|
2859 |
|
2860 xmlSecAssert2(buffer != NULL, -1); |
|
2861 xmlSecAssert2(buffer->mode == xmlSecTransformIOBufferModeRead, -1); |
|
2862 xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1); |
|
2863 xmlSecAssert2(buffer->transformCtx != NULL, -1); |
|
2864 xmlSecAssert2(buf != NULL, -1); |
|
2865 |
|
2866 ret = xmlSecTransformPopBin(buffer->transform, buf, size, &size, buffer->transformCtx); |
|
2867 if(ret < 0) { |
|
2868 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2869 xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)), |
|
2870 "xmlSecTransformPopBin", |
|
2871 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2872 XMLSEC_ERRORS_NO_MESSAGE); |
|
2873 return(-1); |
|
2874 } |
|
2875 return(size); |
|
2876 } |
|
2877 |
|
2878 static int |
|
2879 xmlSecTransformIOBufferWrite(xmlSecTransformIOBufferPtr buffer, |
|
2880 const xmlSecByte *buf, xmlSecSize size) { |
|
2881 int ret; |
|
2882 |
|
2883 xmlSecAssert2(buffer != NULL, -1); |
|
2884 xmlSecAssert2(buffer->mode == xmlSecTransformIOBufferModeWrite, -1); |
|
2885 xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1); |
|
2886 xmlSecAssert2(buffer->transformCtx != NULL, -1); |
|
2887 xmlSecAssert2(buf != NULL, -1); |
|
2888 |
|
2889 ret = xmlSecTransformPushBin(buffer->transform, buf, size, 0, buffer->transformCtx); |
|
2890 if(ret < 0) { |
|
2891 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2892 xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)), |
|
2893 "xmlSecTransformPushBin", |
|
2894 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2895 XMLSEC_ERRORS_NO_MESSAGE); |
|
2896 return(-1); |
|
2897 } |
|
2898 return(size); |
|
2899 } |
|
2900 |
|
2901 static int |
|
2902 xmlSecTransformIOBufferClose(xmlSecTransformIOBufferPtr buffer) { |
|
2903 int ret; |
|
2904 |
|
2905 xmlSecAssert2(buffer != NULL, -1); |
|
2906 xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1); |
|
2907 xmlSecAssert2(buffer->transformCtx != NULL, -1); |
|
2908 |
|
2909 /* need to flush write buffer before destroing */ |
|
2910 if(buffer->mode == xmlSecTransformIOBufferModeWrite) { |
|
2911 ret = xmlSecTransformPushBin(buffer->transform, NULL, 0, 1, buffer->transformCtx); |
|
2912 if(ret < 0) { |
|
2913 xmlSecError(XMLSEC_ERRORS_HERE, |
|
2914 xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)), |
|
2915 "xmlSecTransformPushBin", |
|
2916 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
2917 XMLSEC_ERRORS_NO_MESSAGE); |
|
2918 xmlSecTransformIOBufferDestroy(buffer); |
|
2919 return(-1); |
|
2920 } |
|
2921 } |
|
2922 |
|
2923 xmlSecTransformIOBufferDestroy(buffer); |
|
2924 return(0); |
|
2925 } |