1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_xmlsecurity.hxx" 26 27 /* 28 * Implementation of the I/O interfaces based on stream and URI binding 29 */ 30 #include "xmlstreamio.hxx" 31 #include <rtl/ustring.hxx> 32 #include "rtl/uri.hxx" 33 34 #include <libxml/uri.h> 35 #include <sal/types.h> 36 //For reasons that escape me, this is what xmlsec does when size_t is not 4 37 #if SAL_TYPES_SIZEOFPOINTER != 4 38 # define XMLSEC_NO_SIZE_T 39 #endif 40 #include <xmlsec/io.h> 41 42 #define XMLSTREAMIO_INITIALIZED 0x01 43 #define XMLSTREAMIO_REGISTERED 0x02 44 45 /* Global variables */ 46 /*- 47 * Enable stream I/O or not. 48 */ 49 static char enableXmlStreamIO = 0x00 ; 50 51 ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XUriBinding > m_xUriBinding ; 52 53 extern "C" 54 int xmlStreamMatch( const char* uri ) 55 { 56 ::com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream ; 57 58 if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) && 59 ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 60 if( uri == NULL || !m_xUriBinding.is() ) 61 return 0 ; 62 //XMLSec first unescapes the uri and calls this function. For example, we pass the Uri 63 //ObjectReplacements/Object%201 then XMLSec passes ObjectReplacements/Object 1 64 //first. If this failed it would try this 65 //again with the original escaped string. However, it does not get this far, because there 66 //is another callback registered by libxml which claims to be able to handle this uri. 67 ::rtl::OUString sUri = 68 ::rtl::Uri::encode( ::rtl::OUString::createFromAscii( uri ), 69 rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes, RTL_TEXTENCODING_UTF8); 70 xInputStream = m_xUriBinding->getUriBinding( sUri ) ; 71 if (!xInputStream.is()) 72 { 73 //Try the the passed in uri directly. 74 //For old documents prior OOo 3.0. We did not use URIs then. 75 xInputStream = m_xUriBinding->getUriBinding( 76 ::rtl::OUString::createFromAscii(uri)); 77 } 78 } 79 if (xInputStream.is()) 80 return 1; 81 else 82 return 0 ; 83 } 84 85 extern "C" 86 void* xmlStreamOpen( const char* uri ) 87 { 88 ::com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream ; 89 ::com::sun::star::io::XInputStream* pInputStream ; 90 91 if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) && 92 ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 93 if( uri == NULL || !m_xUriBinding.is() ) 94 return NULL ; 95 96 //see xmlStreamMatch 97 ::rtl::OUString sUri = 98 ::rtl::Uri::encode( ::rtl::OUString::createFromAscii( uri ), 99 rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes, RTL_TEXTENCODING_UTF8); 100 xInputStream = m_xUriBinding->getUriBinding( sUri ) ; 101 if (!xInputStream.is()) 102 { 103 //For old documents. 104 //try the the passed in uri directly. 105 xInputStream = m_xUriBinding->getUriBinding( 106 ::rtl::OUString::createFromAscii(uri)); 107 } 108 109 if( xInputStream.is() ) { 110 pInputStream = xInputStream.get() ; 111 pInputStream->acquire() ; 112 return ( void* )pInputStream ; 113 } 114 } 115 116 return NULL ; 117 } 118 119 extern "C" 120 int xmlStreamRead( void* context, char* buffer, int len ) 121 { 122 int numbers ; 123 ::com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream ; 124 ::com::sun::star::uno::Sequence< sal_Int8 > outSeqs( len ) ; 125 126 numbers = 0 ; 127 if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) && 128 ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 129 if( context != NULL ) { 130 xInputStream = ( com::sun::star::io::XInputStream* )context ; 131 if( !xInputStream.is() ) 132 return 0 ; 133 134 numbers = xInputStream->readBytes( outSeqs, len ) ; 135 const sal_Int8* readBytes = ( const sal_Int8* )outSeqs.getArray() ; 136 for( int i = 0 ; i < numbers ; i ++ ) 137 *( buffer + i ) = *( readBytes + i ) ; 138 } 139 } 140 141 return numbers ; 142 } 143 144 extern "C" 145 int xmlStreamClose( void * context ) 146 { 147 ::com::sun::star::io::XInputStream* pInputStream ; 148 149 if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) && 150 ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 151 if( context != NULL ) { 152 pInputStream = ( ::com::sun::star::io::XInputStream* )context ; 153 pInputStream->release() ; 154 } 155 } 156 157 return 0 ; 158 } 159 160 int xmlEnableStreamInputCallbacks() 161 { 162 int cbs = 0 ; 163 164 if( !( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) ) { 165 //Register the callbacks into libxml2 166 //cbs = xmlRegisterInputCallbacks( 167 // xmlStreamMatch, 168 // xmlStreamOpen, 169 // xmlStreamRead, 170 // xmlStreamClose ) ; 171 //if( cbs < 0 ) { 172 // return -1 ; 173 //} 174 175 //Register the callbacks into xmlSec 176 //In order to make the xmlsec io finding the callbacks firstly, 177 //I put the callbacks at the very begining. 178 179 //Cleanup the older callbacks. 180 //Notes: all none default callbacks will lose. 181 xmlSecIOCleanupCallbacks() ; 182 183 //Register my classbacks. 184 cbs = xmlSecIORegisterCallbacks( 185 xmlStreamMatch, 186 xmlStreamOpen, 187 xmlStreamRead, 188 xmlStreamClose ) ; 189 if( cbs < 0 ) { 190 return -1 ; 191 } 192 193 //Register the default callbacks. 194 //Notes: the error will cause xmlsec working problems. 195 cbs = xmlSecIORegisterDefaultCallbacks() ; 196 if( cbs < 0 ) { 197 return -1 ; 198 } 199 200 enableXmlStreamIO |= XMLSTREAMIO_INITIALIZED ; 201 } 202 203 return 0 ; 204 } 205 206 int xmlRegisterStreamInputCallbacks( 207 ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XUriBinding >& aUriBinding 208 ) { 209 if( !( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) ) { 210 if( xmlEnableStreamInputCallbacks() < 0 ) 211 return -1 ; 212 } 213 214 if( !( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 215 enableXmlStreamIO |= XMLSTREAMIO_REGISTERED ; 216 } 217 218 m_xUriBinding = aUriBinding ; 219 220 return 0 ; 221 } 222 223 int xmlUnregisterStreamInputCallbacks( void ) 224 { 225 if( ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 226 //Clear the uir-stream binding 227 m_xUriBinding.clear() ; 228 229 //disable the registered flag 230 enableXmlStreamIO &= ~XMLSTREAMIO_REGISTERED ; 231 } 232 233 return 0 ; 234 } 235 236 void xmlDisableStreamInputCallbacks() { 237 xmlUnregisterStreamInputCallbacks() ; 238 enableXmlStreamIO &= ~XMLSTREAMIO_INITIALIZED ; 239 } 240 241