LCOV - code coverage report
Current view: top level - xmlsecurity/source/xmlsec/nss - nssinitializer.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 109 168 64.9 %
Date: 2015-06-13 12:38:46 Functions: 12 20 60.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : /*
      22             :  * and turn off the additional virtual methods which are part of some interfaces when compiled
      23             :  * with debug
      24             :  */
      25             : #ifdef DEBUG
      26             : #undef DEBUG
      27             : #endif
      28             : 
      29             : 
      30             : #include <com/sun/star/mozilla/XMozillaBootstrap.hpp>
      31             : #include <com/sun/star/xml/crypto/DigestID.hpp>
      32             : #include <com/sun/star/xml/crypto/CipherID.hpp>
      33             : #include <cppuhelper/supportsservice.hxx>
      34             : 
      35             : #include <officecfg/Office/Common.hxx>
      36             : 
      37             : #include <sal/types.h>
      38             : #include <rtl/instance.hxx>
      39             : #include <rtl/bootstrap.hxx>
      40             : #include <rtl/string.hxx>
      41             : #include <rtl/strbuf.hxx>
      42             : #include <osl/file.hxx>
      43             : #include <osl/thread.h>
      44             : #include <sal/log.hxx>
      45             : 
      46             : #include "seinitializer_nssimpl.hxx"
      47             : 
      48             : #include "securityenvironment_nssimpl.hxx"
      49             : #include "digestcontext.hxx"
      50             : #include "ciphercontext.hxx"
      51             : 
      52             : #include <boost/scoped_array.hpp>
      53             : 
      54             : #include <nspr.h>
      55             : #include <cert.h>
      56             : #include <nss.h>
      57             : #include <pk11pub.h>
      58             : #include <secmod.h>
      59             : #include <nssckbi.h>
      60             : 
      61             : namespace cssu = css::uno;
      62             : namespace cssl = css::lang;
      63             : 
      64             : using namespace com::sun::star;
      65             : 
      66             : #define IMPLEMENTATION_NAME "com.sun.star.xml.security.bridge.xmlsec.NSSInitializer_NssImpl"
      67             : 
      68             : #define ROOT_CERTS "Root Certs for OpenOffice.org"
      69             : 
      70             : extern "C" void nsscrypto_finalize();
      71             : 
      72             : 
      73             : namespace
      74             : {
      75             : 
      76             : bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool & out_nss_init );
      77             : 
      78          65 : struct InitNSSInitialize
      79             : {
      80             :     css::uno::Reference< css::uno::XComponentContext > m_xContext;
      81             : 
      82          65 :     explicit InitNSSInitialize(const css::uno::Reference<css::uno::XComponentContext> &rxContext)
      83          65 :         : m_xContext(rxContext)
      84             :     {
      85          65 :     }
      86             : 
      87           3 :     bool * operator()()
      88             :         {
      89             :             static bool bInitialized = false;
      90           3 :             bool bNSSInit = false;
      91           3 :             bInitialized = nsscrypto_initialize( m_xContext, bNSSInit );
      92           3 :             if (bNSSInit)
      93           3 :                 atexit(nsscrypto_finalize );
      94           3 :              return & bInitialized;
      95             :         }
      96             : };
      97             : 
      98             : struct GetNSSInitStaticMutex
      99             : {
     100           3 :     ::osl::Mutex* operator()()
     101             :     {
     102           3 :         static ::osl::Mutex aNSSInitMutex;
     103           3 :         return &aNSSInitMutex;
     104             :     }
     105             : };
     106             : 
     107           3 : void deleteRootsModule()
     108             : {
     109           3 :     SECMODModule *RootsModule = 0;
     110           3 :     SECMODModuleList *list = SECMOD_GetDefaultModuleList();
     111           3 :     SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
     112           3 :     SECMOD_GetReadLock(lock);
     113             : 
     114           9 :     while (!RootsModule && list)
     115             :     {
     116           3 :         SECMODModule *module = list->module;
     117             : 
     118           9 :         for (int i=0; i < module->slotCount; i++)
     119             :         {
     120           6 :             PK11SlotInfo *slot = module->slots[i];
     121           6 :             if (PK11_IsPresent(slot))
     122             :             {
     123           6 :                 if (PK11_HasRootCerts(slot))
     124             :                 {
     125             :                     SAL_INFO("xmlsecurity.xmlsec", "The root certifificates module \"" << module->commonName << "\" is already loaded: " << module->dllName);
     126             : 
     127           0 :                     RootsModule = SECMOD_ReferenceModule(module);
     128           0 :                     break;
     129             :                 }
     130             :             }
     131             :         }
     132           3 :         list = list->next;
     133             :     }
     134           3 :     SECMOD_ReleaseReadLock(lock);
     135             : 
     136           3 :     if (RootsModule)
     137             :     {
     138             :         PRInt32 modType;
     139           0 :         if (SECSuccess == SECMOD_DeleteModule(RootsModule->commonName, &modType))
     140             :         {
     141             :             SAL_INFO("xmlsecurity.xmlsec", "Deleted module \"" << RootsModule->commonName << "\".");
     142             :         }
     143             :         else
     144             :         {
     145             :             SAL_INFO("xmlsecurity.xmlsec", "Failed to delete \"" << RootsModule->commonName << "\": " << RootsModule->dllName);
     146             :         }
     147           0 :         SECMOD_DestroyModule(RootsModule);
     148           0 :         RootsModule = 0;
     149             :     }
     150           3 : }
     151             : 
     152           3 : OString getMozillaCurrentProfile( const css::uno::Reference< css::uno::XComponentContext > &rxContext )
     153             : {
     154             :     // first, try to get the profile from "MOZILLA_CERTIFICATE_FOLDER"
     155           3 :     const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER");
     156           3 :     if (pEnv)
     157             :     {
     158             :         SAL_INFO(
     159             :             "xmlsecurity.xmlsec",
     160             :             "Using Mozilla profile from MOZILLA_CERTIFICATE_FOLDER=" << pEnv);
     161           0 :         return OString(pEnv);
     162             :     }
     163             : 
     164             :     // second, try to get saved user-preference
     165             :     try
     166             :     {
     167             :         OUString sUserSetCertPath =
     168           3 :             officecfg::Office::Common::Security::Scripting::CertDir::get().get_value_or(OUString());
     169             : 
     170           3 :         if (!sUserSetCertPath.isEmpty())
     171             :         {
     172             :             SAL_INFO(
     173             :                 "xmlsecurity.xmlsec",
     174             :                 "Using Mozilla profile from /org.openoffice.Office.Common/"
     175             :                     "Security/Scripting/CertDir: " << sUserSetCertPath);
     176           0 :             return OUStringToOString(sUserSetCertPath, osl_getThreadTextEncoding());
     177           3 :         }
     178             :     }
     179           0 :     catch (const uno::Exception &e)
     180             :     {
     181             :         SAL_WARN(
     182             :             "xmlsecurity.xmlsec",
     183             :             "getMozillaCurrentProfile: caught exception " << e.Message);
     184             :     }
     185             : 
     186             :     // third, dig around to see if there's one available
     187             :     mozilla::MozillaProductType productTypes[3] = {
     188             :         mozilla::MozillaProductType_Thunderbird,
     189             :         mozilla::MozillaProductType_Firefox,
     190           3 :         mozilla::MozillaProductType_Mozilla };
     191           3 :     int nProduct = SAL_N_ELEMENTS(productTypes);
     192             : 
     193           3 :     uno::Reference<uno::XInterface> xInstance = rxContext->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", rxContext);
     194             :     OSL_ENSURE( xInstance.is(), "failed to create instance" );
     195             : 
     196             :     uno::Reference<mozilla::XMozillaBootstrap> xMozillaBootstrap
     197           6 :         =  uno::Reference<mozilla::XMozillaBootstrap>(xInstance,uno::UNO_QUERY);
     198             :     OSL_ENSURE( xMozillaBootstrap.is(), "failed to create instance" );
     199             : 
     200           3 :     if (xMozillaBootstrap.is())
     201             :     {
     202           0 :         for (int i=0; i<nProduct; ++i)
     203             :         {
     204           0 :             OUString profile = xMozillaBootstrap->getDefaultProfile(productTypes[i]);
     205             : 
     206           0 :             if (!profile.isEmpty())
     207             :             {
     208           0 :                 OUString sProfilePath = xMozillaBootstrap->getProfilePath( productTypes[i], profile );
     209             :                 SAL_INFO(
     210             :                     "xmlsecurity.xmlsec",
     211             :                     "Using Mozilla profile " << sProfilePath);
     212           0 :                 return OUStringToOString(sProfilePath, osl_getThreadTextEncoding());
     213             :             }
     214           0 :         }
     215             :     }
     216             : 
     217             :     SAL_INFO("xmlsecurity.xmlsec", "No Mozilla profile found");
     218           6 :     return OString();
     219             : }
     220             : 
     221             : //Older versions of Firefox (FF), for example FF2, and Thunderbird (TB) 2 write
     222             : //the roots certificate module (libnssckbi.so), which they use, into the
     223             : //profile. This module will then already be loaded during NSS_Init (and the
     224             : //other init functions). This fails in two cases. First, FF3 was used to create
     225             : //the profile, or possibly used that profile before, and second the profile was
     226             : //used on a different platform.
     227             : //
     228             : //Then one needs to add the roots module oneself. This should be done with
     229             : //SECMOD_LoadUserModule rather then SECMOD_AddNewModule. The latter would write
     230             : //the location of the roots module to the profile, which makes FF2 and TB2 use
     231             : //it instead of there own module.
     232             : //
     233             : //When using SYSTEM_NSS then the libnss3.so lib is typically found in /usr/lib.
     234             : //This folder may, however, NOT contain the roots certificate module. That is,
     235             : //just providing the library name in SECMOD_LoadUserModule or
     236             : //SECMOD_AddNewModule will FAIL to load the mozilla unless the LD_LIBRARY_PATH
     237             : //contains an FF or TB installation.
     238             : //ATTENTION: DO NOT call this function directly instead use initNSS
     239             : //return true - whole initialization was successful
     240             : //param out_nss_init = true: at least the NSS initialization (NSS_InitReadWrite
     241             : //was successful and therefore NSS_Shutdown should be called when terminating.
     242           3 : bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool & out_nss_init )
     243             : {
     244           3 :     bool return_value = true;
     245             : 
     246             :     // this method must be called only once, no need for additional lock
     247           3 :     OString sCertDir;
     248             : 
     249             : #ifdef XMLSEC_CRYPTO_NSS
     250           3 :     sCertDir = getMozillaCurrentProfile(rxContext);
     251             : #else
     252             :     (void) rxContext;
     253             : #endif
     254             :     SAL_INFO("xmlsecurity.xmlsec",  "Using profile: " << sCertDir.getStr() );
     255             : 
     256           3 :     PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ;
     257             : 
     258           3 :     bool bSuccess = true;
     259             :     // there might be no profile
     260           3 :     if ( !sCertDir.isEmpty() )
     261             :     {
     262           0 :         if( NSS_InitReadWrite( sCertDir.getStr() ) != SECSuccess )
     263             :         {
     264             :             SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with profile failed.");
     265           0 :             int errlen = PR_GetErrorTextLength();
     266           0 :             if(errlen > 0)
     267             :             {
     268           0 :                 boost::scoped_array<char> const error(new char[errlen + 1]);
     269           0 :                 PR_GetErrorText(error.get());
     270           0 :                 SAL_INFO("xmlsecurity.xmlsec", error.get());
     271             :             }
     272           0 :             bSuccess = false;
     273             :         }
     274             :     }
     275             : 
     276           3 :     if( sCertDir.isEmpty() || !bSuccess )
     277             :     {
     278             :         SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS without profile.");
     279           3 :         if ( NSS_NoDB_Init(NULL) != SECSuccess )
     280             :         {
     281             :             SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS without profile failed.");
     282           0 :             int errlen = PR_GetErrorTextLength();
     283           0 :             if(errlen > 0)
     284             :             {
     285           0 :                 boost::scoped_array<char> const error(new char[errlen + 1]);
     286           0 :                 PR_GetErrorText(error.get());
     287           0 :                 SAL_INFO("xmlsecurity.xmlsec", error.get());
     288             :             }
     289           0 :             return false ;
     290             :         }
     291             :     }
     292           3 :     out_nss_init = true;
     293             : 
     294             : #ifdef XMLSEC_CRYPTO_NSS
     295             : #if defined SYSTEM_NSS
     296           3 :     if (!SECMOD_HasRootCerts())
     297             : #endif
     298             :     {
     299           3 :         deleteRootsModule();
     300             : 
     301             : #if defined SYSTEM_NSS
     302           3 :         OUString rootModule("libnssckbi" SAL_DLLEXTENSION);
     303             : #else
     304             :         OUString rootModule("${LO_LIB_DIR}/libnssckbi" SAL_DLLEXTENSION);
     305             : #endif
     306           3 :         ::rtl::Bootstrap::expandMacros(rootModule);
     307             : 
     308           6 :         OUString rootModulePath;
     309           3 :         if (::osl::File::E_None == ::osl::File::getSystemPathFromFileURL(rootModule, rootModulePath))
     310             :         {
     311           3 :             OString ospath = OUStringToOString(rootModulePath, osl_getThreadTextEncoding());
     312           6 :             OString aStr = "name=\"" ROOT_CERTS "\" library=\"" + ospath + "\"";
     313             : 
     314             :             SECMODModule * RootsModule =
     315             :                 SECMOD_LoadUserModule(
     316           3 :                     const_cast<char*>(aStr.getStr()),
     317             :                     0, // no parent
     318           3 :                     PR_FALSE); // do not recurse
     319             : 
     320           3 :             if (RootsModule)
     321             :             {
     322             : 
     323           3 :                 bool found = RootsModule->loaded;
     324             : 
     325           3 :                 SECMOD_DestroyModule(RootsModule);
     326           3 :                 RootsModule = 0;
     327           3 :                 if (found)
     328             :                     SAL_INFO("xmlsecurity.xmlsec", "Added new root certificate module " ROOT_CERTS " contained in " << ospath);
     329             :                 else
     330             :                 {
     331             :                     SAL_INFO("xmlsecurity.xmlsec", "FAILED to load the new root certificate module " ROOT_CERTS "contained in " << ospath);
     332           0 :                     return_value = false;
     333             :                 }
     334             :             }
     335             :             else
     336             :             {
     337             :                 SAL_INFO("xmlsecurity.xmlsec", "FAILED to add new root certifice module " ROOT_CERTS  " contained in " << ospath);
     338           0 :                 return_value = false;
     339             : 
     340           3 :             }
     341             :         }
     342             :         else
     343             :         {
     344             :             SAL_INFO("xmlsecurity.xmlsec", "Adding new root certificate module failed.");
     345           0 :             return_value = false;
     346           3 :         }
     347             :     }
     348             : #endif
     349             : 
     350           3 :     return return_value;
     351             : }
     352             : 
     353             : } // namespace
     354             : 
     355             : // must be extern "C" because we pass the function pointer to atexit
     356           3 : extern "C" void nsscrypto_finalize()
     357             : {
     358           3 :     SECMODModule *RootsModule = SECMOD_FindModule(ROOT_CERTS);
     359             : 
     360           3 :     if (RootsModule)
     361             :     {
     362             : 
     363           3 :         if (SECSuccess == SECMOD_UnloadUserModule(RootsModule))
     364             :         {
     365             :             SAL_INFO("xmlsecurity.xmlsec", "Unloaded module \"" ROOT_CERTS "\".");
     366             :         }
     367             :         else
     368             :         {
     369             :             SAL_INFO("xmlsecurity.xmlsec", "Failed unloading module \"" ROOT_CERTS "\".");
     370             :         }
     371           3 :         SECMOD_DestroyModule(RootsModule);
     372             :     }
     373             :     else
     374             :     {
     375             :         SAL_INFO("xmlsecurity.xmlsec", "Unloading module \"" ROOT_CERTS "\" failed because it was not found.");
     376             :     }
     377           3 :     PK11_LogoutAll();
     378           3 :     (void)NSS_Shutdown();
     379           3 : }
     380             : 
     381           0 : ONSSInitializer::ONSSInitializer(
     382             :     const css::uno::Reference< css::uno::XComponentContext > &rxContext)
     383           0 :     :m_xContext( rxContext )
     384             : {
     385           0 : }
     386             : 
     387          67 : ONSSInitializer::~ONSSInitializer()
     388             : {
     389          67 : }
     390             : 
     391          65 : bool ONSSInitializer::initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext )
     392             : {
     393             :     return *rtl_Instance< bool, InitNSSInitialize, ::osl::MutexGuard, GetNSSInitStaticMutex >
     394          65 :                 ::create( InitNSSInitialize( rxContext ), GetNSSInitStaticMutex() );
     395             : }
     396             : 
     397          29 : css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL ONSSInitializer::getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams )
     398             :     throw (css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception)
     399             : {
     400          29 :     SECOidTag nNSSDigestID = SEC_OID_UNKNOWN;
     401          29 :     sal_Int32 nDigestLength = 0;
     402          29 :     bool b1KData = false;
     403          29 :     if ( nDigestID == css::xml::crypto::DigestID::SHA256
     404          22 :       || nDigestID == css::xml::crypto::DigestID::SHA256_1K )
     405             :     {
     406          29 :         nNSSDigestID = SEC_OID_SHA256;
     407          29 :         nDigestLength = 32;
     408          29 :         b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA256_1K );
     409             :     }
     410           0 :     else if ( nDigestID == css::xml::crypto::DigestID::SHA1
     411           0 :            || nDigestID == css::xml::crypto::DigestID::SHA1_1K )
     412             :     {
     413           0 :         nNSSDigestID = SEC_OID_SHA1;
     414           0 :         nDigestLength = 20;
     415           0 :         b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA1_1K );
     416             :     }
     417             :     else
     418           0 :         throw css::lang::IllegalArgumentException("Unexpected digest requested.", css::uno::Reference< css::uno::XInterface >(), 1 );
     419             : 
     420          29 :     if ( aParams.getLength() )
     421           0 :         throw css::lang::IllegalArgumentException("Unexpected arguments provided for digest creation.", css::uno::Reference< css::uno::XInterface >(), 2 );
     422             : 
     423          29 :     css::uno::Reference< css::xml::crypto::XDigestContext > xResult;
     424          29 :     if( initNSS( m_xContext ) )
     425             :     {
     426          29 :         PK11Context* pContext = PK11_CreateDigestContext( nNSSDigestID );
     427          29 :         if ( pContext && PK11_DigestBegin( pContext ) == SECSuccess )
     428          29 :             xResult = new ODigestContext( pContext, nDigestLength, b1KData );
     429             :     }
     430             : 
     431          29 :     return xResult;
     432             : }
     433             : 
     434          36 : css::uno::Reference< css::xml::crypto::XCipherContext > SAL_CALL ONSSInitializer::getCipherContext( ::sal_Int32 nCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, sal_Bool bEncryption, const css::uno::Sequence< css::beans::NamedValue >& aParams )
     435             :     throw (css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception)
     436             : {
     437          36 :     CK_MECHANISM_TYPE nNSSCipherID = 0;
     438          36 :     bool bW3CPadding = false;
     439          36 :     if ( nCipherID == css::xml::crypto::CipherID::AES_CBC_W3C_PADDING )
     440             :     {
     441          36 :         nNSSCipherID = CKM_AES_CBC;
     442          36 :         bW3CPadding = true;
     443             : 
     444          36 :         if ( aKey.getLength() != 16 && aKey.getLength() != 24 && aKey.getLength() != 32 )
     445           0 :             throw css::lang::IllegalArgumentException("Unexpected key length.", css::uno::Reference< css::uno::XInterface >(), 2 );
     446             : 
     447          36 :         if ( aParams.getLength() )
     448           0 :             throw css::lang::IllegalArgumentException("Unexpected arguments provided for cipher creation.", css::uno::Reference< css::uno::XInterface >(), 5 );
     449             :     }
     450             :     else
     451           0 :         throw css::lang::IllegalArgumentException("Unexpected cipher requested.", css::uno::Reference< css::uno::XInterface >(), 1 );
     452             : 
     453          36 :     css::uno::Reference< css::xml::crypto::XCipherContext > xResult;
     454          36 :     if( initNSS( m_xContext ) )
     455             :     {
     456          36 :         if ( aInitializationVector.getLength() != PK11_GetIVLength( nNSSCipherID ) )
     457           0 :             throw css::lang::IllegalArgumentException("Unexpected length of initialization vector.", css::uno::Reference< css::uno::XInterface >(), 3 );
     458             : 
     459          36 :         xResult = OCipherContext::Create( nNSSCipherID, aKey, aInitializationVector, bEncryption, bW3CPadding );
     460             :     }
     461             : 
     462          36 :     return xResult;
     463             : }
     464             : 
     465           0 : OUString ONSSInitializer_getImplementationName ()
     466             :     throw (cssu::RuntimeException)
     467             : {
     468             : 
     469           0 :     return OUString ( IMPLEMENTATION_NAME );
     470             : }
     471             : 
     472           0 : cssu::Sequence< OUString > SAL_CALL ONSSInitializer_getSupportedServiceNames(  )
     473             :     throw (cssu::RuntimeException)
     474             : {
     475           0 :     cssu::Sequence < OUString > aRet(1);
     476           0 :     OUString* pArray = aRet.getArray();
     477           0 :     pArray[0] = NSS_SERVICE_NAME;
     478           0 :     return aRet;
     479             : }
     480             : 
     481           0 : cssu::Reference< cssu::XInterface > SAL_CALL ONSSInitializer_createInstance( const cssu::Reference< cssl::XMultiServiceFactory > & rSMgr)
     482             :     throw( cssu::Exception )
     483             : {
     484           0 :     return static_cast<cppu::OWeakObject*>(new ONSSInitializer( comphelper::getComponentContext(rSMgr) ));
     485             : }
     486             : 
     487             : /* XServiceInfo */
     488           0 : OUString SAL_CALL ONSSInitializer::getImplementationName()
     489             :     throw (cssu::RuntimeException, std::exception)
     490             : {
     491           0 :     return ONSSInitializer_getImplementationName();
     492             : }
     493             : 
     494           0 : sal_Bool SAL_CALL ONSSInitializer::supportsService( const OUString& rServiceName )
     495             :     throw (cssu::RuntimeException, std::exception)
     496             : {
     497           0 :     return cppu::supportsService(this, rServiceName);
     498             : }
     499             : 
     500           0 : cssu::Sequence< OUString > SAL_CALL ONSSInitializer::getSupportedServiceNames(  )
     501             :     throw (cssu::RuntimeException, std::exception)
     502             : {
     503           0 :     return ONSSInitializer_getSupportedServiceNames();
     504             : }
     505             : 
     506             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11