xref: /AOO41X/main/uui/source/iahndl-ssl.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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 
29 #include "com/sun/star/security/CertificateValidity.hpp"
30 #include "com/sun/star/security/XCertificateExtension.hpp"
31 #include "com/sun/star/security/XSanExtension.hpp"
32 #include <com/sun/star/security/ExtAltNameType.hpp>
33 #include "com/sun/star/task/XInteractionAbort.hpp"
34 #include "com/sun/star/task/XInteractionApprove.hpp"
35 #include "com/sun/star/task/XInteractionRequest.hpp"
36 #include "com/sun/star/ucb/CertificateValidationRequest.hpp"
37 #include <com/sun/star/uno/Reference.hxx>
38 
39 #include <com/sun/star/uno/Sequence.hxx>
40 #include "vos/mutex.hxx"
41 #include "tools/datetime.hxx"
42 #include "svl/zforlist.hxx"
43 #include "vcl/svapp.hxx"
44 
45 #include "ids.hrc"
46 #include "getcontinuations.hxx"
47 #include "sslwarndlg.hxx"
48 #include "unknownauthdlg.hxx"
49 
50 #include "iahndl.hxx"
51 
52 #define DESCRIPTION_1 1
53 #define DESCRIPTION_2 2
54 #define TITLE 3
55 
56 #define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17"
57 
58 
59 using namespace com::sun::star;
60 
61 namespace {
62 
63 String
64 getContentPart( const String& _rRawString )
65 {
66     // search over some parts to find a string
67     //static char* aIDs[] = { "CN", "OU", "O", "E", NULL };
68     static char const * aIDs[] = { "CN=", "OU=", "O=", "E=", NULL };// By CP
69     String sPart;
70     int i = 0;
71     while ( aIDs[i] )
72     {
73         String sPartId = String::CreateFromAscii( aIDs[i++] );
74         xub_StrLen nContStart = _rRawString.Search( sPartId );
75         if ( nContStart != STRING_NOTFOUND )
76         {
77             nContStart = nContStart + sPartId.Len();
78             xub_StrLen nContEnd
79                 = _rRawString.Search( sal_Unicode( ',' ), nContStart );
80             sPart = String( _rRawString, nContStart, nContEnd - nContStart );
81             break;
82         }
83     }
84     return sPart;
85 }
86 
87 bool
88 isDomainMatch(
89               rtl::OUString hostName, uno::Sequence< ::rtl::OUString > certHostNames)
90 {
91     for ( int i = 0; i < certHostNames.getLength(); i++){
92         ::rtl::OUString element = certHostNames[i];
93 
94        if (element.getLength() == 0)
95            continue;
96 
97        if (hostName.equalsIgnoreAsciiCase( element ))
98            return true;
99 
100        if ( 0 == element.indexOf( rtl::OUString::createFromAscii( "*" ) ) &&
101                  hostName.getLength() >= element.getLength()  )
102        {
103            rtl::OUString cmpStr = element.copy( 1 );
104            if ( hostName.matchIgnoreAsciiCase(
105                     cmpStr, hostName.getLength() - cmpStr.getLength()) )
106                return true;
107        }
108     }
109 
110     return false;
111 }
112 
113 rtl::OUString
114 getLocalizedDatTimeStr(
115     uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
116     util::DateTime const & rDateTime )
117 {
118     rtl::OUString aDateTimeStr;
119     Date  aDate;
120     Time  aTime;
121 
122     aDate = Date( rDateTime.Day, rDateTime.Month, rDateTime.Year );
123     aTime = Time( rDateTime.Hours, rDateTime.Minutes, rDateTime.Seconds );
124 
125     LanguageType eUILang = Application::GetSettings().GetUILanguage();
126     SvNumberFormatter *pNumberFormatter
127         = new SvNumberFormatter( xServiceFactory, eUILang );
128     String      aTmpStr;
129     Color*      pColor = NULL;
130     Date*       pNullDate = pNumberFormatter->GetNullDate();
131     sal_uInt32  nFormat
132         = pNumberFormatter->GetStandardFormat( NUMBERFORMAT_DATE, eUILang );
133 
134     pNumberFormatter->GetOutputString(
135         aDate - *pNullDate, nFormat, aTmpStr, &pColor );
136     aDateTimeStr = aTmpStr + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" "));
137 
138     nFormat = pNumberFormatter->GetStandardFormat( NUMBERFORMAT_TIME, eUILang );
139     pNumberFormatter->GetOutputString(
140         aTime.GetTimeInDays(), nFormat, aTmpStr, &pColor );
141     aDateTimeStr += aTmpStr;
142 
143     return aDateTimeStr;
144 }
145 
146 sal_Bool
147 executeUnknownAuthDialog(
148     Window * pParent,
149     uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
150     const uno::Reference< security::XCertificate >& rXCert)
151     SAL_THROW((uno::RuntimeException))
152 {
153     try
154     {
155         vos::OGuard aGuard(Application::GetSolarMutex());
156 
157         std::auto_ptr< ResMgr > xManager(
158             ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(uui)));
159         std::auto_ptr< UnknownAuthDialog > xDialog(
160             new UnknownAuthDialog( pParent,
161                                    rXCert,
162                                    xServiceFactory,
163                                    xManager.get()));
164 
165         // Get correct ressource string
166         rtl::OUString aMessage;
167 
168         std::vector< rtl::OUString > aArguments;
169         aArguments.push_back( getContentPart( rXCert->getSubjectName()) );
170 
171         if (xManager.get())
172         {
173             ResId aResId(RID_UUI_ERRHDL, *xManager.get());
174             if (ErrorResource(aResId).getString(
175                     ERRCODE_UUI_UNKNOWNAUTH_UNTRUSTED, &aMessage))
176             {
177                 aMessage = UUIInteractionHelper::replaceMessageWithArguments(
178                     aMessage, aArguments );
179                 xDialog->setDescriptionText( aMessage );
180             }
181         }
182 
183         return static_cast<sal_Bool> (xDialog->Execute());
184     }
185     catch (std::bad_alloc const &)
186     {
187         throw uno::RuntimeException(
188                   rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("out of memory")),
189                   uno::Reference< uno::XInterface >());
190     }
191 }
192 
193 sal_Bool
194 executeSSLWarnDialog(
195     Window * pParent,
196     uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
197     const uno::Reference< security::XCertificate >& rXCert,
198     sal_Int32 const & failure,
199     const rtl::OUString & hostName )
200     SAL_THROW((uno::RuntimeException))
201 {
202     try
203     {
204         vos::OGuard aGuard(Application::GetSolarMutex());
205 
206         std::auto_ptr< ResMgr > xManager(
207            ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(uui)));
208         std::auto_ptr< SSLWarnDialog > xDialog(
209            new SSLWarnDialog( pParent,
210                               rXCert,
211                               xServiceFactory,
212                               xManager.get()));
213 
214         // Get correct ressource string
215         rtl::OUString aMessage_1;
216         std::vector< rtl::OUString > aArguments_1;
217 
218         switch( failure )
219         {
220             case SSLWARN_TYPE_DOMAINMISMATCH:
221                 aArguments_1.push_back( hostName );
222                 aArguments_1.push_back(
223                     getContentPart( rXCert->getSubjectName()) );
224                 aArguments_1.push_back( hostName );
225                 break;
226             case SSLWARN_TYPE_EXPIRED:
227                 aArguments_1.push_back(
228                     getContentPart( rXCert->getSubjectName()) );
229                 aArguments_1.push_back(
230                     getLocalizedDatTimeStr( xServiceFactory,
231                                             rXCert->getNotValidAfter() ) );
232                 aArguments_1.push_back(
233                     getLocalizedDatTimeStr( xServiceFactory,
234                                             rXCert->getNotValidAfter() ) );
235                 break;
236             case SSLWARN_TYPE_INVALID:
237                 break;
238         }
239 
240         if (xManager.get())
241         {
242             ResId aResId(RID_UUI_ERRHDL, *xManager.get());
243             if (ErrorResource(aResId).getString(
244                     ERRCODE_AREA_UUI_UNKNOWNAUTH + failure + DESCRIPTION_1,
245                     &aMessage_1))
246             {
247                 aMessage_1 = UUIInteractionHelper::replaceMessageWithArguments(
248                     aMessage_1, aArguments_1 );
249                 xDialog->setDescription1Text( aMessage_1 );
250             }
251 
252             rtl::OUString aTitle;
253             ErrorResource(aResId).getString(
254                 ERRCODE_AREA_UUI_UNKNOWNAUTH + failure + TITLE, &aTitle);
255             xDialog->SetText( aTitle );
256         }
257 
258         return static_cast<sal_Bool> (xDialog->Execute());
259     }
260     catch (std::bad_alloc const &)
261     {
262         throw uno::RuntimeException(
263                   rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("out of memory")),
264                   uno::Reference< uno::XInterface >());
265     }
266 }
267 
268 void
269 handleCertificateValidationRequest_(
270     Window * pParent,
271     uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
272     ucb::CertificateValidationRequest const & rRequest,
273     uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
274         rContinuations)
275     SAL_THROW((uno::RuntimeException))
276 {
277     uno::Reference< task::XInteractionApprove > xApprove;
278     uno::Reference< task::XInteractionAbort > xAbort;
279     getContinuations(rContinuations, &xApprove, &xAbort);
280 
281     sal_Int32 failures = rRequest.CertificateValidity;
282     sal_Bool trustCert = sal_True;
283 
284     if ( ((failures & security::CertificateValidity::UNTRUSTED)
285              == security::CertificateValidity::UNTRUSTED ) ||
286          ((failures & security::CertificateValidity::ISSUER_UNTRUSTED)
287              == security::CertificateValidity::ISSUER_UNTRUSTED) ||
288          ((failures & security::CertificateValidity::ROOT_UNTRUSTED)
289              == security::CertificateValidity::ROOT_UNTRUSTED) )
290     {
291         trustCert = executeUnknownAuthDialog( pParent,
292                                               xServiceFactory,
293                                               rRequest.Certificate );
294     }
295 
296     uno::Sequence< uno::Reference< security::XCertificateExtension > > extensions = rRequest.Certificate->getExtensions();
297     uno::Sequence< security::CertAltNameEntry > altNames;
298     for (sal_Int32 i = 0 ; i < extensions.getLength(); i++){
299         uno::Reference< security::XCertificateExtension >element = extensions[i];
300 
301         rtl::OString aId ( (const sal_Char *)element->getExtensionId().getArray(), element->getExtensionId().getLength());
302         if (aId.equals(OID_SUBJECT_ALTERNATIVE_NAME))
303         {
304            uno::Reference< security::XSanExtension > sanExtension ( element, uno::UNO_QUERY );
305            altNames =  sanExtension->getAlternativeNames();
306            break;
307         }
308     }
309 
310     ::rtl::OUString certHostName = getContentPart( rRequest.Certificate->getSubjectName() );
311     uno::Sequence< ::rtl::OUString > certHostNames(altNames.getLength() + 1);
312 
313     certHostNames[0] = certHostName;
314 
315     for(int n = 1; n < altNames.getLength(); n++){
316         if (altNames[n].Type ==  security::ExtAltNameType_DNS_NAME){
317            altNames[n].Value >>= certHostNames[n];
318         }
319     }
320 
321     if ( (!isDomainMatch(
322               rRequest.HostName,
323               certHostNames )) &&
324           trustCert )
325     {
326         trustCert = executeSSLWarnDialog( pParent,
327                                           xServiceFactory,
328                                           rRequest.Certificate,
329                                           SSLWARN_TYPE_DOMAINMISMATCH,
330                                           rRequest.HostName );
331     }
332 
333     if ( (((failures & security::CertificateValidity::TIME_INVALID)
334               == security::CertificateValidity::TIME_INVALID) ||
335           ((failures & security::CertificateValidity::NOT_TIME_NESTED)
336               == security::CertificateValidity::NOT_TIME_NESTED)) &&
337          trustCert )
338     {
339         trustCert = executeSSLWarnDialog( pParent,
340                                           xServiceFactory,
341                                           rRequest.Certificate,
342                                           SSLWARN_TYPE_EXPIRED,
343                                           rRequest.HostName );
344     }
345 
346     if ( (((failures & security::CertificateValidity::REVOKED)
347               == security::CertificateValidity::REVOKED) ||
348           ((failures & security::CertificateValidity::SIGNATURE_INVALID)
349               == security::CertificateValidity::SIGNATURE_INVALID) ||
350           ((failures & security::CertificateValidity::EXTENSION_INVALID)
351               == security::CertificateValidity::EXTENSION_INVALID) ||
352           ((failures & security::CertificateValidity::INVALID)
353               == security::CertificateValidity::INVALID)) &&
354          trustCert )
355     {
356         trustCert = executeSSLWarnDialog( pParent,
357                                           xServiceFactory,
358                                           rRequest.Certificate,
359                                           SSLWARN_TYPE_INVALID,
360                                           rRequest.HostName );
361     }
362 
363     if ( trustCert )
364     {
365         if (xApprove.is())
366             xApprove->select();
367     }
368     else
369     {
370         if (xAbort.is())
371             xAbort->select();
372     }
373 }
374 
375 } // namespace
376 
377 bool
378 UUIInteractionHelper::handleCertificateValidationRequest(
379     uno::Reference< task::XInteractionRequest > const & rRequest)
380     SAL_THROW((uno::RuntimeException))
381 {
382     uno::Any aAnyRequest(rRequest->getRequest());
383 
384     ucb::CertificateValidationRequest aCertificateValidationRequest;
385     if (aAnyRequest >>= aCertificateValidationRequest)
386     {
387         handleCertificateValidationRequest_(getParentProperty(),
388                                             m_xServiceFactory,
389                                             aCertificateValidationRequest,
390                                             rRequest->getContinuations());
391         return true;
392     }
393 
394     return false;
395 }
396 
397