1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmlsecurity.hxx"
30 
31 #include "xsecparser.hxx"
32 #include <tools/debug.hxx>
33 #include "cppuhelper/exc_hlp.hxx"
34 
35 #include <string.h>
36 
37 namespace cssu = com::sun::star::uno;
38 namespace cssxs = com::sun::star::xml::sax;
39 
40 #define RTL_ASCII_USTRINGPARAM( asciiStr ) asciiStr, strlen( asciiStr ), RTL_TEXTENCODING_ASCII_US
41 
42 XSecParser::XSecParser(
43 	XSecController* pXSecController,
44 	const cssu::Reference< cssxs::XDocumentHandler >& xNextHandler )
45 	: m_pXSecController(pXSecController),
46 	  m_xNextHandler(xNextHandler),
47 	  m_bReferenceUnresolved(false)
48 {
49 }
50 
51 rtl::OUString XSecParser::getIdAttr(const cssu::Reference< cssxs::XAttributeList >& xAttribs )
52 {
53 	rtl::OUString ouIdAttr = xAttribs->getValueByName(
54 		rtl::OUString(RTL_ASCII_USTRINGPARAM("id")));
55 
56 	if (ouIdAttr == NULL)
57 	{
58 		ouIdAttr = xAttribs->getValueByName(
59 			rtl::OUString(RTL_ASCII_USTRINGPARAM("Id")));
60 	}
61 
62 	return ouIdAttr;
63 }
64 
65 /*
66  * XDocumentHandler
67  */
68 void SAL_CALL XSecParser::startDocument(  )
69 	throw (cssxs::SAXException, cssu::RuntimeException)
70 {
71 	m_bInX509IssuerName = false;
72 	m_bInX509SerialNumber = false;
73 	m_bInX509Certificate = false;
74 	m_bInSignatureValue = false;
75 	m_bInDigestValue = false;
76 	m_bInDate = false;
77 	//m_bInTime = false;
78 
79 	if (m_xNextHandler.is())
80 	{
81 		m_xNextHandler->startDocument();
82 	}
83 }
84 
85 void SAL_CALL XSecParser::endDocument(  )
86 	throw (cssxs::SAXException, cssu::RuntimeException)
87 {
88 	if (m_xNextHandler.is())
89 	{
90 		m_xNextHandler->endDocument();
91 	}
92 }
93 
94 void SAL_CALL XSecParser::startElement(
95 	const rtl::OUString& aName,
96 	const cssu::Reference< cssxs::XAttributeList >& xAttribs )
97 	throw (cssxs::SAXException, cssu::RuntimeException)
98 {
99 	try
100 	{
101 		rtl::OUString ouIdAttr = getIdAttr(xAttribs);
102 		if (ouIdAttr != NULL)
103 		{
104 			m_pXSecController->collectToVerify( ouIdAttr );
105 		}
106 
107 		if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_SIGNATURE)) )
108 		{
109 			m_pXSecController->addSignature();
110 			if (ouIdAttr != NULL)
111 			{
112 				m_pXSecController->setId( ouIdAttr );
113 			}
114 		}
115 		else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_REFERENCE)) )
116 		{
117 			rtl::OUString ouUri = xAttribs->getValueByName(rtl::OUString(RTL_ASCII_USTRINGPARAM(ATTR_URI)));
118 			DBG_ASSERT( ouUri != NULL, "URI == NULL" );
119 
120 			if (0 == ouUri.compareTo(rtl::OUString(RTL_ASCII_USTRINGPARAM(CHAR_FRAGMENT)),1))
121 			{
122 				/*
123 				* remove the first character '#' from the attribute value
124 				*/
125 				m_pXSecController->addReference( ouUri.copy(1) );
126 			}
127 			else
128 			{
129 				/*
130 				* remember the uri
131 				*/
132 				m_currentReferenceURI = ouUri;
133 				m_bReferenceUnresolved = true;
134 			}
135 		}
136 			else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_TRANSFORM)))
137 			{
138 			if ( m_bReferenceUnresolved )
139 			{
140 				rtl::OUString ouAlgorithm = xAttribs->getValueByName(rtl::OUString(RTL_ASCII_USTRINGPARAM(ATTR_ALGORITHM)));
141 
142 				if (ouAlgorithm != NULL && ouAlgorithm == rtl::OUString(RTL_ASCII_USTRINGPARAM(ALGO_C14N)))
143 				/*
144 				* a xml stream
145 				*/
146 				{
147 					m_pXSecController->addStreamReference( m_currentReferenceURI, sal_False);
148 					m_bReferenceUnresolved = false;
149 				}
150 			}
151 			}
152 			else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509ISSUERNAME)))
153 			{
154 			m_ouX509IssuerName = rtl::OUString::createFromAscii("");
155 			m_bInX509IssuerName = true;
156 			}
157 			else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509SERIALNUMBER)))
158 			{
159 			m_ouX509SerialNumber = rtl::OUString::createFromAscii("");
160 			m_bInX509SerialNumber = true;
161 			}
162 			else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509CERTIFICATE)))
163 			{
164 			m_ouX509Certificate = rtl::OUString::createFromAscii("");
165 			m_bInX509Certificate = true;
166 			}
167 			else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_SIGNATUREVALUE)))
168 			{
169 			m_ouSignatureValue = rtl::OUString::createFromAscii("");
170         		m_bInSignatureValue = true;
171 			}
172 			else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_DIGESTVALUE)))
173 			{
174 			m_ouDigestValue = rtl::OUString::createFromAscii("");
175         		m_bInDigestValue = true;
176 			}
177 			else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_SIGNATUREPROPERTY)) )
178 		{
179 			if (ouIdAttr != NULL)
180 			{
181 				m_pXSecController->setPropertyId( ouIdAttr );
182 			}
183 		}
184 			else if (aName == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NSTAG_DC))
185         				+rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(":"))
186         				+rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(TAG_DATE)))
187 			{
188 			m_ouDate = rtl::OUString::createFromAscii("");
189         		m_bInDate = true;
190 			}
191 			/*
192 			else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_TIME)))
193 			{
194 			m_ouTime = rtl::OUString::createFromAscii("");
195         		m_bInTime = true;
196 			}
197 			*/
198 
199 		if (m_xNextHandler.is())
200 		{
201 			m_xNextHandler->startElement(aName, xAttribs);
202 		}
203 	}
204 	catch (cssu::Exception& )
205 	{//getCaughtException MUST be the first line in the catch block
206         cssu::Any exc =  cppu::getCaughtException();
207         throw cssxs::SAXException(
208 			rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
209                               "xmlsecurity: Exception in XSecParser::startElement")),
210             0, exc);
211 	}
212 	catch (...)
213 	{
214 		throw cssxs::SAXException(
215 			rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xmlsecurity: unexpected exception in XSecParser::startElement")), 0,
216 			cssu::Any());
217 	}
218 }
219 
220 void SAL_CALL XSecParser::endElement( const rtl::OUString& aName )
221 	throw (cssxs::SAXException, cssu::RuntimeException)
222 {
223 	try
224 	{
225         if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_DIGESTVALUE)))
226 			{
227         		m_bInDigestValue = false;
228 			}
229 		else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_REFERENCE)) )
230 		{
231 			if ( m_bReferenceUnresolved )
232 			/*
233 			* it must be a octet stream
234 			*/
235 			{
236 				m_pXSecController->addStreamReference( m_currentReferenceURI, sal_True);
237 				m_bReferenceUnresolved = false;
238 			}
239 
240 			m_pXSecController->setDigestValue( m_ouDigestValue );
241 		}
242 		else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_SIGNEDINFO)) )
243 		{
244 			m_pXSecController->setReferenceCount();
245 		}
246 		else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_SIGNATUREVALUE)) )
247 		{
248 			m_pXSecController->setSignatureValue( m_ouSignatureValue );
249         		m_bInSignatureValue = false;
250 		}
251 			else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509ISSUERNAME)))
252 			{
253 			m_pXSecController->setX509IssuerName( m_ouX509IssuerName );
254 			m_bInX509IssuerName = false;
255 			}
256 			else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509SERIALNUMBER)))
257 			{
258 			m_pXSecController->setX509SerialNumber( m_ouX509SerialNumber );
259 			m_bInX509SerialNumber = false;
260 			}
261 			else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509CERTIFICATE)))
262 			{
263 			m_pXSecController->setX509Certificate( m_ouX509Certificate );
264 			m_bInX509Certificate = false;
265 			}
266 			else if (aName == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NSTAG_DC))
267         				+rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(":"))
268         				+rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(TAG_DATE)))
269 		{
270 			m_pXSecController->setDate( m_ouDate );
271         		m_bInDate = false;
272 		}
273 		/*
274 		else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_TIME)) )
275 		{
276 			m_pXSecController->setTime( m_ouTime );
277         		m_bInTime = false;
278 		}
279 		*/
280 
281 		if (m_xNextHandler.is())
282 		{
283 			m_xNextHandler->endElement(aName);
284 		}
285 	}
286 	catch (cssu::Exception& )
287 	{//getCaughtException MUST be the first line in the catch block
288         cssu::Any exc =  cppu::getCaughtException();
289         throw cssxs::SAXException(
290 			rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
291                               "xmlsecurity: Exception in XSecParser::endElement")),
292             0, exc);
293 	}
294 	catch (...)
295 	{
296 		throw cssxs::SAXException(
297 			rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xmlsecurity: unexpected exception in XSecParser::endElement")), 0,
298 			cssu::Any());
299 	}
300 }
301 
302 void SAL_CALL XSecParser::characters( const rtl::OUString& aChars )
303 	throw (cssxs::SAXException, cssu::RuntimeException)
304 {
305 	if (m_bInX509IssuerName)
306 	{
307 		m_ouX509IssuerName += aChars;
308 	}
309 	else if (m_bInX509SerialNumber)
310 	{
311 		m_ouX509SerialNumber += aChars;
312 	}
313 	else if (m_bInX509Certificate)
314 	{
315 		m_ouX509Certificate += aChars;
316 	}
317 	else if (m_bInSignatureValue)
318 	{
319 		m_ouSignatureValue += aChars;
320 	}
321 	else if (m_bInDigestValue)
322 	{
323 		m_ouDigestValue += aChars;
324 	}
325 	else if (m_bInDate)
326 	{
327 		m_ouDate += aChars;
328 	}
329 	/*
330 	else if (m_bInTime)
331 	{
332 		m_ouTime += aChars;
333 	}
334 	*/
335 
336 	if (m_xNextHandler.is())
337 	{
338 		m_xNextHandler->characters(aChars);
339         }
340 }
341 
342 void SAL_CALL XSecParser::ignorableWhitespace( const rtl::OUString& aWhitespaces )
343 	throw (cssxs::SAXException, cssu::RuntimeException)
344 {
345 	if (m_xNextHandler.is())
346 	{
347 		m_xNextHandler->ignorableWhitespace( aWhitespaces );
348         }
349 }
350 
351 void SAL_CALL XSecParser::processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData )
352 	throw (cssxs::SAXException, cssu::RuntimeException)
353 {
354 	if (m_xNextHandler.is())
355 	{
356 		m_xNextHandler->processingInstruction(aTarget, aData);
357         }
358 }
359 
360 void SAL_CALL XSecParser::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator )
361 	throw (cssxs::SAXException, cssu::RuntimeException)
362 {
363 	if (m_xNextHandler.is())
364 	{
365 		m_xNextHandler->setDocumentLocator( xLocator );
366         }
367 }
368 
369 /*
370  * XInitialization
371  */
372 void SAL_CALL XSecParser::initialize(
373 	const cssu::Sequence< cssu::Any >& aArguments )
374 	throw(cssu::Exception, cssu::RuntimeException)
375 {
376 	aArguments[0] >>= m_xNextHandler;
377 }
378