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