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 <xmlsecurity/certificatechooser.hxx> 32 #include <xmlsecurity/certificateviewer.hxx> 33 #include <xmlsecurity/biginteger.hxx> 34 #include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> 35 #include <comphelper/sequence.hxx> 36 #include <comphelper/processfactory.hxx> 37 38 #include <com/sun/star/security/NoPasswordException.hpp> 39 #include <com/sun/star/security/CertificateCharacters.hpp> 40 #include <com/sun/star/security/SerialNumberAdapter.hpp> 41 42 #include <dialogs.hrc> 43 #include <resourcemanager.hxx> 44 #include <vcl/msgbox.hxx> 45 46 /* HACK: disable some warnings for MS-C */ 47 #ifdef _MSC_VER 48 #pragma warning (disable : 4355) // 4355: this used in initializer-list 49 #endif 50 51 using namespace ::com::sun::star; 52 53 #define INVAL_SEL 0xFFFF 54 55 sal_uInt16 CertificateChooser::GetSelectedEntryPos( void ) const 56 { 57 sal_uInt16 nSel = INVAL_SEL; 58 59 SvLBoxEntry* pSel = maCertLB.FirstSelected(); 60 if( pSel ) 61 nSel = (sal_uInt16) ( sal_uIntPtr ) pSel->GetUserData(); 62 63 return (sal_uInt16) nSel; 64 } 65 66 CertificateChooser::CertificateChooser( Window* _pParent, uno::Reference< uno::XComponentContext>& _rxCtx, uno::Reference< dcss::xml::crypto::XSecurityEnvironment >& _rxSecurityEnvironment, const SignatureInformations& _rCertsToIgnore ) 67 :ModalDialog ( _pParent, XMLSEC_RES( RID_XMLSECDLG_CERTCHOOSER ) ) 68 ,maCertsToIgnore( _rCertsToIgnore ) 69 ,maHintFT ( this, XMLSEC_RES( FT_HINT_SELECT ) ) 70 ,maCertLB ( this, XMLSEC_RES( LB_SIGNATURES ) ) 71 ,maViewBtn ( this, XMLSEC_RES( BTN_VIEWCERT ) ) 72 ,maBottomSepFL ( this, XMLSEC_RES( FL_BOTTOM_SEP ) ) 73 ,maOKBtn ( this, XMLSEC_RES( BTN_OK ) ) 74 ,maCancelBtn ( this, XMLSEC_RES( BTN_CANCEL ) ) 75 ,maHelpBtn ( this, XMLSEC_RES( BTN_HELP ) ) 76 { 77 static long nTabs[] = { 3, 0, 30*CS_LB_WIDTH/100, 60*CS_LB_WIDTH/100 }; 78 maCertLB.SetTabs( &nTabs[0] ); 79 maCertLB.InsertHeaderEntry( String( XMLSEC_RES( STR_HEADERBAR ) ) ); 80 maCertLB.SetSelectHdl( LINK( this, CertificateChooser, CertificateHighlightHdl ) ); 81 maCertLB.SetDoubleClickHdl( LINK( this, CertificateChooser, CertificateSelectHdl ) ); 82 maViewBtn.SetClickHdl( LINK( this, CertificateChooser, ViewButtonHdl ) ); 83 84 FreeResource(); 85 86 mxCtx = _rxCtx; 87 mxSecurityEnvironment = _rxSecurityEnvironment; 88 mbInitialized = sal_False; 89 90 // disable buttons 91 CertificateHighlightHdl( NULL ); 92 } 93 94 CertificateChooser::~CertificateChooser() 95 { 96 } 97 98 short CertificateChooser::Execute() 99 { 100 // #i48432# 101 // We can't check for personal certificates before raising this dialog, 102 // because the mozilla implementation throws a NoPassword exception, 103 // if the user pressed cancel, and also if the database does not exist! 104 // But in the later case, the is no password query, and the user is confused 105 // that nothing happens when pressing "Add..." in the SignatureDialog. 106 107 // PostUserEvent( LINK( this, CertificateChooser, Initialize ) ); 108 109 // PostUserLink behavior is to slow, so do it directly before Execute(). 110 // Problem: This Dialog should be visible right now, and the parent should not be accessible. 111 // Show, Update, DIsableInput... 112 113 Window* pMe = this; 114 Window* pParent = GetParent(); 115 if ( pParent ) 116 pParent->EnableInput( sal_False ); 117 pMe->Show(); 118 pMe->Update(); 119 ImplInitialize(); 120 if ( pParent ) 121 pParent->EnableInput( sal_True ); 122 return ModalDialog::Execute(); 123 } 124 125 // IMPL_LINK( CertificateChooser, Initialize, void*, EMPTYARG ) 126 void CertificateChooser::ImplInitialize() 127 { 128 if ( !mbInitialized ) 129 { 130 try 131 { 132 maCerts = mxSecurityEnvironment->getPersonalCertificates(); 133 } 134 catch (security::NoPasswordException&) 135 { 136 } 137 138 uno::Reference< dcss::security::XSerialNumberAdapter> xSerialNumberAdapter = 139 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx); 140 141 sal_Int32 nCertificates = maCerts.getLength(); 142 sal_Int32 nCertificatesToIgnore = maCertsToIgnore.size(); 143 for( sal_Int32 nCert = nCertificates; nCert; ) 144 { 145 uno::Reference< security::XCertificate > xCert = maCerts[ --nCert ]; 146 sal_Bool bIgnoreThis = false; 147 148 // Do we already use that? 149 if( nCertificatesToIgnore ) 150 { 151 rtl::OUString aIssuerName = xCert->getIssuerName(); 152 for( sal_Int32 nSig = 0; nSig < nCertificatesToIgnore; ++nSig ) 153 { 154 const SignatureInformation& rInf = maCertsToIgnore[ nSig ]; 155 if ( ( aIssuerName == rInf.ouX509IssuerName ) && 156 ( xSerialNumberAdapter->toString( xCert->getSerialNumber() ) == rInf.ouX509SerialNumber ) ) 157 { 158 bIgnoreThis = true; 159 break; 160 } 161 } 162 } 163 164 if ( !bIgnoreThis ) 165 { 166 // Check if we have a private key for this... 167 long nCertificateCharacters = mxSecurityEnvironment->getCertificateCharacters( xCert ); 168 169 if ( !( nCertificateCharacters & security::CertificateCharacters::HAS_PRIVATE_KEY ) ) 170 bIgnoreThis = true; 171 172 } 173 174 if ( bIgnoreThis ) 175 { 176 ::comphelper::removeElementAt( maCerts, nCert ); 177 nCertificates = maCerts.getLength(); 178 } 179 } 180 181 // fill list of certificates; the first entry will be selected 182 for ( sal_Int32 nC = 0; nC < nCertificates; ++nC ) 183 { 184 String sEntry( XmlSec::GetContentPart( maCerts[ nC ]->getSubjectName() ) ); 185 sEntry += '\t'; 186 sEntry += XmlSec::GetContentPart( maCerts[ nC ]->getIssuerName() ); 187 sEntry += '\t'; 188 sEntry += XmlSec::GetDateString( maCerts[ nC ]->getNotValidAfter() ); 189 SvLBoxEntry* pEntry = maCertLB.InsertEntry( sEntry ); 190 pEntry->SetUserData( ( void* )nC ); // missuse user data as index 191 } 192 193 // enable/disable buttons 194 CertificateHighlightHdl( NULL ); 195 mbInitialized = sal_True; 196 } 197 } 198 199 200 uno::Reference< dcss::security::XCertificate > CertificateChooser::GetSelectedCertificate() 201 { 202 uno::Reference< dcss::security::XCertificate > xCert; 203 sal_uInt16 nSelected = GetSelectedEntryPos(); 204 if ( nSelected < maCerts.getLength() ) 205 xCert = maCerts[ nSelected ]; 206 return xCert; 207 } 208 209 IMPL_LINK( CertificateChooser, CertificateHighlightHdl, void*, EMPTYARG ) 210 { 211 sal_Bool bEnable = GetSelectedCertificate().is(); 212 maViewBtn.Enable( bEnable ); 213 maOKBtn.Enable( bEnable ); 214 return 0; 215 } 216 217 IMPL_LINK( CertificateChooser, CertificateSelectHdl, void*, EMPTYARG ) 218 { 219 EndDialog( RET_OK ); 220 return 0; 221 } 222 223 IMPL_LINK( CertificateChooser, ViewButtonHdl, Button*, EMPTYARG ) 224 { 225 ImplShowCertificateDetails(); 226 return 0; 227 } 228 229 void CertificateChooser::ImplShowCertificateDetails() 230 { 231 uno::Reference< dcss::security::XCertificate > xCert = GetSelectedCertificate(); 232 if( xCert.is() ) 233 { 234 CertificateViewer aViewer( this, mxSecurityEnvironment, xCert, sal_True ); 235 aViewer.Execute(); 236 } 237 } 238 239