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 #ifndef INCLUDED_CURLSESSION_HXX
25 #define INCLUDED_CURLSESSION_HXX
26 
27 #include <vector>
28 #include <boost/shared_ptr.hpp>
29 #include <osl/mutex.hxx>
30 #include <comphelper/componentcontext.hxx>
31 #include <comphelper/logging.hxx>
32 #include "DAVResource.hxx"
33 #include "DAVSession.hxx"
34 #include "CurlTypes.hxx"
35 #include "CurlRequest.hxx"
36 #include "CurlLockStore.hxx"
37 #include "CurlUri.hxx"
38 #include "CurlInputStream.hxx"
39 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
40 #include <com/sun/star/security/CertificateContainer.hpp>
41 #include <com/sun/star/security/XCertificateContainer.hpp>
42 #include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
43 #include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
44 #include <curl/curl.h>
45 #include <openssl/ssl.h>
46 
47 namespace ucbhelper { class ProxyDecider; }
48 
49 namespace http_dav_ucp
50 {
51 
52 // -------------------------------------------------------------------
53 // CurlSession
54 // A DAVSession implementation using the Curl library
55 // -------------------------------------------------------------------
56 
57 class CurlSession : public DAVSession
58 {
59 private:
60     osl::Mutex                      m_aMutex;
61     ::comphelper::ComponentContext  m_aContext;
62     ::comphelper::EventLogger       m_aLogger;
63 
64     CurlUri                 m_aUri;
65 
66     rtl::OUString           m_aProxyName;
67     sal_Int32               m_nProxyPort;
68     // The server, according RFC7231
69     // http://tools.ietf.org/html/rfc7231#section-7.4.2
70     rtl::OString            m_aServerHeaderField;
71 
72     CURL*                   m_pCurl;
73     bool                    m_bUseChunkedEncoding;
74     bool                    m_bTransferEncodingSwitched;
75 
76     const ucbhelper::InternetProxyDecider & m_rProxyDecider;
77 
78     DAVRequestEnvironment m_aEnv;
79 
80     static CurlLockStore m_aCurlLockStore;
81 
82     ::com::sun::star::uno::Reference< ::com::sun::star::security::XCertificateContainer > m_xCertificateContainer;
83     ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XXMLSecurityContext > m_xSecurityContext;
84     ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > m_xSecurityEnv;
85 
86     bool isSSLNeeded();
87 
88 
89     rtl::OUString           composeCurrentUri( const rtl::OUString & inPath );
90     void                    addEnvironmentRequestHeaders( CurlRequest &curlRequest,
91                                                           const DAVRequestEnvironment &env )
92                                 throw ( DAVException );
93     void                    processResponse( CurlRequest &curlRequest,
94                                              CURLcode curlCode )
95                                 throw ( DAVException );
96 
97     static CURLcode         Curl_SSLContextCallback( CURL *curl,
98                                                      void *ssl_ctx,
99                                                      void *userptr );
100     static int              OPENSSL_VerifyCertificate( X509_STORE_CTX *x509_ctx, void *arg );
101     int                     verifyServerX509Certificate( X509_STORE_CTX *x509StoreContext );
102     int                     verifyCertificateChain (
103                                 std::vector< uno::Sequence< sal_Int8 > > &asn1DerCertificates );
104 
105     static int              Curl_DebugCallback( CURL *,
106                                                 curl_infotype type,
107                                                 unsigned char *data,
108                                                 size_t size,
109                                                 void* userdata );
110     int                     curlDebugOutput( curl_infotype type, char *data, int size );
111 
112     static bool             Curl_ProvideCredentials( long statusCode,
113                                                      void *userdata ) throw (DAVException);
114     bool                    provideCredentials( const DAVRequestEnvironment &env,
115                                                 CurlRequest &request,
116                                                 long statusCode ) throw (DAVException);
117 
118 protected:
119     virtual ~CurlSession();
120 
121 public:
122     CurlSession( const rtl::Reference< DAVSessionFactory > & rSessionFactory,
123                  const rtl::OUString& inUri,
124                  const ucbhelper::InternetProxyDecider & rProxyDecider )
125         throw ( DAVException );
126 
127     // DAVSession methods
128     virtual sal_Bool CanUse( const ::rtl::OUString & inUri );
129 
130     virtual sal_Bool UsesProxy();
131 
getRequestEnvironment() const132     const DAVRequestEnvironment & getRequestEnvironment() const
133     { return m_aEnv; }
134 
135     // allprop & named
136     virtual void
137     PROPFIND( const ::rtl::OUString & inPath,
138               const Depth inDepth,
139               const std::vector< ::rtl::OUString > & inPropNames,
140               std::vector< DAVResource > & ioResources,
141               const DAVRequestEnvironment & rEnv )
142         throw ( DAVException );
143 
144     // propnames
145     virtual void
146     PROPFIND( const ::rtl::OUString & inPath,
147               const Depth inDepth,
148               std::vector< DAVResourceInfo >& ioResInfo,
149               const DAVRequestEnvironment & rEnv )
150         throw ( DAVException );
151 
152     virtual void
153     PROPPATCH( const ::rtl::OUString & inPath,
154                const std::vector< ProppatchValue > & inValues,
155                const DAVRequestEnvironment & rEnv )
156         throw ( DAVException );
157 
158     virtual void
159     HEAD( const ::rtl::OUString &  inPath,
160           const std::vector< ::rtl::OUString > & inHeaderNames,
161           DAVResource & ioResource,
162           const DAVRequestEnvironment & rEnv )
163         throw ( DAVException );
164 
165     virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
166     GET( const ::rtl::OUString & inPath,
167          const DAVRequestEnvironment & rEnv )
168         throw ( DAVException );
169 
170     virtual void
171     GET( const ::rtl::OUString & inPath,
172          com::sun::star::uno::Reference<
173              com::sun::star::io::XOutputStream > &  ioOutputStream,
174          const DAVRequestEnvironment & rEnv )
175         throw ( DAVException );
176 
177     virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
178     GET( const ::rtl::OUString & inPath,
179          const std::vector< ::rtl::OUString > & inHeaderNames,
180          DAVResource & ioResource,
181          const DAVRequestEnvironment & rEnv )
182         throw ( DAVException );
183 
184     virtual void
185     GET( const ::rtl::OUString & inPath,
186          com::sun::star::uno::Reference<
187              com::sun::star::io::XOutputStream > & ioOutputStream,
188          const std::vector< ::rtl::OUString > & inHeaderNames,
189          DAVResource & ioResource,
190          const DAVRequestEnvironment & rEnv )
191         throw ( DAVException );
192 
193     virtual void
194     PUT( const ::rtl::OUString & inPath,
195          const com::sun::star::uno::Reference<
196              com::sun::star::io::XInputStream > & inInputStream,
197          const DAVRequestEnvironment & rEnv )
198         throw ( DAVException );
199 
200     virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
201     POST( const rtl::OUString & inPath,
202           const rtl::OUString & rContentType,
203           const rtl::OUString & rReferer,
204           const com::sun::star::uno::Reference<
205               com::sun::star::io::XInputStream > & inInputStream,
206           const DAVRequestEnvironment & rEnv )
207         throw ( DAVException );
208 
209     virtual void
210     POST( const rtl::OUString & inPath,
211           const rtl::OUString & rContentType,
212           const rtl::OUString & rReferer,
213           const com::sun::star::uno::Reference<
214               com::sun::star::io::XInputStream > & inInputStream,
215           com::sun::star::uno::Reference<
216               com::sun::star::io::XOutputStream > & oOutputStream,
217           const DAVRequestEnvironment & rEnv )
218         throw ( DAVException );
219 
220     virtual void
221     MKCOL( const ::rtl::OUString & inPath,
222            const DAVRequestEnvironment & rEnv )
223         throw ( DAVException );
224 
225     virtual void
226     COPY( const ::rtl::OUString & inSourceURL,
227           const ::rtl::OUString & inDestinationURL,
228           const DAVRequestEnvironment & rEnv,
229           sal_Bool inOverWrite )
230         throw ( DAVException );
231 
232     virtual void
233     MOVE( const ::rtl::OUString & inSourceURL,
234           const ::rtl::OUString & inDestinationURL,
235           const DAVRequestEnvironment & rEnv,
236           sal_Bool inOverWrite )
237         throw ( DAVException );
238 
239     virtual void DESTROY( const ::rtl::OUString & inPath,
240                           const DAVRequestEnvironment & rEnv )
241         throw ( DAVException );
242 
243     // set new lock.
244     virtual void LOCK( const ::rtl::OUString & inURL,
245                        com::sun::star::ucb::Lock & inLock,
246                        const DAVRequestEnvironment & rEnv )
247         throw ( DAVException );
248 
249     // refresh existing lock.
250     virtual sal_Int64 LOCK( const ::rtl::OUString & inURL,
251                             sal_Int64 nTimeout,
252                             const DAVRequestEnvironment & rEnv )
253         throw ( DAVException );
254 
255     virtual void UNLOCK( const ::rtl::OUString & inURL,
256                          const DAVRequestEnvironment & rEnv )
257         throw ( DAVException );
258 
259     // helpers
260     virtual void abort()
261         throw ( DAVException );
262 
getHostName() const263     const rtl::OUString & getHostName() const { return m_aUri.GetHost(); }
getPort() const264     int getPort() const { return m_aUri.GetPort(); }
265 
getMSF()266     const ::uno::Reference< ::lang::XMultiServiceFactory > getMSF()
267     { return m_xFactory->getServiceFactory(); }
268 
269     sal_Bool isDomainMatch( rtl::OUString certHostName );
270 
getServerHeaderField()271     const rtl::OString & getServerHeaderField() { return m_aServerHeaderField; };
272 
273 private:
274     friend class CurlLockStore;
275 
276     void Init( void )
277         throw ( DAVException );
278 
279     void Init( const DAVRequestEnvironment & rEnv )
280         throw ( DAVException );
281 
282     const ucbhelper::InternetProxyServer & getProxySettings() const;
283 
284     void propfind( CurlRequest &curlRequest,
285                    const rtl::OUString &inPath,
286                    const Depth inDepth,
287                    const std::vector< ::rtl::OUString > * propNames,
288                    const bool onlyPropertyNames,
289                    const DAVRequestEnvironment & rEnv );
290 
291     bool removeExpiredLocktoken( const rtl::OUString & inURL,
292                                  const DAVRequestEnvironment & rEnv );
293 
294     // refresh lock, called by CurlLockStore::refreshLocks
295     bool LOCK( CurlLock * pLock,
296                sal_Int32 & rlastChanceToSendRefreshRequest );
297 
298     // unlock, called by CurlLockStore::~CurlLockStore
299     bool UNLOCK( CurlLock * pLock );
300 
301     /*
302     // low level GET implementation, used by public GET implementations
303     static int GET( CurlConnection * sess,
304                     const char * uri,
305                     //ne_block_reader reader,
306                     bool getheaders,
307                     void * userdata );
308 
309     // Buffer-based PUT implementation. Serf only has file descriptor-
310     // based API.
311     static int PUT( CurlConnection * sess,
312                     const char * uri,
313                     const char * buffer,
314                     size_t size );
315 
316     // Buffer-based POST implementation. Serf only has file descriptor-
317     // based API.
318     int POST( CurlConnection * sess,
319               const char * uri,
320               const char * buffer,
321               //ne_block_reader reader,
322               void * userdata,
323               const rtl::OUString & rContentType,
324               const rtl::OUString & rReferer );
325     */
326 
327     // Helper: XInputStream -> Sequence< sal_Int8 >
328     static bool getDataFromInputStream(
329         const com::sun::star::uno::Reference<
330             com::sun::star::io::XInputStream > & xStream,
331         com::sun::star::uno::Sequence< sal_Int8 > & rData,
332         bool bAppendTrailingZeroByte );
333 
334     /*
335     rtl::OUString makeAbsoluteURL( rtl::OUString const & rURL ) const;
336     */
337 };
338 
339 } // namespace http_dav_ucp
340 
341 #endif // INCLUDED_CURLSESSION_HXX
342