| File: | libxmlsec/unxlngi6.pro/misc/build/xmlsec1-1.2.14/src/xmldsig.c |
| Location: | line 776, column 36 |
| Description: | Access to field 'next' results in a dereference of a null pointer (loaded from variable 'cur') |
| 1 | /** | |||
| 2 | * XML Security Library (http://www.aleksey.com/xmlsec). | |||
| 3 | * | |||
| 4 | * "XML Digital Signature" implementation | |||
| 5 | * http://www.w3.org/TR/xmldsig-core/ | |||
| 6 | * http://www.w3.org/Signature/Overview.html | |||
| 7 | * | |||
| 8 | * This is free software; see Copyright file in the source | |||
| 9 | * distribution for preciese wording. | |||
| 10 | * | |||
| 11 | * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> | |||
| 12 | */ | |||
| 13 | #include "globals.h" | |||
| 14 | ||||
| 15 | #ifndef XMLSEC_NO_XMLDSIG | |||
| 16 | ||||
| 17 | #include <stdlib.h> | |||
| 18 | #include <stdio.h> | |||
| 19 | #include <string.h> | |||
| 20 | ||||
| 21 | #include <libxml/tree.h> | |||
| 22 | #include <libxml/parser.h> | |||
| 23 | ||||
| 24 | #include <xmlsec/xmlsec.h> | |||
| 25 | #include <xmlsec/buffer.h> | |||
| 26 | #include <xmlsec/xmltree.h> | |||
| 27 | #include <xmlsec/keys.h> | |||
| 28 | #include <xmlsec/keysmngr.h> | |||
| 29 | #include <xmlsec/transforms.h> | |||
| 30 | #include <xmlsec/membuf.h> | |||
| 31 | #include <xmlsec/xmldsig.h> | |||
| 32 | #include <xmlsec/errors.h> | |||
| 33 | ||||
| 34 | /************************************************************************** | |||
| 35 | * | |||
| 36 | * xmlSecDSigCtx | |||
| 37 | * | |||
| 38 | *************************************************************************/ | |||
| 39 | static int xmlSecDSigCtxProcessSignatureNode (xmlSecDSigCtxPtr dsigCtx, | |||
| 40 | xmlNodePtr node); | |||
| 41 | static int xmlSecDSigCtxProcessSignedInfoNode (xmlSecDSigCtxPtr dsigCtx, | |||
| 42 | xmlNodePtr node); | |||
| 43 | static int xmlSecDSigCtxProcessKeyInfoNode (xmlSecDSigCtxPtr dsigCtx, | |||
| 44 | xmlNodePtr node); | |||
| 45 | static int xmlSecDSigCtxProcessObjectNode (xmlSecDSigCtxPtr dsigCtx, | |||
| 46 | xmlNodePtr node); | |||
| 47 | static int xmlSecDSigCtxProcessManifestNode (xmlSecDSigCtxPtr dsigCtx, | |||
| 48 | xmlNodePtr node); | |||
| 49 | ||||
| 50 | /* The ID attribute in XMLDSig is 'Id' */ | |||
| 51 | static const xmlChar* xmlSecDSigIds[] = { xmlSecAttrId, NULL((void*)0) }; | |||
| 52 | ||||
| 53 | /** | |||
| 54 | * xmlSecDSigCtxCreate: | |||
| 55 | * @keysMngr: the pointer to keys manager. | |||
| 56 | * | |||
| 57 | * Creates <dsig:Signature/> element processing context. | |||
| 58 | * The caller is responsible for destroying returend object by calling | |||
| 59 | * #xmlSecDSigCtxDestroy function. | |||
| 60 | * | |||
| 61 | * Returns: pointer to newly allocated context object or NULL if an error | |||
| 62 | * occurs. | |||
| 63 | */ | |||
| 64 | xmlSecDSigCtxPtr | |||
| 65 | xmlSecDSigCtxCreate(xmlSecKeysMngrPtr keysMngr) { | |||
| 66 | xmlSecDSigCtxPtr dsigCtx; | |||
| 67 | int ret; | |||
| 68 | ||||
| 69 | dsigCtx = (xmlSecDSigCtxPtr) xmlMalloc(sizeof(xmlSecDSigCtx)); | |||
| 70 | if(dsigCtx == NULL((void*)0)) { | |||
| 71 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",71,__FUNCTION__, | |||
| 72 | NULL((void*)0), | |||
| 73 | NULL((void*)0), | |||
| 74 | XMLSEC_ERRORS_R_MALLOC_FAILED2, | |||
| 75 | "sizeof(xmlSecDSigCtx)=%d", | |||
| 76 | sizeof(xmlSecDSigCtx)); | |||
| 77 | return(NULL((void*)0)); | |||
| 78 | } | |||
| 79 | ||||
| 80 | ret = xmlSecDSigCtxInitialize(dsigCtx, keysMngr); | |||
| 81 | if(ret < 0) { | |||
| 82 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",82,__FUNCTION__, | |||
| 83 | NULL((void*)0), | |||
| 84 | "xmlSecDSigCtxInitialize", | |||
| 85 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 86 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 87 | xmlSecDSigCtxDestroy(dsigCtx); | |||
| 88 | return(NULL((void*)0)); | |||
| 89 | } | |||
| 90 | return(dsigCtx); | |||
| 91 | } | |||
| 92 | ||||
| 93 | /** | |||
| 94 | * xmlSecDSigCtxDestroy: | |||
| 95 | * @dsigCtx: the pointer to <dsig:Signature/> processing context. | |||
| 96 | * | |||
| 97 | * Destroy context object created with #xmlSecDSigCtxCreate function. | |||
| 98 | */ | |||
| 99 | void | |||
| 100 | xmlSecDSigCtxDestroy(xmlSecDSigCtxPtr dsigCtx) { | |||
| 101 | xmlSecAssert(dsigCtx != NULL)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",101 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return ; }; | |||
| 102 | ||||
| 103 | xmlSecDSigCtxFinalize(dsigCtx); | |||
| 104 | xmlFree(dsigCtx); | |||
| 105 | } | |||
| 106 | ||||
| 107 | /** | |||
| 108 | * xmlSecDSigCtxInitialize: | |||
| 109 | * @dsigCtx: the pointer to <dsig:Signature/> processing context. | |||
| 110 | * @keysMngr: the pointer to keys manager. | |||
| 111 | * | |||
| 112 | * Initializes <dsig:Signature/> element processing context. | |||
| 113 | * The caller is responsible for cleaing up returend object by calling | |||
| 114 | * #xmlSecDSigCtxFinalize function. | |||
| 115 | * | |||
| 116 | * Returns: 0 on success or a negative value if an error occurs. | |||
| 117 | */ | |||
| 118 | int | |||
| 119 | xmlSecDSigCtxInitialize(xmlSecDSigCtxPtr dsigCtx, xmlSecKeysMngrPtr keysMngr) { | |||
| 120 | int ret; | |||
| 121 | ||||
| 122 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",122 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 123 | ||||
| 124 | memset(dsigCtx, 0, sizeof(xmlSecDSigCtx)); | |||
| 125 | ||||
| 126 | /* initialize key info */ | |||
| 127 | ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoReadCtx), keysMngr); | |||
| 128 | if(ret < 0) { | |||
| 129 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",129,__FUNCTION__, | |||
| 130 | NULL((void*)0), | |||
| 131 | "xmlSecKeyInfoCtxInitialize", | |||
| 132 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 133 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 134 | return(-1); | |||
| 135 | } | |||
| 136 | dsigCtx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead; | |||
| 137 | ||||
| 138 | ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoWriteCtx), keysMngr); | |||
| 139 | if(ret < 0) { | |||
| 140 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",140,__FUNCTION__, | |||
| 141 | NULL((void*)0), | |||
| 142 | "xmlSecKeyInfoCtxInitialize", | |||
| 143 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 144 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 145 | return(-1); | |||
| 146 | } | |||
| 147 | dsigCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite; | |||
| 148 | /* it's not wise to write private key :) */ | |||
| 149 | dsigCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic0x0001; | |||
| 150 | ||||
| 151 | /* initializes transforms dsigCtx */ | |||
| 152 | ret = xmlSecTransformCtxInitialize(&(dsigCtx->transformCtx)); | |||
| 153 | if(ret < 0) { | |||
| 154 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",154,__FUNCTION__, | |||
| 155 | NULL((void*)0), | |||
| 156 | "xmlSecTransformCtxInitialize", | |||
| 157 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 158 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 159 | return(-1); | |||
| 160 | } | |||
| 161 | ||||
| 162 | /* references lists from SignedInfo and Manifest elements */ | |||
| 163 | xmlSecPtrListInitialize(&(dsigCtx->signedInfoReferences), | |||
| 164 | xmlSecDSigReferenceCtxListIdxmlSecDSigReferenceCtxListGetKlass()); | |||
| 165 | xmlSecPtrListInitialize(&(dsigCtx->manifestReferences), | |||
| 166 | xmlSecDSigReferenceCtxListIdxmlSecDSigReferenceCtxListGetKlass()); | |||
| 167 | ||||
| 168 | dsigCtx->enabledReferenceUris = xmlSecTransformUriTypeAny0xFFFF; | |||
| 169 | return(0); | |||
| 170 | } | |||
| 171 | ||||
| 172 | /** | |||
| 173 | * xmlSecDSigCtxFinalize: | |||
| 174 | * @dsigCtx: the pointer to <dsig:Signature/> processing context. | |||
| 175 | * | |||
| 176 | * Cleans up @dsigCtx object initialized with #xmlSecDSigCtxInitialize function. | |||
| 177 | */ | |||
| 178 | void | |||
| 179 | xmlSecDSigCtxFinalize(xmlSecDSigCtxPtr dsigCtx) { | |||
| 180 | xmlSecAssert(dsigCtx != NULL)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",180 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return ; }; | |||
| 181 | ||||
| 182 | xmlSecTransformCtxFinalize(&(dsigCtx->transformCtx)); | |||
| 183 | xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoReadCtx)); | |||
| 184 | xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoWriteCtx)); | |||
| 185 | xmlSecPtrListFinalize(&(dsigCtx->signedInfoReferences)); | |||
| 186 | xmlSecPtrListFinalize(&(dsigCtx->manifestReferences)); | |||
| 187 | ||||
| 188 | if(dsigCtx->enabledReferenceTransforms != NULL((void*)0)) { | |||
| 189 | xmlSecPtrListDestroy(dsigCtx->enabledReferenceTransforms); | |||
| 190 | } | |||
| 191 | if(dsigCtx->signKey != NULL((void*)0)) { | |||
| 192 | xmlSecKeyDestroy(dsigCtx->signKey); | |||
| 193 | } | |||
| 194 | if(dsigCtx->id != NULL((void*)0)) { | |||
| 195 | xmlFree(dsigCtx->id); | |||
| 196 | } | |||
| 197 | memset(dsigCtx, 0, sizeof(xmlSecDSigCtx)); | |||
| 198 | } | |||
| 199 | ||||
| 200 | /** | |||
| 201 | * xmlSecDSigCtxEnableReferenceTransform: | |||
| 202 | * @dsigCtx: the pointer to <dsig:Signature/> processing context. | |||
| 203 | * @transformId: the transform klass. | |||
| 204 | * | |||
| 205 | * Enables @transformId for <dsig:Reference/> elements processing. | |||
| 206 | * | |||
| 207 | * Returns: 0 on success or a negative value if an error occurs. | |||
| 208 | */ | |||
| 209 | int | |||
| 210 | xmlSecDSigCtxEnableReferenceTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) { | |||
| 211 | int ret; | |||
| 212 | ||||
| 213 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",213 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 214 | xmlSecAssert2(dsigCtx->result == NULL, -1)if(!( dsigCtx->result == ((void*)0) ) ) { xmlSecError("xmldsig.c" ,214,__FUNCTION__, ((void*)0), "dsigCtx->result == NULL", 100 , " "); return(-1); }; | |||
| 215 | xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1)if(!( transformId != ((xmlSecTransformId)((void*)0)) ) ) { xmlSecError ("xmldsig.c",215,__FUNCTION__, ((void*)0), "transformId != xmlSecTransformIdUnknown" , 100, " "); return(-1); }; | |||
| 216 | ||||
| 217 | if(dsigCtx->enabledReferenceTransforms == NULL((void*)0)) { | |||
| 218 | dsigCtx->enabledReferenceTransforms = xmlSecPtrListCreate(xmlSecTransformIdListIdxmlSecTransformIdListGetKlass()); | |||
| 219 | if(dsigCtx->enabledReferenceTransforms == NULL((void*)0)) { | |||
| 220 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",220,__FUNCTION__, | |||
| 221 | NULL((void*)0), | |||
| 222 | "xmlSecPtrListCreate", | |||
| 223 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 224 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 225 | return(-1); | |||
| 226 | } | |||
| 227 | } | |||
| 228 | ||||
| 229 | ret = xmlSecPtrListAdd(dsigCtx->enabledReferenceTransforms, (void*)transformId); | |||
| 230 | if(ret < 0) { | |||
| 231 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",231,__FUNCTION__, | |||
| 232 | NULL((void*)0), | |||
| 233 | "xmlSecPtrListAdd", | |||
| 234 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 235 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 236 | return(-1); | |||
| 237 | } | |||
| 238 | return(0); | |||
| 239 | } | |||
| 240 | ||||
| 241 | /** | |||
| 242 | * xmlSecDSigCtxEnableSignatureTransform: | |||
| 243 | * @dsigCtx: the pointer to <dsig:Signature/> processing context. | |||
| 244 | * @transformId: the transform klass. | |||
| 245 | * | |||
| 246 | * Enables @transformId for <dsig:SignedInfo/> element processing. | |||
| 247 | * | |||
| 248 | * Returns: 0 on success or a negative value if an error occurs. | |||
| 249 | */ | |||
| 250 | int | |||
| 251 | xmlSecDSigCtxEnableSignatureTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) { | |||
| 252 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",252 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 253 | xmlSecAssert2(dsigCtx->result == NULL, -1)if(!( dsigCtx->result == ((void*)0) ) ) { xmlSecError("xmldsig.c" ,253,__FUNCTION__, ((void*)0), "dsigCtx->result == NULL", 100 , " "); return(-1); }; | |||
| 254 | xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1)if(!( transformId != ((xmlSecTransformId)((void*)0)) ) ) { xmlSecError ("xmldsig.c",254,__FUNCTION__, ((void*)0), "transformId != xmlSecTransformIdUnknown" , 100, " "); return(-1); }; | |||
| 255 | ||||
| 256 | return(xmlSecPtrListAdd(&(dsigCtx->transformCtx.enabledTransforms), (void*)transformId)); | |||
| 257 | } | |||
| 258 | ||||
| 259 | /** | |||
| 260 | * xmlSecDSigCtxGetPreSignBuffer: | |||
| 261 | * @dsigCtx: the pointer to <dsig:Signature/> processing context. | |||
| 262 | * | |||
| 263 | * Gets pointer to the buffer with serialized <dsig:SignedInfo/> element | |||
| 264 | * just before signature claculation (valid if and only if | |||
| 265 | * #XMLSEC_DSIG_FLAGS_STORE_SIGNATURE context flag is set. | |||
| 266 | * | |||
| 267 | * Returns: 0 on success or a negative value if an error occurs. | |||
| 268 | */ | |||
| 269 | xmlSecBufferPtr | |||
| 270 | xmlSecDSigCtxGetPreSignBuffer(xmlSecDSigCtxPtr dsigCtx) { | |||
| 271 | xmlSecAssert2(dsigCtx != NULL, NULL)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",271 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (((void*)0)); }; | |||
| 272 | ||||
| 273 | return((dsigCtx->preSignMemBufMethod != NULL((void*)0)) ? | |||
| 274 | xmlSecTransformMemBufGetBuffer(dsigCtx->preSignMemBufMethod) : NULL((void*)0)); | |||
| 275 | } | |||
| 276 | ||||
| 277 | /** | |||
| 278 | * xmlSecDSigCtxSign: | |||
| 279 | * @dsigCtx: the pointer to <dsig:Signature/> processing context. | |||
| 280 | * @tmpl: the pointer to <dsig:Signature/> node with signature template. | |||
| 281 | * | |||
| 282 | * Signs the data as described in @tmpl node. | |||
| 283 | * | |||
| 284 | * Returns: 0 on success or a negative value if an error occurs. | |||
| 285 | */ | |||
| 286 | int | |||
| 287 | xmlSecDSigCtxSign(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr tmpl) { | |||
| 288 | int ret; | |||
| 289 | ||||
| 290 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",290 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 291 | xmlSecAssert2(dsigCtx->result == NULL, -1)if(!( dsigCtx->result == ((void*)0) ) ) { xmlSecError("xmldsig.c" ,291,__FUNCTION__, ((void*)0), "dsigCtx->result == NULL", 100 , " "); return(-1); }; | |||
| 292 | xmlSecAssert2(tmpl != NULL, -1)if(!( tmpl != ((void*)0) ) ) { xmlSecError("xmldsig.c",292,__FUNCTION__ , ((void*)0), "tmpl != NULL", 100, " "); return(-1); }; | |||
| 293 | xmlSecAssert2(tmpl->doc != NULL, -1)if(!( tmpl->doc != ((void*)0) ) ) { xmlSecError("xmldsig.c" ,293,__FUNCTION__, ((void*)0), "tmpl->doc != NULL", 100, " " ); return(-1); }; | |||
| 294 | ||||
| 295 | /* add ids for Signature nodes */ | |||
| 296 | dsigCtx->operation = xmlSecTransformOperationSign; | |||
| 297 | dsigCtx->status = xmlSecDSigStatusUnknown; | |||
| 298 | xmlSecAddIDs(tmpl->doc, tmpl, xmlSecDSigIds); | |||
| 299 | ||||
| 300 | /* read signature template */ | |||
| 301 | ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, tmpl); | |||
| 302 | if(ret < 0) { | |||
| 303 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",303,__FUNCTION__, | |||
| 304 | NULL((void*)0), | |||
| 305 | "xmlSecDSigCtxSigantureProcessNode", | |||
| 306 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 307 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 308 | return(-1); | |||
| 309 | } | |||
| 310 | xmlSecAssert2(dsigCtx->signMethod != NULL, -1)if(!( dsigCtx->signMethod != ((void*)0) ) ) { xmlSecError( "xmldsig.c",310,__FUNCTION__, ((void*)0), "dsigCtx->signMethod != NULL" , 100, " "); return(-1); }; | |||
| 311 | xmlSecAssert2(dsigCtx->signValueNode != NULL, -1)if(!( dsigCtx->signValueNode != ((void*)0) ) ) { xmlSecError ("xmldsig.c",311,__FUNCTION__, ((void*)0), "dsigCtx->signValueNode != NULL" , 100, " "); return(-1); }; | |||
| 312 | ||||
| 313 | /* references processing might change the status */ | |||
| 314 | if(dsigCtx->status != xmlSecDSigStatusUnknown) { | |||
| 315 | return(0); | |||
| 316 | } | |||
| 317 | ||||
| 318 | /* check what we've got */ | |||
| 319 | dsigCtx->result = dsigCtx->transformCtx.result; | |||
| 320 | if((dsigCtx->result == NULL((void*)0)) || (xmlSecBufferGetData(dsigCtx->result) == NULL((void*)0))) { | |||
| 321 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",321,__FUNCTION__, | |||
| 322 | NULL((void*)0), | |||
| 323 | NULL((void*)0), | |||
| 324 | XMLSEC_ERRORS_R_INVALID_RESULT13, | |||
| 325 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 326 | return(-1); | |||
| 327 | } | |||
| 328 | ||||
| 329 | /* write signed data to xml */ | |||
| 330 | xmlNodeSetContentLen(dsigCtx->signValueNode, | |||
| 331 | xmlSecBufferGetData(dsigCtx->result), | |||
| 332 | xmlSecBufferGetSize(dsigCtx->result)); | |||
| 333 | ||||
| 334 | /* set success status and we are done */ | |||
| 335 | dsigCtx->status = xmlSecDSigStatusSucceeded; | |||
| 336 | return(0); | |||
| 337 | } | |||
| 338 | ||||
| 339 | /** | |||
| 340 | * xmlSecDSigCtxVerify: | |||
| 341 | * @dsigCtx: the pointer to <dsig:Signature/> processing context. | |||
| 342 | * @node: the pointer with <dsig:Signature/> node. | |||
| 343 | * | |||
| 344 | * Vaidates signature in the @node. The verification result is returned | |||
| 345 | * in #status member of the @dsigCtx object. | |||
| 346 | * | |||
| 347 | * Returns: 0 on success (check #status member of @dsigCtx to get | |||
| 348 | * signature verification result) or a negative value if an error occurs. | |||
| 349 | */ | |||
| 350 | int | |||
| 351 | xmlSecDSigCtxVerify(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) { | |||
| 352 | int ret; | |||
| 353 | ||||
| 354 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",354 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 355 | xmlSecAssert2(node != NULL, -1)if(!( node != ((void*)0) ) ) { xmlSecError("xmldsig.c",355,__FUNCTION__ , ((void*)0), "node != NULL", 100, " "); return(-1); }; | |||
| 356 | xmlSecAssert2(node->doc != NULL, -1)if(!( node->doc != ((void*)0) ) ) { xmlSecError("xmldsig.c" ,356,__FUNCTION__, ((void*)0), "node->doc != NULL", 100, " " ); return(-1); }; | |||
| 357 | ||||
| 358 | /* add ids for Signature nodes */ | |||
| 359 | dsigCtx->operation = xmlSecTransformOperationVerify; | |||
| 360 | dsigCtx->status = xmlSecDSigStatusUnknown; | |||
| 361 | xmlSecAddIDs(node->doc, node, xmlSecDSigIds); | |||
| 362 | ||||
| 363 | /* read siganture info */ | |||
| 364 | ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, node); | |||
| 365 | if(ret < 0) { | |||
| 366 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",366,__FUNCTION__, | |||
| 367 | NULL((void*)0), | |||
| 368 | "xmlSecDSigCtxSigantureProcessNode", | |||
| 369 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 370 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 371 | return(-1); | |||
| 372 | } | |||
| 373 | xmlSecAssert2(dsigCtx->signMethod != NULL, -1)if(!( dsigCtx->signMethod != ((void*)0) ) ) { xmlSecError( "xmldsig.c",373,__FUNCTION__, ((void*)0), "dsigCtx->signMethod != NULL" , 100, " "); return(-1); }; | |||
| 374 | xmlSecAssert2(dsigCtx->signValueNode != NULL, -1)if(!( dsigCtx->signValueNode != ((void*)0) ) ) { xmlSecError ("xmldsig.c",374,__FUNCTION__, ((void*)0), "dsigCtx->signValueNode != NULL" , 100, " "); return(-1); }; | |||
| 375 | ||||
| 376 | /* references processing might change the status */ | |||
| 377 | if(dsigCtx->status != xmlSecDSigStatusUnknown) { | |||
| 378 | return(0); | |||
| 379 | } | |||
| 380 | ||||
| 381 | /* verify SignatureValue node content */ | |||
| 382 | ret = xmlSecTransformVerifyNodeContent(dsigCtx->signMethod, dsigCtx->signValueNode, | |||
| 383 | &(dsigCtx->transformCtx)); | |||
| 384 | if(ret < 0) { | |||
| 385 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",385,__FUNCTION__, | |||
| 386 | NULL((void*)0), | |||
| 387 | "xmlSecTransformVerifyNodeContent", | |||
| 388 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 389 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 390 | return(-1); | |||
| 391 | } | |||
| 392 | ||||
| 393 | /* set status and we are done */ | |||
| 394 | if(dsigCtx->signMethod->status == xmlSecTransformStatusOk) { | |||
| 395 | dsigCtx->status = xmlSecDSigStatusSucceeded; | |||
| 396 | } else { | |||
| 397 | dsigCtx->status = xmlSecDSigStatusInvalid; | |||
| 398 | } | |||
| 399 | return(0); | |||
| 400 | } | |||
| 401 | ||||
| 402 | /** | |||
| 403 | * xmlSecDSigCtxProcessSignatureNode: | |||
| 404 | * | |||
| 405 | * The Signature element (http://www.w3.org/TR/xmldsig-core/#sec-Signature) | |||
| 406 | * | |||
| 407 | * The Signature element is the root element of an XML Signature. | |||
| 408 | * Implementation MUST generate laxly schema valid [XML-schema] Signature | |||
| 409 | * elements as specified by the following schema: | |||
| 410 | * The way in which the SignedInfo element is presented to the | |||
| 411 | * canonicalization method is dependent on that method. The following | |||
| 412 | * applies to algorithms which process XML as nodes or characters: | |||
| 413 | * | |||
| 414 | * - XML based canonicalization implementations MUST be provided with | |||
| 415 | * a [XPath] node-set originally formed from the document containing | |||
| 416 | * the SignedInfo and currently indicating the SignedInfo, its descendants, | |||
| 417 | * and the attribute and namespace nodes of SignedInfo and its descendant | |||
| 418 | * elements. | |||
| 419 | * | |||
| 420 | * - Text based canonicalization algorithms (such as CRLF and charset | |||
| 421 | * normalization) should be provided with the UTF-8 octets that represent | |||
| 422 | * the well-formed SignedInfo element, from the first character to the | |||
| 423 | * last character of the XML representation, inclusive. This includes | |||
| 424 | * the entire text of the start and end tags of the SignedInfo element | |||
| 425 | * as well as all descendant markup and character data (i.e., the text) | |||
| 426 | * between those tags. Use of text based canonicalization of SignedInfo | |||
| 427 | * is NOT RECOMMENDED. | |||
| 428 | * | |||
| 429 | * ================================= | |||
| 430 | * we do not support any non XML based C14N | |||
| 431 | * | |||
| 432 | * Schema Definition: | |||
| 433 | * | |||
| 434 | * <element name="Signature" type="ds:SignatureType"/> | |||
| 435 | * <complexType name="SignatureType"> | |||
| 436 | * <sequence> | |||
| 437 | * <element ref="ds:SignedInfo"/> | |||
| 438 | * <element ref="ds:SignatureValue"/> | |||
| 439 | * <element ref="ds:KeyInfo" minOccurs="0"/> | |||
| 440 | * <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/> | |||
| 441 | * </sequence> <attribute name="Id" type="ID" use="optional"/> | |||
| 442 | * </complexType> | |||
| 443 | * | |||
| 444 | * DTD: | |||
| 445 | * | |||
| 446 | * <!ELEMENT Signature (SignedInfo, SignatureValue, KeyInfo?, Object*) > | |||
| 447 | * <!ATTLIST Signature | |||
| 448 | * xmlns CDATA #FIXED 'http://www.w3.org/2000/09/xmldsig#' | |||
| 449 | * Id ID #IMPLIED > | |||
| 450 | * | |||
| 451 | */ | |||
| 452 | static int | |||
| 453 | xmlSecDSigCtxProcessSignatureNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) { | |||
| 454 | xmlSecTransformDataType firstType; | |||
| 455 | xmlNodePtr signedInfoNode = NULL((void*)0); | |||
| 456 | xmlNodePtr keyInfoNode = NULL((void*)0); | |||
| 457 | xmlNodePtr cur; | |||
| 458 | int ret; | |||
| 459 | ||||
| 460 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",460 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 461 | xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1)if(!( (dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify) ) ) { xmlSecError("xmldsig.c",461,__FUNCTION__, ((void*)0), "(dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify)" , 100, " "); return(-1); }; | |||
| 462 | xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1)if(!( dsigCtx->status == xmlSecDSigStatusUnknown ) ) { xmlSecError ("xmldsig.c",462,__FUNCTION__, ((void*)0), "dsigCtx->status == xmlSecDSigStatusUnknown" , 100, " "); return(-1); }; | |||
| 463 | xmlSecAssert2(dsigCtx->signValueNode == NULL, -1)if(!( dsigCtx->signValueNode == ((void*)0) ) ) { xmlSecError ("xmldsig.c",463,__FUNCTION__, ((void*)0), "dsigCtx->signValueNode == NULL" , 100, " "); return(-1); }; | |||
| 464 | xmlSecAssert2(dsigCtx->signMethod == NULL, -1)if(!( dsigCtx->signMethod == ((void*)0) ) ) { xmlSecError( "xmldsig.c",464,__FUNCTION__, ((void*)0), "dsigCtx->signMethod == NULL" , 100, " "); return(-1); }; | |||
| 465 | xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1)if(!( dsigCtx->c14nMethod == ((void*)0) ) ) { xmlSecError( "xmldsig.c",465,__FUNCTION__, ((void*)0), "dsigCtx->c14nMethod == NULL" , 100, " "); return(-1); }; | |||
| 466 | xmlSecAssert2(node != NULL, -1)if(!( node != ((void*)0) ) ) { xmlSecError("xmldsig.c",466,__FUNCTION__ , ((void*)0), "node != NULL", 100, " "); return(-1); }; | |||
| 467 | ||||
| 468 | if(!xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs)) { | |||
| 469 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",469,__FUNCTION__, | |||
| 470 | NULL((void*)0), | |||
| 471 | xmlSecErrorsSafeString(xmlSecNodeGetName(node))((((((node)) ? ((const char*)((node)->name)) : ((void*)0)) ) != ((void*)0)) ? ((char*)((((node)) ? ((const char*)((node) ->name)) : ((void*)0)))) : (char*)"NULL"), | |||
| 472 | XMLSEC_ERRORS_R_INVALID_NODE21, | |||
| 473 | "expected=%s", | |||
| 474 | xmlSecErrorsSafeString(xmlSecNodeSignature)(((xmlSecNodeSignature) != ((void*)0)) ? ((char*)(xmlSecNodeSignature )) : (char*)"NULL")); | |||
| 475 | return(-1); | |||
| 476 | } | |||
| 477 | ||||
| 478 | /* read node data */ | |||
| 479 | xmlSecAssert2(dsigCtx->id == NULL, -1)if(!( dsigCtx->id == ((void*)0) ) ) { xmlSecError("xmldsig.c" ,479,__FUNCTION__, ((void*)0), "dsigCtx->id == NULL", 100, " "); return(-1); }; | |||
| 480 | dsigCtx->id = xmlGetProp(node, xmlSecAttrId); | |||
| 481 | ||||
| 482 | /* first node is required SignedInfo */ | |||
| 483 | cur = xmlSecGetNextElementNode(node->children); | |||
| 484 | if((cur == NULL((void*)0)) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignedInfo, xmlSecDSigNs))) { | |||
| 485 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",485,__FUNCTION__, | |||
| 486 | NULL((void*)0), | |||
| 487 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL"), | |||
| 488 | XMLSEC_ERRORS_R_INVALID_NODE21, | |||
| 489 | "expected=%s", | |||
| 490 | xmlSecErrorsSafeString(xmlSecNodeSignedInfo)(((xmlSecNodeSignedInfo) != ((void*)0)) ? ((char*)(xmlSecNodeSignedInfo )) : (char*)"NULL")); | |||
| 491 | return(-1); | |||
| 492 | } | |||
| 493 | signedInfoNode = cur; | |||
| 494 | cur = xmlSecGetNextElementNode(cur->next); | |||
| 495 | ||||
| 496 | /* next node is required SignatureValue */ | |||
| 497 | if((cur == NULL((void*)0)) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))) { | |||
| 498 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",498,__FUNCTION__, | |||
| 499 | NULL((void*)0), | |||
| 500 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL"), | |||
| 501 | XMLSEC_ERRORS_R_INVALID_NODE21, | |||
| 502 | "expected=%s", | |||
| 503 | xmlSecErrorsSafeString(xmlSecNodeSignatureValue)(((xmlSecNodeSignatureValue) != ((void*)0)) ? ((char*)(xmlSecNodeSignatureValue )) : (char*)"NULL")); | |||
| 504 | return(-1); | |||
| 505 | } | |||
| 506 | dsigCtx->signValueNode = cur; | |||
| 507 | cur = xmlSecGetNextElementNode(cur->next); | |||
| 508 | ||||
| 509 | /* next node is optional KeyInfo */ | |||
| 510 | if((cur != NULL((void*)0)) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) { | |||
| 511 | keyInfoNode = cur; | |||
| 512 | cur = xmlSecGetNextElementNode(cur->next); | |||
| 513 | } else { | |||
| 514 | keyInfoNode = NULL((void*)0); | |||
| 515 | } | |||
| 516 | ||||
| 517 | /* next nodes are optional Object nodes */ | |||
| 518 | while((cur != NULL((void*)0)) && (xmlSecCheckNodeName(cur, xmlSecNodeObject, xmlSecDSigNs))) { | |||
| 519 | /* read manifests from objects */ | |||
| 520 | if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS0x00000001) == 0) { | |||
| 521 | ret = xmlSecDSigCtxProcessObjectNode(dsigCtx, cur); | |||
| 522 | if(ret < 0) { | |||
| 523 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",523,__FUNCTION__, | |||
| 524 | NULL((void*)0), | |||
| 525 | "xmlSecDSigCtxProcessObjectNode", | |||
| 526 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 527 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 528 | return(-1); | |||
| 529 | } | |||
| 530 | } | |||
| 531 | cur = xmlSecGetNextElementNode(cur->next); | |||
| 532 | } | |||
| 533 | ||||
| 534 | /* if there is something left than it's an error */ | |||
| 535 | if(cur != NULL((void*)0)) { | |||
| 536 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",536,__FUNCTION__, | |||
| 537 | NULL((void*)0), | |||
| 538 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL"), | |||
| 539 | XMLSEC_ERRORS_R_UNEXPECTED_NODE27, | |||
| 540 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 541 | return(-1); | |||
| 542 | } | |||
| 543 | ||||
| 544 | /* now validated all the references and prepare transform */ | |||
| 545 | ret = xmlSecDSigCtxProcessSignedInfoNode(dsigCtx, signedInfoNode); | |||
| 546 | if(ret < 0) { | |||
| 547 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",547,__FUNCTION__, | |||
| 548 | NULL((void*)0), | |||
| 549 | "xmlSecDSigCtxProcessSignedInfoNode", | |||
| 550 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 551 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 552 | return(-1); | |||
| 553 | } | |||
| 554 | /* references processing might change the status */ | |||
| 555 | if(dsigCtx->status != xmlSecDSigStatusUnknown) { | |||
| 556 | return(0); | |||
| 557 | } | |||
| 558 | ||||
| 559 | /* as the result, we should have sign and c14n methods set */ | |||
| 560 | xmlSecAssert2(dsigCtx->signMethod != NULL, -1)if(!( dsigCtx->signMethod != ((void*)0) ) ) { xmlSecError( "xmldsig.c",560,__FUNCTION__, ((void*)0), "dsigCtx->signMethod != NULL" , 100, " "); return(-1); }; | |||
| 561 | xmlSecAssert2(dsigCtx->c14nMethod != NULL, -1)if(!( dsigCtx->c14nMethod != ((void*)0) ) ) { xmlSecError( "xmldsig.c",561,__FUNCTION__, ((void*)0), "dsigCtx->c14nMethod != NULL" , 100, " "); return(-1); }; | |||
| 562 | ||||
| 563 | ret = xmlSecDSigCtxProcessKeyInfoNode(dsigCtx, keyInfoNode); | |||
| 564 | if(ret < 0) { | |||
| 565 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",565,__FUNCTION__, | |||
| 566 | NULL((void*)0), | |||
| 567 | "xmlSecDSigCtxProcessKeyInfoNode", | |||
| 568 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 569 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 570 | return(-1); | |||
| 571 | } | |||
| 572 | /* as the result, we should have a key */ | |||
| 573 | xmlSecAssert2(dsigCtx->signKey != NULL, -1)if(!( dsigCtx->signKey != ((void*)0) ) ) { xmlSecError("xmldsig.c" ,573,__FUNCTION__, ((void*)0), "dsigCtx->signKey != NULL", 100, " "); return(-1); }; | |||
| 574 | ||||
| 575 | /* if we need to write result to xml node then we need base64 encode result */ | |||
| 576 | if(dsigCtx->operation == xmlSecTransformOperationSign) { | |||
| 577 | xmlSecTransformPtr base64Encode; | |||
| 578 | ||||
| 579 | /* we need to add base64 encode transform */ | |||
| 580 | base64Encode = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), | |||
| 581 | xmlSecTransformBase64IdxmlSecTransformBase64GetKlass()); | |||
| 582 | if(base64Encode == NULL((void*)0)) { | |||
| 583 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",583,__FUNCTION__, | |||
| 584 | NULL((void*)0), | |||
| 585 | "xmlSecTransformCtxCreateAndAppend", | |||
| 586 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 587 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 588 | return(-1); | |||
| 589 | } | |||
| 590 | base64Encode->operation = xmlSecTransformOperationEncode; | |||
| 591 | } | |||
| 592 | ||||
| 593 | firstType = xmlSecTransformGetDataType(dsigCtx->transformCtx.first, | |||
| 594 | xmlSecTransformModePush, | |||
| 595 | &(dsigCtx->transformCtx)); | |||
| 596 | if((firstType & xmlSecTransformDataTypeXml0x0002) != 0) { | |||
| 597 | xmlSecNodeSetPtr nodeset = NULL((void*)0); | |||
| 598 | ||||
| 599 | xmlSecAssert2(signedInfoNode != NULL, -1)if(!( signedInfoNode != ((void*)0) ) ) { xmlSecError("xmldsig.c" ,599,__FUNCTION__, ((void*)0), "signedInfoNode != NULL", 100, " "); return(-1); }; | |||
| 600 | nodeset = xmlSecNodeSetGetChildren(signedInfoNode->doc, signedInfoNode, 1, 0); | |||
| 601 | if(nodeset == NULL((void*)0)) { | |||
| 602 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",602,__FUNCTION__, | |||
| 603 | NULL((void*)0), | |||
| 604 | "xmlSecNodeSetGetChildren", | |||
| 605 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 606 | "node=%s", | |||
| 607 | xmlSecErrorsSafeString(xmlSecNodeGetName(signedInfoNode))((((((signedInfoNode)) ? ((const char*)((signedInfoNode)-> name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((signedInfoNode )) ? ((const char*)((signedInfoNode)->name)) : ((void*)0)) )) : (char*)"NULL")); | |||
| 608 | return(-1); | |||
| 609 | } | |||
| 610 | ||||
| 611 | /* calculate the signature */ | |||
| 612 | ret = xmlSecTransformCtxXmlExecute(&(dsigCtx->transformCtx), nodeset); | |||
| 613 | if(ret < 0) { | |||
| 614 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",614,__FUNCTION__, | |||
| 615 | NULL((void*)0), | |||
| 616 | "xmlSecTransformCtxXmlExecute", | |||
| 617 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 618 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 619 | xmlSecNodeSetDestroy(nodeset); | |||
| 620 | return(-1); | |||
| 621 | } | |||
| 622 | xmlSecNodeSetDestroy(nodeset); | |||
| 623 | } else { | |||
| 624 | /* TODO */ | |||
| 625 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",625,__FUNCTION__, | |||
| 626 | NULL((void*)0), | |||
| 627 | "the binary c14n transforms are not supported yet", | |||
| 628 | XMLSEC_ERRORS_R_NOT_IMPLEMENTED9, | |||
| 629 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 630 | return(-1); | |||
| 631 | } | |||
| 632 | return(0); | |||
| 633 | } | |||
| 634 | ||||
| 635 | /** | |||
| 636 | * xmlSecDSigCtxProcessSignedInfoNode: | |||
| 637 | * | |||
| 638 | * The SignedInfo Element (http://www.w3.org/TR/xmldsig-core/#sec-SignedInfo) | |||
| 639 | * | |||
| 640 | * The structure of SignedInfo includes the canonicalization algorithm, | |||
| 641 | * a result algorithm, and one or more references. The SignedInfo element | |||
| 642 | * may contain an optional ID attribute that will allow it to be referenced by | |||
| 643 | * other signatures and objects. | |||
| 644 | * | |||
| 645 | * SignedInfo does not include explicit result or digest properties (such as | |||
| 646 | * calculation time, cryptographic device serial number, etc.). If an | |||
| 647 | * application needs to associate properties with the result or digest, | |||
| 648 | * it may include such information in a SignatureProperties element within | |||
| 649 | * an Object element. | |||
| 650 | * | |||
| 651 | * Schema Definition: | |||
| 652 | * | |||
| 653 | * <element name="SignedInfo" type="ds:SignedInfoType"/> | |||
| 654 | * <complexType name="SignedInfoType"> | |||
| 655 | * <sequence> | |||
| 656 | * <element ref="ds:CanonicalizationMethod"/> | |||
| 657 | * <element ref="ds:SignatureMethod"/> | |||
| 658 | * <element ref="ds:Reference" maxOccurs="unbounded"/> | |||
| 659 | * </sequence> | |||
| 660 | * <attribute name="Id" type="ID" use="optional"/> | |||
| 661 | * </complexType> | |||
| 662 | * | |||
| 663 | * DTD: | |||
| 664 | * | |||
| 665 | * <!ELEMENT SignedInfo (CanonicalizationMethod, SignatureMethod, Reference+) > | |||
| 666 | * <!ATTLIST SignedInfo Id ID #IMPLIED> | |||
| 667 | * | |||
| 668 | */ | |||
| 669 | static int | |||
| 670 | xmlSecDSigCtxProcessSignedInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) { | |||
| 671 | xmlSecDSigReferenceCtxPtr dsigRefCtx; | |||
| 672 | xmlNodePtr cur; | |||
| 673 | int ret; | |||
| 674 | ||||
| 675 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",675 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 676 | xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1)if(!( dsigCtx->status == xmlSecDSigStatusUnknown ) ) { xmlSecError ("xmldsig.c",676,__FUNCTION__, ((void*)0), "dsigCtx->status == xmlSecDSigStatusUnknown" , 100, " "); return(-1); }; | |||
| 677 | xmlSecAssert2(dsigCtx->signMethod == NULL, -1)if(!( dsigCtx->signMethod == ((void*)0) ) ) { xmlSecError( "xmldsig.c",677,__FUNCTION__, ((void*)0), "dsigCtx->signMethod == NULL" , 100, " "); return(-1); }; | |||
| 678 | xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1)if(!( dsigCtx->c14nMethod == ((void*)0) ) ) { xmlSecError( "xmldsig.c",678,__FUNCTION__, ((void*)0), "dsigCtx->c14nMethod == NULL" , 100, " "); return(-1); }; | |||
| 679 | xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1)if(!( (dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify) ) ) { xmlSecError("xmldsig.c",679,__FUNCTION__, ((void*)0), "(dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify)" , 100, " "); return(-1); }; | |||
| 680 | xmlSecAssert2(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0, -1)if(!( xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences )) == 0 ) ) { xmlSecError("xmldsig.c",680,__FUNCTION__, ((void *)0), "xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0" , 100, " "); return(-1); }; | |||
| 681 | xmlSecAssert2(node != NULL, -1)if(!( node != ((void*)0) ) ) { xmlSecError("xmldsig.c",681,__FUNCTION__ , ((void*)0), "node != NULL", 100, " "); return(-1); }; | |||
| 682 | ||||
| 683 | /* first node is required CanonicalizationMethod. */ | |||
| 684 | cur = xmlSecGetNextElementNode(node->children); | |||
| 685 | if((cur != NULL((void*)0)) && (xmlSecCheckNodeName(cur, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs))) { | |||
| ||||
| 686 | dsigCtx->c14nMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx), | |||
| 687 | cur, xmlSecTransformUsageC14NMethod0x0002); | |||
| 688 | if(dsigCtx->c14nMethod == NULL((void*)0)) { | |||
| 689 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",689,__FUNCTION__, | |||
| 690 | NULL((void*)0), | |||
| 691 | "xmlSecTransformCtxNodeRead", | |||
| 692 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 693 | "node=%s", | |||
| 694 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL")); | |||
| 695 | return(-1); | |||
| 696 | } | |||
| 697 | } else if(dsigCtx->defC14NMethodId != xmlSecTransformIdUnknown((xmlSecTransformId)((void*)0))) { | |||
| 698 | /* the dsig spec does require CanonicalizationMethod node | |||
| 699 | * to be present but in some case it application might decide to | |||
| 700 | * minimize traffic */ | |||
| 701 | dsigCtx->c14nMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), | |||
| 702 | dsigCtx->defC14NMethodId); | |||
| 703 | if(dsigCtx->c14nMethod == NULL((void*)0)) { | |||
| 704 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",704,__FUNCTION__, | |||
| 705 | NULL((void*)0), | |||
| 706 | "xmlSecTransformCtxAppend", | |||
| 707 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 708 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 709 | return(-1); | |||
| 710 | } | |||
| 711 | } else { | |||
| 712 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",712,__FUNCTION__, | |||
| 713 | NULL((void*)0), | |||
| 714 | "CanonicalizationMethod", | |||
| 715 | XMLSEC_ERRORS_R_INVALID_NODE21, | |||
| 716 | "expected=%s", | |||
| 717 | xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod)(((xmlSecNodeCanonicalizationMethod) != ((void*)0)) ? ((char* )(xmlSecNodeCanonicalizationMethod)) : (char*)"NULL")); | |||
| 718 | return(-1); | |||
| 719 | } | |||
| 720 | ||||
| 721 | /* insert membuf if requested */ | |||
| 722 | if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE0x00000008) != 0) { | |||
| 723 | xmlSecAssert2(dsigCtx->preSignMemBufMethod == NULL, -1)if(!( dsigCtx->preSignMemBufMethod == ((void*)0) ) ) { xmlSecError ("xmldsig.c",723,__FUNCTION__, ((void*)0), "dsigCtx->preSignMemBufMethod == NULL" , 100, " "); return(-1); }; | |||
| 724 | dsigCtx->preSignMemBufMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), | |||
| 725 | xmlSecTransformMemBufIdxmlSecTransformMemBufGetKlass()); | |||
| 726 | if(dsigCtx->preSignMemBufMethod == NULL((void*)0)) { | |||
| 727 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",727,__FUNCTION__, | |||
| 728 | NULL((void*)0), | |||
| 729 | "xmlSecTransformCtxCreateAndAppend", | |||
| 730 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 731 | "transform=%s", | |||
| 732 | xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId))((((((xmlSecTransformMemBufGetKlass())) ? ((xmlSecTransformMemBufGetKlass ())->name) : ((void*)0))) != ((void*)0)) ? ((char*)((((xmlSecTransformMemBufGetKlass ())) ? ((xmlSecTransformMemBufGetKlass())->name) : ((void* )0)))) : (char*)"NULL")); | |||
| 733 | } | |||
| 734 | } | |||
| 735 | ||||
| 736 | /* next node is required SignatureMethod. */ | |||
| 737 | cur = xmlSecGetNextElementNode( ((cur != NULL((void*)0)) ? cur->next : node->children) ); | |||
| 738 | if((cur != NULL((void*)0)) && (xmlSecCheckNodeName(cur, xmlSecNodeSignatureMethod, xmlSecDSigNs))) { | |||
| 739 | dsigCtx->signMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx), | |||
| 740 | cur, xmlSecTransformUsageSignatureMethod0x0008); | |||
| 741 | if(dsigCtx->signMethod == NULL((void*)0)) { | |||
| 742 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",742,__FUNCTION__, | |||
| 743 | NULL((void*)0), | |||
| 744 | "xmlSecTransformCtxNodeRead", | |||
| 745 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 746 | "node=%s", | |||
| 747 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL")); | |||
| 748 | return(-1); | |||
| 749 | } | |||
| 750 | } else if(dsigCtx->defSignMethodId != xmlSecTransformIdUnknown((xmlSecTransformId)((void*)0))) { | |||
| 751 | /* the dsig spec does require SignatureMethod node | |||
| 752 | * to be present but in some case it application might decide to | |||
| 753 | * minimize traffic */ | |||
| 754 | dsigCtx->signMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), | |||
| 755 | dsigCtx->defSignMethodId); | |||
| 756 | if(dsigCtx->signMethod == NULL((void*)0)) { | |||
| 757 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",757,__FUNCTION__, | |||
| 758 | NULL((void*)0), | |||
| 759 | "xmlSecTransformCtxAppend", | |||
| 760 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 761 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 762 | return(-1); | |||
| 763 | } | |||
| 764 | } else { | |||
| 765 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",765,__FUNCTION__, | |||
| 766 | NULL((void*)0), | |||
| 767 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL"), | |||
| 768 | XMLSEC_ERRORS_R_INVALID_NODE21, | |||
| 769 | "expected=%s", | |||
| 770 | xmlSecErrorsSafeString(xmlSecNodeSignatureMethod)(((xmlSecNodeSignatureMethod) != ((void*)0)) ? ((char*)(xmlSecNodeSignatureMethod )) : (char*)"NULL")); | |||
| 771 | return(-1); | |||
| 772 | } | |||
| 773 | dsigCtx->signMethod->operation = dsigCtx->operation; | |||
| 774 | ||||
| 775 | /* calculate references */ | |||
| 776 | cur = xmlSecGetNextElementNode(cur->next); | |||
| ||||
| 777 | while((cur != NULL((void*)0)) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) { | |||
| 778 | /* create reference */ | |||
| 779 | dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginSignedInfo); | |||
| 780 | if(dsigRefCtx == NULL((void*)0)) { | |||
| 781 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",781,__FUNCTION__, | |||
| 782 | NULL((void*)0), | |||
| 783 | "xmlSecDSigReferenceCtxCreate", | |||
| 784 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 785 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 786 | return(-1); | |||
| 787 | } | |||
| 788 | ||||
| 789 | /* add to the list */ | |||
| 790 | ret = xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx); | |||
| 791 | if(ret < 0) { | |||
| 792 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",792,__FUNCTION__, | |||
| 793 | NULL((void*)0), | |||
| 794 | "xmlSecPtrListAdd", | |||
| 795 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 796 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 797 | xmlSecDSigReferenceCtxDestroy(dsigRefCtx); | |||
| 798 | return(-1); | |||
| 799 | } | |||
| 800 | ||||
| 801 | /* process */ | |||
| 802 | ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur); | |||
| 803 | if(ret < 0) { | |||
| 804 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",804,__FUNCTION__, | |||
| 805 | NULL((void*)0), | |||
| 806 | "xmlSecDSigReferenceCtxProcessNode", | |||
| 807 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 808 | "node=%s", | |||
| 809 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL")); | |||
| 810 | return(-1); | |||
| 811 | } | |||
| 812 | ||||
| 813 | /* bail out if next Reference processing failed */ | |||
| 814 | if(dsigRefCtx->status != xmlSecDSigStatusSucceeded) { | |||
| 815 | dsigCtx->status = xmlSecDSigStatusInvalid; | |||
| 816 | return(0); | |||
| 817 | } | |||
| 818 | cur = xmlSecGetNextElementNode(cur->next); | |||
| 819 | } | |||
| 820 | ||||
| 821 | /* check that we have at least one Reference */ | |||
| 822 | if(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0) { | |||
| 823 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",823,__FUNCTION__, | |||
| 824 | NULL((void*)0), | |||
| 825 | NULL((void*)0), | |||
| 826 | XMLSEC_ERRORS_R_DSIG_NO_REFERENCES81, | |||
| 827 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 828 | return(-1); | |||
| 829 | } | |||
| 830 | ||||
| 831 | /* if there is something left than it's an error */ | |||
| 832 | if(cur != NULL((void*)0)) { | |||
| 833 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",833,__FUNCTION__, | |||
| 834 | NULL((void*)0), | |||
| 835 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL"), | |||
| 836 | XMLSEC_ERRORS_R_UNEXPECTED_NODE27, | |||
| 837 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 838 | return(-1); | |||
| 839 | } | |||
| 840 | return(0); | |||
| 841 | } | |||
| 842 | ||||
| 843 | static int | |||
| 844 | xmlSecDSigCtxProcessKeyInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) { | |||
| 845 | int ret; | |||
| 846 | ||||
| 847 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",847 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 848 | xmlSecAssert2(dsigCtx->signMethod != NULL, -1)if(!( dsigCtx->signMethod != ((void*)0) ) ) { xmlSecError( "xmldsig.c",848,__FUNCTION__, ((void*)0), "dsigCtx->signMethod != NULL" , 100, " "); return(-1); }; | |||
| 849 | ||||
| 850 | /* set key requirements */ | |||
| 851 | ret = xmlSecTransformSetKeyReq(dsigCtx->signMethod, &(dsigCtx->keyInfoReadCtx.keyReq)); | |||
| 852 | if(ret < 0) { | |||
| 853 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",853,__FUNCTION__, | |||
| 854 | NULL((void*)0), | |||
| 855 | "xmlSecTransformSetKeyReq", | |||
| 856 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 857 | "transform=%s", | |||
| 858 | xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod))(((((((( (dsigCtx->signMethod) ) != ((void*)0)) && (( (dsigCtx->signMethod) )->id != ((void*)0)) && (( (dsigCtx->signMethod) )->id->klassSize >= sizeof (xmlSecTransformKlass)) && (( (dsigCtx->signMethod ) )->id->objSize >= sizeof(xmlSecTransform)) && (( (dsigCtx->signMethod) )->id->name != ((void*)0)) )) ? ((((dsigCtx->signMethod)->id)) ? (((dsigCtx->signMethod )->id)->name) : ((void*)0)) : ((void*)0))) != ((void*)0 )) ? ((char*)(((((( (dsigCtx->signMethod) ) != ((void*)0)) && (( (dsigCtx->signMethod) )->id != ((void*)0 )) && (( (dsigCtx->signMethod) )->id->klassSize >= sizeof(xmlSecTransformKlass)) && (( (dsigCtx-> signMethod) )->id->objSize >= sizeof(xmlSecTransform )) && (( (dsigCtx->signMethod) )->id->name != ((void*)0)))) ? ((((dsigCtx->signMethod)->id)) ? (((dsigCtx ->signMethod)->id)->name) : ((void*)0)) : ((void*)0) ))) : (char*)"NULL")); | |||
| 859 | return(-1); | |||
| 860 | } | |||
| 861 | ||||
| 862 | /* ignore <dsig:KeyInfo /> if there is the key is already set */ | |||
| 863 | /* todo: throw an error if key is set and node != NULL? */ | |||
| 864 | if((dsigCtx->signKey == NULL((void*)0)) && (dsigCtx->keyInfoReadCtx.keysMngr != NULL((void*)0)) | |||
| 865 | && (dsigCtx->keyInfoReadCtx.keysMngr->getKey != NULL((void*)0))) { | |||
| 866 | dsigCtx->signKey = (dsigCtx->keyInfoReadCtx.keysMngr->getKey)(node, &(dsigCtx->keyInfoReadCtx)); | |||
| 867 | } | |||
| 868 | ||||
| 869 | /* check that we have exactly what we want */ | |||
| 870 | if((dsigCtx->signKey == NULL((void*)0)) || (!xmlSecKeyMatch(dsigCtx->signKey, NULL((void*)0), &(dsigCtx->keyInfoReadCtx.keyReq)))) { | |||
| 871 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",871,__FUNCTION__, | |||
| 872 | NULL((void*)0), | |||
| 873 | NULL((void*)0), | |||
| 874 | XMLSEC_ERRORS_R_KEY_NOT_FOUND45, | |||
| 875 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 876 | return(-1); | |||
| 877 | } | |||
| 878 | ||||
| 879 | /* set the key to the transform */ | |||
| 880 | ret = xmlSecTransformSetKey(dsigCtx->signMethod, dsigCtx->signKey); | |||
| 881 | if(ret < 0) { | |||
| 882 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",882,__FUNCTION__, | |||
| 883 | NULL((void*)0), | |||
| 884 | "xmlSecTransformSetKey", | |||
| 885 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 886 | "transform=%s", | |||
| 887 | xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod))(((((((( (dsigCtx->signMethod) ) != ((void*)0)) && (( (dsigCtx->signMethod) )->id != ((void*)0)) && (( (dsigCtx->signMethod) )->id->klassSize >= sizeof (xmlSecTransformKlass)) && (( (dsigCtx->signMethod ) )->id->objSize >= sizeof(xmlSecTransform)) && (( (dsigCtx->signMethod) )->id->name != ((void*)0)) )) ? ((((dsigCtx->signMethod)->id)) ? (((dsigCtx->signMethod )->id)->name) : ((void*)0)) : ((void*)0))) != ((void*)0 )) ? ((char*)(((((( (dsigCtx->signMethod) ) != ((void*)0)) && (( (dsigCtx->signMethod) )->id != ((void*)0 )) && (( (dsigCtx->signMethod) )->id->klassSize >= sizeof(xmlSecTransformKlass)) && (( (dsigCtx-> signMethod) )->id->objSize >= sizeof(xmlSecTransform )) && (( (dsigCtx->signMethod) )->id->name != ((void*)0)))) ? ((((dsigCtx->signMethod)->id)) ? (((dsigCtx ->signMethod)->id)->name) : ((void*)0)) : ((void*)0) ))) : (char*)"NULL")); | |||
| 888 | return(-1); | |||
| 889 | } | |||
| 890 | ||||
| 891 | /* if we are signing document, update <dsig:KeyInfo/> node */ | |||
| 892 | if((node != NULL((void*)0)) && (dsigCtx->operation == xmlSecTransformOperationSign)) { | |||
| 893 | ret = xmlSecKeyInfoNodeWrite(node, dsigCtx->signKey, &(dsigCtx->keyInfoWriteCtx)); | |||
| 894 | if(ret < 0) { | |||
| 895 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",895,__FUNCTION__, | |||
| 896 | NULL((void*)0), | |||
| 897 | "xmlSecKeyInfoNodeWrite", | |||
| 898 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 899 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 900 | return(-1); | |||
| 901 | } | |||
| 902 | } | |||
| 903 | ||||
| 904 | return(0); | |||
| 905 | } | |||
| 906 | ||||
| 907 | /** | |||
| 908 | * xmlSecDSigCtxProcessObjectNode: | |||
| 909 | * | |||
| 910 | * The Object Element (http://www.w3.org/TR/xmldsig-core/#sec-Object) | |||
| 911 | * | |||
| 912 | * Object is an optional element that may occur one or more times. When | |||
| 913 | * present, this element may contain any data. The Object element may include | |||
| 914 | * optional MIME type, ID, and encoding attributes. | |||
| 915 | * | |||
| 916 | * Schema Definition: | |||
| 917 | * | |||
| 918 | * <element name="Object" type="ds:ObjectType"/> | |||
| 919 | * <complexType name="ObjectType" mixed="true"> | |||
| 920 | * <sequence minOccurs="0" maxOccurs="unbounded"> | |||
| 921 | * <any namespace="##any" processContents="lax"/> | |||
| 922 | * </sequence> | |||
| 923 | * <attribute name="Id" type="ID" use="optional"/> | |||
| 924 | * <attribute name="MimeType" type="string" use="optional"/> | |||
| 925 | * <attribute name="Encoding" type="anyURI" use="optional"/> | |||
| 926 | * </complexType> | |||
| 927 | * | |||
| 928 | * DTD: | |||
| 929 | * | |||
| 930 | * <!ELEMENT Object (#PCDATA|Signature|SignatureProperties|Manifest %Object.ANY;)* > | |||
| 931 | * <!ATTLIST Object Id ID #IMPLIED | |||
| 932 | * MimeType CDATA #IMPLIED | |||
| 933 | * Encoding CDATA #IMPLIED > | |||
| 934 | */ | |||
| 935 | static int | |||
| 936 | xmlSecDSigCtxProcessObjectNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) { | |||
| 937 | xmlNodePtr cur; | |||
| 938 | int ret; | |||
| 939 | ||||
| 940 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",940 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 941 | xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1)if(!( dsigCtx->status == xmlSecDSigStatusUnknown ) ) { xmlSecError ("xmldsig.c",941,__FUNCTION__, ((void*)0), "dsigCtx->status == xmlSecDSigStatusUnknown" , 100, " "); return(-1); }; | |||
| 942 | xmlSecAssert2(node != NULL, -1)if(!( node != ((void*)0) ) ) { xmlSecError("xmldsig.c",942,__FUNCTION__ , ((void*)0), "node != NULL", 100, " "); return(-1); }; | |||
| 943 | ||||
| 944 | /* we care about Manifest nodes only; ignore everything else */ | |||
| 945 | cur = xmlSecGetNextElementNode(node->children); | |||
| 946 | while(cur != NULL((void*)0)) { | |||
| 947 | if(xmlSecCheckNodeName(cur, xmlSecNodeManifest, xmlSecDSigNs)) { | |||
| 948 | ret = xmlSecDSigCtxProcessManifestNode(dsigCtx, cur); | |||
| 949 | if(ret < 0){ | |||
| 950 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",950,__FUNCTION__, | |||
| 951 | NULL((void*)0), | |||
| 952 | "xmlSecDSigCtxProcessManifestNode", | |||
| 953 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 954 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 955 | return(-1); | |||
| 956 | } | |||
| 957 | } | |||
| 958 | cur = xmlSecGetNextElementNode(cur->next); | |||
| 959 | } | |||
| 960 | return(0); | |||
| 961 | } | |||
| 962 | ||||
| 963 | /** | |||
| 964 | * xmlSecDSigCtxProcessManifestNode: | |||
| 965 | * | |||
| 966 | * The Manifest Element (http://www.w3.org/TR/xmldsig-core/#sec-Manifest) | |||
| 967 | * | |||
| 968 | * The Manifest element provides a list of References. The difference from | |||
| 969 | * the list in SignedInfo is that it is application defined which, if any, of | |||
| 970 | * the digests are actually checked against the objects referenced and what to | |||
| 971 | * do if the object is inaccessible or the digest compare fails. If a Manifest | |||
| 972 | * is pointed to from SignedInfo, the digest over the Manifest itself will be | |||
| 973 | * checked by the core result validation behavior. The digests within such | |||
| 974 | * a Manifest are checked at the application's discretion. If a Manifest is | |||
| 975 | * referenced from another Manifest, even the overall digest of this two level | |||
| 976 | * deep Manifest might not be checked. | |||
| 977 | * | |||
| 978 | * Schema Definition: | |||
| 979 | * | |||
| 980 | * <element name="Manifest" type="ds:ManifestType"/> | |||
| 981 | * <complexType name="ManifestType"> | |||
| 982 | * <sequence> | |||
| 983 | * <element ref="ds:Reference" maxOccurs="unbounded"/> | |||
| 984 | * </sequence> | |||
| 985 | * <attribute name="Id" type="ID" use="optional"/> | |||
| 986 | * </complexType> | |||
| 987 | * | |||
| 988 | * DTD: | |||
| 989 | * | |||
| 990 | * <!ELEMENT Manifest (Reference+) > | |||
| 991 | * <!ATTLIST Manifest Id ID #IMPLIED > | |||
| 992 | */ | |||
| 993 | static int | |||
| 994 | xmlSecDSigCtxProcessManifestNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) { | |||
| 995 | xmlSecDSigReferenceCtxPtr dsigRefCtx; | |||
| 996 | xmlNodePtr cur; | |||
| 997 | int ret; | |||
| 998 | ||||
| 999 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",999 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 1000 | xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1)if(!( dsigCtx->status == xmlSecDSigStatusUnknown ) ) { xmlSecError ("xmldsig.c",1000,__FUNCTION__, ((void*)0), "dsigCtx->status == xmlSecDSigStatusUnknown" , 100, " "); return(-1); }; | |||
| 1001 | xmlSecAssert2(node != NULL, -1)if(!( node != ((void*)0) ) ) { xmlSecError("xmldsig.c",1001,__FUNCTION__ , ((void*)0), "node != NULL", 100, " "); return(-1); }; | |||
| 1002 | ||||
| 1003 | /* calculate references */ | |||
| 1004 | cur = xmlSecGetNextElementNode(node->children); | |||
| 1005 | while((cur != NULL((void*)0)) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) { | |||
| 1006 | /* create reference */ | |||
| 1007 | dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginManifest); | |||
| 1008 | if(dsigRefCtx == NULL((void*)0)) { | |||
| 1009 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1009,__FUNCTION__, | |||
| 1010 | NULL((void*)0), | |||
| 1011 | "xmlSecDSigReferenceCtxCreate", | |||
| 1012 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1013 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1014 | return(-1); | |||
| 1015 | } | |||
| 1016 | ||||
| 1017 | /* add to the list */ | |||
| 1018 | ret = xmlSecPtrListAdd(&(dsigCtx->manifestReferences), dsigRefCtx); | |||
| 1019 | if(ret < 0) { | |||
| 1020 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1020,__FUNCTION__, | |||
| 1021 | NULL((void*)0), | |||
| 1022 | "xmlSecPtrListAdd", | |||
| 1023 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1024 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1025 | xmlSecDSigReferenceCtxDestroy(dsigRefCtx); | |||
| 1026 | return(-1); | |||
| 1027 | } | |||
| 1028 | ||||
| 1029 | /* process */ | |||
| 1030 | ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur); | |||
| 1031 | if(ret < 0) { | |||
| 1032 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1032,__FUNCTION__, | |||
| 1033 | NULL((void*)0), | |||
| 1034 | "xmlSecDSigReferenceCtxProcessNode", | |||
| 1035 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1036 | "node=%s", | |||
| 1037 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL")); | |||
| 1038 | return(-1); | |||
| 1039 | } | |||
| 1040 | ||||
| 1041 | /* we don;t care if Reference processing failed because | |||
| 1042 | * it's Manifest node */ | |||
| 1043 | cur = xmlSecGetNextElementNode(cur->next); | |||
| 1044 | } | |||
| 1045 | ||||
| 1046 | /* we should have nothing else here */ | |||
| 1047 | if(cur != NULL((void*)0)) { | |||
| 1048 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1048,__FUNCTION__, | |||
| 1049 | NULL((void*)0), | |||
| 1050 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL"), | |||
| 1051 | XMLSEC_ERRORS_R_UNEXPECTED_NODE27, | |||
| 1052 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1053 | return(-1); | |||
| 1054 | } | |||
| 1055 | return(0); | |||
| 1056 | } | |||
| 1057 | ||||
| 1058 | /** | |||
| 1059 | * xmlSecDSigCtxDebugDump: | |||
| 1060 | * @dsigCtx: the pointer to <dsig:Signature/> processing context. | |||
| 1061 | * @output: the pointer to output FILE. | |||
| 1062 | * | |||
| 1063 | * Prints the debug information about @dsigCtx to @output. | |||
| 1064 | */ | |||
| 1065 | void | |||
| 1066 | xmlSecDSigCtxDebugDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) { | |||
| 1067 | xmlSecAssert(dsigCtx != NULL)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",1067 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return ; }; | |||
| 1068 | xmlSecAssert(output != NULL)if(!( output != ((void*)0) ) ) { xmlSecError("xmldsig.c",1068 ,__FUNCTION__, ((void*)0), "output != NULL", 100, " "); return ; }; | |||
| 1069 | ||||
| 1070 | if(dsigCtx->operation == xmlSecTransformOperationSign) { | |||
| 1071 | fprintf(output, "= SIGNATURE CONTEXT\n"); | |||
| 1072 | } else { | |||
| 1073 | fprintf(output, "= VERIFICATION CONTEXT\n"); | |||
| 1074 | } | |||
| 1075 | switch(dsigCtx->status) { | |||
| 1076 | case xmlSecDSigStatusUnknown: | |||
| 1077 | fprintf(output, "== Status: unknown\n"); | |||
| 1078 | break; | |||
| 1079 | case xmlSecDSigStatusSucceeded: | |||
| 1080 | fprintf(output, "== Status: succeeded\n"); | |||
| 1081 | break; | |||
| 1082 | case xmlSecDSigStatusInvalid: | |||
| 1083 | fprintf(output, "== Status: invalid\n"); | |||
| 1084 | break; | |||
| 1085 | } | |||
| 1086 | fprintf(output, "== flags: 0x%08x\n", dsigCtx->flags); | |||
| 1087 | fprintf(output, "== flags2: 0x%08x\n", dsigCtx->flags2); | |||
| 1088 | ||||
| 1089 | if(dsigCtx->id != NULL((void*)0)) { | |||
| 1090 | fprintf(output, "== Id: \"%s\"\n", dsigCtx->id); | |||
| 1091 | } | |||
| 1092 | ||||
| 1093 | fprintf(output, "== Key Info Read Ctx:\n"); | |||
| 1094 | xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoReadCtx), output); | |||
| 1095 | fprintf(output, "== Key Info Write Ctx:\n"); | |||
| 1096 | xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoWriteCtx), output); | |||
| 1097 | ||||
| 1098 | fprintf(output, "== Signature Transform Ctx:\n"); | |||
| 1099 | xmlSecTransformCtxDebugDump(&(dsigCtx->transformCtx), output); | |||
| 1100 | ||||
| 1101 | if(dsigCtx->signMethod != NULL((void*)0)) { | |||
| 1102 | fprintf(output, "== Signature Method:\n"); | |||
| 1103 | xmlSecTransformDebugDump(dsigCtx->signMethod, output); | |||
| 1104 | } | |||
| 1105 | ||||
| 1106 | if(dsigCtx->signKey != NULL((void*)0)) { | |||
| 1107 | fprintf(output, "== Signature Key:\n"); | |||
| 1108 | xmlSecKeyDebugDump(dsigCtx->signKey, output); | |||
| 1109 | } | |||
| 1110 | ||||
| 1111 | fprintf(output, "== SignedInfo References List:\n"); | |||
| 1112 | xmlSecPtrListDebugDump(&(dsigCtx->signedInfoReferences), output); | |||
| 1113 | ||||
| 1114 | fprintf(output, "== Manifest References List:\n"); | |||
| 1115 | xmlSecPtrListDebugDump(&(dsigCtx->manifestReferences), output); | |||
| 1116 | ||||
| 1117 | if((dsigCtx->result != NULL((void*)0)) && | |||
| 1118 | (xmlSecBufferGetData(dsigCtx->result) != NULL((void*)0))) { | |||
| 1119 | ||||
| 1120 | fprintf(output, "== Result - start buffer:\n"); | |||
| 1121 | fwrite(xmlSecBufferGetData(dsigCtx->result), | |||
| 1122 | xmlSecBufferGetSize(dsigCtx->result), | |||
| 1123 | 1, output); | |||
| 1124 | fprintf(output, "\n== Result - end buffer\n"); | |||
| 1125 | } | |||
| 1126 | if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE0x00000008) != 0) && | |||
| 1127 | (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL((void*)0)) && | |||
| 1128 | (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL((void*)0))) { | |||
| 1129 | ||||
| 1130 | fprintf(output, "== PreSigned data - start buffer:\n"); | |||
| 1131 | fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), | |||
| 1132 | xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), | |||
| 1133 | 1, output); | |||
| 1134 | fprintf(output, "\n== PreSigned data - end buffer\n"); | |||
| 1135 | } | |||
| 1136 | } | |||
| 1137 | ||||
| 1138 | /** | |||
| 1139 | * xmlSecDSigCtxDebugXmlDump: | |||
| 1140 | * @dsigCtx: the pointer to <dsig:Signature/> processing context. | |||
| 1141 | * @output: the pointer to output FILE. | |||
| 1142 | * | |||
| 1143 | * Prints the debug information about @dsigCtx to @output in XML format. | |||
| 1144 | */ | |||
| 1145 | void | |||
| 1146 | xmlSecDSigCtxDebugXmlDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) { | |||
| 1147 | xmlSecAssert(dsigCtx != NULL)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",1147 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return ; }; | |||
| 1148 | xmlSecAssert(output != NULL)if(!( output != ((void*)0) ) ) { xmlSecError("xmldsig.c",1148 ,__FUNCTION__, ((void*)0), "output != NULL", 100, " "); return ; }; | |||
| 1149 | ||||
| 1150 | if(dsigCtx->operation == xmlSecTransformOperationSign) { | |||
| 1151 | fprintf(output, "<SignatureContext \n"); | |||
| 1152 | } else { | |||
| 1153 | fprintf(output, "<VerificationContext \n"); | |||
| 1154 | } | |||
| 1155 | switch(dsigCtx->status) { | |||
| 1156 | case xmlSecDSigStatusUnknown: | |||
| 1157 | fprintf(output, "status=\"unknown\" >\n"); | |||
| 1158 | break; | |||
| 1159 | case xmlSecDSigStatusSucceeded: | |||
| 1160 | fprintf(output, "status=\"succeeded\" >\n"); | |||
| 1161 | break; | |||
| 1162 | case xmlSecDSigStatusInvalid: | |||
| 1163 | fprintf(output, "status=\"invalid\" >\n"); | |||
| 1164 | break; | |||
| 1165 | } | |||
| 1166 | ||||
| 1167 | fprintf(output, "<Flags>%08x</Flags>\n", dsigCtx->flags); | |||
| 1168 | fprintf(output, "<Flags2>%08x</Flags2>\n", dsigCtx->flags2); | |||
| 1169 | ||||
| 1170 | fprintf(output, "<Id>"); | |||
| 1171 | xmlSecPrintXmlString(output, dsigCtx->id); | |||
| 1172 | fprintf(output, "</Id>\n"); | |||
| 1173 | ||||
| 1174 | fprintf(output, "<KeyInfoReadCtx>\n"); | |||
| 1175 | xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoReadCtx), output); | |||
| 1176 | fprintf(output, "</KeyInfoReadCtx>\n"); | |||
| 1177 | ||||
| 1178 | fprintf(output, "<KeyInfoWriteCtx>\n"); | |||
| 1179 | xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoWriteCtx), output); | |||
| 1180 | fprintf(output, "</KeyInfoWriteCtx>\n"); | |||
| 1181 | ||||
| 1182 | fprintf(output, "<SignatureTransformCtx>\n"); | |||
| 1183 | xmlSecTransformCtxDebugXmlDump(&(dsigCtx->transformCtx), output); | |||
| 1184 | fprintf(output, "</SignatureTransformCtx>\n"); | |||
| 1185 | ||||
| 1186 | if(dsigCtx->signMethod != NULL((void*)0)) { | |||
| 1187 | fprintf(output, "<SignatureMethod>\n"); | |||
| 1188 | xmlSecTransformDebugXmlDump(dsigCtx->signMethod, output); | |||
| 1189 | fprintf(output, "</SignatureMethod>\n"); | |||
| 1190 | } | |||
| 1191 | ||||
| 1192 | if(dsigCtx->signKey != NULL((void*)0)) { | |||
| 1193 | fprintf(output, "<SignatureKey>\n"); | |||
| 1194 | xmlSecKeyDebugXmlDump(dsigCtx->signKey, output); | |||
| 1195 | fprintf(output, "</SignatureKey>\n"); | |||
| 1196 | } | |||
| 1197 | ||||
| 1198 | fprintf(output, "<SignedInfoReferences>\n"); | |||
| 1199 | xmlSecPtrListDebugXmlDump(&(dsigCtx->signedInfoReferences), output); | |||
| 1200 | fprintf(output, "</SignedInfoReferences>\n"); | |||
| 1201 | ||||
| 1202 | fprintf(output, "<ManifestReferences>\n"); | |||
| 1203 | xmlSecPtrListDebugXmlDump(&(dsigCtx->manifestReferences), output); | |||
| 1204 | fprintf(output, "</ManifestReferences>\n"); | |||
| 1205 | ||||
| 1206 | if((dsigCtx->result != NULL((void*)0)) && | |||
| 1207 | (xmlSecBufferGetData(dsigCtx->result) != NULL((void*)0))) { | |||
| 1208 | ||||
| 1209 | fprintf(output, "<Result>"); | |||
| 1210 | fwrite(xmlSecBufferGetData(dsigCtx->result), | |||
| 1211 | xmlSecBufferGetSize(dsigCtx->result), | |||
| 1212 | 1, output); | |||
| 1213 | fprintf(output, "</Result>\n"); | |||
| 1214 | } | |||
| 1215 | if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE0x00000008) != 0) && | |||
| 1216 | (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL((void*)0)) && | |||
| 1217 | (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL((void*)0))) { | |||
| 1218 | ||||
| 1219 | fprintf(output, "<PreSignedData>"); | |||
| 1220 | fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), | |||
| 1221 | xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), | |||
| 1222 | 1, output); | |||
| 1223 | fprintf(output, "</PreSignedData>\n"); | |||
| 1224 | } | |||
| 1225 | ||||
| 1226 | if(dsigCtx->operation == xmlSecTransformOperationSign) { | |||
| 1227 | fprintf(output, "</SignatureContext>\n"); | |||
| 1228 | } else { | |||
| 1229 | fprintf(output, "</VerificationContext>\n"); | |||
| 1230 | } | |||
| 1231 | } | |||
| 1232 | ||||
| 1233 | /************************************************************************** | |||
| 1234 | * | |||
| 1235 | * xmlSecDSigReferenceCtx | |||
| 1236 | * | |||
| 1237 | *************************************************************************/ | |||
| 1238 | /** | |||
| 1239 | * xmlSecDSigReferenceCtxCreate: | |||
| 1240 | * @dsigCtx: the pointer to parent <dsig:Signature/> node processing context. | |||
| 1241 | * @origin: the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node). | |||
| 1242 | * | |||
| 1243 | * Creates new <dsig:Reference/> element processing context. Caller is responsible | |||
| 1244 | * for destroying the returned context by calling #xmlSecDSigReferenceCtxDestroy | |||
| 1245 | * function. | |||
| 1246 | * | |||
| 1247 | * Returns: pointer to newly created context or NULL if an error occurs. | |||
| 1248 | */ | |||
| 1249 | xmlSecDSigReferenceCtxPtr | |||
| 1250 | xmlSecDSigReferenceCtxCreate(xmlSecDSigCtxPtr dsigCtx, xmlSecDSigReferenceOrigin origin) { | |||
| 1251 | xmlSecDSigReferenceCtxPtr dsigRefCtx; | |||
| 1252 | int ret; | |||
| 1253 | ||||
| 1254 | xmlSecAssert2(dsigCtx != NULL, NULL)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",1254 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (((void*)0)); }; | |||
| 1255 | ||||
| 1256 | dsigRefCtx = (xmlSecDSigReferenceCtxPtr) xmlMalloc(sizeof(xmlSecDSigReferenceCtx)); | |||
| 1257 | if(dsigRefCtx == NULL((void*)0)) { | |||
| 1258 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1258,__FUNCTION__, | |||
| 1259 | NULL((void*)0), | |||
| 1260 | NULL((void*)0), | |||
| 1261 | XMLSEC_ERRORS_R_MALLOC_FAILED2, | |||
| 1262 | "sizeof(xmlSecDSigReferenceCtx)=%d", | |||
| 1263 | sizeof(xmlSecDSigReferenceCtx)); | |||
| 1264 | return(NULL((void*)0)); | |||
| 1265 | } | |||
| 1266 | ||||
| 1267 | ret = xmlSecDSigReferenceCtxInitialize(dsigRefCtx, dsigCtx, origin); | |||
| 1268 | if(ret < 0) { | |||
| 1269 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1269,__FUNCTION__, | |||
| 1270 | NULL((void*)0), | |||
| 1271 | "xmlSecDSigReferenceCtxInitialize", | |||
| 1272 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1273 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1274 | xmlSecDSigReferenceCtxDestroy(dsigRefCtx); | |||
| 1275 | return(NULL((void*)0)); | |||
| 1276 | } | |||
| 1277 | return(dsigRefCtx); | |||
| 1278 | } | |||
| 1279 | ||||
| 1280 | /** | |||
| 1281 | * xmlSecDSigReferenceCtxDestroy: | |||
| 1282 | * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context. | |||
| 1283 | * | |||
| 1284 | * Destroy context object created with #xmlSecDSigReferenceCtxCreate function. | |||
| 1285 | */ | |||
| 1286 | void | |||
| 1287 | xmlSecDSigReferenceCtxDestroy(xmlSecDSigReferenceCtxPtr dsigRefCtx) { | |||
| 1288 | xmlSecAssert(dsigRefCtx != NULL)if(!( dsigRefCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c", 1288,__FUNCTION__, ((void*)0), "dsigRefCtx != NULL", 100, " " ); return; }; | |||
| 1289 | ||||
| 1290 | xmlSecDSigReferenceCtxFinalize(dsigRefCtx); | |||
| 1291 | xmlFree(dsigRefCtx); | |||
| 1292 | } | |||
| 1293 | ||||
| 1294 | /** | |||
| 1295 | * xmlSecDSigReferenceCtxInitialize: | |||
| 1296 | * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context. | |||
| 1297 | * @dsigCtx: the pointer to parent <dsig:Signature/> node processing context. | |||
| 1298 | * @origin: the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node). | |||
| 1299 | * | |||
| 1300 | * Initializes new <dsig:Reference/> element processing context. Caller is responsible | |||
| 1301 | * for cleaning up the returned context by calling #xmlSecDSigReferenceCtxFinalize | |||
| 1302 | * function. | |||
| 1303 | * | |||
| 1304 | * Returns: 0 on succes or aa negative value otherwise. | |||
| 1305 | */ | |||
| 1306 | int | |||
| 1307 | xmlSecDSigReferenceCtxInitialize(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlSecDSigCtxPtr dsigCtx, | |||
| 1308 | xmlSecDSigReferenceOrigin origin) { | |||
| 1309 | int ret; | |||
| 1310 | ||||
| 1311 | xmlSecAssert2(dsigCtx != NULL, -1)if(!( dsigCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c",1311 ,__FUNCTION__, ((void*)0), "dsigCtx != NULL", 100, " "); return (-1); }; | |||
| 1312 | xmlSecAssert2(dsigRefCtx != NULL, -1)if(!( dsigRefCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c", 1312,__FUNCTION__, ((void*)0), "dsigRefCtx != NULL", 100, " " ); return(-1); }; | |||
| 1313 | ||||
| 1314 | memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx)); | |||
| 1315 | ||||
| 1316 | dsigRefCtx->dsigCtx = dsigCtx; | |||
| 1317 | dsigRefCtx->origin = origin; | |||
| 1318 | ||||
| 1319 | /* initializes transforms dsigRefCtx */ | |||
| 1320 | ret = xmlSecTransformCtxInitialize(&(dsigRefCtx->transformCtx)); | |||
| 1321 | if(ret < 0) { | |||
| 1322 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1322,__FUNCTION__, | |||
| 1323 | NULL((void*)0), | |||
| 1324 | "xmlSecTransformCtxInitialize", | |||
| 1325 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1326 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1327 | return(-1); | |||
| 1328 | } | |||
| 1329 | ||||
| 1330 | /* copy enabled transforms */ | |||
| 1331 | if(dsigCtx->enabledReferenceTransforms != NULL((void*)0)) { | |||
| 1332 | ret = xmlSecPtrListCopy(&(dsigRefCtx->transformCtx.enabledTransforms), | |||
| 1333 | dsigCtx->enabledReferenceTransforms); | |||
| 1334 | if(ret < 0) { | |||
| 1335 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1335,__FUNCTION__, | |||
| 1336 | NULL((void*)0), | |||
| 1337 | "xmlSecPtrListCopy", | |||
| 1338 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1339 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1340 | return(-1); | |||
| 1341 | } | |||
| 1342 | } | |||
| 1343 | dsigRefCtx->transformCtx.preExecCallback = dsigCtx->referencePreExecuteCallback; | |||
| 1344 | dsigRefCtx->transformCtx.enabledUris = dsigCtx->enabledReferenceUris; | |||
| 1345 | ||||
| 1346 | if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_USE_VISA3D_HACK0x00000010) != 0) { | |||
| 1347 | dsigRefCtx->transformCtx.flags |= XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK0x00000001; | |||
| 1348 | } | |||
| 1349 | return(0); | |||
| 1350 | } | |||
| 1351 | ||||
| 1352 | /** | |||
| 1353 | * xmlSecDSigReferenceCtxFinalize: | |||
| 1354 | * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context. | |||
| 1355 | * | |||
| 1356 | * Cleans up context object created with #xmlSecDSigReferenceCtxInitialize function. | |||
| 1357 | */ | |||
| 1358 | void | |||
| 1359 | xmlSecDSigReferenceCtxFinalize(xmlSecDSigReferenceCtxPtr dsigRefCtx) { | |||
| 1360 | xmlSecAssert(dsigRefCtx != NULL)if(!( dsigRefCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c", 1360,__FUNCTION__, ((void*)0), "dsigRefCtx != NULL", 100, " " ); return; }; | |||
| 1361 | ||||
| 1362 | xmlSecTransformCtxFinalize(&(dsigRefCtx->transformCtx)); | |||
| 1363 | if(dsigRefCtx->id != NULL((void*)0)) { | |||
| 1364 | xmlFree(dsigRefCtx->id); | |||
| 1365 | } | |||
| 1366 | if(dsigRefCtx->uri != NULL((void*)0)) { | |||
| 1367 | xmlFree(dsigRefCtx->uri); | |||
| 1368 | } | |||
| 1369 | if(dsigRefCtx->type != NULL((void*)0)) { | |||
| 1370 | xmlFree(dsigRefCtx->type); | |||
| 1371 | } | |||
| 1372 | memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx)); | |||
| 1373 | } | |||
| 1374 | ||||
| 1375 | /** | |||
| 1376 | * xmlSecDSigReferenceCtxGetPreDigestBuffer: | |||
| 1377 | * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context. | |||
| 1378 | * | |||
| 1379 | * Gets the results of <dsig:Reference/> node processing just before digesting | |||
| 1380 | * (valid only if #XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES or | |||
| 1381 | * #XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES flas of signature context | |||
| 1382 | * is set). | |||
| 1383 | * | |||
| 1384 | * Returns: pointer to the buffer or NULL if an error occurs. | |||
| 1385 | */ | |||
| 1386 | xmlSecBufferPtr | |||
| 1387 | xmlSecDSigReferenceCtxGetPreDigestBuffer(xmlSecDSigReferenceCtxPtr dsigRefCtx) { | |||
| 1388 | xmlSecAssert2(dsigRefCtx != NULL, NULL)if(!( dsigRefCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c", 1388,__FUNCTION__, ((void*)0), "dsigRefCtx != NULL", 100, " " ); return(((void*)0)); }; | |||
| 1389 | ||||
| 1390 | return((dsigRefCtx->preDigestMemBufMethod != NULL((void*)0)) ? | |||
| 1391 | xmlSecTransformMemBufGetBuffer(dsigRefCtx->preDigestMemBufMethod) : NULL((void*)0)); | |||
| 1392 | } | |||
| 1393 | ||||
| 1394 | /** | |||
| 1395 | * xmlSecDSigReferenceCtxProcessNode: | |||
| 1396 | * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context. | |||
| 1397 | * @node: the pointer to <dsig:Reference/> node. | |||
| 1398 | ||||
| 1399 | * The Reference Element (http://www.w3.org/TR/xmldsig-core/#sec-Reference) | |||
| 1400 | * | |||
| 1401 | * Reference is an element that may occur one or more times. It specifies | |||
| 1402 | * a digest algorithm and digest value, and optionally an identifier of the | |||
| 1403 | * object being signed, the type of the object, and/or a list of transforms | |||
| 1404 | * to be applied prior to digesting. The identification (URI) and transforms | |||
| 1405 | * describe how the digested content (i.e., the input to the digest method) | |||
| 1406 | * was created. The Type attribute facilitates the processing of referenced | |||
| 1407 | * data. For example, while this specification makes no requirements over | |||
| 1408 | * external data, an application may wish to signal that the referent is a | |||
| 1409 | * Manifest. An optional ID attribute permits a Reference to be referenced | |||
| 1410 | * from elsewhere. | |||
| 1411 | * | |||
| 1412 | * Returns: 0 on succes or aa negative value otherwise. | |||
| 1413 | */ | |||
| 1414 | int | |||
| 1415 | xmlSecDSigReferenceCtxProcessNode(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodePtr node) { | |||
| 1416 | xmlSecTransformCtxPtr transformCtx; | |||
| 1417 | xmlNodePtr digestValueNode; | |||
| 1418 | xmlNodePtr cur; | |||
| 1419 | int ret; | |||
| 1420 | ||||
| 1421 | xmlSecAssert2(dsigRefCtx != NULL, -1)if(!( dsigRefCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c", 1421,__FUNCTION__, ((void*)0), "dsigRefCtx != NULL", 100, " " ); return(-1); }; | |||
| 1422 | xmlSecAssert2(dsigRefCtx->dsigCtx != NULL, -1)if(!( dsigRefCtx->dsigCtx != ((void*)0) ) ) { xmlSecError( "xmldsig.c",1422,__FUNCTION__, ((void*)0), "dsigRefCtx->dsigCtx != NULL" , 100, " "); return(-1); }; | |||
| 1423 | xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1)if(!( dsigRefCtx->digestMethod == ((void*)0) ) ) { xmlSecError ("xmldsig.c",1423,__FUNCTION__, ((void*)0), "dsigRefCtx->digestMethod == NULL" , 100, " "); return(-1); }; | |||
| 1424 | xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1)if(!( dsigRefCtx->digestMethod == ((void*)0) ) ) { xmlSecError ("xmldsig.c",1424,__FUNCTION__, ((void*)0), "dsigRefCtx->digestMethod == NULL" , 100, " "); return(-1); }; | |||
| 1425 | xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1)if(!( dsigRefCtx->preDigestMemBufMethod == ((void*)0) ) ) { xmlSecError("xmldsig.c",1425,__FUNCTION__, ((void*)0), "dsigRefCtx->preDigestMemBufMethod == NULL" , 100, " "); return(-1); }; | |||
| 1426 | xmlSecAssert2(node != NULL, -1)if(!( node != ((void*)0) ) ) { xmlSecError("xmldsig.c",1426,__FUNCTION__ , ((void*)0), "node != NULL", 100, " "); return(-1); }; | |||
| 1427 | xmlSecAssert2(node->doc != NULL, -1)if(!( node->doc != ((void*)0) ) ) { xmlSecError("xmldsig.c" ,1427,__FUNCTION__, ((void*)0), "node->doc != NULL", 100, " " ); return(-1); }; | |||
| 1428 | ||||
| 1429 | transformCtx = &(dsigRefCtx->transformCtx); | |||
| 1430 | ||||
| 1431 | /* read attributes first */ | |||
| 1432 | dsigRefCtx->uri = xmlGetProp(node, xmlSecAttrURI); | |||
| 1433 | dsigRefCtx->id = xmlGetProp(node, xmlSecAttrId); | |||
| 1434 | dsigRefCtx->type= xmlGetProp(node, xmlSecAttrType); | |||
| 1435 | ||||
| 1436 | /* set start URI (and check that it is enabled!) */ | |||
| 1437 | ret = xmlSecTransformCtxSetUri(transformCtx, dsigRefCtx->uri, node); | |||
| 1438 | if(ret < 0) { | |||
| 1439 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1439,__FUNCTION__, | |||
| 1440 | NULL((void*)0), | |||
| 1441 | "xmlSecTransformCtxSetUri", | |||
| 1442 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1443 | "uri=%s", | |||
| 1444 | xmlSecErrorsSafeString(dsigRefCtx->uri)(((dsigRefCtx->uri) != ((void*)0)) ? ((char*)(dsigRefCtx-> uri)) : (char*)"NULL")); | |||
| 1445 | return(-1); | |||
| 1446 | } | |||
| 1447 | ||||
| 1448 | /* first is optional Transforms node */ | |||
| 1449 | cur = xmlSecGetNextElementNode(node->children); | |||
| 1450 | if((cur != NULL((void*)0)) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) { | |||
| 1451 | ret = xmlSecTransformCtxNodesListRead(transformCtx, | |||
| 1452 | cur, xmlSecTransformUsageDSigTransform0x0001); | |||
| 1453 | if(ret < 0) { | |||
| 1454 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1454,__FUNCTION__, | |||
| 1455 | NULL((void*)0), | |||
| 1456 | "xmlSecTransformCtxNodesListRead", | |||
| 1457 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1458 | "node=%s", | |||
| 1459 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL")); | |||
| 1460 | return(-1); | |||
| 1461 | } | |||
| 1462 | ||||
| 1463 | cur = xmlSecGetNextElementNode(cur->next); | |||
| 1464 | } | |||
| 1465 | ||||
| 1466 | /* insert membuf if requested */ | |||
| 1467 | if(((dsigRefCtx->origin == xmlSecDSigReferenceOriginSignedInfo) && | |||
| 1468 | ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES0x00000002) != 0)) || | |||
| 1469 | ((dsigRefCtx->origin == xmlSecDSigReferenceOriginManifest) && | |||
| 1470 | ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES0x00000004) != 0))) { | |||
| 1471 | ||||
| 1472 | xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1)if(!( dsigRefCtx->preDigestMemBufMethod == ((void*)0) ) ) { xmlSecError("xmldsig.c",1472,__FUNCTION__, ((void*)0), "dsigRefCtx->preDigestMemBufMethod == NULL" , 100, " "); return(-1); }; | |||
| 1473 | dsigRefCtx->preDigestMemBufMethod = xmlSecTransformCtxCreateAndAppend( | |||
| 1474 | transformCtx, | |||
| 1475 | xmlSecTransformMemBufIdxmlSecTransformMemBufGetKlass()); | |||
| 1476 | if(dsigRefCtx->preDigestMemBufMethod == NULL((void*)0)) { | |||
| 1477 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1477,__FUNCTION__, | |||
| 1478 | NULL((void*)0), | |||
| 1479 | "xmlSecTransformCtxCreateAndAppend", | |||
| 1480 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1481 | "transform=%s", | |||
| 1482 | xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId))((((((xmlSecTransformMemBufGetKlass())) ? ((xmlSecTransformMemBufGetKlass ())->name) : ((void*)0))) != ((void*)0)) ? ((char*)((((xmlSecTransformMemBufGetKlass ())) ? ((xmlSecTransformMemBufGetKlass())->name) : ((void* )0)))) : (char*)"NULL")); | |||
| 1483 | return(-1); | |||
| 1484 | } | |||
| 1485 | } | |||
| 1486 | ||||
| 1487 | /* next node is required DigestMethod. */ | |||
| 1488 | if((cur != NULL((void*)0)) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs))) { | |||
| 1489 | dsigRefCtx->digestMethod = xmlSecTransformCtxNodeRead(&(dsigRefCtx->transformCtx), | |||
| 1490 | cur, xmlSecTransformUsageDigestMethod0x0004); | |||
| 1491 | if(dsigRefCtx->digestMethod == NULL((void*)0)) { | |||
| 1492 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1492,__FUNCTION__, | |||
| 1493 | NULL((void*)0), | |||
| 1494 | "xmlSecTransformCtxNodeRead", | |||
| 1495 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1496 | "node=%s", | |||
| 1497 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL")); | |||
| 1498 | return(-1); | |||
| 1499 | } | |||
| 1500 | ||||
| 1501 | cur = xmlSecGetNextElementNode(cur->next); | |||
| 1502 | } else if(dsigRefCtx->dsigCtx->defSignMethodId != xmlSecTransformIdUnknown((xmlSecTransformId)((void*)0))) { | |||
| 1503 | /* the dsig spec does require DigestMethod node | |||
| 1504 | * to be present but in some case it application might decide to | |||
| 1505 | * minimize traffic */ | |||
| 1506 | dsigRefCtx->digestMethod = xmlSecTransformCtxCreateAndAppend(&(dsigRefCtx->transformCtx), | |||
| 1507 | dsigRefCtx->dsigCtx->defSignMethodId); | |||
| 1508 | if(dsigRefCtx->digestMethod == NULL((void*)0)) { | |||
| 1509 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1509,__FUNCTION__, | |||
| 1510 | NULL((void*)0), | |||
| 1511 | "xmlSecTransformCtxAppend", | |||
| 1512 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1513 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1514 | return(-1); | |||
| 1515 | } | |||
| 1516 | } else { | |||
| 1517 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1517,__FUNCTION__, | |||
| 1518 | NULL((void*)0), | |||
| 1519 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL"), | |||
| 1520 | XMLSEC_ERRORS_R_INVALID_NODE21, | |||
| 1521 | "expected=%s", | |||
| 1522 | xmlSecErrorsSafeString(xmlSecNodeDigestMethod)(((xmlSecNodeDigestMethod) != ((void*)0)) ? ((char*)(xmlSecNodeDigestMethod )) : (char*)"NULL")); | |||
| 1523 | return(-1); | |||
| 1524 | } | |||
| 1525 | dsigRefCtx->digestMethod->operation = dsigRefCtx->dsigCtx->operation; | |||
| 1526 | ||||
| 1527 | /* last node is required DigestValue */ | |||
| 1528 | if((cur != NULL((void*)0)) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestValue, xmlSecDSigNs))) { | |||
| 1529 | digestValueNode = cur; | |||
| 1530 | cur = xmlSecGetNextElementNode(cur->next); | |||
| 1531 | } else { | |||
| 1532 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1532,__FUNCTION__, | |||
| 1533 | NULL((void*)0), | |||
| 1534 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL"), | |||
| 1535 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1536 | "node=%s", | |||
| 1537 | xmlSecErrorsSafeString(xmlSecNodeDigestValue)(((xmlSecNodeDigestValue) != ((void*)0)) ? ((char*)(xmlSecNodeDigestValue )) : (char*)"NULL")); | |||
| 1538 | return(-1); | |||
| 1539 | } | |||
| 1540 | ||||
| 1541 | /* if we have something else then it's an error */ | |||
| 1542 | if(cur != NULL((void*)0)) { | |||
| 1543 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1543,__FUNCTION__, | |||
| 1544 | NULL((void*)0), | |||
| 1545 | xmlSecErrorsSafeString(xmlSecNodeGetName(cur))((((((cur)) ? ((const char*)((cur)->name)) : ((void*)0))) != ((void*)0)) ? ((char*)((((cur)) ? ((const char*)((cur)->name )) : ((void*)0)))) : (char*)"NULL"), | |||
| 1546 | XMLSEC_ERRORS_R_UNEXPECTED_NODE27, | |||
| 1547 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1548 | return(-1); | |||
| 1549 | } | |||
| 1550 | ||||
| 1551 | /* if we need to write result to xml node then we need base64 encode result */ | |||
| 1552 | if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) { | |||
| 1553 | xmlSecTransformPtr base64Encode; | |||
| 1554 | ||||
| 1555 | /* we need to add base64 encode transform */ | |||
| 1556 | base64Encode = xmlSecTransformCtxCreateAndAppend(transformCtx, xmlSecTransformBase64IdxmlSecTransformBase64GetKlass()); | |||
| 1557 | if(base64Encode == NULL((void*)0)) { | |||
| 1558 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1558,__FUNCTION__, | |||
| 1559 | NULL((void*)0), | |||
| 1560 | "xmlSecTransformCtxCreateAndAppend", | |||
| 1561 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1562 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1563 | return(-1); | |||
| 1564 | } | |||
| 1565 | base64Encode->operation = xmlSecTransformOperationEncode; | |||
| 1566 | } | |||
| 1567 | ||||
| 1568 | /* finally get transforms results */ | |||
| 1569 | ret = xmlSecTransformCtxExecute(transformCtx, node->doc); | |||
| 1570 | if(ret < 0) { | |||
| 1571 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1571,__FUNCTION__, | |||
| 1572 | NULL((void*)0), | |||
| 1573 | "xmlSecTransformCtxExecute", | |||
| 1574 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1575 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1576 | return(-1); | |||
| 1577 | } | |||
| 1578 | dsigRefCtx->result = transformCtx->result; | |||
| 1579 | ||||
| 1580 | if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) { | |||
| 1581 | if((dsigRefCtx->result == NULL((void*)0)) || (xmlSecBufferGetData(dsigRefCtx->result) == NULL((void*)0))) { | |||
| 1582 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1582,__FUNCTION__, | |||
| 1583 | NULL((void*)0), | |||
| 1584 | "xmlSecTransformCtxExecute", | |||
| 1585 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1586 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1587 | return(-1); | |||
| 1588 | } | |||
| 1589 | ||||
| 1590 | /* write signed data to xml */ | |||
| 1591 | xmlNodeSetContentLen(digestValueNode, | |||
| 1592 | xmlSecBufferGetData(dsigRefCtx->result), | |||
| 1593 | xmlSecBufferGetSize(dsigRefCtx->result)); | |||
| 1594 | ||||
| 1595 | /* set success status and we are done */ | |||
| 1596 | dsigRefCtx->status = xmlSecDSigStatusSucceeded; | |||
| 1597 | } else { | |||
| 1598 | /* verify SignatureValue node content */ | |||
| 1599 | ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod, | |||
| 1600 | digestValueNode, transformCtx); | |||
| 1601 | if(ret < 0) { | |||
| 1602 | xmlSecError(XMLSEC_ERRORS_HERE"xmldsig.c",1602,__FUNCTION__, | |||
| 1603 | NULL((void*)0), | |||
| 1604 | "xmlSecTransformVerifyNodeContent", | |||
| 1605 | XMLSEC_ERRORS_R_XMLSEC_FAILED1, | |||
| 1606 | XMLSEC_ERRORS_NO_MESSAGE" "); | |||
| 1607 | return(-1); | |||
| 1608 | } | |||
| 1609 | ||||
| 1610 | /* set status and we are done */ | |||
| 1611 | if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) { | |||
| 1612 | dsigRefCtx->status = xmlSecDSigStatusSucceeded; | |||
| 1613 | } else { | |||
| 1614 | dsigRefCtx->status = xmlSecDSigStatusInvalid; | |||
| 1615 | } | |||
| 1616 | } | |||
| 1617 | ||||
| 1618 | return(0); | |||
| 1619 | } | |||
| 1620 | ||||
| 1621 | /** | |||
| 1622 | * xmlSecDSigReferenceCtxDebugDump: | |||
| 1623 | * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context. | |||
| 1624 | * @output: the pointer to output FILE. | |||
| 1625 | * | |||
| 1626 | * Prints debug information about @dsigRefCtx to @output. | |||
| 1627 | */ | |||
| 1628 | void | |||
| 1629 | xmlSecDSigReferenceCtxDebugDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) { | |||
| 1630 | xmlSecAssert(dsigRefCtx != NULL)if(!( dsigRefCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c", 1630,__FUNCTION__, ((void*)0), "dsigRefCtx != NULL", 100, " " ); return; }; | |||
| 1631 | xmlSecAssert(dsigRefCtx->dsigCtx != NULL)if(!( dsigRefCtx->dsigCtx != ((void*)0) ) ) { xmlSecError( "xmldsig.c",1631,__FUNCTION__, ((void*)0), "dsigRefCtx->dsigCtx != NULL" , 100, " "); return; }; | |||
| 1632 | xmlSecAssert(output != NULL)if(!( output != ((void*)0) ) ) { xmlSecError("xmldsig.c",1632 ,__FUNCTION__, ((void*)0), "output != NULL", 100, " "); return ; }; | |||
| 1633 | ||||
| 1634 | if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) { | |||
| 1635 | fprintf(output, "= REFERENCE CALCULATION CONTEXT\n"); | |||
| 1636 | } else { | |||
| 1637 | fprintf(output, "= REFERENCE VERIFICATION CONTEXT\n"); | |||
| 1638 | } | |||
| 1639 | switch(dsigRefCtx->status) { | |||
| 1640 | case xmlSecDSigStatusUnknown: | |||
| 1641 | fprintf(output, "== Status: unknown\n"); | |||
| 1642 | break; | |||
| 1643 | case xmlSecDSigStatusSucceeded: | |||
| 1644 | fprintf(output, "== Status: succeeded\n"); | |||
| 1645 | break; | |||
| 1646 | case xmlSecDSigStatusInvalid: | |||
| 1647 | fprintf(output, "== Status: invalid\n"); | |||
| 1648 | break; | |||
| 1649 | } | |||
| 1650 | if(dsigRefCtx->id != NULL((void*)0)) { | |||
| 1651 | fprintf(output, "== Id: \"%s\"\n", dsigRefCtx->id); | |||
| 1652 | } | |||
| 1653 | if(dsigRefCtx->uri != NULL((void*)0)) { | |||
| 1654 | fprintf(output, "== URI: \"%s\"\n", dsigRefCtx->uri); | |||
| 1655 | } | |||
| 1656 | if(dsigRefCtx->type != NULL((void*)0)) { | |||
| 1657 | fprintf(output, "== Type: \"%s\"\n", dsigRefCtx->type); | |||
| 1658 | } | |||
| 1659 | ||||
| 1660 | fprintf(output, "== Reference Transform Ctx:\n"); | |||
| 1661 | xmlSecTransformCtxDebugDump(&(dsigRefCtx->transformCtx), output); | |||
| 1662 | ||||
| 1663 | if(dsigRefCtx->digestMethod != NULL((void*)0)) { | |||
| 1664 | fprintf(output, "== Digest Method:\n"); | |||
| 1665 | xmlSecTransformDebugDump(dsigRefCtx->digestMethod, output); | |||
| 1666 | } | |||
| 1667 | ||||
| 1668 | if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL((void*)0)) && | |||
| 1669 | (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL((void*)0))) { | |||
| 1670 | ||||
| 1671 | fprintf(output, "== PreDigest data - start buffer:\n"); | |||
| 1672 | fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), | |||
| 1673 | xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), | |||
| 1674 | 1, output); | |||
| 1675 | fprintf(output, "\n== PreDigest data - end buffer\n"); | |||
| 1676 | } | |||
| 1677 | ||||
| 1678 | if((dsigRefCtx->result != NULL((void*)0)) && | |||
| 1679 | (xmlSecBufferGetData(dsigRefCtx->result) != NULL((void*)0))) { | |||
| 1680 | ||||
| 1681 | fprintf(output, "== Result - start buffer:\n"); | |||
| 1682 | fwrite(xmlSecBufferGetData(dsigRefCtx->result), | |||
| 1683 | xmlSecBufferGetSize(dsigRefCtx->result), 1, | |||
| 1684 | output); | |||
| 1685 | fprintf(output, "\n== Result - end buffer\n"); | |||
| 1686 | } | |||
| 1687 | } | |||
| 1688 | ||||
| 1689 | /** | |||
| 1690 | * xmlSecDSigReferenceCtxDebugXmlDump: | |||
| 1691 | * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context. | |||
| 1692 | * @output: the pointer to output FILE. | |||
| 1693 | * | |||
| 1694 | * Prints debug information about @dsigRefCtx to @output in output format. | |||
| 1695 | */ | |||
| 1696 | void | |||
| 1697 | xmlSecDSigReferenceCtxDebugXmlDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) { | |||
| 1698 | xmlSecAssert(dsigRefCtx != NULL)if(!( dsigRefCtx != ((void*)0) ) ) { xmlSecError("xmldsig.c", 1698,__FUNCTION__, ((void*)0), "dsigRefCtx != NULL", 100, " " ); return; }; | |||
| 1699 | xmlSecAssert(dsigRefCtx->dsigCtx != NULL)if(!( dsigRefCtx->dsigCtx != ((void*)0) ) ) { xmlSecError( "xmldsig.c",1699,__FUNCTION__, ((void*)0), "dsigRefCtx->dsigCtx != NULL" , 100, " "); return; }; | |||
| 1700 | xmlSecAssert(output != NULL)if(!( output != ((void*)0) ) ) { xmlSecError("xmldsig.c",1700 ,__FUNCTION__, ((void*)0), "output != NULL", 100, " "); return ; }; | |||
| 1701 | ||||
| 1702 | if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) { | |||
| 1703 | fprintf(output, "<ReferenceCalculationContext "); | |||
| 1704 | } else { | |||
| 1705 | fprintf(output, "<ReferenceVerificationContext "); | |||
| 1706 | } | |||
| 1707 | switch(dsigRefCtx->status) { | |||
| 1708 | case xmlSecDSigStatusUnknown: | |||
| 1709 | fprintf(output, "status=\"unknown\" >\n"); | |||
| 1710 | break; | |||
| 1711 | case xmlSecDSigStatusSucceeded: | |||
| 1712 | fprintf(output, "status=\"succeeded\" >\n"); | |||
| 1713 | break; | |||
| 1714 | case xmlSecDSigStatusInvalid: | |||
| 1715 | fprintf(output, "status=\"invalid\" >\n"); | |||
| 1716 | break; | |||
| 1717 | } | |||
| 1718 | ||||
| 1719 | fprintf(output, "<Id>"); | |||
| 1720 | xmlSecPrintXmlString(output, dsigRefCtx->id); | |||
| 1721 | fprintf(output, "</Id>\n"); | |||
| 1722 | ||||
| 1723 | fprintf(output, "<URI>"); | |||
| 1724 | xmlSecPrintXmlString(output, dsigRefCtx->uri); | |||
| 1725 | fprintf(output, "</URI>\n"); | |||
| 1726 | ||||
| 1727 | fprintf(output, "<Type>"); | |||
| 1728 | xmlSecPrintXmlString(output, dsigRefCtx->type); | |||
| 1729 | fprintf(output, "</Type>\n"); | |||
| 1730 | ||||
| 1731 | fprintf(output, "<ReferenceTransformCtx>\n"); | |||
| 1732 | xmlSecTransformCtxDebugXmlDump(&(dsigRefCtx->transformCtx), output); | |||
| 1733 | fprintf(output, "</ReferenceTransformCtx>\n"); | |||
| 1734 | ||||
| 1735 | if(dsigRefCtx->digestMethod != NULL((void*)0)) { | |||
| 1736 | fprintf(output, "<DigestMethod>\n"); | |||
| 1737 | xmlSecTransformDebugXmlDump(dsigRefCtx->digestMethod, output); | |||
| 1738 | fprintf(output, "</DigestMethod>\n"); | |||
| 1739 | } | |||
| 1740 | ||||
| 1741 | if((dsigRefCtx->result != NULL((void*)0)) && | |||
| 1742 | (xmlSecBufferGetData(dsigRefCtx->result) != NULL((void*)0))) { | |||
| 1743 | ||||
| 1744 | fprintf(output, "<Result>"); | |||
| 1745 | fwrite(xmlSecBufferGetData(dsigRefCtx->result), | |||
| 1746 | xmlSecBufferGetSize(dsigRefCtx->result), 1, | |||
| 1747 | output); | |||
| 1748 | fprintf(output, "</Result>\n"); | |||
| 1749 | } | |||
| 1750 | ||||
| 1751 | if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL((void*)0)) && | |||
| 1752 | (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL((void*)0))) { | |||
| 1753 | ||||
| 1754 | fprintf(output, "<PreDigestData>"); | |||
| 1755 | fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), | |||
| 1756 | xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), | |||
| 1757 | 1, output); | |||
| 1758 | fprintf(output, "</PreDigestData>\n"); | |||
| 1759 | } | |||
| 1760 | if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) { | |||
| 1761 | fprintf(output, "</ReferenceCalculationContext>\n"); | |||
| 1762 | } else { | |||
| 1763 | fprintf(output, "</ReferenceVerificationContext>\n"); | |||
| 1764 | } | |||
| 1765 | } | |||
| 1766 | ||||
| 1767 | ||||
| 1768 | /************************************************************************** | |||
| 1769 | * | |||
| 1770 | * xmlSecDSigReferenceCtxListKlass | |||
| 1771 | * | |||
| 1772 | *************************************************************************/ | |||
| 1773 | static xmlSecPtrListKlass xmlSecDSigReferenceCtxListKlass = { | |||
| 1774 | BAD_CAST(xmlChar *) "dsig-reference-list", | |||
| 1775 | NULL((void*)0), /* xmlSecPtrDuplicateItemMethod duplicateItem; */ | |||
| 1776 | (xmlSecPtrDestroyItemMethod)xmlSecDSigReferenceCtxDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */ | |||
| 1777 | (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */ | |||
| 1778 | (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */ | |||
| 1779 | }; | |||
| 1780 | ||||
| 1781 | /** | |||
| 1782 | * xmlSecDSigReferenceCtxListGetKlass: | |||
| 1783 | * | |||
| 1784 | * The <dsig:Reference/> element processing contexts list klass. | |||
| 1785 | * | |||
| 1786 | * Returns: <dsig:Reference/> element processing context list klass. | |||
| 1787 | */ | |||
| 1788 | xmlSecPtrListId | |||
| 1789 | xmlSecDSigReferenceCtxListGetKlass(void) { | |||
| 1790 | return(&xmlSecDSigReferenceCtxListKlass); | |||
| 1791 | } | |||
| 1792 | ||||
| 1793 | #endif /* XMLSEC_NO_XMLDSIG */ | |||
| 1794 | ||||
| 1795 |