1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /*
21  * XSEC
22  *
23  * DSIGKeyX509 := A "Super" key that defines a certificate with a sub-key that defines
24  *                the signing key
25  *
26  * $Id: DSIGKeyInfoX509.cpp 1833341 2018-06-11 16:25:41Z scantor $
27  *
28  */
29 
30 #include <xsec/dsig/DSIGKeyInfoX509.hpp>
31 #include <xsec/dsig/DSIGSignature.hpp>
32 #include <xsec/framework/XSECEnv.hpp>
33 #include <xsec/framework/XSECError.hpp>
34 #include <xsec/utils/XSECPlatformUtils.hpp>
35 
36 #include "../utils/XSECAutoPtr.hpp"
37 #include "../utils/XSECDOMUtils.hpp"
38 
39 XERCES_CPP_NAMESPACE_USE
40 
41 // --------------------------------------------------------------------------------
42 //           Constructors and Destructors
43 // --------------------------------------------------------------------------------
44 
45 
DSIGKeyInfoX509(const XSECEnv * env,DOMNode * X509Data)46 DSIGKeyInfoX509::DSIGKeyInfoX509(const XSECEnv * env, DOMNode *X509Data) :
47 DSIGKeyInfo(env),
48 mp_X509IssuerName(NULL),
49 mp_X509SerialNumber(NULL),
50 mp_X509SubjectName(NULL),
51 mp_X509SKI(NULL),
52 mp_rawRetrievalURI(NULL),
53 mp_X509SubjectNameTextNode(0),
54 mp_X509IssuerNameTextNode(0),
55 mp_X509SerialNumberTextNode(0),
56 mp_X509SKITextNode(0),
57 mp_X509DigestTextNode(0) {
58 
59 	mp_keyInfoDOMNode = X509Data;
60 	m_X509List.clear();
61 	m_X509CRLList.clear();
62 }
63 
DSIGKeyInfoX509(const XSECEnv * env)64 DSIGKeyInfoX509::DSIGKeyInfoX509(const XSECEnv * env) :
65 DSIGKeyInfo(env),
66 mp_X509IssuerName(NULL),
67 mp_X509SerialNumber(NULL),
68 mp_X509SubjectName(NULL),
69 mp_X509SKI(NULL),
70 mp_rawRetrievalURI(NULL),
71 mp_X509SubjectNameTextNode(0),
72 mp_X509IssuerNameTextNode(0),
73 mp_X509SerialNumberTextNode(0),
74 mp_X509SKITextNode(0),
75 mp_X509DigestTextNode(0){
76 
77 	mp_keyInfoDOMNode = 0;
78 	m_X509List.clear();
79     m_X509CRLList.clear();
80 }
81 
82 
~DSIGKeyInfoX509()83 DSIGKeyInfoX509::~DSIGKeyInfoX509() {
84 
85 	// SubjectName and IssuerName are local (decoded) copies of the
86 	// encoded DName held in the DOM
87 
88 	if (mp_X509IssuerName != NULL)
89 		XSEC_RELEASE_XMLCH(mp_X509IssuerName);
90 
91 	if (mp_X509SubjectName != NULL)
92 		XSEC_RELEASE_XMLCH(mp_X509SubjectName);
93 
94 	X509ListType::iterator i;
95 
96 	for (i = m_X509List.begin(); i != m_X509List.end(); ++i) {
97 
98 		if ((*i)->mp_cryptoX509 != NULL)
99 			delete ((*i)->mp_cryptoX509);
100 		delete (*i);
101 
102 	}
103 
104 	m_X509List.clear();
105     m_X509CRLList.clear();
106 
107 	if (mp_rawRetrievalURI != NULL)
108 		XSEC_RELEASE_XMLCH(mp_rawRetrievalURI);
109 
110 
111 };
112 
113 // --------------------------------------------------------------------------------
114 //           Load and Get
115 // --------------------------------------------------------------------------------
116 
117 
118 // Methods unique to DSIGKeyInfoX509
119 
load(void)120 void DSIGKeyInfoX509::load(void) {
121 
122 	// Assuming we have a valid DOM_Node to start with, load the signing key so that it can
123 	// be used later on
124 
125 	if (mp_keyInfoDOMNode == NULL) {
126 
127 		// Attempt to load an empty signature element
128 		throw XSECException(XSECException::LoadEmptyX509);
129 
130 	}
131 
132 	if (!strEquals(getDSIGLocalName(mp_keyInfoDOMNode), "X509Data")) {
133 
134 		throw XSECException(XSECException::LoadNonX509);
135 
136 	}
137 
138 	// Now check for an X509 Data Element we understand
139 
140 	DOMNode *tmpElt = mp_keyInfoDOMNode->getFirstChild();
141 	DOMNode *child;	// Worker
142 
143 	while (tmpElt != 0) {
144 
145 		if (tmpElt->getNodeType() == DOMNode::ELEMENT_NODE) {
146 
147 			// See if it's a known element type
148 			if (strEquals(getDSIGLocalName(tmpElt), "X509Certificate")) {
149 
150 			    // Loop over Text nodes until we successfully load a certificate.
151 			    // If we run out, throw out the last exception raised.
152 
153 				X509Holder * h;
154                 XSECCryptoX509* cryptoX509 = XSECPlatformUtils::g_cryptoProvider->X509();
155 				DOMNode *certElt = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE);
156 				while (certElt) {
157                     XSECAutoPtrChar charX509(certElt->getNodeValue());
158 				    try {
159                         cryptoX509->loadX509Base64Bin(charX509.get(), (int) strlen(charX509.get()));
160 
161 	                    // Add to the list
162                         XSECnew(h, X509Holder);
163 	                    m_X509List.push_back(h);
164 	                    h->mp_encodedX509 = certElt->getNodeValue();
165 	                    h->mp_cryptoX509 = cryptoX509;
166 	                    break;
167 				    }
168 			catch (const XSECCryptoException&) {
169 	                    certElt = findNextChildOfType(certElt, DOMNode::TEXT_NODE);
170 	                    if (!certElt) {
171 	                        delete cryptoX509;
172 	                        throw;
173 	                    }
174 				    }
175 				}
176 			}
177 
178 			else if (strEquals(getDSIGLocalName(tmpElt), "X509SubjectName")) {
179 
180 				child = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE);
181 
182 				if (child == NULL) {
183 
184 					throw XSECException(XSECException::ExpectedDSIGChildNotFound,
185 						"Expected TEXT_NODE child of <X509SubjectName>");
186 
187 				}
188 
189 				mp_X509SubjectName = decodeDName(child->getNodeValue());
190 
191 			}
192 
193 			else if (strEquals(getDSIGLocalName(tmpElt), "X509IssuerSerial")) {
194 
195 				child = tmpElt->getFirstChild();
196 				while (child != 0 && child->getNodeType() != DOMNode::ELEMENT_NODE &&
197 					!strEquals(getDSIGLocalName(child), "X509IssuerName"))
198 					child = child->getNextSibling();
199 
200 				if (child == NULL) {
201 
202 					throw XSECException(XSECException::ExpectedDSIGChildNotFound,
203 						"Expected <X509IssuerName> child of <X509IssuerSerial>");
204 
205 				}
206 
207 				child = child->getFirstChild();
208 				while (child != 0 && child->getNodeType() != DOMNode::TEXT_NODE)
209 					child = child->getNextSibling();
210 
211 				if (child == NULL) {
212 
213 					throw XSECException(XSECException::ExpectedDSIGChildNotFound,
214 						"Expected TEXT_NODE child of <X509IssuerSerial>");
215 
216 				}
217 
218 				mp_X509IssuerName = decodeDName(child->getNodeValue());
219 
220 				// Now find the serial number
221 				child = tmpElt->getFirstChild();
222 				while (child != 0 && (child->getNodeType() != DOMNode::ELEMENT_NODE ||
223 					!strEquals(getDSIGLocalName(child), "X509SerialNumber")))
224 					child = child->getNextSibling();
225 
226 				if (child == NULL) {
227 
228 					throw XSECException(XSECException::ExpectedDSIGChildNotFound,
229 						"Expected <X509SerialNumber> child of <X509IssuerSerial>");
230 
231 				}
232 
233 				child = child->getFirstChild();
234 				while (child != 0 && child->getNodeType() != DOMNode::TEXT_NODE)
235 					child = child->getNextSibling();
236 
237 				if (child == NULL) {
238 
239 					throw XSECException(XSECException::ExpectedDSIGChildNotFound,
240 						"Expected TEXT_NODE child of <X509IssuerSerial>");
241 
242 				}
243 
244 				mp_X509SerialNumber = child->getNodeValue();
245 
246 			}
247 
248 			else if (strEquals(getDSIGLocalName(tmpElt), "X509CRL")) {
249 
250                 DOMNode *crlElt = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE);
251 
252                 if (crlElt != 0) {
253 
254                     // Add to the list
255                     m_X509CRLList.push_back(crlElt->getNodeValue());
256 
257                 }
258 
259 			}
260 			else if (strEquals(getDSIGLocalName(tmpElt), "X509SKI")) {
261 
262 				child = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE);
263 
264 				if (child == NULL) {
265 
266 					throw XSECException(XSECException::ExpectedDSIGChildNotFound,
267 						"Expected TEXT_NODE child of <X509SKI>");
268 
269 				}
270 
271 				mp_X509SKITextNode = child;
272 				mp_X509SKI = child->getNodeValue();
273 
274 			}
275             else if (strEquals(getDSIG11LocalName(tmpElt), "X509Digest")) {
276 
277                 child = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE);
278 
279                 if (child == NULL) {
280 
281                     throw XSECException(XSECException::ExpectedDSIGChildNotFound,
282                         "Expected TEXT_NODE child of <X509Digest>");
283 
284                 }
285 
286                 mp_X509DigestTextNode = child;
287 
288             }
289 		}
290 
291 		// Go to next data element to load if we understand
292 
293 		tmpElt = tmpElt->getNextSibling();
294 
295 	}
296 
297 }
298 
getKeyName(void) const299 const XMLCh * DSIGKeyInfoX509::getKeyName(void) const {
300 
301 	return mp_X509SubjectName;
302 
303 	// Should return DN
304 
305 }
306 
getX509SubjectName(void) const307 const XMLCh * DSIGKeyInfoX509::getX509SubjectName(void) const {
308 
309 
310 	return mp_X509SubjectName;
311 
312 }
313 
getX509DigestAlgorithm(void) const314 const XMLCh * DSIGKeyInfoX509::getX509DigestAlgorithm(void) const {
315 
316     return mp_X509DigestTextNode ?
317         static_cast<DOMElement*>(mp_X509DigestTextNode->getParentNode())->getAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm) :
318             NULL;
319 
320 }
321 
getX509DigestValue(void) const322 const XMLCh * DSIGKeyInfoX509::getX509DigestValue(void) const {
323 
324     return mp_X509DigestTextNode ? mp_X509DigestTextNode->getNodeValue() : NULL;
325 
326 }
327 
getX509IssuerName(void) const328 const XMLCh * DSIGKeyInfoX509::getX509IssuerName(void) const {
329 
330 	return mp_X509IssuerName;
331 
332 }
333 
getX509IssuerSerialNumber(void) const334 const XMLCh * DSIGKeyInfoX509::getX509IssuerSerialNumber(void) const {
335 
336     return mp_X509SerialNumber;
337 
338 }
339 
getX509CRL(void) const340 const XMLCh * DSIGKeyInfoX509::getX509CRL(void) const {
341 
342 	return m_X509CRLList.empty() ? NULL : m_X509CRLList.front();
343 
344 }
345 
getX509CRLListSize(void) const346 int DSIGKeyInfoX509::getX509CRLListSize(void) const {
347 
348     return (int) m_X509CRLList.size();
349 
350 }
351 
352 
getX509CRLItem(int item) const353 const XMLCh * DSIGKeyInfoX509::getX509CRLItem(int item) const {
354 
355     if (item >=0 && (unsigned int) item < m_X509CRLList.size())
356         return m_X509CRLList[item];
357 
358     return 0;
359 
360 }
361 
getX509SKI(void) const362 const XMLCh * DSIGKeyInfoX509::getX509SKI(void) const {
363 
364 	return mp_X509SKI;
365 
366 }
367 
getCertificateListSize(void) const368 int DSIGKeyInfoX509::getCertificateListSize(void) const {
369 
370 	return (int) m_X509List.size();
371 
372 }
373 
getCertificateItem(int item) const374 const XMLCh * DSIGKeyInfoX509::getCertificateItem(int item) const {
375 
376 	if (item >=0 && (unsigned int) item < m_X509List.size())
377 		return m_X509List[item]->mp_encodedX509;
378 
379 	return 0;
380 
381 }
382 
getCertificateCryptoItem(int item)383 XSECCryptoX509 * DSIGKeyInfoX509::getCertificateCryptoItem(int item) {
384 
385     if (item >=0 && (unsigned int) item < m_X509List.size())
386         return m_X509List[item]->mp_cryptoX509;
387 
388     return 0;
389 }
390 
getCertificateCryptoItem(int item) const391 const XSECCryptoX509 * DSIGKeyInfoX509::getCertificateCryptoItem(int item) const {
392 
393 	if (item >=0 && (unsigned int) item < m_X509List.size())
394 		return m_X509List[item]->mp_cryptoX509;
395 
396 	return 0;
397 }
398 
getRawRetrievalURI(void) const399 const XMLCh * DSIGKeyInfoX509::getRawRetrievalURI(void) const {
400 
401 	return mp_rawRetrievalURI;
402 
403 }
404 
405 // --------------------------------------------------------------------------------
406 //           Create and Set
407 // --------------------------------------------------------------------------------
408 
createBlankX509Data(void)409 DOMElement * DSIGKeyInfoX509::createBlankX509Data(void) {
410 
411 	// Create the DOM Structure
412 
413 	safeBuffer str;
414 	DOMDocument *doc = mp_env->getParentDocument();
415 	const XMLCh * prefix = mp_env->getDSIGNSPrefix();
416 
417 	makeQName(str, prefix, "X509Data");
418 
419 	DOMElement *ret = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
420 	mp_keyInfoDOMNode = ret;
421 	mp_env->doPrettyPrint(ret);
422 
423 	return ret;
424 
425 }
426 
setX509CRL(const XMLCh * crl)427 void DSIGKeyInfoX509::setX509CRL(const XMLCh * crl) {
428     appendX509CRL(crl);
429 }
430 
appendX509CRL(const XMLCh * crl)431 void DSIGKeyInfoX509::appendX509CRL(const XMLCh * crl) {
432 
433     safeBuffer str;
434     DOMDocument *doc = mp_env->getParentDocument();
435     const XMLCh * prefix = mp_env->getDSIGNSPrefix();
436 
437     makeQName(str, prefix, "X509CRL");
438 
439     DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
440     DOMNode * b64Txt = doc->createTextNode(crl);
441     s->appendChild(b64Txt);
442 
443     mp_keyInfoDOMNode->appendChild(s);
444     mp_env->doPrettyPrint(mp_keyInfoDOMNode);
445 
446     // Add to the list
447 
448     m_X509CRLList.push_back(b64Txt->getNodeValue());
449 }
450 
setX509SKI(const XMLCh * ski)451 void DSIGKeyInfoX509::setX509SKI(const XMLCh * ski) {
452 
453 	if (mp_X509SKITextNode == 0) {
454 
455 		safeBuffer str;
456 		DOMDocument *doc = mp_env->getParentDocument();
457 		const XMLCh * prefix = mp_env->getDSIGNSPrefix();
458 
459 		makeQName(str, prefix, "X509SKI");
460 
461 		DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
462 		mp_X509SKITextNode = doc->createTextNode(ski);
463 		s->appendChild(mp_X509SKITextNode);
464 
465 		// Add to the over-arching node
466 		mp_keyInfoDOMNode->appendChild(s);
467 		mp_env->doPrettyPrint(mp_keyInfoDOMNode);
468 
469 	}
470 
471 	else {
472 
473 		mp_X509SKITextNode->setNodeValue(ski);
474 
475 	}
476 
477 	mp_X509SKI = mp_X509SKITextNode->getNodeValue();
478 
479 }
480 
setX509SubjectName(const XMLCh * name)481 void DSIGKeyInfoX509::setX509SubjectName(const XMLCh * name) {
482 
483 	if (mp_X509SubjectName != NULL)
484 		XSEC_RELEASE_XMLCH(mp_X509SubjectName);
485 
486 	mp_X509SubjectName = XMLString::replicate(name);
487 
488 	XMLCh * encodedName = encodeDName(name);
489 
490 	if (mp_X509SubjectNameTextNode == 0) {
491 
492 		// Does not yet exist in the DOM
493 
494 		safeBuffer str;
495 		DOMDocument *doc = mp_env->getParentDocument();
496 		const XMLCh * prefix = mp_env->getDSIGNSPrefix();
497 
498 		makeQName(str, prefix, "X509SubjectName");
499 
500 		DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
501 		mp_X509SubjectNameTextNode = doc->createTextNode(encodedName);
502 		s->appendChild(mp_X509SubjectNameTextNode);
503 
504 		// Add to the over-arching node
505 		mp_keyInfoDOMNode->appendChild(s);
506 		mp_env->doPrettyPrint(mp_keyInfoDOMNode);
507 
508 	}
509 
510 	else {
511 
512 		mp_X509SubjectNameTextNode->setNodeValue(encodedName);
513 
514 	}
515 	XSEC_RELEASE_XMLCH(encodedName);
516 }
517 
setX509IssuerSerial(const XMLCh * name,const XMLCh * serial)518 void DSIGKeyInfoX509::setX509IssuerSerial(const XMLCh * name, const XMLCh * serial) {
519 
520 	if (mp_X509IssuerName != NULL)
521 		XSEC_RELEASE_XMLCH(mp_X509IssuerName);
522 
523 	mp_X509IssuerName = XMLString::replicate(name);
524 
525 	XMLCh * encodedName = encodeDName(name);
526 
527 	if (mp_X509IssuerNameTextNode == 0) {
528 
529 		// Does not yet exist in the DOM
530 
531 		safeBuffer str;
532 		DOMDocument *doc = mp_env->getParentDocument();
533 		const XMLCh * prefix = mp_env->getDSIGNSPrefix();
534 
535 		makeQName(str, prefix, "X509IssuerSerial");
536 
537 		DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
538 		mp_env->doPrettyPrint(s);
539 
540 		// Create the text nodes with the contents
541 
542 		mp_X509IssuerNameTextNode = doc->createTextNode(encodedName);
543 		mp_X509SerialNumberTextNode = doc->createTextNode(serial);
544 
545 		// Create the sub elements
546 
547 		makeQName(str, prefix, "X509IssuerName");
548 		DOMElement * t = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
549 		t->appendChild(mp_X509IssuerNameTextNode);
550 
551 		s->appendChild(t);
552 		mp_env->doPrettyPrint(s);
553 
554 		makeQName(str, prefix, "X509SerialNumber");
555 		t = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
556 		t->appendChild(mp_X509SerialNumberTextNode);
557 
558 		s->appendChild(t);
559 		mp_env->doPrettyPrint(s);
560 
561 		// Add to the over-arching X509Data
562 
563 		mp_keyInfoDOMNode->appendChild(s);
564 		mp_env->doPrettyPrint(mp_keyInfoDOMNode);
565 
566 	}
567 
568 	else {
569 
570 		mp_X509IssuerNameTextNode->setNodeValue(encodedName);
571 		mp_X509SerialNumberTextNode->setNodeValue(serial);
572 
573 	}
574 
575 	XSEC_RELEASE_XMLCH(encodedName);
576 }
577 
setX509Digest(const XMLCh * algorithm,const XMLCh * value)578 void DSIGKeyInfoX509::setX509Digest(const XMLCh * algorithm, const XMLCh * value) {
579 
580     if (mp_X509DigestTextNode == 0) {
581 
582         // Does not yet exist in the DOM
583 
584         safeBuffer str;
585         DOMDocument *doc = mp_env->getParentDocument();
586         const XMLCh * prefix = mp_env->getDSIG11NSPrefix();
587 
588         makeQName(str, prefix, "X509Digest");
589 
590         DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG11, str.rawXMLChBuffer());
591         s->setAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm, algorithm);
592 
593         // Create the text node with the contents
594 
595         mp_X509DigestTextNode = doc->createTextNode(value);
596         s->appendChild(mp_X509DigestTextNode);
597 
598         mp_env->doPrettyPrint(s);
599 
600         // Add to the over-arching X509Data
601 
602         mp_keyInfoDOMNode->appendChild(s);
603         mp_env->doPrettyPrint(mp_keyInfoDOMNode);
604 
605     }
606 
607     else {
608 
609         mp_X509DigestTextNode->setNodeValue(value);
610         static_cast<DOMElement*>(mp_X509DigestTextNode->getParentNode())->setAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm, algorithm);
611 
612     }
613 
614 }
615 
setRawRetrievalURI(const XMLCh * uri)616 void DSIGKeyInfoX509::setRawRetrievalURI(const XMLCh * uri) {
617 
618 	if (mp_rawRetrievalURI != NULL)
619 		XSEC_RELEASE_XMLCH(mp_rawRetrievalURI);
620 
621 	mp_rawRetrievalURI = XMLString::replicate(uri);
622 
623 }
624 
appendX509Certificate(const XMLCh * base64Certificate)625 void DSIGKeyInfoX509::appendX509Certificate(const XMLCh * base64Certificate) {
626 
627 	safeBuffer str;
628 	DOMDocument *doc = mp_env->getParentDocument();
629 	const XMLCh * prefix = mp_env->getDSIGNSPrefix();
630 
631 	makeQName(str, prefix, "X509Certificate");
632 
633 	DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
634 	DOMNode * b64Txt = doc->createTextNode(base64Certificate);
635 	s->appendChild(b64Txt);
636 
637 	mp_keyInfoDOMNode->appendChild(s);
638 	mp_env->doPrettyPrint(mp_keyInfoDOMNode);
639 
640 	// Add to the list
641 
642 	X509Holder * h;
643 	XSECnew(h, X509Holder);
644 	m_X509List.push_back(h);
645 	h->mp_encodedX509 = b64Txt->getNodeValue();
646 	h->mp_cryptoX509 = XSECPlatformUtils::g_cryptoProvider->X509();
647 	XSECAutoPtrChar charX509(h->mp_encodedX509);
648 	h->mp_cryptoX509->loadX509Base64Bin(charX509.get(), (unsigned int) strlen(charX509.get()));
649 
650 }
651