diff options
108 files changed, 4326 insertions, 1093 deletions
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk index 5db8ff9b9f06..3f15773b9f36 100644 --- a/RepositoryExternal.mk +++ b/RepositoryExternal.mk @@ -1558,7 +1558,7 @@ $(call gb_ExternalProject_use_package,$(1),openssl) endef define gb_LinkTarget__use_openssl_headers -$(call gb_LinkTarget_use_external_project,$(1),openssl) +$(call gb_LinkTarget_use_external_project,$(1),openssl,full) $(call gb_LinkTarget_set_include,$(1),\ -I$(call gb_UnpackedTarball_get_dir,openssl)/include \ $$(INCLUDE) \ @@ -2753,7 +2753,7 @@ $(call gb_LinkTarget_set_include,$(1),\ ifeq ($(COM),MSC) $(call gb_LinkTarget_add_libs,$(1),\ - $(call gb_UnpackedTarball_get_dir,curl)/builds/libcurl-vc12-$(if $(filter X86_64,$(CPUNAME)),x64,x86)-$(if $(MSVC_USE_DEBUG_RUNTIME),debug,release)-dll-ipv6-sspi-winssl/lib/libcurl$(if $(MSVC_USE_DEBUG_RUNTIME),_debug).lib \ + $(call gb_UnpackedTarball_get_dir,curl)/builds/libcurl-vc12-$(if $(filter X86_64,$(CPUNAME)),x64,x86)-$(if $(MSVC_USE_DEBUG_RUNTIME),debug,release)-dll-ipv6-sspi-schannel/lib/libcurl$(if $(MSVC_USE_DEBUG_RUNTIME),_debug).lib \ ) else $(call gb_LinkTarget_add_libs,$(1),\ diff --git a/configure.ac b/configure.ac index 74fa63e31fe7..3d894cfbdd4e 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,7 @@ dnl in order to create a configure script. # several non-alphanumeric characters, those are split off and used only for the # ABOUTBOXPRODUCTVERSIONSUFFIX in openoffice.lst. Why that is necessary, no idea. -AC_INIT([Collabora Office],[6.2.10.30],[],[],[https://collaboraoffice.com/]) +AC_INIT([Collabora Office],[6.2.10.36],[],[],[https://collaboraoffice.com/]) AC_PREREQ([2.59]) @@ -2736,7 +2736,7 @@ dnl ENABLE_JAVA="TRUE" if we want there to be *run-time* (and build-time) suppor dnl ENABLE_JAVA="" indicate no Java support at all dnl =================================================================== -dnl Check OS X SDK and compiler +dnl Check macOS SDK and compiler dnl =================================================================== if test $_os = Darwin; then @@ -2749,8 +2749,8 @@ if test $_os = Darwin; then # For developers with a current Xcode, the lowest-numbered SDK # higher than or equal to the minimum required should be found. - AC_MSG_CHECKING([what Mac OS X SDK to use]) - for _macosx_sdk in ${with_macosx_sdk-11.1 10.15 10.14 10.13 10.12}; do + AC_MSG_CHECKING([what macOS SDK to use]) + for _macosx_sdk in ${with_macosx_sdk-11.3 11.1 11.0 10.15 10.14 10.13}; do MACOSX_SDK_PATH=`xcrun --sdk macosx${_macosx_sdk} --show-sdk-path 2> /dev/null` if test -d "$MACOSX_SDK_PATH"; then with_macosx_sdk="${_macosx_sdk}" @@ -2764,24 +2764,12 @@ if test $_os = Darwin; then fi done if test ! -d "$MACOSX_SDK_PATH"; then - AC_MSG_ERROR([Could not find an appropriate Mac OS X SDK]) + AC_MSG_ERROR([Could not find an appropriate macOS SDK]) fi - if test $_os = iOS; then - if test "$enable_ios_simulator" = "yes"; then - useos=iphonesimulator - else - useos=iphoneos - fi - MACOSX_SDK_PATH=`xcrun --sdk ${useos} --show-sdk-path 2> /dev/null` - fi AC_MSG_RESULT([SDK $with_macosx_sdk at $MACOSX_SDK_PATH]) - case $with_macosx_sdk in - 10.12) - MACOSX_SDK_VERSION=101200 - ;; 10.13) MACOSX_SDK_VERSION=101300 ;; @@ -2791,16 +2779,30 @@ if test $_os = Darwin; then 10.15) MACOSX_SDK_VERSION=101500 ;; + 11.0) + MACOSX_SDK_VERSION=110000 + ;; 11.1) MACOSX_SDK_VERSION=110100 ;; + 11.3) + MACOSX_SDK_VERSION=110300 + ;; *) - AC_MSG_ERROR([with-macosx-sdk $with_macosx_sdk is not a supported value, supported values are 10.12--11.1]) + AC_MSG_ERROR([with-macosx-sdk $with_macosx_sdk is not a supported value, supported values are 10.13--11.3]) ;; esac + if test "$host_cpu" = arm64 -a $MACOSX_SDK_VERSION -lt 110000; then + AC_MSG_ERROR([with-macosx-sdk $with_macosx_sdk is not a supported value for Apple Silicon]) + fi + if test "$with_macosx_version_min_required" = "" ; then - with_macosx_version_min_required="10.9"; + if test "$host_cpu" = x86_64; then + with_macosx_version_min_required="10.10"; + else + with_macosx_version_min_required="11.0"; + fi fi if test "$with_macosx_version_max_allowed" = "" ; then @@ -2814,10 +2816,17 @@ if test $_os = Darwin; then FRAMEWORKSHOME="$MACOSX_SDK_PATH/System/Library/Frameworks" MACOSX_DEPLOYMENT_TARGET="$with_macosx_version_min_required" + AC_MSG_CHECKING([whether Xcode is new enough]) + my_xcode_ver1=$(xcrun xcodebuild -version | head -n 1) + my_xcode_ver2=${my_xcode_ver1#Xcode } + my_xcode_ver3=$(printf %s "$my_xcode_ver2" | $AWK -F. '{ print $1*100+($2<100?$2:99) }') + if test "$my_xcode_ver3" -ge 1103; then + AC_MSG_RESULT([yes ($my_xcode_ver2)]) + else + AC_MSG_ERROR(["$my_xcode_ver1" is too old or unrecognized, must be at least Xcode 11.3]) + fi + case "$with_macosx_version_min_required" in - 10.9) - MAC_OS_X_VERSION_MIN_REQUIRED="1090" - ;; 10.10) MAC_OS_X_VERSION_MIN_REQUIRED="101000" ;; @@ -2836,35 +2845,59 @@ if test $_os = Darwin; then 10.15) MAC_OS_X_VERSION_MIN_REQUIRED="101500" ;; + 10.16) + MAC_OS_X_VERSION_MIN_REQUIRED="101600" + ;; + 11.0) + MAC_OS_X_VERSION_MIN_REQUIRED="110000" + ;; + 11.1) + MAC_OS_X_VERSION_MIN_REQUIRED="110100" + ;; + 11.3) + MAC_OS_X_VERSION_MIN_REQUIRED="110300" + ;; *) - AC_MSG_ERROR([with-macosx-version-min-required $with_macosx_version_min_required is not a supported value, supported values are 10.9--15]) + AC_MSG_ERROR([with-macosx-version-min-required $with_macosx_version_min_required is not a supported value, supported values are 10.10--11.3]) ;; esac - MAC_OS_X_VERSION_MIN_REQUIRED_DOTS=$with_macosx_version_min_required LIBTOOL=/usr/bin/libtool INSTALL_NAME_TOOL=install_name_tool if test -z "$save_CC"; then - AC_MSG_CHECKING([what compiler to use]) stdlib=-stdlib=libc++ - if test "$ENABLE_LTO" = TRUE; then - lto=-flto + + AC_MSG_CHECKING([what C compiler to use]) + CC="`xcrun -find clang`" + CC_BASE=`first_arg_basename "$CC"` + if test "$host_cpu" = x86_64; then + CC+=" -target x86_64-apple-macos" + else + CC+=" -target arm64-apple-macos" fi - CC="`xcrun -find clang` -m64 $lto -mmacosx-version-min=$with_macosx_version_min_required -isysroot $MACOSX_SDK_PATH" - CXX="`xcrun -find clang++` -m64 $lto $stdlib -mmacosx-version-min=$with_macosx_version_min_required -isysroot $MACOSX_SDK_PATH" + CC+=" -mmacosx-version-min=$with_macosx_version_min_required -isysroot $MACOSX_SDK_PATH" + AC_MSG_RESULT([$CC]) + + AC_MSG_CHECKING([what C++ compiler to use]) + CXX="`xcrun -find clang++`" + CXX_BASE=`first_arg_basename "$CXX"` + if test "$host_cpu" = x86_64; then + CXX+=" -target x86_64-apple-macos" + else + CXX+=" -target arm64-apple-macos" + fi + CXX+=" $stdlib -mmacosx-version-min=$with_macosx_version_min_required -isysroot $MACOSX_SDK_PATH" + AC_MSG_RESULT([$CXX]) + INSTALL_NAME_TOOL=`xcrun -find install_name_tool` AR=`xcrun -find ar` NM=`xcrun -find nm` STRIP=`xcrun -find strip` LIBTOOL=`xcrun -find libtool` RANLIB=`xcrun -find ranlib` - AC_MSG_RESULT([$CC and $CXX]) fi case "$with_macosx_version_max_allowed" in - 10.9) - MAC_OS_X_VERSION_MAX_ALLOWED="1090" - ;; 10.10) MAC_OS_X_VERSION_MAX_ALLOWED="101000" ;; @@ -2883,17 +2916,23 @@ if test $_os = Darwin; then 10.15) MAC_OS_X_VERSION_MAX_ALLOWED="101500" ;; + 11.0) + MAC_OS_X_VERSION_MAX_ALLOWED="110000" + ;; 11.1) MAC_OS_X_VERSION_MAX_ALLOWED="110100" ;; + 11.3) + MAC_OS_X_VERSION_MAX_ALLOWED="110300" + ;; *) - AC_MSG_ERROR([with-macosx-version-max-allowed $with_macosx_version_max_allowed is not a supported value, supported values are 10.9--11.1]) + AC_MSG_ERROR([with-macosx-version-max-allowed $with_macosx_version_max_allowed is not a supported value, supported values are 10.10--11.3]) ;; esac AC_MSG_CHECKING([that macosx-version-min-required is coherent with macosx-version-max-allowed]) if test $MAC_OS_X_VERSION_MIN_REQUIRED -gt $MAC_OS_X_VERSION_MAX_ALLOWED; then - AC_MSG_ERROR([the version minimumn required, $MAC_OS_X_VERSION_MIN_REQUIRED, must be <= the version maximum allowed, $MAC_OS_X_VERSION_MAX_ALLOWED]) + AC_MSG_ERROR([the version minimum required, $MAC_OS_X_VERSION_MIN_REQUIRED, must be <= the version maximum allowed, $MAC_OS_X_VERSION_MAX_ALLOWED]) else AC_MSG_RESULT([ok]) fi @@ -2964,11 +3003,9 @@ if test $_os = Darwin; then AC_MSG_CHECKING([whether to sandbox the application]) - if test -z "$MACOSX_CODESIGNING_IDENTITY" -a "$enable_macosx_sandbox" = yes; then - AC_MSG_ERROR([OS X sandboxing requires code signing]) - elif test -n "$ENABLE_JAVA" -a "$enable_macosx_sandbox" = yes; then - AC_MSG_ERROR([OS X sandboxing (actually App Store rules) disallows use of Java]) - elif test -n "$MACOSX_CODESIGNING_IDENTITY" -a "$enable_macosx_sandbox" = yes; then + if test -n "$ENABLE_JAVA" -a "$enable_macosx_sandbox" = yes; then + AC_MSG_ERROR([macOS sandboxing (actually App Store rules) disallows use of Java]) + elif test "$enable_macosx_sandbox" = yes; then ENABLE_MACOSX_SANDBOX=TRUE AC_DEFINE(HAVE_FEATURE_MACOSX_SANDBOX) AC_MSG_RESULT([yes]) @@ -2976,17 +3013,16 @@ if test $_os = Darwin; then AC_MSG_RESULT([no]) fi - AC_MSG_CHECKING([what OS X app bundle identifier to use]) + AC_MSG_CHECKING([what macOS app bundle identifier to use]) MACOSX_BUNDLE_IDENTIFIER=$with_macosx_bundle_identifier AC_MSG_RESULT([$MACOSX_BUNDLE_IDENTIFIER]) fi AC_SUBST(MACOSX_SDK_PATH) AC_SUBST(MACOSX_DEPLOYMENT_TARGET) AC_SUBST(MAC_OS_X_VERSION_MIN_REQUIRED) -AC_SUBST(MAC_OS_X_VERSION_MIN_REQUIRED_DOTS) AC_SUBST(MAC_OS_X_VERSION_MAX_ALLOWED) AC_SUBST(INSTALL_NAME_TOOL) -AC_SUBST(LIBTOOL) # Note that the OS X libtool command is unrelated to GNU libtool +AC_SUBST(LIBTOOL) # Note that the macOS libtool command is unrelated to GNU libtool AC_SUBST(MACOSX_CODESIGNING_IDENTITY) AC_SUBST(MACOSX_PACKAGE_SIGNING_IDENTITY) AC_SUBST(ENABLE_MACOSX_SANDBOX) diff --git a/connectivity/source/parse/sqlbison.y b/connectivity/source/parse/sqlbison.y index a93f3401cabc..0d2853e73105 100644 --- a/connectivity/source/parse/sqlbison.y +++ b/connectivity/source/parse/sqlbison.y @@ -74,9 +74,15 @@ inline connectivity::OSQLInternalNode* newNode(const OUString& _newValue, // yyi is the internal number of the rule that is currently being reduced // This can be mapped to external rule number via the yyrmap. +#if defined YYBISON && YYBISON >= 30800 +#define SQL_NEW_RULE newNode("", SQLNodeType::Rule, yyr1[yyrule]) +#define SQL_NEW_LISTRULE newNode("", SQLNodeType::ListRule, yyr1[yyrule]) +#define SQL_NEW_COMMALISTRULE newNode("", SQLNodeType::CommaListRule, yyr1[yyrule]) +#else #define SQL_NEW_RULE newNode("", SQLNodeType::Rule, yyr1[yyn]) #define SQL_NEW_LISTRULE newNode("", SQLNodeType::ListRule, yyr1[yyn]) #define SQL_NEW_COMMALISTRULE newNode("", SQLNodeType::CommaListRule, yyr1[yyn]) +#endif extern connectivity::OSQLParser* xxx_pGLOBAL_SQLPARSER; diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx index 381147cd534e..846714158e25 100644 --- a/desktop/source/app/cmdlineargs.cxx +++ b/desktop/source/app/cmdlineargs.cxx @@ -29,6 +29,7 @@ #include <tools/stream.hxx> #include <vcl/svapp.hxx> #include <rtl/uri.hxx> +#include <tools/urlobj.hxx> #include <rtl/ustring.hxx> #include <rtl/process.h> #include <comphelper/lok.hxx> @@ -169,7 +170,14 @@ CommandLineEvent CheckOfficeURI(/* in,out */ OUString& arg, CommandLineEvent cur } if (nURIlen < 0) nURIlen = rest2.getLength(); - arg = rest2.copy(0, nURIlen); + auto const uri = rest2.copy(0, nURIlen); + if (INetURLObject(uri).GetProtocol() == INetProtocol::Macro) { + // Let the "Open" machinery process the full command URI (leading to failure, by intention, + // as the "Open" machinery does not know about those command URI schemes): + curEvt = CommandLineEvent::Open; + } else { + arg = uri; + } return curEvt; } diff --git a/download.lst b/download.lst index 5a4ad84c0e46..3473daf8e1ab 100644 --- a/download.lst +++ b/download.lst @@ -29,8 +29,8 @@ export CPPUNIT_SHA256SUM := 3d569869d27b48860210c758c4f313082103a5e58219a7669b52 export CPPUNIT_TARBALL := cppunit-1.14.0.tar.gz export CT2N_SHA256SUM := 71b238efd2734be9800af07566daea8d6685aeed28db5eb5fa0e6453f4d85de3 export CT2N_TARBALL := 1f467e5bb703f12cbbb09d5cf67ecf4a-converttexttonumber-1-5-0.oxt -export CURL_SHA256SUM := cdf18794393d8bead915312708a9e5d819c6e9919de14b20d5c8e7987abd9772 -export CURL_TARBALL := curl-7.71.0.tar.xz +export CURL_SHA256SUM := be42766d5664a739c3974ee3dfbbcbe978a4ccb1fe628bb1d9b59ac79e445fb5 +export CURL_TARBALL := curl-7.78.0.tar.xz export EBOOK_SHA256SUM := 7e8d8ff34f27831aca3bc6f9cc532c2f90d2057c778963b884ff3d1e34dfe1f9 export EBOOK_TARBALL := libe-book-0.1.3.tar.xz export EPOXY_SHA256SUM := 002958c5528321edd53440235d3c44e71b5b1e09b9177e8daf677450b6c4433d @@ -42,8 +42,8 @@ export EPUBGEN_TARBALL := libepubgen-0.1.1.tar.xz export ETONYEK_SHA256SUM := e61677e8799ce6e55b25afc11aa5339113f6a49cff031f336e32fa58635b1a4a export ETONYEK_VERSION_MICRO := 9 export ETONYEK_TARBALL := libetonyek-0.1.$(ETONYEK_VERSION_MICRO).tar.xz -export EXPAT_SHA256SUM := 9a130948b05a82da34e4171d5f5ae5d321d9630277af02c8fa51e431f6475102 -export EXPAT_TARBALL := expat-2.2.8.tar.bz2 +export EXPAT_SHA256SUM := f2af8fc7cdc63a87920da38cd6d12cb113c3c3a3f437495b1b6541e0cff32579 +export EXPAT_TARBALL := expat-2.4.5.tar.xz export FIREBIRD_SHA256SUM := 6994be3555e23226630c587444be19d309b25b0fcf1f87df3b4e3f88943e5860 export FIREBIRD_TARBALL := Firebird-3.0.0.32483-0.tar.bz2 export FONTCONFIG_SHA256SUM := 19e5b1bc9d013a52063a44e1307629711f0bfef35b9aca16f9c793971e2eb1e5 @@ -178,8 +178,8 @@ export LIBTOMMATH_SHA256SUM := 083daa92d8ee6f4af96a6143b12d7fc8fe1a547e14f862304 export LIBTOMMATH_TARBALL := ltm-1.0.zip export XMLSEC_SHA256SUM := 13eec4811ea30e3f0e16a734d1dbf7f9d246a71d540b48d143a07b489f6222d4 export XMLSEC_TARBALL := xmlsec1-1.2.28.tar.gz -export LIBXML_SHA256SUM := aafee193ffb8fe0c82d4afef6ef91972cbaf5feea100edc2f262750611b4be1f -export LIBXML_VERSION_MICRO := 10 +export LIBXML_SHA256SUM := c8d6681e38c56f172892c85ddc0852e1fd4b53b4209e7f4ebf17f7e2eae71d92 +export LIBXML_VERSION_MICRO := 12 export LIBXML_TARBALL := libxml2-2.9.$(LIBXML_VERSION_MICRO).tar.gz export LIBXSLT_SHA256SUM := 98b1bd46d6792925ad2dfe9a87452ea2adebf69dcb9919ffd55bf926a7f93f7f export LIBXSLT_VERSION_MICRO := 34 @@ -203,8 +203,8 @@ export MYTHES_SHA256SUM := 1e81f395d8c851c3e4e75b568e20fa2fa549354e75ab397f9de4b export MYTHES_TARBALL := a8c2c5b8f09e7ede322d5c602ff6a4b6-mythes-1.2.4.tar.gz export NEON_SHA256SUM := db0bd8cdec329b48f53a6f00199c92d5ba40b0f015b153718d1b15d3d967fbca export NEON_TARBALL := neon-0.30.2.tar.gz -export NSS_SHA256SUM := ec6032d78663c6ef90b4b83eb552dedf721d2bce208cec3bf527b8f637db7e45 -export NSS_TARBALL := nss-3.55-with-nspr-4.27.tar.gz +export NSS_SHA256SUM := 07a9e5b70f121a62706140d4cacc3006d3efb869da40f3a2bf7a65d37847f4d9 +export NSS_TARBALL := nss-3.73-with-nspr-4.32.tar.gz export ODFGEN_SHA256SUM := 2c7b21892f84a4c67546f84611eccdad6259875c971e98ddb027da66ea0ac9c2 export ODFGEN_VERSION_MICRO := 6 export ODFGEN_TARBALL := libodfgen-0.1.$(ODFGEN_VERSION_MICRO).tar.bz2 diff --git a/external/curl/ExternalPackage_curl.mk b/external/curl/ExternalPackage_curl.mk index 8da569e3e0cf..1fb360c85ca9 100644 --- a/external/curl/ExternalPackage_curl.mk +++ b/external/curl/ExternalPackage_curl.mk @@ -14,13 +14,13 @@ $(eval $(call gb_ExternalPackage_use_external_project,curl,curl)) ifneq ($(DISABLE_DYNLOADING),TRUE) ifeq ($(COM),MSC) -$(eval $(call gb_ExternalPackage_add_file,curl,$(LIBO_LIB_FOLDER)/libcurl$(if $(MSVC_USE_DEBUG_RUNTIME),_debug).dll,builds/libcurl-vc12-$(if $(filter X86_64,$(CPUNAME)),x64,x86)-$(if $(MSVC_USE_DEBUG_RUNTIME),debug,release)-dll-ipv6-sspi-winssl/bin/libcurl$(if $(MSVC_USE_DEBUG_RUNTIME),_debug).dll)) +$(eval $(call gb_ExternalPackage_add_file,curl,$(LIBO_LIB_FOLDER)/libcurl$(if $(MSVC_USE_DEBUG_RUNTIME),_debug).dll,builds/libcurl-vc12-$(if $(filter X86_64,$(CPUNAME)),x64,x86)-$(if $(MSVC_USE_DEBUG_RUNTIME),debug,release)-dll-ipv6-sspi-schannel/bin/libcurl$(if $(MSVC_USE_DEBUG_RUNTIME),_debug).dll)) else ifeq ($(OS),MACOSX) $(eval $(call gb_ExternalPackage_add_file,curl,$(LIBO_LIB_FOLDER)/libcurl.4.dylib,lib/.libs/libcurl.4.dylib)) else ifeq ($(OS),AIX) $(eval $(call gb_ExternalPackage_add_file,curl,$(LIBO_LIB_FOLDER)/libcurl.so,lib/.libs/libcurl.so.4)) else -$(eval $(call gb_ExternalPackage_add_file,curl,$(LIBO_LIB_FOLDER)/libcurl.so.4,lib/.libs/libcurl.so.4.6.0)) +$(eval $(call gb_ExternalPackage_add_file,curl,$(LIBO_LIB_FOLDER)/libcurl.so.4,lib/.libs/libcurl.so.4.7.0)) endif endif # $(DISABLE_DYNLOADING) diff --git a/external/curl/ExternalProject_curl.mk b/external/curl/ExternalProject_curl.mk index b1029ea779e3..81886b36fbc5 100644 --- a/external/curl/ExternalProject_curl.mk +++ b/external/curl/ExternalProject_curl.mk @@ -35,13 +35,13 @@ ifeq ($(SYSTEM_NSS),) curl_CPPFLAGS += -I$(call gb_UnpackedTarball_get_dir,nss)/dist/public/nss endif -# use --with-darwinssl on Mac OS X >10.5 and iOS to get a native UI for SSL certs for CMIS usage +# use --with-secure-transport on Mac OS X >10.5 and iOS to get a native UI for SSL certs for CMIS usage # use --with-nss only on platforms other than Mac OS X and iOS $(call gb_ExternalProject_get_state_target,curl,build): $(call gb_ExternalProject_run,build,\ ./configure \ - $(if $(filter iOS MACOSX,$(OS)),\ - --with-darwinssl,\ + $(if $(filter IOS MACOSX,$(OS)),\ + --with-secure-transport,\ $(if $(ENABLE_NSS),--with-nss$(if $(SYSTEM_NSS),,="$(call gb_UnpackedTarball_get_dir,nss)/dist/out"),--without-nss)) \ --without-ssl --without-gnutls --without-polarssl --without-cyassl --without-axtls --without-mbedtls \ --enable-ftp --enable-http --enable-ipv6 \ @@ -49,7 +49,8 @@ $(call gb_ExternalProject_get_state_target,curl,build): --without-libssh2 --without-metalink --without-nghttp2 \ --without-libssh --without-brotli \ --without-ngtcp2 --without-quiche \ - --disable-ares \ + --without-zstd --without-hyper --without-gsasl --without-gssapi \ + --disable-mqtt --disable-ares \ --disable-dict --disable-file --disable-gopher --disable-imap \ --disable-ldap --disable-ldaps --disable-manual --disable-pop3 \ --disable-rtsp --disable-smb --disable-smtp --disable-telnet \ diff --git a/external/curl/UnpackedTarball_curl.mk b/external/curl/UnpackedTarball_curl.mk index 6171f17cba48..1cdb64c0bca2 100644 --- a/external/curl/UnpackedTarball_curl.mk +++ b/external/curl/UnpackedTarball_curl.mk @@ -11,8 +11,6 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,curl)) $(eval $(call gb_UnpackedTarball_set_tarball,curl,$(CURL_TARBALL),,curl)) -$(eval $(call gb_UnpackedTarball_update_autoconf_configs,curl)) - $(eval $(call gb_UnpackedTarball_set_patchlevel,curl,1)) $(eval $(call gb_UnpackedTarball_fix_end_of_line,curl,\ @@ -24,7 +22,6 @@ $(eval $(call gb_UnpackedTarball_add_patches,curl,\ external/curl/curl-msvc-disable-protocols.patch.1 \ external/curl/curl-7.26.0_win-proxy.patch \ external/curl/zlib.patch.0 \ - external/curl/curl-ios.patch.1 \ )) ifeq ($(SYSTEM_NSS),) diff --git a/external/curl/curl-7.26.0_win-proxy.patch b/external/curl/curl-7.26.0_win-proxy.patch index 5361433a917b..5bb98fa04741 100644 --- a/external/curl/curl-7.26.0_win-proxy.patch +++ b/external/curl/curl-7.26.0_win-proxy.patch @@ -114,7 +114,7 @@ @@ -4663,6 +4739,7 @@ } if(proxy) - infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy); + infof(data, "Uses proxy env variable %s == '%s'", envp, proxy); +#endif /* WIN32 */ return proxy; diff --git a/external/curl/curl-ios.patch.1 b/external/curl/curl-ios.patch.1 deleted file mode 100644 index 1c8fd8f70566..000000000000 --- a/external/curl/curl-ios.patch.1 +++ /dev/null @@ -1,17 +0,0 @@ -# -*- Mode: Diff -*- -# -# We don't want curl's configure script to add a -mmacosx-version-min -# option when it is for iOS we are building. In that case already $CC -# contains a -miphoneos-version-min option. - ---- curl/configure -+++ curl/configure -@@ -18976,7 +18976,7 @@ - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for *version-min in CFLAGS" >&5 - $as_echo_n "checking for *version-min in CFLAGS... " >&6; } - min="" -- if test -z "$(echo $CFLAGS | grep m.*os.*-version-min)"; then -+ if test -z "$(echo $CC $CFLAGS | grep m.*os.*-version-min)"; then - min="-mmacosx-version-min=10.8" - CFLAGS="$CFLAGS $min" - fi diff --git a/external/curl/curl-msvc-disable-protocols.patch.1 b/external/curl/curl-msvc-disable-protocols.patch.1 index c8747a5fcc1d..a6d06c69b004 100644 --- a/external/curl/curl-msvc-disable-protocols.patch.1 +++ b/external/curl/curl-msvc-disable-protocols.patch.1 @@ -2,18 +2,19 @@ disable protocols nobody needs in MSVC build --- curl/lib/config-win32.h.orig 2017-08-09 16:43:29.464000000 +0200 +++ curl/lib/config-win32.h 2017-08-09 16:47:38.549200000 +0200 -@@ -733,4 +733,19 @@ +@@ -733,4 +733,20 @@ # define ENABLE_IPV6 1 #endif +#define CURL_DISABLE_DICT 1 +#define CURL_DISABLE_FILE 1 -+//#undef CURL_DISABLE_FTP ++#undef CURL_DISABLE_FTP +#define CURL_DISABLE_GOPHER 1 -+//#undef CURL_DISABLE_HTTP ++#undef CURL_DISABLE_HTTP +#define CURL_DISABLE_IMAP 1 +#define CURL_DISABLE_LDAP 1 +#define CURL_DISABLE_LDAPS 1 ++#define CURL_DISABLE_MQTT 1 +#define CURL_DISABLE_POP3 1 +#define CURL_DISABLE_RTSP 1 +#define CURL_DISABLE_SMB 1 diff --git a/external/curl/zlib.patch.0 b/external/curl/zlib.patch.0 index 189e820d1afa..f4a0ad4b152f 100644 --- a/external/curl/zlib.patch.0 +++ b/external/curl/zlib.patch.0 @@ -54,8 +54,8 @@ clean_LIBS=$LIBS -ZLIB_LIBS="" AC_ARG_WITH(zlib, - AC_HELP_STRING([--with-zlib=PATH],[search for zlib in PATH]) - AC_HELP_STRING([--without-zlib],[disable use of zlib]), + AS_HELP_STRING([--with-zlib=PATH],[search for zlib in PATH]) + AS_HELP_STRING([--without-zlib],[disable use of zlib]), [OPT_ZLIB="$withval"]) if test "$OPT_ZLIB" = "no" ; then diff --git a/external/expat/expat-winapi.patch b/external/expat/expat-winapi.patch index b33c12b83b4c..7eae7d5d6139 100644 --- a/external/expat/expat-winapi.patch +++ b/external/expat/expat-winapi.patch @@ -11,3 +11,14 @@ # endif #endif /* not defined XML_STATIC */ +--- misc/expat-2.1.0/lib/xmlparse.c 2021-05-23 16:56:25.000000000 +0100 ++++ misc/build/expat-2.1.0/lib/xmlparse.c 2021-05-25 12:42:11.997173600 +0100 +@@ -64,6 +64,8 @@ + #endif + + #ifdef _WIN32 ++# undef HAVE_GETRANDOM ++# undef HAVE_SYSCALL_GETRANDOM + /* force stdlib to define rand_s() */ + # if ! defined(_CRT_RAND_S) + # define _CRT_RAND_S diff --git a/external/gpgmepp/ExternalProject_gpgmepp.mk b/external/gpgmepp/ExternalProject_gpgmepp.mk index 452f922750d6..dac2fad1361b 100644 --- a/external/gpgmepp/ExternalProject_gpgmepp.mk +++ b/external/gpgmepp/ExternalProject_gpgmepp.mk @@ -40,7 +40,7 @@ $(call gb_ExternalProject_get_state_target,gpgmepp,build): $(call gb_Executable_ $(if $(ENABLE_DEBUG),$(gb_DEBUG_CFLAGS)) \ $(if $(filter $(true),$(gb_SYMBOL)),$(gb_DEBUGINFO_FLAGS))' \ --host=$(gb_ExternalProject_gpgmepp_host) \ - RC='windres -O COFF --target=$(gb_ExternalProject_gpgmepp_target) --preprocessor='\''$(call gb_Executable_get_target,cpp) -+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)'\' \ + RC='windres -O COFF --target=$(gb_ExternalProject_gpgmepp_target) --preprocessor=$(call gb_Executable_get_target,cpp) --preprocessor-arg=-+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)' \ MAKE=$(MAKE) \ && $(MAKE) \ ) diff --git a/external/libassuan/ExternalProject_libassuan.mk b/external/libassuan/ExternalProject_libassuan.mk index 83d79a520988..899c21e4cec9 100644 --- a/external/libassuan/ExternalProject_libassuan.mk +++ b/external/libassuan/ExternalProject_libassuan.mk @@ -34,7 +34,7 @@ $(call gb_ExternalProject_get_state_target,libassuan,build): $(call gb_Executabl GPG_ERROR_CFLAGS="$(GPG_ERROR_CFLAGS)" \ GPG_ERROR_LIBS="$(GPG_ERROR_LIBS)" \ --host=$(gb_ExternalProject_libassuan_host) \ - RC='windres -O COFF --target=$(gb_ExternalProject_libassuan_target) --preprocessor='\''$(call gb_Executable_get_target,cpp) -+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)'\' \ + RC='windres -O COFF --target=$(gb_ExternalProject_libassuan_target) --preprocessor=$(call gb_Executable_get_target,cpp) --preprocessor-arg=-+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)' \ MAKE=$(MAKE) \ && $(MAKE) \ ) diff --git a/external/libgpg-error/ExternalProject_libgpg-error.mk b/external/libgpg-error/ExternalProject_libgpg-error.mk index 1fcd63180e20..e5155aad94c1 100644 --- a/external/libgpg-error/ExternalProject_libgpg-error.mk +++ b/external/libgpg-error/ExternalProject_libgpg-error.mk @@ -28,7 +28,7 @@ $(call gb_ExternalProject_get_state_target,libgpg-error,build): $(call gb_Execut --disable-doc \ --disable-tests \ --host=$(gb_ExternalProject_libgpg-error_host) \ - RC='windres -O COFF --target=$(gb_ExternalProject_libgpg-error_target) --preprocessor='\''$(call gb_Executable_get_target,cpp) -+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)'\' \ + RC='windres -O COFF --target=$(gb_ExternalProject_libgpg-error_target) --preprocessor=$(call gb_Executable_get_target,cpp) --preprocessor-arg=-+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)' \ && $(MAKE) \ ) else diff --git a/external/liblangtag/UnpackedTarball_liblangtag.mk b/external/liblangtag/UnpackedTarball_liblangtag.mk index cd52b169fa57..66b8051782d0 100644 --- a/external/liblangtag/UnpackedTarball_liblangtag.mk +++ b/external/liblangtag/UnpackedTarball_liblangtag.mk @@ -17,6 +17,8 @@ $(eval $(call gb_UnpackedTarball_set_pre_action,liblangtag,\ $(eval $(call gb_UnpackedTarball_update_autoconf_configs,liblangtag)) +$(eval $(call gb_UnpackedTarball_set_patchlevel,liblangtag,0)) + ifneq ($(OS),MACOSX) ifneq ($(OS),WNT) $(eval $(call gb_UnpackedTarball_add_patches,liblangtag,\ @@ -29,6 +31,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,liblangtag, \ $(if $(SYSTEM_LIBXML),,external/liblangtag/langtag-libtool-rpath.patch.0) \ external/liblangtag/clang-cl.patch.0 \ external/liblangtag/langtag-valencia.patch.0 \ + external/liblangtag/Wformat-overflow.patch \ )) # vim: set noet sw=4 ts=4: diff --git a/external/liblangtag/Wformat-overflow.patch b/external/liblangtag/Wformat-overflow.patch new file mode 100644 index 000000000000..f2d017e4b395 --- /dev/null +++ b/external/liblangtag/Wformat-overflow.patch @@ -0,0 +1,17 @@ +--- liblangtag/lt-script-db.c ++++ liblangtag/lt-script-db.c +@@ -134,8 +134,12 @@ + cnode = cnode->next; + } + if (!subtag) { +- lt_warning("No subtag node: description = '%s'", +- desc); ++ if (!desc) { ++ lt_warning("No subtag nor description node"); ++ } else { ++ lt_warning("No subtag node: description = '%s'", ++ desc); ++ } + goto bail1; + } + if (!desc) { diff --git a/external/libxml2/libxml2-config.patch.1 b/external/libxml2/libxml2-config.patch.1 index 8c28fb6a7806..5a2ef1485e92 100644 --- a/external/libxml2/libxml2-config.patch.1 +++ b/external/libxml2/libxml2-config.patch.1 @@ -18,9 +18,9 @@ Hack the xml2-config to return paths into WORKDIR. +exec_prefix=${WORKDIR}/UnpackedTarball/libxml2 +includedir=${WORKDIR}/UnpackedTarball/libxml2/include +libdir=${WORKDIR}/UnpackedTarball/libxml2/.libs + cflags= + libs= - usage() - { @@ -67,7 +72,8 @@ ;; diff --git a/external/libxml2/libxml2-global-symbols.patch b/external/libxml2/libxml2-global-symbols.patch index 49ee73731562..cfec9c530281 100644 --- a/external/libxml2/libxml2-global-symbols.patch +++ b/external/libxml2/libxml2-global-symbols.patch @@ -14,8 +14,8 @@ LIBXML2_2.6.32 { @@ -2231,3 +2231,43 @@ - xmlHashDefaultDeallocator; - } LIBXML2_2.9.1; + xmlPopOutputCallbacks; + } LIBXML2_2.9.8; +# HACK: export global variable accessor functions (globals.h) +LIBXML2_GLOBAL_VARIABLES { diff --git a/external/nss/ExternalProject_nss.mk b/external/nss/ExternalProject_nss.mk index 05c270e9baed..ef98734f85ad 100644 --- a/external/nss/ExternalProject_nss.mk +++ b/external/nss/ExternalProject_nss.mk @@ -16,7 +16,9 @@ $(eval $(call gb_ExternalProject_register_targets,nss,\ )) ifeq ($(OS),WNT) -$(call gb_ExternalProject_get_state_target,nss,build): $(call gb_ExternalExecutable_get_dependencies,python) +$(call gb_ExternalProject_get_state_target,nss,build): \ + $(call gb_ExternalExecutable_get_dependencies,python) \ + $(SRCDIR)/external/nss/nsinstall.py $(call gb_ExternalProject_run,build,\ $(if $(MSVC_USE_DEBUG_RUNTIME),USE_DEBUG_RTL=1,BUILD_OPT=1) \ OS_TARGET=WIN95 \ @@ -31,7 +33,9 @@ $(call gb_ExternalProject_get_state_target,nss,build): $(call gb_ExternalExecuta else # OS!=WNT # make sure to specify NSPR_CONFIGURE_OPTS as env (before make command), so nss can append it's own defaults # OTOH specify e.g. CC and NSINSTALL as arguments (after make command), so they will overrule nss makefile values -$(call gb_ExternalProject_get_state_target,nss,build): $(call gb_ExternalExecutable_get_dependencies,python) +$(call gb_ExternalProject_get_state_target,nss,build): \ + $(call gb_ExternalExecutable_get_dependencies,python) \ + $(SRCDIR)/external/nss/nsinstall.py $(call gb_ExternalProject_run,build,\ $(if $(filter ANDROID FREEBSD LINUX MACOSX,$(OS)),$(if $(filter X86_64,$(CPUNAME)),USE_64=1)) \ $(if $(filter ANDROID,$(OS)),$(if $(filter AARCH64,$(CPUNAME)),USE_64=1)) \ diff --git a/external/nss/UnpackedTarball_nss.mk b/external/nss/UnpackedTarball_nss.mk index b6fcd1346b82..8fa1edd530cc 100644 --- a/external/nss/UnpackedTarball_nss.mk +++ b/external/nss/UnpackedTarball_nss.mk @@ -24,7 +24,6 @@ $(eval $(call gb_UnpackedTarball_add_patches,nss,\ external/nss/nss.bzmozilla1238154.patch \ external/nss/nss-bz1646594.patch.1 \ external/nss/macos-dlopen.patch.0 \ - external/nss/nss.getopt.patch.0 \ $(if $(filter iOS,$(OS)), \ external/nss/nss-ios.patch) \ $(if $(filter ANDROID,$(OS)), \ diff --git a/external/nss/nsinstall.py b/external/nss/nsinstall.py index 80e9c1679373..d90a85e6c540 100644 --- a/external/nss/nsinstall.py +++ b/external/nss/nsinstall.py @@ -99,17 +99,17 @@ def nsinstall(argv): if options.D: if len(args) != 1: return 1 - if os.path.exists(args[0]): + try: + if options.m: + os.makedirs(args[0], options.m) + else: + os.makedirs(args[0]) + except FileExistsError: if not os.path.isdir(args[0]): sys.stderr.write('nsinstall: ' + args[0] + ' is not a directory\n') sys.exit(1) if options.m: os.chmod(args[0], options.m) - sys.exit() - if options.m: - os.makedirs(args[0], options.m) - else: - os.makedirs(args[0]) return 0 # nsinstall arg1 [...] directory diff --git a/external/nss/nss-android.patch.1 b/external/nss/nss-android.patch.1 index 9b120d63ab8c..828892533781 100644 --- a/external/nss/nss-android.patch.1 +++ b/external/nss/nss-android.patch.1 @@ -10,9 +10,9 @@ diff -ur nss.org/nspr/build/autoconf/config.sub nss/nspr/build/autoconf/config.s +if test $1 = "i686-pc-linux-android"; then echo $1; exit; fi +if test $1 = "x86_64-pc-linux-android"; then echo $1; exit; fi + - # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). - # Here we must recognize all the valid KERNEL-OS combinations. - maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` + # Split fields of configuration type + # shellcheck disable=SC2162 + IFS="-" read field1 field2 field3 field4 <<EOF diff -ur nss.org/nspr/configure nss/nspr/configure --- nss.org/nspr/configure 2017-09-07 15:29:45.018246359 +0200 +++ nss/nspr/configure 2017-09-07 15:31:47.604075663 +0200 diff --git a/external/nss/nss-ios.patch b/external/nss/nss-ios.patch index 65115a96e806..da09b8d8edf8 100644 --- a/external/nss/nss-ios.patch +++ b/external/nss/nss-ios.patch @@ -193,9 +193,9 @@ +if test $1 = "arm64-apple-darwin"; then echo $1; exit; fi +if test $1 = "aarch64-apple-darwin"; then echo $1; exit; fi + - # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). - # Here we must recognize all the valid KERNEL-OS combinations. - maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` + # Split fields of configuration type + # shellcheck disable=SC2162 + IFS="-" read field1 field2 field3 field4 <<EOF --- a/a/nspr/config/autoconf.mk.in +++ a/a/nspr/config/autoconf.mk.in @@ -67,7 +67,7 @@ diff --git a/external/nss/nss.getopt.patch.0 b/external/nss/nss.getopt.patch.0 deleted file mode 100644 index aeabb33f9b97..000000000000 --- a/external/nss/nss.getopt.patch.0 +++ /dev/null @@ -1,25 +0,0 @@ -# pr/tests/sel_spd.c:427:20: error: implicit declaration of function 'getopt' is invalid in C99 [-Werror,-Wimplicit-function-declaration] ---- nspr/pr/tests/sel_spd.c -+++ nspr/pr/tests/sel_spd.c -@@ -15,6 +15,9 @@ - #include <stdio.h> - #include <errno.h> - #include <string.h> -+ -+extern char *optarg; -+int getopt(int argc, char *const argv[], const char *optstring); - - #ifdef DEBUG - #define PORT_INC_DO +100 ---- nspr/pr/tests/testfile.c -+++ nspr/pr/tests/testfile.c -@@ -23,6 +23,9 @@ - #include <getopt.h> - #include <errno.h> - #endif /* XP_OS2 */ -+ -+extern char *optarg; -+int getopt(int argc, char *const argv[], const char *optstring); - - static int _debug_on = 0; - diff --git a/external/openssl/UnpackedTarball_openssl.mk b/external/openssl/UnpackedTarball_openssl.mk index ad600cce1412..e7fca1116545 100644 --- a/external/openssl/UnpackedTarball_openssl.mk +++ b/external/openssl/UnpackedTarball_openssl.mk @@ -22,6 +22,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,openssl,\ external/openssl/openssl-3650-masm.patch.1 \ external/openssl/openssl-fixbuild.patch.1 \ external/openssl/openssl-1.0.2k-cve-2020-1971.patch.1 \ + external/openssl/ccb0a11145ee72b042d10593a64eaf9e8a55ec12.patch.1 \ )) # vim: set noet sw=4 ts=4: diff --git a/external/openssl/ccb0a11145ee72b042d10593a64eaf9e8a55ec12.patch.1 b/external/openssl/ccb0a11145ee72b042d10593a64eaf9e8a55ec12.patch.1 new file mode 100644 index 000000000000..cf809750ecfb --- /dev/null +++ b/external/openssl/ccb0a11145ee72b042d10593a64eaf9e8a55ec12.patch.1 @@ -0,0 +1,56 @@ +From ccb0a11145ee72b042d10593a64eaf9e8a55ec12 Mon Sep 17 00:00:00 2001 +From: Matt Caswell <matt@openssl.org> +Date: Tue, 17 Aug 2021 14:41:48 +0100 +Subject: [PATCH] Fix a read buffer overrun in X509_CERT_AUX_print() + +This is a backport of commit c5dc9ab965f to 1.0.2. That commit fixed +the same bug but in master/1.1.1 it is in the function X509_aux_print(). +The original commit had the following description: + +Fix a read buffer overrun in X509_aux_print(). + +The ASN1_STRING_get0_data(3) manual explitely cautions the reader +that the data is not necessarily NUL-terminated, and the function +X509_alias_set1(3) does not sanitize the data passed into it in any +way either, so we must assume the return value from X509_alias_get0(3) +is merely a byte array and not necessarily a string in the sense +of the C language. + +I found this bug while writing manual pages for X509_print_ex(3) +and related functions. Theo Buehler <tb@openbsd.org> checked my +patch to fix the same bug in LibreSSL, see + +http://cvsweb.openbsd.org/src/lib/libcrypto/asn1/t_x509a.c#rev1.9 + +As an aside, note that the function still produces incomplete and +misleading results when the data contains a NUL byte in the middle +and that error handling is consistently absent throughout, even +though the function provides an "int" return value obviously intended +to be 1 for success and 0 for failure, and even though this function +is called by another function that also wants to return 1 for success +and 0 for failure and even does so in many of its code paths, though +not in others. But let's stay focussed. Many things would be nice +to have in the wide wild world, but a buffer overflow must not be +allowed to remain in our backyard. + +CVE-2021-3712 + +Reviewed-by: Paul Dale <pauli@openssl.org> +--- + crypto/asn1/t_x509a.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/crypto/asn1/t_x509a.c b/crypto/asn1/t_x509a.c +index d1b897a469fd..b1bc9d0cd28b 100644 +--- a/crypto/asn1/t_x509a.c ++++ b/crypto/asn1/t_x509a.c +@@ -104,7 +104,8 @@ int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) + } else + BIO_printf(out, "%*sNo Rejected Uses.\n", indent, ""); + if (aux->alias) +- BIO_printf(out, "%*sAlias: %s\n", indent, "", aux->alias->data); ++ BIO_printf(out, "%*sAlias: %.*s\n", indent, "", aux->alias->length, ++ aux->alias->data); + if (aux->keyid) { + BIO_printf(out, "%*sKey Id: ", indent, ""); + for (i = 0; i < aux->keyid->length; i++) diff --git a/external/xmlsec/0001-xmlSecX509DataGetNodeContent-don-t-return-0-for-non-.patch.1 b/external/xmlsec/0001-xmlSecX509DataGetNodeContent-don-t-return-0-for-non-.patch.1 new file mode 100644 index 000000000000..51607ca6ee73 --- /dev/null +++ b/external/xmlsec/0001-xmlSecX509DataGetNodeContent-don-t-return-0-for-non-.patch.1 @@ -0,0 +1,68 @@ +From a39b110cb2c25680259a38b2f397b350151bc6e7 Mon Sep 17 00:00:00 2001 +From: Michael Stahl <michael.stahl@allotropia.de> +Date: Wed, 7 Apr 2021 16:43:48 +0200 +Subject: [PATCH] xmlSecX509DataGetNodeContent(): don't return 0 for non-empty + elements + +LibreOffice wants to write the content of KeyInfo itself and thus writes +X509Certificate element with content. + +But then xmlSecMSCngKeyDataX509XmlWrite() writes a duplicate +X509Certificate element, which then makes a new additional consistency +check in LO unhappy. + +The duplicate is written because xmlSecX509DataGetNodeContent() returns +0 because it only checks for empty nodes; if there are only non-empty +nodes a fallback to XMLSEC_X509DATA_DEFAULT occurs in all backends. + +Change the return value to be non-0 without changing the signature of +the function, as it is apparently public. + +This doesn't happen in LO in the NSS backend due to another accident, +where the private key flag isn't set when the X509Certificate is read, +but otherwise the code is the same. +--- + src/x509.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/src/x509.c b/src/x509.c +index ed8788ae..dac8bd2b 100644 +--- a/src/x509.c ++++ b/src/x509.c +@@ -60,22 +60,33 @@ xmlSecX509DataGetNodeContent (xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + if(xmlSecCheckNodeName(cur, xmlSecNodeX509Certificate, xmlSecDSigNs)) { + if(xmlSecIsEmptyNode(cur) == 1) { + content |= XMLSEC_X509DATA_CERTIFICATE_NODE; ++ } else { ++ /* ensure return value isn't 0 if there are non-empty elements */ ++ content |= (XMLSEC_X509DATA_CERTIFICATE_NODE << 16); + } + } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) { + if(xmlSecIsEmptyNode(cur) == 1) { + content |= XMLSEC_X509DATA_SUBJECTNAME_NODE; ++ } else { ++ content |= (XMLSEC_X509DATA_SUBJECTNAME_NODE << 16); + } + } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) { + if(xmlSecIsEmptyNode(cur) == 1) { + content |= XMLSEC_X509DATA_ISSUERSERIAL_NODE; ++ } else { ++ content |= (XMLSEC_X509DATA_ISSUERSERIAL_NODE << 16); + } + } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) { + if(xmlSecIsEmptyNode(cur) == 1) { + content |= XMLSEC_X509DATA_SKI_NODE; ++ } else { ++ content |= (XMLSEC_X509DATA_SKI_NODE << 16); + } + } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509CRL, xmlSecDSigNs)) { + if(xmlSecIsEmptyNode(cur) == 1) { + content |= XMLSEC_X509DATA_CRL_NODE; ++ } else { ++ content |= (XMLSEC_X509DATA_CRL_NODE << 16); + } + } else { + /* todo: fail on unknown child node? */ +-- +2.30.2 + diff --git a/external/xmlsec/UnpackedTarball_xmlsec.mk b/external/xmlsec/UnpackedTarball_xmlsec.mk index 3ad978cdb829..c0591ddcea0d 100644 --- a/external/xmlsec/UnpackedTarball_xmlsec.mk +++ b/external/xmlsec/UnpackedTarball_xmlsec.mk @@ -8,6 +8,7 @@ # xmlsec_patches := +xmlsec_patches += 0001-xmlSecX509DataGetNodeContent-don-t-return-0-for-non-.patch.1 $(eval $(call gb_UnpackedTarball_UnpackedTarball,xmlsec)) diff --git a/filter/source/graphicfilter/icgm/bitmap.cxx b/filter/source/graphicfilter/icgm/bitmap.cxx index f74ba6fb5d5b..c5613be6acf1 100644 --- a/filter/source/graphicfilter/icgm/bitmap.cxx +++ b/filter/source/graphicfilter/icgm/bitmap.cxx @@ -271,7 +271,15 @@ bool CGMBitmap::ImplGetDimensions( CGMBitmapDescriptor& rDesc ) rDesc.mbStatus = false; sal_uInt32 nHeaderSize = 2 + 3 * nPrecision + 3 * mpCGM->ImplGetPointSize(); - rDesc.mnScanSize = ( ( rDesc.mnX * rDesc.mnDstBitsPerPixel + 7 ) >> 3 ); + + sal_uInt32 nWidthBits; + if (o3tl::checked_multiply(rDesc.mnX, rDesc.mnDstBitsPerPixel, nWidthBits)) + { + rDesc.mbStatus = false; + return false; + } + + rDesc.mnScanSize = (nWidthBits + 7) >> 3; sal_uInt32 nScanSize; nScanSize = rDesc.mnScanSize; diff --git a/include/svl/sigstruct.hxx b/include/svl/sigstruct.hxx index ceed929752ab..02b5c11e73a3 100644 --- a/include/svl/sigstruct.hxx +++ b/include/svl/sigstruct.hxx @@ -22,6 +22,7 @@ #include <rtl/ustring.hxx> #include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> #include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp> #include <com/sun/star/xml/crypto/DigestID.hpp> #include <com/sun/star/uno/Sequence.hxx> @@ -29,8 +30,6 @@ #include <set> #include <vector> -namespace com { namespace sun { namespace star { namespace graphic { class XGraphic; } } } } - /* * type of reference */ @@ -89,9 +88,30 @@ struct SignatureInformation sal_Int32 nSecurityId; css::xml::crypto::SecurityOperationStatus nStatus; SignatureReferenceInformations vSignatureReferenceInfors; - OUString ouX509IssuerName; - OUString ouX509SerialNumber; - OUString ouX509Certificate; + struct X509CertInfo + { + OUString X509IssuerName; + OUString X509SerialNumber; + OUString X509Certificate; + /// OOXML certificate SHA-256 digest, empty for ODF except when doing XAdES signature. + OUString CertDigest; + /// The certificate owner (aka subject). + OUString X509Subject; + }; + typedef std::vector<X509CertInfo> X509Data; + // note: at parse time, it's unkown which one is the signing certificate; + // ImplVerifySignatures() figures it out and puts it at the back + std::vector<X509Data> X509Datas; + + X509CertInfo const* GetSigningCertificate() const + { + if (X509Datas.empty()) + { + return nullptr; + } + assert(!X509Datas.back().empty()); + return & X509Datas.back().back(); + } OUString ouGpgKeyID; OUString ouGpgCertificate; @@ -103,6 +123,9 @@ struct SignatureInformation // XAdES EncapsulatedX509Certificate values std::set<OUString> maEncapsulatedX509Certificates; + OUString ouSignatureId; + // signature may contain multiple time stamps - check they're consistent + bool hasInconsistentSigningTime = false; //We also keep the date and time as string. This is done when this //structure is created as a result of a XML signature being read. //When then a signature is added or another removed, then the original @@ -115,14 +138,12 @@ struct SignatureInformation //and the converted time is written back, then the string looks different //and the signature is broken. OUString ouDateTime; - OUString ouSignatureId; - OUString ouPropertyId; + /// The Id attribute of the <SignatureProperty> element that contains the <dc:date>. + OUString ouDateTimePropertyId; /// Characters of the <dc:description> element inside the signature. OUString ouDescription; /// The Id attribute of the <SignatureProperty> element that contains the <dc:description>. OUString ouDescriptionPropertyId; - /// OOXML certificate SHA-256 digest, empty for ODF except when doing XAdES signature. - OUString ouCertDigest; /// Valid and invalid signature line images css::uno::Reference<css::graphic::XGraphic> aValidSignatureImage; css::uno::Reference<css::graphic::XGraphic> aInvalidSignatureImage; @@ -137,9 +158,6 @@ struct SignatureInformation /// For PDF: the byte range doesn't cover the whole document. bool bPartialDocumentSignature; - /// The certificate owner (aka subject). - OUString ouSubject; - svl::crypto::SignatureMethodAlgorithm eAlgorithmID; SignatureInformation( sal_Int32 nId ) diff --git a/include/svx/sdr/table/tablecontroller.hxx b/include/svx/sdr/table/tablecontroller.hxx index cec83b996c87..9018e2587a2d 100644 --- a/include/svx/sdr/table/tablecontroller.hxx +++ b/include/svx/sdr/table/tablecontroller.hxx @@ -58,6 +58,7 @@ public: SVX_DLLPRIVATE virtual bool DeleteMarked() override; SVX_DLLPRIVATE virtual void onSelectionHasChanged() override; + SVX_DLLPRIVATE virtual void onSelectAll() override; SVX_DLLPRIVATE virtual void GetState( SfxItemSet& rSet ) override; SVX_DLLPRIVATE virtual void Execute( SfxRequest& rReq ) override; diff --git a/include/svx/selectioncontroller.hxx b/include/svx/selectioncontroller.hxx index 11acdac3cd59..3ce5f7849ec3 100644 --- a/include/svx/selectioncontroller.hxx +++ b/include/svx/selectioncontroller.hxx @@ -51,6 +51,8 @@ public: virtual void onSelectionHasChanged(); + virtual void onSelectAll(); + virtual void GetState( SfxItemSet& rSet ); virtual void Execute( SfxRequest& rReq ); diff --git a/include/vcl/BitmapTools.hxx b/include/vcl/BitmapTools.hxx index 6a8f6c8b9605..3f4847609d30 100644 --- a/include/vcl/BitmapTools.hxx +++ b/include/vcl/BitmapTools.hxx @@ -45,7 +45,8 @@ public: assert(nBitCount == 24 || nBitCount == 32); sal_Int32 nRowSize, nDataSize; if (o3tl::checked_multiply<sal_Int32>(rSize.getWidth(), nBitCount/8, nRowSize) || - o3tl::checked_multiply<sal_Int32>(nRowSize, rSize.getHeight(), nDataSize)) + o3tl::checked_multiply<sal_Int32>(nRowSize, rSize.getHeight(), nDataSize) || + nDataSize < 0) { throw std::bad_alloc(); } diff --git a/include/xmloff/xmlimp.hxx b/include/xmloff/xmlimp.hxx index 86af82e61fa5..3cb69376a258 100644 --- a/include/xmloff/xmlimp.hxx +++ b/include/xmloff/xmlimp.hxx @@ -232,8 +232,12 @@ class XMLOFF_DLLPUBLIC SvXMLImport : public cppu::WeakImplHelper< static void initializeNamespaceMaps(); void registerNamespaces(); - std::unique_ptr<SvXMLNamespaceMap> processNSAttributes( +public: + static std::unique_ptr<SvXMLNamespaceMap> processNSAttributes( + std::unique_ptr<SvXMLNamespaceMap> & rpNamespaceMap, + SvXMLImport *const pImport, const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList); +private: void Characters(const OUString& aChars); css::uno::Reference< css::task::XStatusIndicator > mxStatusIndicator; diff --git a/include/xmloff/xmlnmspe.hxx b/include/xmloff/xmlnmspe.hxx index a00628b6b999..a7505a64190d 100644 --- a/include/xmloff/xmlnmspe.hxx +++ b/include/xmloff/xmlnmspe.hxx @@ -138,6 +138,16 @@ XML_NAMESPACE( XML_NAMESPACE_FIELD, 100U ) XML_NAMESPACE( XML_NAMESPACE_CSS3TEXT, 103U ) // CSS Text Level 3 XML_NAMESPACE( XML_NAMESPACE_FORMX, 101U ) // form interop extensions +// OOo extension digital signatures, used in ODF 1.1 +const sal_uInt16 XML_NAMESPACE_DSIG_OOO = 200; +// ODF 1.2 digital signature namespaces +const sal_uInt16 XML_NAMESPACE_DSIG = 201; +const sal_uInt16 XML_NAMESPACE_DS = 202; +const sal_uInt16 XML_NAMESPACE_XADES132 = 203; +const sal_uInt16 XML_NAMESPACE_XADES141 = 204; +// OOXML digital signature extension namespaces, also based on xmldsig-core +const sal_uInt16 XML_NAMESPACE_MDSSI = 205; +const sal_uInt16 XML_NAMESPACE_MSODIGSIG = 206; #endif // INCLUDED_XMLOFF_XMLNMSPE_HXX diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx index f572e338715e..6e56bdf4d6b0 100644 --- a/include/xmloff/xmltoken.hxx +++ b/include/xmloff/xmltoken.hxx @@ -132,6 +132,19 @@ namespace xmloff { namespace token { XML_NP_GRDDL, XML_N_GRDDL, + // OOo extension digital signatures, used in ODF 1.1 + XML_NP_DSIG_OOO, + XML_N_DSIG_OOO, + // ODF 1.2 digital signatures + XML_NP_DSIG, + XML_N_DSIG, + XML_NP_DS, + XML_N_DS, + XML_NP_XADES132, + XML_N_XADES132, + XML_NP_XADES141, + XML_N_XADES141, + // ODF Enhanced namespaces XML_NP_OFFICE_EXT, XML_N_OFFICE_EXT, diff --git a/instsetoo_native/inc_openoffice/unix/find-requires-x11.sh b/instsetoo_native/inc_openoffice/unix/find-requires-x11.sh index 0fe0b1d27dde..6808b3631d73 100644 --- a/instsetoo_native/inc_openoffice/unix/find-requires-x11.sh +++ b/instsetoo_native/inc_openoffice/unix/find-requires-x11.sh @@ -23,5 +23,7 @@ if [[ "${OS}" == "AIX" ]]; then echo "libfreetype.a(libfreetype.so.6${mark64})" else echo "libfreetype.so.6${mark64}" - echo "libXinerama.so.1${mark64}" + if [[ "${XINERAMA_LINK}" == "dynamic" ]]; then + echo "libXinerama.so.1${mark64}" + fi fi diff --git a/libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar.cxx b/libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar.cxx index 619b2a87b13f..9a454c61ba52 100644 --- a/libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar.cxx +++ b/libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar.cxx @@ -9,6 +9,7 @@ #include <gtk/gtk.h> +#include <cassert> #include <cmath> #include <iostream> @@ -132,6 +133,10 @@ static gboolean gtv_calc_header_bar_draw_impl(GtkWidget* pWidget, cairo_t* pCair cairo_rectangle(pCairo, aRectangle.x, aRectangle.height, aRectangle.width, 1); cairo_fill(pCairo); } + else + { + assert(false); // should never happen + } gtv_calc_header_bar_draw_text(pCairo, aRectangle, rHeader.m_aText); nPrevious = rHeader.m_nSize; diff --git a/lotuswordpro/qa/cppunit/data/pass/ofz20517-1.lwp b/lotuswordpro/qa/cppunit/data/pass/ofz20517-1.lwp Binary files differnew file mode 100644 index 000000000000..de6dcbf1c5d5 --- /dev/null +++ b/lotuswordpro/qa/cppunit/data/pass/ofz20517-1.lwp diff --git a/lotuswordpro/source/filter/lwprowlayout.cxx b/lotuswordpro/source/filter/lwprowlayout.cxx index a0a90a417c69..da10c32888f7 100644 --- a/lotuswordpro/source/filter/lwprowlayout.cxx +++ b/lotuswordpro/source/filter/lwprowlayout.cxx @@ -191,6 +191,8 @@ void LwpRowLayout::Read() void LwpRowLayout::ConvertRow(rtl::Reference<XFTable> const & pXFTable,sal_uInt8 nStartCol,sal_uInt8 nEndCol) { LwpTableLayout* pTableLayout = GetParentTableLayout(); + if (!pTableLayout) + throw std::runtime_error("missing TableLayout"); LwpTable* pTable = pTableLayout->GetTable(); //calculate the connected cell position @@ -281,14 +283,15 @@ void LwpRowLayout::RegisterCurRowStyle(XFRow* pXFRow,sal_uInt16 nRowMark) { pRowStyle = static_cast<XFRowStyle*>( pXFStyleManager->FindStyle(pTableLayout->GetDefaultRowStyleName())); - fHeight += pRowStyle->GetRowHeight(); } else { pRowStyle = static_cast<XFRowStyle*>( pXFStyleManager->FindStyle(iter->second->GetStyleName())); - fHeight+=pRowStyle->GetRowHeight(); } + if (!pRowStyle) + throw std::runtime_error("missing RowStyle"); + fHeight += pRowStyle->GetRowHeight(); } if (m_nDirection & 0x0030) @@ -376,11 +379,13 @@ void LwpRowLayout::ConvertCommonRow(rtl::Reference<XFTable> const & pXFTable, sa LwpTableLayout* pTableLayout = GetParentTableLayout(); if (!pTableLayout) return; + LwpTable* pTable = pTableLayout->GetTable(); + if (!pTable) + return; rtl::Reference<XFRow> xRow(new XFRow); xRow->SetStyleName(m_StyleName); - LwpTable* pTable = pTableLayout->GetTable(); sal_uInt8 nCellStartCol,nCellEndCol; for (sal_uInt8 i = nStartCol; i < nEndCol ; i++) diff --git a/lotuswordpro/source/filter/lwptablelayout.cxx b/lotuswordpro/source/filter/lwptablelayout.cxx index b595dc152c6a..54e359efc963 100644 --- a/lotuswordpro/source/filter/lwptablelayout.cxx +++ b/lotuswordpro/source/filter/lwptablelayout.cxx @@ -877,7 +877,14 @@ sal_uInt16 LwpTableLayout::ConvertHeadingRow( XFRow* pXFRow = pTmpTable->GetRow(1); pXFTable->AddHeaderRow(pXFRow); pTmpTable->RemoveRow(1); - nContentRow = m_RowsMap[0]->GetCurMaxSpannedRows(0,nCol); + auto iter = m_RowsMap.find(0); + if (iter == m_RowsMap.end()) + { + SAL_WARN("lwp", "row 0 is unknown"); + nContentRow = 0; + } + else + nContentRow = iter->second->GetCurMaxSpannedRows(0,nCol); } } return nContentRow; diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index 1b7eb5343560..0fa752be89fe 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -111,6 +111,7 @@ public: void testJumpToLastRowInvalidation(); void testDeleteCellMultilineContent(); void testFunctionDlg(); + void testSheetViewDataCrash(); CPPUNIT_TEST_SUITE(ScTiledRenderingTest); CPPUNIT_TEST(testRowColumnHeaders); @@ -153,6 +154,7 @@ public: CPPUNIT_TEST(testJumpToLastRowInvalidation); CPPUNIT_TEST(testDeleteCellMultilineContent); CPPUNIT_TEST(testFunctionDlg); + CPPUNIT_TEST(testSheetViewDataCrash); CPPUNIT_TEST_SUITE_END(); private: @@ -2028,6 +2030,47 @@ void ScTiledRenderingTest::testDeleteCellMultilineContent() SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); } +void ScTiledRenderingTest::testSheetViewDataCrash() +{ + comphelper::LibreOfficeKit::setActive(); + + ScModelObj* pModelObj = createDoc("empty.ods"); + + // view #1 + int nView1 = SfxLokHelper::getView(); + SfxLokHelper::setView(nView1); + + // Imitate online while creating a new sheet on empty.ods. + uno::Sequence<beans::PropertyValue> aArgs( + comphelper::InitPropertySequence({ + { "Name", uno::Any(OUString("NewSheet")) }, + { "Index", uno::Any(sal_Int32(2)) } + })); + comphelper::dispatchCommand(".uno:Insert", aArgs); + Scheduler::ProcessEventsToIdle(); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::PAGEDOWN | KEY_MOD1); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::PAGEDOWN | KEY_MOD1); + Scheduler::ProcessEventsToIdle(); + ScTabViewShell* pView1 = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); + CPPUNIT_ASSERT(pView1); + + // view #2 + SfxLokHelper::createView(); + ScTabViewShell* pView2 = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); + CPPUNIT_ASSERT(pView2); + Scheduler::ProcessEventsToIdle(); + + SfxLokHelper::setView(nView1); + // Delete a range. + pView1->SetCursor(1, 1); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::DOWN | KEY_SHIFT); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::DOWN | KEY_SHIFT); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::DELETE); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::DELETE); + // It will crash at this point without the fix. + Scheduler::ProcessEventsToIdle(); +} + } CPPUNIT_TEST_SUITE_REGISTRATION(ScTiledRenderingTest); diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index 38af064a918c..15a57dc42400 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -161,7 +161,8 @@ bool ScDocFunc::AdjustRowHeight( const ScRange& rRange, bool bPaint ) ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); if (pTabViewShell) { - pTabViewShell->GetViewData().GetLOKHeightHelper(nTab)->invalidateByIndex(nStartRow); + if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKHeightHelper(nTab)) + pPosHelper->invalidateByIndex(nStartRow); } pViewShell = SfxViewShell::GetNext(*pViewShell); } diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx index d1f57b46dead..c7f7d81a8a9e 100644 --- a/sc/source/ui/view/dbfunc3.cxx +++ b/sc/source/ui/view/dbfunc3.cxx @@ -2260,9 +2260,15 @@ void ScDBFunc::OnLOKShowHideColRow(bool bColumns, SCCOLROW nStart) if (pTabViewShell) { if (bColumns) - pTabViewShell->GetViewData().GetLOKWidthHelper(nCurrentTabIndex)->invalidateByIndex(nStart); + { + if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKWidthHelper(nCurrentTabIndex)) + pPosHelper->invalidateByIndex(nStart); + } else - pTabViewShell->GetViewData().GetLOKHeightHelper(nCurrentTabIndex)->invalidateByIndex(nStart); + { + if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKHeightHelper(nCurrentTabIndex)) + pPosHelper->invalidateByIndex(nStart); + } if (pTabViewShell->getPart() == nCurrentTabIndex) { diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index 1c7e36ca484a..39f23fb31f62 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -1996,7 +1996,8 @@ void ScViewData::SetTabNo( SCTAB nNewTab ) ScPositionHelper* ScViewData::GetLOKWidthHelper(SCTAB nTabIndex) { - if (!ValidTab(nTabIndex) || (nTabIndex >= static_cast<SCTAB>(maTabData.size()))) + if (!ValidTab(nTabIndex) || (nTabIndex >= static_cast<SCTAB>(maTabData.size())) || + !maTabData[nTabIndex]) { return nullptr; } @@ -2005,7 +2006,8 @@ ScPositionHelper* ScViewData::GetLOKWidthHelper(SCTAB nTabIndex) ScPositionHelper* ScViewData::GetLOKHeightHelper(SCTAB nTabIndex) { - if (!ValidTab(nTabIndex) || (nTabIndex >= static_cast<SCTAB>(maTabData.size()))) + if (!ValidTab(nTabIndex) || (nTabIndex >= static_cast<SCTAB>(maTabData.size())) || + !maTabData[nTabIndex]) { return nullptr; } diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index a0e1185a6d3f..51738b4951af 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -1487,7 +1487,8 @@ void ScViewFunc::OnLOKInsertDeleteColumn(SCCOL nStartCol, long nOffset) ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); if (pTabViewShell) { - pTabViewShell->GetViewData().GetLOKWidthHelper(nCurrentTabIndex)->invalidateByIndex(nStartCol); + if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKWidthHelper(nCurrentTabIndex)) + pPosHelper->invalidateByIndex(nStartCol); // if we remove a column the cursor position and the current selection // in other views could need to be moved on the left by one column. @@ -1542,7 +1543,8 @@ void ScViewFunc::OnLOKInsertDeleteRow(SCROW nStartRow, long nOffset) ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); if (pTabViewShell) { - pTabViewShell->GetViewData().GetLOKHeightHelper(nCurrentTabIndex)->invalidateByIndex(nStartRow); + if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKHeightHelper(nCurrentTabIndex)) + pPosHelper->invalidateByIndex(nStartRow); // if we remove a row the cursor position and the current selection // in other views could need to be moved up by one row. @@ -1598,9 +1600,15 @@ void ScViewFunc::OnLOKSetWidthOrHeight(SCCOLROW nStart, bool bWidth) if (pTabViewShell) { if (bWidth) - pTabViewShell->GetViewData().GetLOKWidthHelper(nCurTab)->invalidateByIndex(nStart); + { + if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKWidthHelper(nCurTab)) + pPosHelper->invalidateByIndex(nStart); + } else - pTabViewShell->GetViewData().GetLOKHeightHelper(nCurTab)->invalidateByIndex(nStart); + { + if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKHeightHelper(nCurTab)) + pPosHelper->invalidateByIndex(nStart); + } } pViewShell = SfxViewShell::GetNext(*pViewShell); } diff --git a/sfx2/source/appl/macroloader.cxx b/sfx2/source/appl/macroloader.cxx index 1c32be75cd90..9edd49bd18a7 100644 --- a/sfx2/source/appl/macroloader.cxx +++ b/sfx2/source/appl/macroloader.cxx @@ -75,10 +75,10 @@ css::uno::Sequence<OUString> SAL_CALL SfxMacroLoader::getSupportedServiceNames() return aSeq; } -SfxObjectShell* SfxMacroLoader::GetObjectShell_Impl() +SfxObjectShell* SfxMacroLoader::GetObjectShell(const Reference <XFrame>& xFrame) { SfxObjectShell* pDocShell = nullptr; - Reference < XFrame > xFrame( m_xFrame.get(), UNO_QUERY ); + if ( xFrame.is() ) { SfxFrame* pFrame=nullptr; @@ -95,6 +95,11 @@ SfxObjectShell* SfxMacroLoader::GetObjectShell_Impl() return pDocShell; } +SfxObjectShell* SfxMacroLoader::GetObjectShell_Impl() +{ + Reference < XFrame > xFrame( m_xFrame.get(), UNO_QUERY ); + return SfxMacroLoader::GetObjectShell(xFrame); +} uno::Reference<frame::XDispatch> SAL_CALL SfxMacroLoader::queryDispatch( const util::URL& aURL , diff --git a/sfx2/source/doc/iframe.cxx b/sfx2/source/doc/iframe.cxx index f6319d58abb3..77d2f17b9970 100644 --- a/sfx2/source/doc/iframe.cxx +++ b/sfx2/source/doc/iframe.cxx @@ -39,10 +39,12 @@ #include <svl/ownlist.hxx> #include <svl/itemprop.hxx> #include <sfx2/frmdescr.hxx> +#include <sfx2/objsh.hxx> #include <sfx2/sfxdlg.hxx> #include <sfx2/sfxsids.hrc> #include <toolkit/helper/vclunohelper.hxx> #include <vcl/window.hxx> +#include <macroloader.hxx> using namespace ::com::sun::star; @@ -158,6 +160,19 @@ sal_Bool SAL_CALL IFrameObject::load( { if ( SvtMiscOptions().IsPluginsEnabled() ) { + util::URL aTargetURL; + aTargetURL.Complete = maFrmDescr.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ); + uno::Reference < util::XURLTransformer > xTrans( util::URLTransformer::create( mxContext ) ); + xTrans->parseStrict( aTargetURL ); + + if (INetURLObject(aTargetURL.Complete).GetProtocol() == INetProtocol::Macro) + { + uno::Reference<frame::XFramesSupplier> xParentFrame = xFrame->getCreator(); + SfxObjectShell* pDoc = SfxMacroLoader::GetObjectShell(xParentFrame); + if (pDoc && !pDoc->AdjustMacroMode()) + return false; + } + DBG_ASSERT( !mxFrame.is(), "Frame already existing!" ); VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); VclPtr<IFrameWindow_Impl> pWin = VclPtr<IFrameWindow_Impl>::Create( pParent, maFrmDescr.IsFrameBorderOn() ); @@ -180,11 +195,6 @@ sal_Bool SAL_CALL IFrameObject::load( if ( xFramesSupplier.is() ) mxFrame->setCreator( xFramesSupplier ); - util::URL aTargetURL; - aTargetURL.Complete = maFrmDescr.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ); - uno::Reference < util::XURLTransformer > xTrans( util::URLTransformer::create( mxContext ) ); - xTrans->parseStrict( aTargetURL ); - uno::Sequence < beans::PropertyValue > aProps(2); aProps[0].Name = "PluginMode"; aProps[0].Value <<= sal_Int16(2); diff --git a/sfx2/source/inc/macroloader.hxx b/sfx2/source/inc/macroloader.hxx index 54decff36a37..8d276423173e 100644 --- a/sfx2/source/inc/macroloader.hxx +++ b/sfx2/source/inc/macroloader.hxx @@ -82,6 +82,8 @@ public: virtual void SAL_CALL addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xControl, const css::util::URL& aURL ) override; virtual void SAL_CALL removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xControl, const css::util::URL& aURL ) override; + + static SfxObjectShell* GetObjectShell(const css::uno::Reference<css::frame::XFrame>& xFrame); }; #endif diff --git a/shell/source/unix/exec/shellexec.cxx b/shell/source/unix/exec/shellexec.cxx index 86c3672162c0..093a8a2ba57f 100644 --- a/shell/source/unix/exec/shellexec.cxx +++ b/shell/source/unix/exec/shellexec.cxx @@ -117,6 +117,7 @@ void SAL_CALL ShellExec::execute( const OUString& aCommand, const OUString& aPar } #ifdef MACOSX + bool dir = false; if (uri->getScheme().equalsIgnoreAsciiCase("file")) { OUString pathname; auto const e1 = osl::FileBase::getSystemPathFromFileURL(aCommand, pathname); @@ -142,12 +143,15 @@ void SAL_CALL ShellExec::execute( const OUString& aCommand, const OUString& aPar auto const e3 = errno; SAL_INFO("shell", "stat(" << pathname8 << ") failed with errno " << e3); } - if (e2 != 0 || !S_ISREG(st.st_mode) - || (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0) + if (e2 == 0 && S_ISDIR(st.st_mode)) { + dir = true; + } else if (e2 != 0 || !S_ISREG(st.st_mode) + || (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0) { throw css::lang::IllegalArgumentException( "XSystemShellExecute.execute, cannot process <" + aCommand + ">", {}, 0); } else if (pathname.endsWithIgnoreAsciiCase(".class") + || pathname.endsWithIgnoreAsciiCase(".fileloc") || pathname.endsWithIgnoreAsciiCase(".jar")) { dir = true; @@ -176,7 +180,11 @@ void SAL_CALL ShellExec::execute( const OUString& aCommand, const OUString& aPar // 2.4 If it does not match an exitsting pathname (relative to CWD): // Results in "The file /.../foo:bar does not exits." (where "/..." is // the CWD) on stderr and SystemShellExecuteException. - aBuffer.append("open --"); + aBuffer.append("open"); + if (dir) { + aBuffer.append(" -R"); + } + aBuffer.append(" --"); #else // Just use xdg-open on non-Mac aBuffer.append("/usr/bin/xdg-open"); diff --git a/solenv/bin/modules/installer/simplepackage.pm b/solenv/bin/modules/installer/simplepackage.pm index b407a4ff668f..9a2d28a764d3 100644 --- a/solenv/bin/modules/installer/simplepackage.pm +++ b/solenv/bin/modules/installer/simplepackage.pm @@ -436,7 +436,7 @@ sub create_package } $systemcall = "cd $localtempdir && hdiutil create -megabytes 1500 -srcfolder $folder $archive -ov -fs HFS+ -volname \"$volume_name\" -format UDBZ"; - if (( $ref ne "" ) && ( $$ref ne "" )) { + if (( $ref ne "" ) && ( $$ref ne "" ) && system("hdiutil 2>&1 | grep unflatten") == 0) { $systemcall .= " && hdiutil unflatten $archive && Rez -a $$ref -o $archive && hdiutil flatten $archive"; } } diff --git a/svl/source/crypto/cryptosign.cxx b/svl/source/crypto/cryptosign.cxx index 617c926201fa..fb5fd7038033 100644 --- a/svl/source/crypto/cryptosign.cxx +++ b/svl/source/crypto/cryptosign.cxx @@ -2111,8 +2111,12 @@ bool Signing::Verify(const std::vector<unsigned char>& aData, aDerCert[i] = pCertificate->derCert.data[i]; OUStringBuffer aBuffer; comphelper::Base64::encode(aBuffer, aDerCert); - rInformation.ouX509Certificate = aBuffer.makeStringAndClear(); - rInformation.ouSubject = OUString(pCertificate->subjectName, PL_strlen(pCertificate->subjectName), RTL_TEXTENCODING_UTF8); + SignatureInformation::X509Data temp; + temp.emplace_back(); + temp.back().X509Certificate = aBuffer.makeStringAndClear(); + temp.back().X509Subject = OUString(pCertificate->subjectName, PL_strlen(pCertificate->subjectName), RTL_TEXTENCODING_UTF8); + rInformation.X509Datas.clear(); + rInformation.X509Datas.emplace_back(temp); } PRTime nSigningTime; @@ -2291,8 +2295,12 @@ bool Signing::Verify(const std::vector<unsigned char>& aData, aDerCert[i] = pSignerCertContext->pbCertEncoded[i]; OUStringBuffer aBuffer; comphelper::Base64::encode(aBuffer, aDerCert); - rInformation.ouX509Certificate = aBuffer.makeStringAndClear(); - rInformation.ouSubject = GetSubjectName(pSignerCertContext); + SignatureInformation::X509Data temp; + temp.emplace_back(); + temp.back().X509Certificate = aBuffer.makeStringAndClear(); + temp.back().X509Subject = GetSubjectName(pSignerCertContext); + rInformation.X509Datas.clear(); + rInformation.X509Datas.emplace_back(temp); } if (bNonDetached) diff --git a/svx/source/svdraw/selectioncontroller.cxx b/svx/source/svdraw/selectioncontroller.cxx index 8cb678d66467..bc31a7543366 100644 --- a/svx/source/svdraw/selectioncontroller.cxx +++ b/svx/source/svdraw/selectioncontroller.cxx @@ -47,6 +47,10 @@ void SelectionController::onSelectionHasChanged() { } +void SelectionController::onSelectAll() +{ +} + void SelectionController::GetState( SfxItemSet& /*rSet*/ ) { } diff --git a/svx/source/svdraw/svdview.cxx b/svx/source/svdraw/svdview.cxx index c68bbe443a72..ad6e4beb7cc4 100644 --- a/svx/source/svdraw/svdview.cxx +++ b/svx/source/svdraw/svdview.cxx @@ -35,6 +35,7 @@ #include <svdibrow.hxx> #endif +#include <svx/sdr/table/tablecontroller.hxx> #include <svx/svdoutl.hxx> #include <svx/svdview.hxx> #include <editeng/editview.hxx> @@ -1359,7 +1360,33 @@ void SdrView::MarkAll() #endif } else if (IsGluePointEditMode()) MarkAllGluePoints(); else if (HasMarkablePoints()) MarkAllPoints(); - else MarkAllObj(); + else { + // check for table + bool bMarkAll = true; + const SdrMarkList& rMarkList = GetMarkedObjectList(); + if (rMarkList.GetMarkCount() == 1) + { + const SdrObject* pObj(rMarkList.GetMark(0)->GetMarkedSdrObj()); + SdrView* pView(dynamic_cast<SdrView*>(this)); + if (pObj && pView && (pObj->GetObjInventor() == SdrInventor::Default) + && (pObj->GetObjIdentifier() == OBJ_TABLE)) + { + mxSelectionController.clear(); + mxSelectionController = sdr::table::CreateTableController( + *pView, static_cast<const sdr::table::SdrTableObj&>(*pObj), + mxLastSelectionController); + + if (mxSelectionController.is()) + { + mxLastSelectionController.clear(); + mxSelectionController->onSelectAll(); + bMarkAll = false; + } + } + } + if ( bMarkAll ) + MarkAllObj(); + } } void SdrView::UnmarkAll() diff --git a/svx/source/table/svdotable.cxx b/svx/source/table/svdotable.cxx index 45d184403c56..18ac30472a7b 100644 --- a/svx/source/table/svdotable.cxx +++ b/svx/source/table/svdotable.cxx @@ -243,6 +243,7 @@ private: static sal_Int32 lastRowCount; static sal_Int32 lastColCount; static std::vector<sal_Int32> lastColWidths; + static bool rowSizeChanged; }; SdrTableObjImpl* SdrTableObjImpl::lastLayoutTable = nullptr; @@ -253,6 +254,7 @@ bool SdrTableObjImpl::lastLayoutFitHeight; WritingMode SdrTableObjImpl::lastLayoutMode; sal_Int32 SdrTableObjImpl::lastRowCount; sal_Int32 SdrTableObjImpl::lastColCount; +bool SdrTableObjImpl::rowSizeChanged = false; std::vector<sal_Int32> SdrTableObjImpl::lastColWidths; SdrTableObjImpl::SdrTableObjImpl() @@ -594,6 +596,7 @@ void SdrTableObjImpl::DragEdge( bool mbHorizontal, int nEdge, sal_Int32 nOffset Reference< XIndexAccess > xRows( mxTable->getRows(), UNO_QUERY_THROW ); Reference< XPropertySet > xRowSet( xRows->getByIndex( (!nEdge)?nEdge:(nEdge-1) ), UNO_QUERY_THROW ); xRowSet->setPropertyValue( sSize, Any( nHeight ) ); + rowSizeChanged = true; } } else @@ -798,7 +801,8 @@ void SdrTableObjImpl::LayoutTable( tools::Rectangle& rArea, bool bFitWidth, bool || lastLayoutMode != writingMode || lastRowCount != getRowCount() || lastColCount != getColumnCount() - || lastColWidths != getColumnWidths() ) + || lastColWidths != getColumnWidths() + || rowSizeChanged ) { lastLayoutTable = this; lastLayoutInputRectangle = rArea; @@ -813,6 +817,7 @@ void SdrTableObjImpl::LayoutTable( tools::Rectangle& rArea, bool bFitWidth, bool TableModelNotifyGuard aGuard( mxTable.get() ); mpLayouter->LayoutTable( rArea, bFitWidth, bFitHeight ); lastLayoutResultRectangle = rArea; + rowSizeChanged = false; } else { diff --git a/svx/source/table/tablecontroller.cxx b/svx/source/table/tablecontroller.cxx index 43c74993961b..d7028fe42c0c 100644 --- a/svx/source/table/tablecontroller.cxx +++ b/svx/source/table/tablecontroller.cxx @@ -399,13 +399,6 @@ void SvxTableController::onSelectionHasChanged() const SdrMarkList& rMarkList= mrView.GetMarkedObjectList(); if( rMarkList.GetMarkCount() == 1 ) bSelected = mxTableObj.get() == rMarkList.GetMark(0)->GetMarkedSdrObj(); - /* fdo#46186 Selecting the table means selecting the entire cells */ - if (!hasSelectedCells() && pTableObj) - { - maCursorFirstPos = SdrTableObj::getFirstCell(); - maCursorLastPos = pTableObj->getLastCell(); - mbCellSelectionMode=true; - } } if( bSelected ) @@ -417,6 +410,14 @@ void SvxTableController::onSelectionHasChanged() destroySelectionOverlay(); } } +void SvxTableController::onSelectAll() +{ + sdr::table::SdrTableObj* pTableObj = mxTableObj.get(); + if ( pTableObj && !pTableObj->IsTextEditActive()) + { + selectAll(); + } +} void SvxTableController::GetState( SfxItemSet& rSet ) @@ -1385,30 +1386,44 @@ bool SvxTableController::DeleteMarked() SdrTableObj& rTableObj(*mxTableObj.get()); SdrModel& rModel(rTableObj.getSdrModelFromSdrObject()); const bool bUndo(rModel.IsUndoEnabled()); + bool bDeleteTable = false; if (bUndo) rModel.BegUndo(SvxResId(STR_TABLE_DELETE_CELL_CONTENTS)); CellPos aStart, aEnd; getSelectedCells( aStart, aEnd ); - for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ ) + const sal_Int32 nRemovedColumns = aEnd.mnCol - aStart.mnCol + 1; + const sal_Int32 nRemovedRows = aEnd.mnRow - aStart.mnRow + 1; + if( nRemovedColumns == mxTable->getColumnCount() && nRemovedRows == mxTable->getRowCount()) { - for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ ) + bDeleteTable = true; + } + else + { + for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ ) { - CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) ); - if (xCell.is() && xCell->hasText()) + for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ ) { - if (bUndo) - xCell->AddUndo(); - xCell->SetOutlinerParaObject(nullptr); + CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) ); + if (xCell.is() && xCell->hasText()) + { + if (bUndo) + xCell->AddUndo(); + xCell->SetOutlinerParaObject(nullptr); + } } } } + if (bDeleteTable) + mrView.DeleteMarkedObj(); + if (bUndo) rModel.EndUndo(); - UpdateTableShape(); + if (!bDeleteTable) + UpdateTableShape(); return true; } diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index e2014a101966..1929880d60a2 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -407,7 +407,8 @@ std::pair<bool, OUString> lcl_MakeParagraphSignatureFieldText(const SignatureDes valid = valid && aInfo.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; - msg = SwResId(STR_SIGNED_BY) + ": " + aInfo.ouSubject + ", "; + assert(aInfo.GetSigningCertificate()); // it was valid + msg = SwResId(STR_SIGNED_BY) + ": " + aInfo.GetSigningCertificate()->X509Subject + ", "; msg += aDescr.msDate; msg += (!aDescr.msUsage.isEmpty() ? (" (" + aDescr.msUsage + "): ") : OUString(": ")); msg += (valid ? SwResId(STR_VALID) : SwResId(STR_INVALID)); diff --git a/sw/source/filter/basflt/fltshell.cxx b/sw/source/filter/basflt/fltshell.cxx index ee4d46bbc833..46d6a8a4098b 100644 --- a/sw/source/filter/basflt/fltshell.cxx +++ b/sw/source/filter/basflt/fltshell.cxx @@ -652,9 +652,8 @@ void SwFltControlStack::SetAttrInDoc(const SwPosition& rTmpPos, { SwTextNode const*const pTextNode( aRegion.End()->nNode.GetNode().GetTextNode()); - assert(pTextNode); - SwTextField const*const pField(pTextNode->GetFieldTextAttrAt( - aRegion.End()->nContent.GetIndex() - 1, true)); + SwTextField const*const pField = pTextNode ? pTextNode->GetFieldTextAttrAt( + aRegion.End()->nContent.GetIndex() - 1, true) : nullptr; if (pField) { SwPostItField const*const pPostIt( diff --git a/sw/source/filter/html/htmlplug.cxx b/sw/source/filter/html/htmlplug.cxx index b6ccae2ee122..5cb439228e94 100644 --- a/sw/source/filter/html/htmlplug.cxx +++ b/sw/source/filter/html/htmlplug.cxx @@ -1087,7 +1087,12 @@ void SwHTMLParser::InsertFloatingFrame() bool bHasBorder = aFrameDesc.HasFrameBorder(); Size aMargin = aFrameDesc.GetMargin(); - xSet->setPropertyValue("FrameURL", uno::makeAny( aFrameDesc.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ); + OUString sHRef = aFrameDesc.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ); + + if (INetURLObject(sHRef).GetProtocol() == INetProtocol::Macro) + NotifyMacroEventRead(); + + xSet->setPropertyValue("FrameURL", uno::makeAny( sHRef ) ); xSet->setPropertyValue("FrameName", uno::makeAny( aName ) ); if ( eScroll == ScrollingMode::Auto ) diff --git a/sw/source/filter/ww8/ww8scan.cxx b/sw/source/filter/ww8/ww8scan.cxx index 643601e144e3..e8e0c06db234 100644 --- a/sw/source/filter/ww8/ww8scan.cxx +++ b/sw/source/filter/ww8/ww8scan.cxx @@ -2331,26 +2331,40 @@ void WW8PLCF::ReadPLCF(SvStream& rSt, WW8_FC nFilePos, sal_uInt32 nPLCF) void WW8PLCF::MakeFailedPLCF() { nIMax = 0; - pPLCF_PosArray.reset( new sal_Int32[2] ); + pPLCF_PosArray.reset( new WW8_CP[2] ); pPLCF_PosArray[0] = pPLCF_PosArray[1] = WW8_CP_MAX; pPLCF_Contents = reinterpret_cast<sal_uInt8*>(&pPLCF_PosArray[nIMax + 1]); } -void WW8PLCF::TruncToSortedRange() +namespace { - //Docs state that: ... all Plcs ... are sorted in ascending order. - //So ensure that here for broken documents. - for (auto nI = 0; nI < nIMax; ++nI) + sal_Int32 TruncToSortedRange(const sal_Int32* pPLCF_PosArray, sal_Int32 nIMax) { - if (pPLCF_PosArray[nI] > pPLCF_PosArray[nI+1]) + //Docs state that: ... all Plcs ... are sorted in ascending order. + //So ensure that here for broken documents. + for (auto nI = 0; nI < nIMax; ++nI) { - SAL_WARN("sw.ww8", "Document has unsorted PLCF, truncated to sorted portion"); - nIMax = nI; - break; + if (pPLCF_PosArray[nI] > pPLCF_PosArray[nI+1]) + { + SAL_WARN("sw.ww8", "Document has unsorted PLCF, truncated to sorted portion"); + nIMax = nI; + break; + } } + return nIMax; } } +void WW8PLCFpcd::TruncToSortedRange() +{ + nIMax = ::TruncToSortedRange(pPLCF_PosArray.get(), nIMax); +} + +void WW8PLCF::TruncToSortedRange() +{ + nIMax = ::TruncToSortedRange(pPLCF_PosArray.get(), nIMax); +} + void WW8PLCF::GeneratePLCF(SvStream& rSt, sal_Int32 nPN, sal_Int32 ncpN) { OSL_ENSURE( nIMax < ncpN, "Pcl.Fkp: Why is PLCF too big?" ); @@ -2372,7 +2386,7 @@ void WW8PLCF::GeneratePLCF(SvStream& rSt, sal_Int32 nPN, sal_Int32 ncpN) { size_t nSiz = (4 + nStru) * nIMax + 4; size_t nElems = ( nSiz + 3 ) / 4; - pPLCF_PosArray.reset( new sal_Int32[ nElems ] ); // Pointer to Pos-array + pPLCF_PosArray.reset( new WW8_CP[ nElems ] ); // Pointer to Pos-array for (sal_Int32 i = 0; i < ncpN && !failure; ++i) { @@ -2506,7 +2520,7 @@ WW8PLCFpcd::WW8PLCFpcd(SvStream* pSt, sal_uInt32 nFilePos, bValid = false; nPLCF = bValid ? std::min(nRemainingSize, static_cast<std::size_t>(nPLCF)) : nValidMin; - pPLCF_PosArray.reset( new sal_Int32[ ( nPLCF + 3 ) / 4 ] ); // Pointer to Pos-array + pPLCF_PosArray.reset( new WW8_CP[ ( nPLCF + 3 ) / 4 ] ); // Pointer to Pos-array pPLCF_PosArray[0] = 0; nPLCF = bValid ? pSt->ReadBytes(pPLCF_PosArray.get(), nPLCF) : nValidMin; @@ -2520,6 +2534,7 @@ WW8PLCFpcd::WW8PLCFpcd(SvStream* pSt, sal_uInt32 nFilePos, // Pointer to content array pPLCF_Contents = reinterpret_cast<sal_uInt8*>(&pPLCF_PosArray[nIMax + 1]); + TruncToSortedRange(); pSt->Seek( nOldPos ); } diff --git a/sw/source/filter/ww8/ww8scan.hxx b/sw/source/filter/ww8/ww8scan.hxx index 3eae6d1b30b3..e8f6db496950 100644 --- a/sw/source/filter/ww8/ww8scan.hxx +++ b/sw/source/filter/ww8/ww8scan.hxx @@ -346,14 +346,16 @@ class WW8PLCFpcd { friend class WW8PLCFpcd_Iter; - std::unique_ptr<sal_Int32[]> pPLCF_PosArray; // pointer to Pos-array and the whole structure + std::unique_ptr<WW8_CP[]> pPLCF_PosArray; // pointer to Pos-array and the whole structure sal_uInt8* pPLCF_Contents; // pointer to content-array-part of Pos-array - long nIMax; + sal_Int32 nIMax; sal_uInt32 nStru; WW8PLCFpcd(const WW8PLCFpcd&) = delete; WW8PLCFpcd& operator=(const WW8PLCFpcd&) = delete; + void TruncToSortedRange(); + public: WW8PLCFpcd(SvStream* pSt, sal_uInt32 nFilePos, sal_uInt32 nPLCF, sal_uInt32 nStruct); diff --git a/sw/source/filter/xml/xmltexti.cxx b/sw/source/filter/xml/xmltexti.cxx index 02851e8e6a48..ad2e26e7039c 100644 --- a/sw/source/filter/xml/xmltexti.cxx +++ b/sw/source/filter/xml/xmltexti.cxx @@ -855,9 +855,14 @@ uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertFloatingFra uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY ); if ( xSet.is() ) { + OUString sHRef = URIHelper::SmartRel2Abs( + INetURLObject( GetXMLImport().GetBaseURL() ), rHRef ); + + if (INetURLObject(sHRef).GetProtocol() == INetProtocol::Macro) + GetXMLImport().NotifyMacroEventRead(); + xSet->setPropertyValue("FrameURL", - makeAny( URIHelper::SmartRel2Abs( - INetURLObject( GetXMLImport().GetBaseURL() ), rHRef ) ) ); + makeAny( sHRef ) ); xSet->setPropertyValue("FrameName", makeAny( rName ) ); diff --git a/sw/source/uibase/uiview/uivwimp.cxx b/sw/source/uibase/uiview/uivwimp.cxx index e7ce5be812ab..2f8b55b00043 100644 --- a/sw/source/uibase/uiview/uivwimp.cxx +++ b/sw/source/uibase/uiview/uivwimp.cxx @@ -289,6 +289,8 @@ SwClipboardChangeListener::~SwClipboardChangeListener() void SAL_CALL SwClipboardChangeListener::disposing( const EventObject& /*rEventObject*/ ) { + SolarMutexGuard aGuard; + pView = nullptr; // so we don't touch the view if changedContents somehow fires afterwards } void SAL_CALL SwClipboardChangeListener::changedContents( const css::datatransfer::clipboard::ClipboardEvent& rEventObject ) diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index c47d46422b53..2b8474f5c0cf 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -53,6 +53,7 @@ #include <vcl/weld.hxx> #include <bitmaps.hlst> #include <vcl/salvtables.hxx> +#include <comphelper/lok.hxx> SalFrame::SalFrame() : m_pWindow(nullptr) @@ -3484,7 +3485,7 @@ void SalInstanceWindow::help() { //show help for widget with keyboard focus vcl::Window* pWidget = ImplGetSVData()->mpWinData->mpFocusWin; - if (!pWidget) + if (!pWidget || comphelper::LibreOfficeKit::isActive()) pWidget = m_xWindow; OString sHelpId = pWidget->GetHelpId(); while (sHelpId.isEmpty()) diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx index 845c397b0eef..d9ce10ae4549 100644 --- a/vcl/source/control/button.cxx +++ b/vcl/source/control/button.cxx @@ -1846,7 +1846,7 @@ void HelpButton::Click() if ( !GetClickHdl() ) { vcl::Window* pFocusWin = Application::GetFocusWindow(); - if ( !pFocusWin ) + if ( !pFocusWin || comphelper::LibreOfficeKit::isActive() ) pFocusWin = this; HelpEvent aEvt( pFocusWin->GetPointerPosPixel(), HelpEventMode::CONTEXT ); diff --git a/vcl/source/font/fontcharmap.cxx b/vcl/source/font/fontcharmap.cxx index ade991626dd9..5ddd4a0fd5f1 100644 --- a/vcl/source/font/fontcharmap.cxx +++ b/vcl/source/font/fontcharmap.cxx @@ -206,7 +206,7 @@ bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult ) // update the glyphid-array with the glyphs in this range pStartGlyphs[i] = -static_cast<int>(aGlyphIdArray.size()); const unsigned char* pGlyphIdPtr = pOffsetBase + 2*i + nRangeOffset; - const size_t nRemainingSize = pEndValidArea - pGlyphIdPtr; + const size_t nRemainingSize = pEndValidArea >= pGlyphIdPtr ? pEndValidArea - pGlyphIdPtr : 0; const size_t nMaxPossibleRecords = nRemainingSize/2; if (nMaxPossibleRecords == 0) { // no sane font should trigger this SAL_WARN("vcl.gdi", "More indexes claimed that space available in font!"); @@ -294,7 +294,8 @@ bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult ) static const int NINSIZE = 64; static const int NOUTSIZE = 64; - sal_Char cCharsInp[ NINSIZE ]; + std::vector<char> cCharsInp; + cCharsInp.reserve(NINSIZE); sal_Unicode cCharsOut[ NOUTSIZE ]; sal_UCS4* pCP = pCodePairs; for( int i = 0; i < nRangeCount; ++i ) @@ -303,25 +304,26 @@ bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult ) sal_UCS4 cEnd = *(pCP++); while( cMin < cEnd ) { - int j = 0; - for(; (cMin < cEnd) && (j < NINSIZE); ++cMin ) + for (int j = 0; (cMin < cEnd) && (j < NINSIZE); ++cMin, ++j) { if( cMin >= 0x0100 ) - cCharsInp[ j++ ] = static_cast<sal_Char>(cMin >> 8); + cCharsInp.push_back(static_cast<char>(cMin >> 8)); if( (cMin >= 0x0100) || (cMin < 0x00A0) ) - cCharsInp[ j++ ] = static_cast<sal_Char>(cMin); + cCharsInp.push_back(static_cast<char>(cMin)); } sal_uInt32 nCvtInfo; sal_Size nSrcCvtBytes; int nOutLen = rtl_convertTextToUnicode( aConverter, aCvtContext, - cCharsInp, j, cCharsOut, NOUTSIZE, + cCharsInp.data(), cCharsInp.size(), cCharsOut, NOUTSIZE, RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE | RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE, &nCvtInfo, &nSrcCvtBytes ); - for( j = 0; j < nOutLen; ++j ) + cCharsInp.clear(); + + for (int j = 0; j < nOutLen; ++j) aSupportedCodePoints.insert( cCharsOut[j] ); } } diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx index 209179cc9591..db183d7ca1d9 100644 --- a/vcl/source/window/dialog.cxx +++ b/vcl/source/window/dialog.cxx @@ -1421,7 +1421,7 @@ IMPL_LINK(Dialog, ResponseHdl, Button*, pButton, void) if (nResponse == RET_HELP) { vcl::Window* pFocusWin = Application::GetFocusWindow(); - if (!pFocusWin) + if (!pFocusWin || comphelper::LibreOfficeKit::isActive()) pFocusWin = pButton; HelpEvent aEvt(pFocusWin->GetPointerPosPixel(), HelpEventMode::CONTEXT); pFocusWin->RequestHelp(aEvt); diff --git a/vcl/source/window/mouse.cxx b/vcl/source/window/mouse.cxx index 47116725856f..663da0ff872c 100644 --- a/vcl/source/window/mouse.cxx +++ b/vcl/source/window/mouse.cxx @@ -253,7 +253,7 @@ void Window::ImplGrabFocus( GetFocusFlags nFlags ) bool bAsyncFocusWaiting = false; vcl::Window *pFrame = pSVData->maFrameData.mpFirstFrame; - while( pFrame ) + while( pFrame && pFrame->mpWindowImpl && pFrame->mpWindowImpl->mpFrameData ) { if( pFrame != mpWindowImpl->mpFrameWindow.get() && pFrame->mpWindowImpl->mpFrameData->mnFocusId ) { @@ -276,6 +276,8 @@ void Window::ImplGrabFocus( GetFocusFlags nFlags ) bMustNotGrabFocus = true; break; } + if (!pParent->mpWindowImpl) + break; pParent = pParent->mpWindowImpl->mpParent; } @@ -333,13 +335,16 @@ void Window::ImplGrabFocus( GetFocusFlags nFlags ) else { vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow(); - vcl::Window* pNewRealWindow = pNewOverlapWindow->ImplGetWindow(); - pNewOverlapWindow->mpWindowImpl->mbActive = true; - pNewOverlapWindow->Activate(); - if ( pNewRealWindow != pNewOverlapWindow ) + if ( pNewOverlapWindow && pNewOverlapWindow->mpWindowImpl ) { - pNewRealWindow->mpWindowImpl->mbActive = true; - pNewRealWindow->Activate(); + vcl::Window* pNewRealWindow = pNewOverlapWindow->ImplGetWindow(); + pNewOverlapWindow->mpWindowImpl->mbActive = true; + pNewOverlapWindow->Activate(); + if ( pNewRealWindow != pNewOverlapWindow && pNewRealWindow && pNewRealWindow->mpWindowImpl ) + { + pNewRealWindow->mpWindowImpl->mbActive = true; + pNewRealWindow->Activate(); + } } } diff --git a/vcl/source/window/toolbox.cxx b/vcl/source/window/toolbox.cxx index ef8641986555..0d22f446dea7 100644 --- a/vcl/source/window/toolbox.cxx +++ b/vcl/source/window/toolbox.cxx @@ -3209,7 +3209,7 @@ void ToolBox::MouseMove( const MouseEvent& rMEvt ) // and do not highlight when focus is in a different toolbox bool bDrawHotSpot = true; vcl::Window *pWin = Application::GetFocusWindow(); - if( pWin && pWin->ImplGetWindowImpl()->mbToolBox && pWin != this ) + if( pWin && pWin->ImplGetWindowImpl() && pWin->ImplGetWindowImpl()->mbToolBox && pWin != this ) bDrawHotSpot = false; if ( mbSelection && bDrawHotSpot ) diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 10638fa43957..bf270d6f2ffb 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -3236,12 +3236,12 @@ void Window::ReleaseLOKNotifier() const vcl::ILibreOfficeKitNotifier* Window::GetLOKNotifier() const { - return mpWindowImpl->mpLOKNotifier; + return mpWindowImpl ? mpWindowImpl->mpLOKNotifier : nullptr; } vcl::LOKWindowId Window::GetLOKWindowId() const { - return mpWindowImpl->mnLOKWindowId; + return mpWindowImpl ? mpWindowImpl->mnLOKWindowId : 0; } VclPtr<vcl::Window> Window::GetParentWithLOKNotifier() diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx index 31620bc6a0ac..4dea82046299 100644 --- a/vcl/source/window/winproc.cxx +++ b/vcl/source/window/winproc.cxx @@ -814,17 +814,20 @@ static vcl::Window* ImplGetKeyInputWindow( vcl::Window* pWindow ) vcl::Window* pChild = pSVData->mpWinData->mpFirstFloat; while (pChild) { - if (pChild->ImplGetWindowImpl()->mbFloatWin) + if (pChild->ImplGetWindowImpl()) { - if (static_cast<FloatingWindow *>(pChild)->GrabsFocus()) - break; - } - else if (pChild->ImplGetWindowImpl()->mbDockWin) - { - vcl::Window* pParent = pChild->GetWindow(GetWindowType::RealParent); - if (pParent && pParent->ImplGetWindowImpl()->mbFloatWin && - static_cast<FloatingWindow *>(pParent)->GrabsFocus()) - break; + if (pChild->ImplGetWindowImpl()->mbFloatWin) + { + if (static_cast<FloatingWindow *>(pChild)->GrabsFocus()) + break; + } + else if (pChild->ImplGetWindowImpl()->mbDockWin) + { + vcl::Window* pParent = pChild->GetWindow(GetWindowType::RealParent); + if (pParent && pParent->ImplGetWindowImpl()->mbFloatWin && + static_cast<FloatingWindow *>(pParent)->GrabsFocus()) + break; + } } pChild = pChild->GetParent(); } @@ -832,7 +835,7 @@ static vcl::Window* ImplGetKeyInputWindow( vcl::Window* pWindow ) if (!pChild) pChild = pWindow; - pChild = pChild->ImplGetWindowImpl()->mpFrameData->mpFocusWin; + pChild = pChild->ImplGetWindowImpl() && pChild->ImplGetWindowImpl()->mpFrameData ? pChild->ImplGetWindowImpl()->mpFrameData->mpFocusWin.get() : nullptr; // no child - then no input if ( !pChild ) @@ -1740,6 +1743,9 @@ static void ImplActivateFloatingWindows( vcl::Window const * pWindow, bool bActi IMPL_LINK_NOARG(vcl::Window, ImplAsyncFocusHdl, void*, void) { + if (!ImplGetWindowImpl() || !ImplGetWindowImpl()->mpFrameData) + return; + ImplGetWindowImpl()->mpFrameData->mnFocusId = nullptr; // If the status has been preserved, because we got back the focus @@ -1798,22 +1804,27 @@ IMPL_LINK_NOARG(vcl::Window, ImplAsyncFocusHdl, void*, void) { // transfer the FocusWindow vcl::Window* pOverlapWindow = pFocusWin->ImplGetFirstOverlapWindow(); - pOverlapWindow->ImplGetWindowImpl()->mpLastFocusWindow = pFocusWin; + if ( pOverlapWindow && pOverlapWindow->ImplGetWindowImpl() ) + pOverlapWindow->ImplGetWindowImpl()->mpLastFocusWindow = pFocusWin; pSVData->mpWinData->mpFocusWin = nullptr; - if ( pFocusWin->ImplGetWindowImpl()->mpCursor ) + if ( pFocusWin->ImplGetWindowImpl() && pFocusWin->ImplGetWindowImpl()->mpCursor ) pFocusWin->ImplGetWindowImpl()->mpCursor->ImplHide(); // call the Deactivate vcl::Window* pOldOverlapWindow = pFocusWin->ImplGetFirstOverlapWindow(); vcl::Window* pOldRealWindow = pOldOverlapWindow->ImplGetWindow(); - pOldOverlapWindow->ImplGetWindowImpl()->mbActive = false; - pOldOverlapWindow->Deactivate(); - if ( pOldRealWindow != pOldOverlapWindow ) + if (pOldOverlapWindow && pOldOverlapWindow->ImplGetWindowImpl() && + pOldRealWindow && pOldRealWindow->ImplGetWindowImpl()) { - pOldRealWindow->ImplGetWindowImpl()->mbActive = false; - pOldRealWindow->Deactivate(); + pOldOverlapWindow->ImplGetWindowImpl()->mbActive = false; + pOldOverlapWindow->Deactivate(); + if ( pOldRealWindow != pOldOverlapWindow ) + { + pOldRealWindow->ImplGetWindowImpl()->mbActive = false; + pOldRealWindow->Deactivate(); + } } // TrackingMode is ended in ImplHandleLoseFocus diff --git a/wizards/source/access2base/DoCmd.xba b/wizards/source/access2base/DoCmd.xba index 588a170dc62f..e479c32a5cd0 100644 --- a/wizards/source/access2base/DoCmd.xba +++ b/wizards/source/access2base/DoCmd.xba @@ -2656,7 +2656,7 @@ Private Sub _ShellExecute(sCommand As String) Dim oShell As Object Set oShell = createUnoService("com.sun.star.system.SystemShellExecute") - oShell.execute(sCommand, "" , com.sun.star.system.SystemShellExecuteFlags.DEFAULTS) + oShell.execute(sCommand, "" , com.sun.star.system.SystemShellExecuteFlags.URIS_ONLY) End Sub ' _ShellExecute V0.8.5 diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx index 0c5437b93ad9..28d5bac8d780 100644 --- a/xmloff/source/core/xmlimp.cxx +++ b/xmloff/source/core/xmlimp.cxx @@ -650,6 +650,8 @@ void SAL_CALL SvXMLImport::endDocument() } std::unique_ptr<SvXMLNamespaceMap> SvXMLImport::processNSAttributes( + std::unique_ptr<SvXMLNamespaceMap> & rpNamespaceMap, + SvXMLImport *const pImport, // TODO??? const uno::Reference< xml::sax::XAttributeList >& xAttrList) { std::unique_ptr<SvXMLNamespaceMap> pRewindMap; @@ -657,12 +659,13 @@ std::unique_ptr<SvXMLNamespaceMap> SvXMLImport::processNSAttributes( for( sal_Int16 i=0; i < nAttrCount; i++ ) { const OUString& rAttrName = xAttrList->getNameByIndex( i ); - if ( rAttrName == "office:version" ) + if (pImport && rAttrName == "office:version") { - mpImpl->aODFVersion = xAttrList->getValueByIndex( i ); + pImport->mpImpl->aODFVersion = xAttrList->getValueByIndex( i ); // the ODF version in content.xml and manifest.xml must be the same starting from ODF1.2 - if ( mpImpl->mStreamName == "content.xml" && !IsODFVersionConsistent( mpImpl->aODFVersion ) ) + if (pImport->mpImpl->mStreamName == "content.xml" + && !pImport->IsODFVersionConsistent(pImport->mpImpl->aODFVersion)) { throw xml::sax::SAXException("Inconsistent ODF versions in content.xml and manifest.xml!", uno::Reference< uno::XInterface >(), @@ -676,8 +679,8 @@ std::unique_ptr<SvXMLNamespaceMap> SvXMLImport::processNSAttributes( { if( !pRewindMap ) { - pRewindMap = std::move(mpNamespaceMap); - mpNamespaceMap.reset(new SvXMLNamespaceMap(*pRewindMap)); + pRewindMap = std::move(rpNamespaceMap); + rpNamespaceMap.reset(new SvXMLNamespaceMap(*pRewindMap)); } const OUString& rAttrValue = xAttrList->getValueByIndex( i ); @@ -685,18 +688,18 @@ std::unique_ptr<SvXMLNamespaceMap> SvXMLImport::processNSAttributes( ? OUString() : rAttrName.copy( 6 ) ); // Add namespace, but only if it is known. - sal_uInt16 nKey = mpNamespaceMap->AddIfKnown( aPrefix, rAttrValue ); + sal_uInt16 nKey = rpNamespaceMap->AddIfKnown( aPrefix, rAttrValue ); // If namespace is unknown, try to match a name with similar // TC Id an version if( XML_NAMESPACE_UNKNOWN == nKey ) { OUString aTestName( rAttrValue ); if( SvXMLNamespaceMap::NormalizeURI( aTestName ) ) - nKey = mpNamespaceMap->AddIfKnown( aPrefix, aTestName ); + nKey = rpNamespaceMap->AddIfKnown( aPrefix, aTestName ); } // If that namespace is not known, too, add it as unknown if( XML_NAMESPACE_UNKNOWN == nKey ) - mpNamespaceMap->Add( aPrefix, rAttrValue ); + rpNamespaceMap->Add( aPrefix, rAttrValue ); } } @@ -709,7 +712,8 @@ void SAL_CALL SvXMLImport::startElement( const OUString& rName, // SAL_INFO("svg", "startElement " << rName); // Process namespace attributes. This must happen before creating the // context, because namespace declaration apply to the element name itself. - std::unique_ptr<SvXMLNamespaceMap> pRewindMap(processNSAttributes(xAttrList)); + std::unique_ptr<SvXMLNamespaceMap> pRewindMap( + processNSAttributes(mpNamespaceMap, this, xAttrList)); // Get element's namespace and local name. OUString aLocalName; @@ -882,7 +886,7 @@ void SAL_CALL SvXMLImport::startFastElement (sal_Int32 Element, maNamespaceHandler->addNSDeclAttributes( maNamespaceAttrList ); std::unique_ptr<SvXMLNamespaceMap> pRewindMap( - processNSAttributes( maNamespaceAttrList.get() )); + processNSAttributes(mpNamespaceMap, this, maNamespaceAttrList.get())); assert( dynamic_cast<SvXMLImportContext*>( xContext.get() ) != nullptr ); SvXMLImportContext *pContext = static_cast<SvXMLImportContext*>( xContext.get() ); if (pRewindMap) @@ -2237,7 +2241,7 @@ void SAL_CALL SvXMLLegacyToFastDocHandler::endDocument() void SAL_CALL SvXMLLegacyToFastDocHandler::startElement( const OUString& rName, const uno::Reference< xml::sax::XAttributeList >& xAttrList ) { - mrImport->processNSAttributes(xAttrList); + SvXMLImport::processNSAttributes(mrImport->mpNamespaceMap, mrImport.get(), xAttrList); OUString aLocalName; sal_uInt16 nPrefix = mrImport->mpNamespaceMap->GetKeyByAttrName( rName, &aLocalName ); Sequence< sal_Int8 > aLocalNameSeq( reinterpret_cast<sal_Int8 const *>( diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx index c4a59a344b95..00191b9a4792 100644 --- a/xmloff/source/core/xmltoken.cxx +++ b/xmloff/source/core/xmltoken.cxx @@ -135,6 +135,19 @@ namespace xmloff { namespace token { TOKEN( "grddl", XML_NP_GRDDL ), TOKEN( "http://www.w3.org/2003/g/data-view#", XML_N_GRDDL ), + // OOo extension digital signatures, used in ODF 1.1 + TOKEN( "dsigooo", XML_NP_DSIG_OOO ), + TOKEN( "http://openoffice.org/2004/documentsignatures", XML_N_DSIG_OOO ), + // ODF 1.2 digital signature namespaces + TOKEN( "dsig", XML_NP_DSIG ), + TOKEN( "urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0", XML_N_DSIG ), + TOKEN( "ds", XML_NP_DS ), + TOKEN( "http://www.w3.org/2000/09/xmldsig#", XML_N_DS ), + TOKEN( "xades132", XML_NP_XADES132 ), + TOKEN( "http://uri.etsi.org/01903/v1.3.2#", XML_N_XADES132 ), + TOKEN( "xades141", XML_NP_XADES141 ), + TOKEN( "http://uri.etsi.org/01903/v1.4.1#", XML_N_XADES141 ), + // ODF Enhanced namespaces TOKEN( "officeooo", XML_NP_OFFICE_EXT ), TOKEN( "http://openoffice.org/2009/office", XML_N_OFFICE_EXT ), diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index 8988e52dd9f1..81aa648837e9 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -85,6 +85,7 @@ #include <basegfx/polygon/b2dpolypolygon.hxx> #include <basegfx/polygon/b2dpolypolygontools.hxx> #include <basegfx/vector/b2dvector.hxx> +#include <tools/urlobj.hxx> #include <o3tl/safeint.hxx> #include <config_features.h> @@ -3251,6 +3252,9 @@ void SdXMLFloatingFrameShapeContext::StartElement( const css::uno::Reference< cs if( !maHref.isEmpty() ) { + if (INetURLObject(maHref).GetProtocol() == INetProtocol::Macro) + GetImport().NotifyMacroEventRead(); + xProps->setPropertyValue("FrameURL", Any(maHref) ); } } diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt index b8ae30c6da3e..1321868b7df4 100644 --- a/xmloff/source/token/tokens.txt +++ b/xmloff/source/token/tokens.txt @@ -70,6 +70,16 @@ xhtml N_XHTML_DUMMY grddl N_GRDDL_DUMMY +dsigooo +N_DSIG_OOO_DUMMY +dsig +N_DSIG_DUMMY +ds +N_DS_DUMMY +xades132 +N_XADES132_DUMMY +xades141 +N_XADES141_DUMMY officeooo N_OFFICE_EXT_DUMMY formx diff --git a/xmlsecurity/inc/biginteger.hxx b/xmlsecurity/inc/biginteger.hxx index d07ecf45d8af..8b4d8a9143b5 100644 --- a/xmlsecurity/inc/biginteger.hxx +++ b/xmlsecurity/inc/biginteger.hxx @@ -31,6 +31,9 @@ namespace xmlsecurity { XSECXMLSEC_DLLPUBLIC OUString bigIntegerToNumericString( const css::uno::Sequence< sal_Int8 >& serial ); XSECXMLSEC_DLLPUBLIC css::uno::Sequence< sal_Int8 > numericStringToBigInteger ( const OUString& serialNumber ); + +XSECXMLSEC_DLLPUBLIC bool EqualDistinguishedNames(OUString const& rName1, + OUString const& rName2); } #endif diff --git a/xmlsecurity/inc/xmlsec-wrapper.h b/xmlsecurity/inc/xmlsec-wrapper.h index c060c8bf23b8..2d06dcfdd549 100644 --- a/xmlsecurity/inc/xmlsec-wrapper.h +++ b/xmlsecurity/inc/xmlsec-wrapper.h @@ -43,6 +43,10 @@ #include <xmlsec/nss/app.h> #include <xmlsec/nss/crypto.h> #include <xmlsec/nss/pkikeys.h> +#include <xmlsec/nss/x509.h> +#endif +#ifdef XMLSEC_CRYPTO_MSCRYPTO +#include <xmlsec/mscng/x509.h> #endif #endif diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsignaturehelper.hxx index 02128bb4f6a8..9d6bf7b3c6de 100644 --- a/xmlsecurity/inc/xmlsignaturehelper.hxx +++ b/xmlsecurity/inc/xmlsignaturehelper.hxx @@ -37,6 +37,9 @@ #include <com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp> #include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp> +#include <com/sun/star/security/XCertificate.hpp> +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> + class DateTime; namespace com { @@ -95,6 +98,15 @@ public: // After signing/verifying, get information about signatures SignatureInformation GetSignatureInformation( sal_Int32 nSecurityId ) const; SignatureInformations GetSignatureInformations() const; + /// ImplVerifySignature calls this to figure out which X509Data is the + /// signing certificate and update the internal state with the result. + /// @return + /// A sequence with the signing certificate at the back on success. + /// An empty sequence on failure. + std::vector<css::uno::Reference<css::security::XCertificate>> + CheckAndUpdateSignatureInformation( + css::uno::Reference<css::xml::crypto::XSecurityEnvironment> const& xSecEnv, + SignatureInformation const& rInfo); // See XSecController for documentation void StartMission(const css::uno::Reference<css::xml::crypto::XXMLSecurityContext>& xSecurityContext); diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx index e84ea1dbe042..1b61be773f7d 100644 --- a/xmlsecurity/inc/xsecctl.hxx +++ b/xmlsecurity/inc/xsecctl.hxx @@ -259,6 +259,7 @@ private: /// Sets algorithm from <SignatureMethod Algorithm="...">. void setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID); void switchGpgSignature(); + bool haveReferenceForId(OUString const& rId) const; void addReference( const OUString& ouUri, sal_Int32 nDigestID, @@ -269,18 +270,21 @@ private: sal_Int32 nDigestID ); void setReferenceCount() const; - void setX509IssuerName( OUString const & ouX509IssuerName ); - void setX509SerialNumber( OUString const & ouX509SerialNumber ); - void setX509Certificate( OUString const & ouX509Certificate ); + void setX509Data( + std::vector<std::pair<OUString, OUString>> & rX509IssuerSerials, + std::vector<OUString> const& rX509Certificates); + void setX509CertDigest( + OUString const& rCertDigest, sal_Int32 const nReferenceDigestID, + OUString const& rX509IssuerName, OUString const& rX509SerialNumber); + void setSignatureValue( OUString const & ouSignatureValue ); void setDigestValue( sal_Int32 nDigestID, OUString const & ouDigestValue ); void setGpgKeyID( OUString const & ouKeyID ); void setGpgCertificate( OUString const & ouGpgCert ); void setGpgOwner( OUString const & ouGpgOwner ); - void setDate( OUString const & ouDate ); - void setDescription(const OUString& rDescription); - void setCertDigest(const OUString& rCertDigest); + void setDate(OUString const& rId, OUString const& ouDate); + void setDescription(OUString const& rId, OUString const& rDescription); void setValidSignatureImage(const OUString& rValidSigImg); void setInvalidSignatureImage(const OUString& rInvalidSigImg); void setSignatureLineId(const OUString& rSignatureLineId); @@ -290,7 +294,6 @@ public: private: void setId( OUString const & ouId ); - void setPropertyId( OUString const & ouPropertyId ); css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToRead( sal_Int32 nSecurityId ); @@ -310,6 +313,9 @@ public: SignatureInformation getSignatureInformation( sal_Int32 nSecurityId ) const; SignatureInformations getSignatureInformations() const; + /// only verify can figure out which X509Data is the signing certificate + void UpdateSignatureInformation(sal_Int32 nSecurityId, + std::vector<SignatureInformation::X509Data> const& rDatas); static void exportSignature( const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt b/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt Binary files differnew file mode 100644 index 000000000000..d63e4b6b7b72 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt Binary files differnew file mode 100644 index 000000000000..0190abb00f23 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt Binary files differnew file mode 100644 index 000000000000..f4b4198f94a6 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt Binary files differnew file mode 100644 index 000000000000..558bdee47e59 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt Binary files differnew file mode 100644 index 000000000000..4136b32e5610 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt diff --git a/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt b/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt Binary files differnew file mode 100644 index 000000000000..5e519dd8b7e7 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx index 5ed480ba819d..729baf586312 100644 --- a/xmlsecurity/qa/unit/signing/signing.cxx +++ b/xmlsecurity/qa/unit/signing/signing.cxx @@ -24,6 +24,7 @@ #include <com/sun/star/frame/Desktop.hpp> #include <com/sun/star/frame/XStorable.hpp> #include <com/sun/star/xml/crypto/SEInitializer.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> #include <com/sun/star/security/DocumentDigitalSignatures.hpp> #include <com/sun/star/security/XDocumentDigitalSignatures.hpp> @@ -80,6 +81,12 @@ public: void testODFBroken(); /// Document has a signature stream, but no actual signatures. void testODFNo(); + void testODFUnsignedTimestamp(); + void testODFX509CertificateChain(); + void testODFDoubleX509Data(); + void testODFTripleX509Data(); + void testODFMacroDoubleX509Data(); + void testODFDoubleX509Certificate(); /// Test a typical OOXML where a number of (but not all) streams are signed. void testOOXMLPartial(); /// Test a typical broken OOXML signature where one stream is corrupted. @@ -133,6 +140,12 @@ public: CPPUNIT_TEST(testODFBroken); CPPUNIT_TEST(testODFNo); CPPUNIT_TEST(testODFBroken); + CPPUNIT_TEST(testODFUnsignedTimestamp); + CPPUNIT_TEST(testODFX509CertificateChain); + CPPUNIT_TEST(testODFDoubleX509Data); + CPPUNIT_TEST(testODFTripleX509Data); + CPPUNIT_TEST(testODFMacroDoubleX509Data); + CPPUNIT_TEST(testODFDoubleX509Certificate); CPPUNIT_TEST(testOOXMLPartial); CPPUNIT_TEST(testOOXMLBroken); CPPUNIT_TEST(testOOXMLDescription); @@ -635,6 +648,128 @@ void SigningTest::testODFNo() static_cast<int>(pObjectShell->GetDocumentSignatureState())); } +// document has one signed timestamp and one unsigned timestamp +void SigningTest::testODFUnsignedTimestamp() +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "02_doc_signed_by_trusted_person_manipulated.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(/*o3tl::underlyingEnumValue(*/ (int)nActual /*)*/).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // was: 66666666 + CPPUNIT_ASSERT_EQUAL(sal_Int32(20210126), infos[0].SignatureDate); + // was: 0 + CPPUNIT_ASSERT_EQUAL(sal_Int32(18183742), infos[0].SignatureTime); +} + +void SigningTest::testODFX509CertificateChain() +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "signed_with_x509certificate_chain.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(/*o3tl::underlyingEnumValue(*/ (int)nActual /*)*/).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // check that the signing certificate was picked, not one of the 2 CA ones + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::VALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(infos[0].Signer.is()); + CPPUNIT_ASSERT_EQUAL( + OUString("CN=Xmlsecurity RSA Test example Alice,O=Xmlsecurity RSA Test,ST=England,C=UK"), + infos[0].Signer->getSubjectName()); +} + +void SigningTest::testODFDoubleX509Data() +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "02_doc_signed_by_attacker_manipulated.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(/*o3tl::underlyingEnumValue(*/ (int)nActual /*)*/).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +void SigningTest::testODFTripleX509Data() +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "02_doc_signed_by_attacker_manipulated_triple.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + // here, libxmlsec will pick the 1st X509Data but signing key is the 2nd + CPPUNIT_ASSERT_EQUAL_MESSAGE( + (OString::number(/*o3tl::underlyingEnumValue(*/ (int)nActual /*)*/).getStr()), + SignatureState::BROKEN, nActual); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +void SigningTest::testODFMacroDoubleX509Data() +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "02_doc_macros_signed_by_attacker_manipulated.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetScriptingSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(/*o3tl::underlyingEnumValue(*/ (int)nActual /*)*/).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(true)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +void SigningTest::testODFDoubleX509Certificate() +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "02_doc_signed_by_attacker_manipulated2.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(/*o3tl::underlyingEnumValue(*/ (int)nActual /*)*/).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + void SigningTest::testOOXMLPartial() { createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx"); diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx index c67d893b0624..fdd08892d24a 100644 --- a/xmlsecurity/source/component/documentdigitalsignatures.cxx +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -499,27 +499,36 @@ DocumentDigitalSignatures::ImplVerifySignatures( const SignatureInformation& rInfo = aSignInfos[n]; css::security::DocumentSignatureInformation& rSigInfo = arInfos[n]; - if (rInfo.ouGpgCertificate.isEmpty()) // X.509 + if (!rInfo.X509Datas.empty()) // X.509 { - if (!rInfo.ouX509Certificate.isEmpty()) - rSigInfo.Signer = xSecEnv->createCertificateFromAscii( rInfo.ouX509Certificate ) ; - if (!rSigInfo.Signer.is()) - rSigInfo.Signer = xSecEnv->getCertificate( rInfo.ouX509IssuerName, - xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) ); - + std::vector<uno::Reference<security::XCertificate>> certs( + rSignatureHelper.CheckAndUpdateSignatureInformation( + xSecEnv, rInfo)); + if (certs.empty()) + { + rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; + } + else + { + rSigInfo.Signer = certs.back(); + // get only intermediates + certs.pop_back(); // On Windows checking the certificate path is buggy. It does name matching (issuer, subject name) // to find the parent certificate. It does not take into account that there can be several certificates // with the same subject name. - - try { - rSigInfo.CertificateStatus = xSecEnv->verifyCertificate(rSigInfo.Signer, - Sequence<Reference<css::security::XCertificate> >()); - } catch (SecurityException& ) { - OSL_FAIL("Verification of certificate failed"); - rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; + try + { + rSigInfo.CertificateStatus = xSecEnv->verifyCertificate( + rSigInfo.Signer, comphelper::containerToSequence(certs)); + } + catch (SecurityException&) + { + SAL_WARN("xmlsecurity.comp", "Verification of certificate failed"); + rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; + } } } - else if (xGpgSecEnv.is()) // GPG + else if (!rInfo.ouGpgCertificate.isEmpty() && xGpgSecEnv.is()) // GPG { // TODO not ideal to retrieve cert by keyID, might // collide, or PGPKeyID format might change - can't we @@ -604,11 +613,15 @@ void DocumentDigitalSignatures::showCertificate( } sal_Bool DocumentDigitalSignatures::isAuthorTrusted( - const Reference< css::security::XCertificate >& Author ) + const Reference<css::security::XCertificate>& xAuthor) { + if (!xAuthor.is()) + { + return false; + } bool bFound = false; - OUString sSerialNum = xmlsecurity::bigIntegerToNumericString( Author->getSerialNumber() ); + OUString sSerialNum = xmlsecurity::bigIntegerToNumericString(xAuthor->getSerialNumber()); Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions().GetTrustedAuthors(); const SvtSecurityOptions::Certificate* pAuthors = aTrustedAuthors.getConstArray(); @@ -616,7 +629,8 @@ sal_Bool DocumentDigitalSignatures::isAuthorTrusted( for ( ; pAuthors != pAuthorsEnd; ++pAuthors ) { SvtSecurityOptions::Certificate aAuthor = *pAuthors; - if ( ( aAuthor[0] == Author->getIssuerName() ) && ( aAuthor[1] == sSerialNum ) ) + if (xmlsecurity::EqualDistinguishedNames(aAuthor[0], xAuthor->getIssuerName()) + && (aAuthor[1] == sSerialNum)) { bFound = true; break; diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx index 2280c77bbfb1..fbaf5a10ef14 100644 --- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -593,7 +593,7 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox() if (!rInfo.ouGpgCertificate.isEmpty()) aType = "OpenPGP"; // XML based: XAdES or not. - else if (!rInfo.ouCertDigest.isEmpty()) + else if (rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->CertDigest.isEmpty()) aType = "XAdES"; else aType = "XML-DSig"; @@ -691,8 +691,8 @@ uno::Reference<security::XCertificate> DigitalSignaturesDialog::getCertificate(c uno::Reference<security::XCertificate> xCert; //First we try to get the certificate which is embedded in the XML Signature - if (xSecEnv.is() && !rInfo.ouX509Certificate.isEmpty()) - xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate); + if (xSecEnv.is() && rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->X509Certificate.isEmpty()) + xCert = xSecEnv->createCertificateFromAscii(rInfo.GetSigningCertificate()->X509Certificate); else { //There must be an embedded certificate because we use it to get the //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName @@ -704,9 +704,12 @@ uno::Reference<security::XCertificate> DigitalSignaturesDialog::getCertificate(c } //In case there is no embedded certificate we try to get it from a local store - if (!xCert.is() && xSecEnv.is()) - xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) ); - if (!xCert.is() && xGpgSecEnv.is()) + if (!xCert.is() && xSecEnv.is() && rInfo.GetSigningCertificate()) + { + xCert = xSecEnv->getCertificate(rInfo.GetSigningCertificate()->X509IssuerName, + xmlsecurity::numericStringToBigInteger(rInfo.GetSigningCertificate()->X509SerialNumber)); + } + if (!xCert.is() && xGpgSecEnv.is() && !rInfo.ouGpgKeyID.isEmpty()) xCert = xGpgSecEnv->getCertificate( rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger("") ); SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" ); diff --git a/xmlsecurity/source/helper/documentsignaturehelper.cxx b/xmlsecurity/source/helper/documentsignaturehelper.cxx index 1dda0be4d7f5..47e788b759bb 100644 --- a/xmlsecurity/source/helper/documentsignaturehelper.cxx +++ b/xmlsecurity/source/helper/documentsignaturehelper.cxx @@ -512,6 +512,29 @@ void DocumentSignatureHelper::writeDigestMethod( xDocumentHandler->endElement("DigestMethod"); } +static void WriteXadesCert( + uno::Reference<xml::sax::XDocumentHandler> const& xDocumentHandler, + SignatureInformation::X509CertInfo const& rCertInfo) +{ + xDocumentHandler->startElement("xd:Cert", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + xDocumentHandler->startElement("xd:CertDigest", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + DocumentSignatureHelper::writeDigestMethod(xDocumentHandler); + xDocumentHandler->startElement("DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + assert(!rCertInfo.CertDigest.isEmpty()); + xDocumentHandler->characters(rCertInfo.CertDigest); + xDocumentHandler->endElement("DigestValue"); + xDocumentHandler->endElement("xd:CertDigest"); + xDocumentHandler->startElement("xd:IssuerSerial", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + xDocumentHandler->startElement("X509IssuerName", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + xDocumentHandler->characters(rCertInfo.X509IssuerName); + xDocumentHandler->endElement("X509IssuerName"); + xDocumentHandler->startElement("X509SerialNumber", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + xDocumentHandler->characters(rCertInfo.X509SerialNumber); + xDocumentHandler->endElement("X509SerialNumber"); + xDocumentHandler->endElement("xd:IssuerSerial"); + xDocumentHandler->endElement("xd:Cert"); +} + void DocumentSignatureHelper::writeSignedProperties( const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, const SignatureInformation& signatureInfo, @@ -528,26 +551,26 @@ void DocumentSignatureHelper::writeSignedProperties( xDocumentHandler->characters(sDate); xDocumentHandler->endElement("xd:SigningTime"); xDocumentHandler->startElement("xd:SigningCertificate", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->startElement("xd:Cert", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->startElement("xd:CertDigest", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - writeDigestMethod(xDocumentHandler); - - xDocumentHandler->startElement("DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - // TODO: this is empty for gpg signatures currently - //assert(!signatureInfo.ouCertDigest.isEmpty()); - xDocumentHandler->characters(signatureInfo.ouCertDigest); - xDocumentHandler->endElement("DigestValue"); - - xDocumentHandler->endElement("xd:CertDigest"); - xDocumentHandler->startElement("xd:IssuerSerial", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->startElement("X509IssuerName", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters(signatureInfo.ouX509IssuerName); - xDocumentHandler->endElement("X509IssuerName"); - xDocumentHandler->startElement("X509SerialNumber", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters(signatureInfo.ouX509SerialNumber); - xDocumentHandler->endElement("X509SerialNumber"); - xDocumentHandler->endElement("xd:IssuerSerial"); - xDocumentHandler->endElement("xd:Cert"); + assert(signatureInfo.GetSigningCertificate() || !signatureInfo.ouGpgKeyID.isEmpty()); + if (signatureInfo.GetSigningCertificate()) + { + // how should this deal with multiple X509Data elements? + // for now, let's write all of the certificates ... + for (auto const& rData : signatureInfo.X509Datas) + { + for (auto const& it : rData) + { + WriteXadesCert(xDocumentHandler, it); + } + } + } + else + { + // for PGP, write empty mandatory X509IssuerName, X509SerialNumber + SignatureInformation::X509CertInfo temp; + temp.CertDigest = signatureInfo.ouGpgKeyID; + WriteXadesCert(xDocumentHandler, temp); + } xDocumentHandler->endElement("xd:SigningCertificate"); xDocumentHandler->startElement("xd:SignaturePolicyIdentifier", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); xDocumentHandler->startElement("xd:SignaturePolicyImplied", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx index 5da6459779f7..ce3beef82a89 100644 --- a/xmlsecurity/source/helper/documentsignaturemanager.cxx +++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx @@ -591,6 +591,18 @@ void DocumentSignatureManager::read(bool bUseTempStream, bool bCacheLastSignatur bCacheLastSignature); maSignatureHelper.EndMission(); + // this parses the XML independently from ImplVerifySignatures() - check + // certificates here too ... + for (auto const& it : maSignatureHelper.GetSignatureInformations()) + { + if (!it.X509Datas.empty()) + { + uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv( + getSecurityEnvironment()); + maSignatureHelper.CheckAndUpdateSignatureInformation(xSecEnv, it); + } + } + maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations(); } else diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.cxx b/xmlsecurity/source/helper/ooxmlsecexporter.cxx index 42a4df0a7792..141ae49176ed 100644 --- a/xmlsecurity/source/helper/ooxmlsecexporter.cxx +++ b/xmlsecurity/source/helper/ooxmlsecexporter.cxx @@ -193,12 +193,23 @@ void OOXMLSecExporter::Impl::writeSignatureValue() void OOXMLSecExporter::Impl::writeKeyInfo() { - m_xDocumentHandler->startElement("KeyInfo", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - m_xDocumentHandler->startElement("X509Data", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - m_xDocumentHandler->startElement("X509Certificate", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - m_xDocumentHandler->characters(m_rInformation.ouX509Certificate); - m_xDocumentHandler->endElement("X509Certificate"); - m_xDocumentHandler->endElement("X509Data"); + m_xDocumentHandler->startElement( + "KeyInfo", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + assert(m_rInformation.GetSigningCertificate()); + for (auto const& rData : m_rInformation.X509Datas) + { + m_xDocumentHandler->startElement( + "X509Data", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + for (auto const& it : rData) + { + m_xDocumentHandler->startElement( + "X509Certificate", + uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(it.X509Certificate); + m_xDocumentHandler->endElement("X509Certificate"); + } + m_xDocumentHandler->endElement("X509Data"); + } m_xDocumentHandler->endElement("KeyInfo"); } diff --git a/xmlsecurity/source/helper/ooxmlsecparser.cxx b/xmlsecurity/source/helper/ooxmlsecparser.cxx index 457ef66bf24b..50fe150419a2 100644 --- a/xmlsecurity/source/helper/ooxmlsecparser.cxx +++ b/xmlsecurity/source/helper/ooxmlsecparser.cxx @@ -12,30 +12,1240 @@ #include <xmlsignaturehelper.hxx> #include <sal/log.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmlimp.hxx> + +#include <com/sun/star/xml/sax/SAXException.hpp> + +#include <sal/log.hxx> + using namespace com::sun::star; +class OOXMLSecParser::Context +{ + protected: + friend class OOXMLSecParser; + OOXMLSecParser & m_rParser; + private: + std::unique_ptr<SvXMLNamespaceMap> m_pOldNamespaceMap; + + public: + Context(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : m_rParser(rParser) + , m_pOldNamespaceMap(std::move(pOldNamespaceMap)) + { + } + + virtual ~Context() = default; + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) + { + } + + virtual void EndElement() + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/); + + virtual void Characters(OUString const& /*rChars*/) + { + } +}; + +// it's possible that an unsupported element has an Id attribute and a +// ds:Reference digesting it - probably this means XSecController needs to know +// about it. (For known elements, the Id attribute is only processed according +// to the schema.) +class OOXMLSecParser::UnknownContext + : public OOXMLSecParser::Context +{ + public: + UnknownContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } +}; + +auto OOXMLSecParser::Context::CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/) +-> std::unique_ptr<Context> +{ + // default: create new base context + return std::make_unique<UnknownContext>(m_rParser, std::move(pOldNamespaceMap)); +} + +/** +note: anything in ds:Object should be trusted *only* if there is a ds:Reference + to it so it is signed (exception: the xades:EncapsulatedX509Certificate). + ds:SignedInfo precedes all ds:Object. + + There may be multiple ds:Signature for purpose of counter-signatures + but the way XAdES describes these, only the ds:SignatureValue element + would be referenced, so requiring a ds:Reference for anything in + ds:Object shouldn't cause issues. + */ +class OOXMLSecParser::ReferencedContextImpl + : public OOXMLSecParser::Context +{ + protected: + bool m_isReferenced; + + public: + ReferencedContextImpl(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_isReferenced(isReferenced) + { + } + + OUString CheckIdAttrReferenced(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) + { + OUString const id(m_rParser.HandleIdAttr(xAttrs)); + if (!id.isEmpty() && m_rParser.m_pXSecController->haveReferenceForId(id)) + { + m_isReferenced = true; + } + return id; + } +}; + +class OOXMLSecParser::DsX509CertificateContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509CertificateContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsX509SerialNumberContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509SerialNumberContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsX509IssuerNameContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509IssuerNameContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsX509IssuerSerialContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rX509IssuerName; + OUString & m_rX509SerialNumber; + + public: + DsX509IssuerSerialContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rIssuerName, OUString & rSerialNumber) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rX509IssuerName(rIssuerName) + , m_rX509SerialNumber(rSerialNumber) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName") + { + return std::make_unique<DsX509IssuerNameContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber") + { + return std::make_unique<DsX509SerialNumberContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509SerialNumber); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +/// can't be sure what is supposed to happen here because the spec is clear as mud +class OOXMLSecParser::DsX509DataContext + : public OOXMLSecParser::Context +{ + private: + // sigh... "No ordering is implied by the above constraints." + // so store the ball of mud in vectors and try to figure it out later. + std::vector<std::pair<OUString, OUString>> m_X509IssuerSerials; + std::vector<OUString> m_X509Certificates; + + public: + DsX509DataContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial") + { + m_X509IssuerSerials.emplace_back(); + return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerSerials.back().first, m_X509IssuerSerials.back().second); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Certificate") + { + m_X509Certificates.emplace_back(); + return std::make_unique<DsX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_X509Certificates.back()); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsKeyInfoContext + : public OOXMLSecParser::Context +{ + public: + DsKeyInfoContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data") + { + return std::make_unique<DsX509DataContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:PGPData + // missing: ds:KeyName, ds:KeyValue, ds:RetrievalMethod, ds:SPKIData, ds:MgmtData + // (old code would read ds:Transform inside ds:RetrievalMethod but + // presumably that was a bug) + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + +}; + +class OOXMLSecParser::DsSignatureValueContext + : public OOXMLSecParser::Context +{ + private: + OUString m_Value; + + public: + DsSignatureValueContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setSignatureValue(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class OOXMLSecParser::DsDigestValueContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsDigestValueContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override + { + m_rValue.clear(); + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsDigestMethodContext + : public OOXMLSecParser::Context +{ + private: + sal_Int32 & m_rReferenceDigestID; + + public: + DsDigestMethodContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_Int32 & rReferenceDigestID) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + + SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" ); + if (!ouAlgorithm.isEmpty()) + { + SAL_WARN_IF( ouAlgorithm != ALGO_XMLDSIGSHA1 + && ouAlgorithm != ALGO_XMLDSIGSHA256 + && ouAlgorithm != ALGO_XMLDSIGSHA512, + "xmlsecurity.helper", "Algorithm neither SHA1, SHA256 nor SHA512"); + if (ouAlgorithm == ALGO_XMLDSIGSHA1) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA1; + else if (ouAlgorithm == ALGO_XMLDSIGSHA256) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA256; + else if (ouAlgorithm == ALGO_XMLDSIGSHA512) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA512; + else + m_rReferenceDigestID = 0; + } + } +}; + +class OOXMLSecParser::DsTransformContext + : public OOXMLSecParser::Context +{ + private: + bool & m_rIsC14N; + + public: + DsTransformContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool & rIsC14N) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString aAlgorithm = xAttrs->getValueByName("Algorithm"); + + if (aAlgorithm == ALGO_RELATIONSHIP) + { + m_rIsC14N = true; + } + } +}; + +class OOXMLSecParser::DsTransformsContext + : public OOXMLSecParser::Context +{ + private: + bool & m_rIsC14N; + + public: + DsTransformsContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool & rIsC14N) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transform") + { + return std::make_unique<DsTransformContext>(m_rParser, std::move(pOldNamespaceMap), m_rIsC14N); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsReferenceContext + : public OOXMLSecParser::Context +{ + private: + OUString m_URI; + OUString m_Type; + OUString m_DigestValue; + bool m_IsC14N = false; + // Relevant for ODF. The digest algorithm selected by the DigestMethod + // element's Algorithm attribute. @see css::xml::crypto::DigestID. + sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA256; + + public: + DsReferenceContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + + m_URI = xAttrs->getValueByName("URI"); + SAL_WARN_IF(m_URI.isEmpty(), "xmlsecurity.helper", "URI is empty"); + // Remember the type of this reference. + m_Type = xAttrs->getValueByName("Type"); + } + + virtual void EndElement() override + { + if (m_URI.startsWith("#")) + { + /* + * remove the first character '#' from the attribute value + */ + m_rParser.m_pXSecController->addReference(m_URI.copy(1), m_nReferenceDigestID, m_Type); + } + else + { + if (m_IsC14N) // this is determined by nested ds:Transform + { + m_rParser.m_pXSecController->addStreamReference(m_URI, false, m_nReferenceDigestID); + } + else + /* + * it must be an octet stream + */ + { + m_rParser.m_pXSecController->addStreamReference(m_URI, true, m_nReferenceDigestID); + } + } + + m_rParser.m_pXSecController->setDigestValue(m_nReferenceDigestID, m_DigestValue); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms") + { + return std::make_unique<DsTransformsContext>(m_rParser, std::move(pOldNamespaceMap), m_IsC14N); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_DigestValue); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsSignatureMethodContext + : public OOXMLSecParser::Context +{ + public: + DsSignatureMethodContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 + || ouAlgorithm == ALGO_ECDSASHA512) + { + m_rParser.m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); + } + } +}; + +class OOXMLSecParser::DsSignedInfoContext + : public OOXMLSecParser::Context +{ + public: + DsSignedInfoContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setReferenceCount(); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod") + { + return std::make_unique<DsSignatureMethodContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:CanonicalizationMethod + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesCertDigestContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rDigestValue; + sal_Int32 & m_rReferenceDigestID; + + public: + XadesCertDigestContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rDigestValue, sal_Int32 & rReferenceDigestID) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rDigestValue(rDigestValue) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rDigestValue); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesCertContext + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; + OUString m_CertDigest; + OUString m_X509IssuerName; + OUString m_X509SerialNumber; + + public: + XadesCertContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setX509CertDigest(m_CertDigest, m_nReferenceDigestID, m_X509IssuerName, m_X509SerialNumber); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned xades:Cert"); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest") + { + return std::make_unique<XadesCertDigestContext>(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial") + { + return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerName, m_X509SerialNumber); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesSigningCertificateContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesSigningCertificateContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert") + { + return std::make_unique<XadesCertContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesSigningTimeContext + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + OUString m_Value; + + public: + XadesSigningTimeContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setDate("", m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SigningTime"); + } + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class OOXMLSecParser::XadesSignedSignaturePropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesSignedSignaturePropertiesContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime") + { + return std::make_unique<XadesSigningTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate") + { + return std::make_unique<XadesSigningCertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignaturePolicyIdentifier, xades:SignatureProductionPlace, xades:SignerRole + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesSignedPropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesSignedPropertiesContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties") + { + return std::make_unique<XadesSignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignedDataObjectProperties + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesQualifyingPropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesQualifyingPropertiesContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties") + { + return std::make_unique<XadesSignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:UnsignedSignatureProperties + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::MsodigsigSetupIDContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MsodigsigSetupIDContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::MsodigsigSignatureCommentsContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MsodigsigSignatureCommentsContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::MsodigsigSignatureInfoV1Context + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + OUString m_SetupID; + OUString m_SignatureComments; + + public: + MsodigsigSignatureInfoV1Context(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SetupID") + { + return std::make_unique<MsodigsigSetupIDContext>(m_rParser, std::move(pOldNamespaceMap), m_SetupID); + } + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureComments") + { + return std::make_unique<MsodigsigSignatureCommentsContext>(m_rParser, std::move(pOldNamespaceMap), m_SignatureComments); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + if (!m_SetupID.isEmpty()) + { + m_rParser.m_pXSecController->setSignatureLineId(m_SetupID); + } + if (!m_SignatureComments.isEmpty()) + { + m_rParser.m_pXSecController->setDescription("", m_SignatureComments); + + } + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureInfoV1"); + } + } +}; + +class OOXMLSecParser::MdssiValueContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MdssiValueContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::MdssiSignatureTimeContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MdssiSignatureTimeContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MDSSI && rName == "Value") + { + return std::make_unique<MdssiValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rValue); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + + +class OOXMLSecParser::DsSignaturePropertyContext + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + enum class SignatureProperty { Unknown, Date, Info }; + SignatureProperty m_Property = SignatureProperty::Unknown; + OUString m_Id; + OUString m_Value; + + public: + DsSignaturePropertyContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_Id = CheckIdAttrReferenced(xAttrs); + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + switch (m_Property) + { + case SignatureProperty::Unknown: + SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored"); + break; + case SignatureProperty::Info: + break; // handled by child context + case SignatureProperty::Date: + m_rParser.m_pXSecController->setDate(m_Id, m_Value); + break; + } + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureProperty"); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MDSSI && rName == "SignatureTime") + { + m_Property = SignatureProperty::Date; + return std::make_unique<MdssiSignatureTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureInfoV1") + { + return std::make_unique<MsodigsigSignatureInfoV1Context>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsSignaturePropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + DsSignaturePropertiesContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty") + { + return std::make_unique<DsSignaturePropertyContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsManifestContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + DsManifestContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + +#if 0 + ??? + virtual void EndElement() override + { + m_rParser.m_pXSecController->setReferenceCount(); + } +#endif + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:CanonicalizationMethod + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsObjectContext + : public OOXMLSecParser::ReferencedContextImpl +{ + enum class Mode { Default, ValidSignatureLineImage, InvalidSignatureLineImage }; + Mode m_Mode = Mode::Default; + OUString m_Value; + + public: + DsObjectContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + // init with "false" here - the Signature element can't be referenced by its child + : OOXMLSecParser::ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), false) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString const id(CheckIdAttrReferenced(xAttrs)); + if (id == "idValidSigLnImg") + { + m_Mode = Mode::ValidSignatureLineImage; + } + else if (id == "idInvalidSigLnImg") + { + m_Mode = Mode::InvalidSignatureLineImage; + } + } + + virtual void EndElement() override + { + switch (m_Mode) + { + case Mode::ValidSignatureLineImage: + if (m_isReferenced) + { + m_rParser.m_pXSecController->setValidSignatureImage(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineValidImage"); + } + break; + case Mode::InvalidSignatureLineImage: + if (m_isReferenced) + { + m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineInvalidImage"); + } + break; + case Mode::Default: + break; + } + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties") + { + return std::make_unique<DsSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties") + { + return std::make_unique<XadesQualifyingPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Manifest") + { + return std::make_unique<DsManifestContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsSignatureContext + : public OOXMLSecParser::Context +{ + public: + DsSignatureContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString const ouIdAttr(m_rParser.HandleIdAttr(xAttrs)); + m_rParser.m_rXMLSignatureHelper.StartVerifySignatureElement(); + m_rParser.m_pXSecController->addSignature(); + if (!ouIdAttr.isEmpty()) + { + m_rParser.m_pXSecController->setId( ouIdAttr ); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo") + { + return std::make_unique<DsSignedInfoContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue") + { + return std::make_unique<DsSignatureValueContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo") + { + return std::make_unique<DsKeyInfoContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Object") + { + return std::make_unique<DsObjectContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + + OOXMLSecParser::OOXMLSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController) - : m_pXSecController(pXSecController) - ,m_bInDigestValue(false) - ,m_bInSignatureValue(false) - ,m_bInX509Certificate(false) - ,m_bInMdssiValue(false) - ,m_bInSignatureComments(false) - ,m_bInX509IssuerName(false) - ,m_bInX509SerialNumber(false) - ,m_bInCertDigest(false) - ,m_bInValidSignatureImage(false) - ,m_bInInvalidSignatureImage(false) - ,m_bInSignatureLineId(false) - ,m_bReferenceUnresolved(false) + : m_pNamespaceMap(new SvXMLNamespaceMap) + , m_pXSecController(pXSecController) ,m_rXMLSignatureHelper(rXMLSignatureHelper) { + using namespace xmloff::token; + m_pNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML ); + m_pNamespaceMap->Add( "_ds", GetXMLToken(XML_N_DS), XML_NAMESPACE_DS ); + m_pNamespaceMap->Add( "_xades132", GetXMLToken(XML_N_XADES132), XML_NAMESPACE_XADES132); + m_pNamespaceMap->Add( "_xades141", GetXMLToken(XML_N_XADES141), XML_NAMESPACE_XADES141); + m_pNamespaceMap->Add( "_dc", GetXMLToken(XML_N_DC), XML_NAMESPACE_DC ); + m_pNamespaceMap->Add( "_mdssi", NS_MDSSI, XML_NAMESPACE_MDSSI ); + m_pNamespaceMap->Add( "_msodigsig", "http://schemas.microsoft.com/office/2006/digsig", XML_NAMESPACE_MSODIGSIG ); + m_pNamespaceMap->Add( "_office_libo", + GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT); } OOXMLSecParser::~OOXMLSecParser() { } +OUString OOXMLSecParser::HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) +{ + OUString const aId = xAttrs->getValueByName("Id"); + if (!aId.isEmpty()) + { + m_pXSecController->collectToVerify(aId); + } + return aId; +} + void SAL_CALL OOXMLSecParser::startDocument() { if (m_xNextHandler.is()) @@ -50,217 +1260,69 @@ void SAL_CALL OOXMLSecParser::endDocument() void SAL_CALL OOXMLSecParser::startElement(const OUString& rName, const uno::Reference<xml::sax::XAttributeList>& xAttribs) { - OUString aId = xAttribs->getValueByName("Id"); - if (!aId.isEmpty()) - m_pXSecController->collectToVerify(aId); + assert(m_pNamespaceMap); + std::unique_ptr<SvXMLNamespaceMap> pRewindMap( + SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs)); - if (rName == "Signature") - { - m_rXMLSignatureHelper.StartVerifySignatureElement(); - m_pXSecController->addSignature(); - if (!aId.isEmpty()) - m_pXSecController->setId(aId); - } - else if (rName == "SignatureMethod") - { - OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); - if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 - || ouAlgorithm == ALGO_ECDSASHA512) - m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); - } - else if (rName == "Reference") - { - OUString aURI = xAttribs->getValueByName("URI"); - if (aURI.startsWith("#")) - m_pXSecController->addReference(aURI.copy(1), xml::crypto::DigestID::SHA1, OUString()); - else - { - m_aReferenceURI = aURI; - m_bReferenceUnresolved = true; - } - } - else if (rName == "Transform") - { - if (m_bReferenceUnresolved) - { - OUString aAlgorithm = xAttribs->getValueByName("Algorithm"); - if (aAlgorithm == ALGO_RELATIONSHIP) - { - m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/false, /*nDigestID=*/xml::crypto::DigestID::SHA256); - m_bReferenceUnresolved = false; - } - } - } - else if (rName == "DigestValue" && !m_bInCertDigest) - { - m_aDigestValue.clear(); - m_bInDigestValue = true; - } - else if (rName == "SignatureValue") - { - m_aSignatureValue.clear(); - m_bInSignatureValue = true; - } - else if (rName == "X509Certificate") - { - m_aX509Certificate.clear(); - m_bInX509Certificate = true; - } - else if (rName == "mdssi:Value") - { - m_aMdssiValue.clear(); - m_bInMdssiValue = true; - } - else if (rName == "SignatureComments") - { - m_aSignatureComments.clear(); - m_bInSignatureComments = true; - } - else if (rName == "X509IssuerName") - { - m_aX509IssuerName.clear(); - m_bInX509IssuerName = true; - } - else if (rName == "X509SerialNumber") - { - m_aX509SerialNumber.clear(); - m_bInX509SerialNumber = true; - } - else if (rName == "xd:CertDigest") - { - m_aCertDigest.clear(); - m_bInCertDigest = true; - } - else if (rName == "Object") + OUString localName; + sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName)); + + std::unique_ptr<Context> pContext; + + if (m_ContextStack.empty()) { - OUString sId = xAttribs->getValueByName("Id"); - if (sId == "idValidSigLnImg") - { - m_aValidSignatureImage.clear(); - m_bInValidSignatureImage = true; - } - else if (sId == "idInvalidSigLnImg") + if (nPrefix == XML_NAMESPACE_DS + && localName == "Signature") { - m_aInvalidSignatureImage.clear(); - m_bInInvalidSignatureImage = true; + pContext.reset(new DsSignatureContext(*this, std::move(pRewindMap))); } else { - SAL_INFO("xmlsecurity.ooxml", "Unknown 'Object' child element: " << rName); + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected root element", nullptr, + css::uno::Any()); } } - else if (rName == "SetupID") - { - m_aSignatureLineId.clear(); - m_bInSignatureLineId = true; - } else { - SAL_INFO("xmlsecurity.ooxml", "Unknown xml element: " << rName); + pContext = m_ContextStack.top()->CreateChildContext( + std::move(pRewindMap), nPrefix, localName); } + m_ContextStack.push(std::move(pContext)); + assert(!pRewindMap); + + m_ContextStack.top()->StartElement(xAttribs); + if (m_xNextHandler.is()) + { m_xNextHandler->startElement(rName, xAttribs); + } + } void SAL_CALL OOXMLSecParser::endElement(const OUString& rName) { - if (rName == "SignedInfo") - m_pXSecController->setReferenceCount(); - else if (rName == "Reference") - { - if (m_bReferenceUnresolved) - { - // No transform algorithm found, assume binary. - m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/true, /*nDigestID=*/xml::crypto::DigestID::SHA256); - m_bReferenceUnresolved = false; - } - m_pXSecController->setDigestValue(xml::crypto::DigestID::SHA256, m_aDigestValue); - } - else if (rName == "DigestValue" && !m_bInCertDigest) - m_bInDigestValue = false; - else if (rName == "SignatureValue") - { - m_pXSecController->setSignatureValue(m_aSignatureValue); - m_bInSignatureValue = false; - } - else if (rName == "X509Certificate") - { - m_pXSecController->setX509Certificate(m_aX509Certificate); - m_bInX509Certificate = false; - } - else if (rName == "mdssi:Value") - { - m_pXSecController->setDate(m_aMdssiValue); - m_bInMdssiValue = false; - } - else if (rName == "SignatureComments") - { - m_pXSecController->setDescription(m_aSignatureComments); - m_bInSignatureComments = false; - } - else if (rName == "X509IssuerName") - { - m_pXSecController->setX509IssuerName(m_aX509IssuerName); - m_bInX509IssuerName = false; - } - else if (rName == "X509SerialNumber") - { - m_pXSecController->setX509SerialNumber(m_aX509SerialNumber); - m_bInX509SerialNumber = false; - } - else if (rName == "xd:CertDigest") - { - m_pXSecController->setCertDigest(m_aCertDigest); - m_bInCertDigest = false; - } - else if (rName == "Object") + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + + m_ContextStack.top()->EndElement(); + + if (m_xNextHandler.is()) { - if (m_bInValidSignatureImage) - { - m_pXSecController->setValidSignatureImage(m_aValidSignatureImage); - m_bInValidSignatureImage = false; - } - else if (m_bInInvalidSignatureImage) - { - m_pXSecController->setInvalidSignatureImage(m_aInvalidSignatureImage); - m_bInInvalidSignatureImage = false; - } + m_xNextHandler->endElement(rName); } - else if (rName == "SetupID") + + if (m_ContextStack.top()->m_pOldNamespaceMap) { - m_pXSecController->setSignatureLineId(m_aSignatureLineId); - m_bInSignatureLineId = false; + m_pNamespaceMap = std::move(m_ContextStack.top()->m_pOldNamespaceMap); } - - if (m_xNextHandler.is()) - m_xNextHandler->endElement(rName); + m_ContextStack.pop(); } void SAL_CALL OOXMLSecParser::characters(const OUString& rChars) { - if (m_bInDigestValue && !m_bInCertDigest) - m_aDigestValue += rChars; - else if (m_bInSignatureValue) - m_aSignatureValue += rChars; - else if (m_bInX509Certificate) - m_aX509Certificate += rChars; - else if (m_bInMdssiValue) - m_aMdssiValue += rChars; - else if (m_bInSignatureComments) - m_aSignatureComments += rChars; - else if (m_bInX509IssuerName) - m_aX509IssuerName += rChars; - else if (m_bInX509SerialNumber) - m_aX509SerialNumber += rChars; - else if (m_bInCertDigest) - m_aCertDigest += rChars; - else if (m_bInValidSignatureImage) - m_aValidSignatureImage += rChars; - else if (m_bInInvalidSignatureImage) - m_aInvalidSignatureImage += rChars; - else if (m_bInSignatureLineId) - m_aSignatureLineId += rChars; + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + m_ContextStack.top()->Characters(rChars); if (m_xNextHandler.is()) m_xNextHandler->characters(rChars); diff --git a/xmlsecurity/source/helper/ooxmlsecparser.hxx b/xmlsecurity/source/helper/ooxmlsecparser.hxx index b425e4c32a0f..88e87fd1c39c 100644 --- a/xmlsecurity/source/helper/ooxmlsecparser.hxx +++ b/xmlsecurity/source/helper/ooxmlsecparser.hxx @@ -19,6 +19,11 @@ #include <xsecctl.hxx> +#include <xmloff/nmspmap.hxx> + +#include <stack> + + /// Parses an OOXML digital signature. class OOXMLSecParser: public cppu::WeakImplHelper < @@ -26,38 +31,62 @@ class OOXMLSecParser: public cppu::WeakImplHelper css::lang::XInitialization > { +public: + class Context; +private: + class UnknownContext; + class ReferencedContextImpl; + class DsX509CertificateContext; + class DsX509SerialNumberContext; + class DsX509IssuerNameContext; + class DsX509IssuerSerialContext; + class DsX509DataContext; + class DsKeyInfoContext; + class DsSignatureValueContext; + class DsDigestValueContext; + class DsDigestMethodContext; + class DsTransformContext; + class DsTransformsContext; + class DsReferenceContext; + class DsSignatureMethodContext; + class DsSignedInfoContext; + class XadesEncapsulatedX509CertificateContext; + class XadesCertificateValuesContext; + class XadesUnsignedSignaturePropertiesContext; + class XadesUnsignedPropertiesContext; + class XadesCertDigestContext; + class XadesCertContext; + class XadesSigningCertificateContext; + class XadesSigningTimeContext; + class XadesSignedSignaturePropertiesContext; + class XadesSignedPropertiesContext; + class XadesQualifyingPropertiesContext; + class MdssiValueContext; + class MdssiSignatureTimeContext; + class MsodigsigSetupIDContext; + class MsodigsigSignatureCommentsContext; + class MsodigsigSignatureInfoV1Context; + class DsSignaturePropertyContext; + class DsSignaturePropertiesContext; + class DsManifestContext; + class DsObjectContext; + class DsSignatureContext; + class DsigSignaturesContext; + + std::stack<std::unique_ptr<Context>> m_ContextStack; + std::unique_ptr<SvXMLNamespaceMap> m_pNamespaceMap; + XSecController* m_pXSecController; css::uno::Reference<css::xml::sax::XDocumentHandler> m_xNextHandler; - bool m_bInDigestValue; - OUString m_aDigestValue; - bool m_bInSignatureValue; - OUString m_aSignatureValue; - bool m_bInX509Certificate; - OUString m_aX509Certificate; - bool m_bInMdssiValue; - OUString m_aMdssiValue; - bool m_bInSignatureComments; - OUString m_aSignatureComments; - bool m_bInX509IssuerName; - OUString m_aX509IssuerName; - bool m_bInX509SerialNumber; - OUString m_aX509SerialNumber; - bool m_bInCertDigest; - OUString m_aCertDigest; - bool m_bInValidSignatureImage; - OUString m_aValidSignatureImage; - bool m_bInInvalidSignatureImage; - OUString m_aInvalidSignatureImage; - bool m_bInSignatureLineId; - OUString m_aSignatureLineId; - /// Last seen <Reference URI="...">. OUString m_aReferenceURI; /// Already called addStreamReference() for this reference. bool m_bReferenceUnresolved; XMLSignatureHelper& m_rXMLSignatureHelper; + OUString HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs); + public: explicit OOXMLSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController); virtual ~OOXMLSecParser() override; diff --git a/xmlsecurity/source/helper/pdfsignaturehelper.cxx b/xmlsecurity/source/helper/pdfsignaturehelper.cxx index 2aea01128869..d00021c9b633 100644 --- a/xmlsecurity/source/helper/pdfsignaturehelper.cxx +++ b/xmlsecurity/source/helper/pdfsignaturehelper.cxx @@ -86,8 +86,12 @@ PDFSignatureHelper::GetDocumentSignatureInformations( security::DocumentSignatureInformation& rExternal = aRet[i]; rExternal.SignatureIsValid = rInternal.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; - if (!rInternal.ouX509Certificate.isEmpty()) - rExternal.Signer = xSecEnv->createCertificateFromAscii(rInternal.ouX509Certificate); + if (rInternal.GetSigningCertificate() + && !rInternal.GetSigningCertificate()->X509Certificate.isEmpty()) + { + rExternal.Signer = xSecEnv->createCertificateFromAscii( + rInternal.GetSigningCertificate()->X509Certificate); + } rExternal.PartialDocumentSignature = rInternal.bPartialDocumentSignature; // Verify certificate. diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx index db80016f84e0..495a230d9277 100644 --- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -21,6 +21,7 @@ #include <xmlsignaturehelper.hxx> #include <documentsignaturehelper.hxx> #include <xsecctl.hxx> +#include <biginteger.hxx> #include <xmlsignaturehelper2.hxx> @@ -49,6 +50,8 @@ #include <tools/diagnose_ex.h> #include <sal/log.hxx> +#include <boost/optional.hpp> + #define NS_DOCUMENTSIGNATURES "http://openoffice.org/2004/documentsignatures" #define NS_DOCUMENTSIGNATURES_ODF_1_2 "urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0" #define OOXML_SIGNATURE_ORIGIN "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin" @@ -409,6 +412,7 @@ bool XMLSignatureHelper::ReadAndVerifySignatureStorageStream(const css::uno::Ref catch(const uno::Exception&) { DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper"); + mbError = true; } mpXSecController->releaseSignatureReader(); @@ -555,4 +559,162 @@ void XMLSignatureHelper::CreateAndWriteOOXMLSignature(const uno::Reference<embed xSaxWriter->endDocument(); } +/** check this constraint from xmldsig-core 4.5.4: + + All certificates appearing in an X509Data element MUST relate to the + validation key by either containing it or being part of a certification + chain that terminates in a certificate containing the validation key. + */ +static auto CheckX509Data( + uno::Reference<xml::crypto::XSecurityEnvironment> const& xSecEnv, + std::vector<SignatureInformation::X509CertInfo> const& rX509CertInfos, + std::vector<uno::Reference<security::XCertificate>> & rCerts, + std::vector<SignatureInformation::X509CertInfo> & rSorted) -> bool +{ + assert(rCerts.empty()); + assert(rSorted.empty()); + if (rX509CertInfos.empty()) + { + SAL_WARN("xmlsecurity.comp", "no X509Data"); + return false; + } + std::vector<uno::Reference<security::XCertificate>> certs; + for (SignatureInformation::X509CertInfo const& it : rX509CertInfos) + { + if (!it.X509Certificate.isEmpty()) + { + certs.emplace_back(xSecEnv->createCertificateFromAscii(it.X509Certificate)); + } + else + { + certs.emplace_back(xSecEnv->getCertificate( + it.X509IssuerName, + xmlsecurity::numericStringToBigInteger(it.X509SerialNumber))); + } + if (!certs.back().is()) + { + SAL_WARN("xmlsecurity.comp", "X509Data cannot be parsed"); + return false; + } + } + + // first, search one whose issuer isn't in the list, or a self-signed one + boost::optional<size_t> start; + for (size_t i = 0; i < certs.size(); ++i) + { + for (size_t j = 0; ; ++j) + { + if (j == certs.size()) + { + if (start) + { + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate has no issuer but already have start of chain: " << certs[i]->getSubjectName()); + return false; + } + start = i; // issuer isn't in the list + break; + } + if (xmlsecurity::EqualDistinguishedNames(certs[i]->getIssuerName(), certs[j]->getSubjectName())) + { + if (i == j) // self signed + { + if (start) + { + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate is self-signed but already have start of chain: " << certs[i]->getSubjectName()); + return false; + } + start = i; + } + break; + } + } + } + std::vector<size_t> chain; + if (!start) + { + // this can only be a cycle? + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: cycle detected"); + return false; + } + chain.emplace_back(*start); + + // second, check that there is a chain, no tree or cycle... + for (size_t i = 0; i < certs.size(); ++i) + { + assert(chain.size() == i + 1); + for (size_t j = 0; j < certs.size(); ++j) + { + if (chain[i] != j) + { + if (xmlsecurity::EqualDistinguishedNames( + certs[chain[i]]->getSubjectName(), certs[j]->getIssuerName())) + { + if (chain.size() != i + 1) // already found issuee? + { + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate issued 2 others: " << certs[chain[i]]->getSubjectName()); + return false; + } + chain.emplace_back(j); + } + } + } + if (i == certs.size() - 1) + { // last one: must be a leaf + if (chain.size() != i + 1) + { + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate in cycle: " << certs[chain[i]]->getSubjectName()); + return false; + } + } + else if (chain.size() != i + 2) + { // not issuer of another? + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate issued 0 others: " << certs[chain[i]]->getSubjectName()); + return false; + } + } + + // success + assert(chain.size() == rX509CertInfos.size()); + for (auto const& it : chain) + { + rSorted.emplace_back(rX509CertInfos[it]); + rCerts.emplace_back(certs[it]); + } + return true; +} + +std::vector<uno::Reference<security::XCertificate>> +XMLSignatureHelper::CheckAndUpdateSignatureInformation( + uno::Reference<xml::crypto::XSecurityEnvironment> const& xSecEnv, + SignatureInformation const& rInfo) +{ + // if the check fails, it's not possible to determine which X509Data + // contained the signing certificate - the UI cannot display something + // useful in this case, so prevent anything misleading by clearing the + // X509Datas. + + std::vector<uno::Reference<security::XCertificate>> certs; + std::vector<SignatureInformation::X509Data> datas; + // TODO: for now, just merge all X509Datas together for checking... + // (this will probably break round-trip of signature with multiple X509Data, + // no idea if that is a problem) + SignatureInformation::X509Data temp; + SignatureInformation::X509Data tempResult; + for (auto const& rData : rInfo.X509Datas) + { + for (auto const& it : rData) + { + temp.emplace_back(it); + } + } + if (CheckX509Data(xSecEnv, temp, certs, tempResult)) + { + datas.emplace_back(tempResult); + } + + // rInfo is a copy, update the original + mpXSecController->UpdateSignatureInformation(rInfo.nSecurityId, datas); + return certs; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx index 5fdc45c2c8c0..e87c8cafee56 100644 --- a/xmlsecurity/source/helper/xsecctl.cxx +++ b/xmlsecurity/source/helper/xsecctl.cxx @@ -46,10 +46,6 @@ #include "ooxmlsecexporter.hxx" #include <xmlsignaturehelper2.hxx> -namespace cssu = com::sun::star::uno; -namespace cssl = com::sun::star::lang; -namespace cssxc = com::sun::star::xml::crypto; -namespace cssxs = com::sun::star::xml::sax; using namespace com::sun::star; namespace @@ -58,11 +54,11 @@ OUString getDigestURI(sal_Int32 nID) { switch( nID ) { - case cssxc::DigestID::SHA1: + case css::xml::crypto::DigestID::SHA1: return OUString(ALGO_XMLDSIGSHA1); - case cssxc::DigestID::SHA256: + case css::xml::crypto::DigestID::SHA256: return OUString(ALGO_XMLDSIGSHA256); - case cssxc::DigestID::SHA512: + case css::xml::crypto::DigestID::SHA512: return OUString(ALGO_XMLDSIGSHA512); default: return OUString(ALGO_XMLDSIGSHA1); @@ -76,13 +72,13 @@ OUString getSignatureURI(svl::crypto::SignatureMethodAlgorithm eAlgorithm, sal_I { switch (nDigestID) { - case cssxc::DigestID::SHA1: + case css::xml::crypto::DigestID::SHA1: aRet = ALGO_ECDSASHA1; break; - case cssxc::DigestID::SHA256: + case css::xml::crypto::DigestID::SHA256: aRet = ALGO_ECDSASHA256; break; - case cssxc::DigestID::SHA512: + case css::xml::crypto::DigestID::SHA512: aRet = ALGO_ECDSASHA512; break; default: @@ -95,11 +91,11 @@ OUString getSignatureURI(svl::crypto::SignatureMethodAlgorithm eAlgorithm, sal_I switch (nDigestID) { - case cssxc::DigestID::SHA1: + case css::xml::crypto::DigestID::SHA1: return OUString(ALGO_RSASHA1); - case cssxc::DigestID::SHA256: + case css::xml::crypto::DigestID::SHA256: return OUString(ALGO_RSASHA256); - case cssxc::DigestID::SHA512: + case css::xml::crypto::DigestID::SHA512: return OUString(ALGO_RSASHA512); default: return OUString(ALGO_RSASHA1); @@ -107,7 +103,7 @@ OUString getSignatureURI(svl::crypto::SignatureMethodAlgorithm eAlgorithm, sal_I } } -XSecController::XSecController( const cssu::Reference<cssu::XComponentContext>& rxCtx ) +XSecController::XSecController( const css::uno::Reference<css::uno::XComponentContext>& rxCtx ) : mxCtx(rxCtx) , m_nNextSecurityId(1) , m_bIsPreviousNodeInitializable(false) @@ -182,15 +178,15 @@ void XSecController::createXSecComponent( ) m_xXMLDocumentWrapper = nullptr; m_xSAXEventKeeper = nullptr; - cssu::Reference< cssl::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() ); + css::uno::Reference< css::lang::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() ); #if HAVE_FEATURE_GPGME - uno::Reference< lang::XServiceInfo > xServiceInfo( m_xSecurityContext, cssu::UNO_QUERY ); + uno::Reference< lang::XServiceInfo > xServiceInfo( m_xSecurityContext, css::uno::UNO_QUERY ); if (xServiceInfo->getImplementationName() == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl") m_xXMLSignature.set(new XMLSignature_GpgImpl()); else // xmlsec or mscrypt #endif - m_xXMLSignature.set(xMCF->createInstanceWithContext("com.sun.star.xml.crypto.XMLSignature", mxCtx), cssu::UNO_QUERY); + m_xXMLSignature.set(xMCF->createInstanceWithContext("com.sun.star.xml.crypto.XMLSignature", mxCtx), css::uno::UNO_QUERY); bool bSuccess = m_xXMLSignature.is(); if ( bSuccess ) @@ -210,11 +206,11 @@ void XSecController::createXSecComponent( ) * SAXEventKeeper created successfully. */ { - cssu::Sequence <cssu::Any> arg(1); + css::uno::Sequence <css::uno::Any> arg(1); arg[0] <<= uno::Reference<xml::wrapper::XXMLDocumentWrapper>(m_xXMLDocumentWrapper.get()); m_xSAXEventKeeper->initialize(arg); - cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener > + css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener > xStatusChangeListener = this; m_xSAXEventKeeper->addSAXEventKeeperStatusChangeListener( xStatusChangeListener ); @@ -277,7 +273,7 @@ bool XSecController::chainOn() */ m_xSAXEventKeeper->setNextHandler( nullptr ); - cssu::Reference< cssxs::XDocumentHandler > xSEKHandler(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()), cssu::UNO_QUERY); + css::uno::Reference< css::xml::sax::XDocumentHandler > xSEKHandler(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()), css::uno::UNO_QUERY); /* * connects the previous document handler on the SAX chain @@ -286,17 +282,17 @@ bool XSecController::chainOn() { if ( m_bIsPreviousNodeInitializable ) { - cssu::Reference< cssl::XInitialization > xInitialization - (m_xPreviousNodeOnSAXChain, cssu::UNO_QUERY); + css::uno::Reference< css::lang::XInitialization > xInitialization + (m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY); - cssu::Sequence<cssu::Any> aArgs( 1 ); + css::uno::Sequence<css::uno::Any> aArgs( 1 ); aArgs[0] <<= xSEKHandler; xInitialization->initialize(aArgs); } else { - cssu::Reference< cssxs::XParser > xParser - (m_xPreviousNodeOnSAXChain, cssu::UNO_QUERY); + css::uno::Reference< css::xml::sax::XParser > xParser + (m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY); xParser->setDocumentHandler( xSEKHandler ); } } @@ -332,16 +328,16 @@ void XSecController::chainOff() { if ( m_bIsPreviousNodeInitializable ) { - cssu::Reference< cssl::XInitialization > xInitialization - (m_xPreviousNodeOnSAXChain, cssu::UNO_QUERY); + css::uno::Reference< css::lang::XInitialization > xInitialization + (m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY); - cssu::Sequence<cssu::Any> aArgs( 1 ); + css::uno::Sequence<css::uno::Any> aArgs( 1 ); aArgs[0] <<= uno::Reference<xml::sax::XDocumentHandler>(); xInitialization->initialize(aArgs); } else { - cssu::Reference< cssxs::XParser > xParser(m_xPreviousNodeOnSAXChain, cssu::UNO_QUERY); + css::uno::Reference< css::xml::sax::XParser > xParser(m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY); xParser->setDocumentHandler(uno::Reference<xml::sax::XDocumentHandler>()); } } @@ -398,7 +394,7 @@ void XSecController::initializeSAXChain() chainOff(); } -cssu::Reference< css::io::XInputStream > +css::uno::Reference< css::io::XInputStream > XSecController::getObjectInputStream( const OUString& objectURL ) /****** XSecController/getObjectInputStream ************************************ * @@ -415,7 +411,7 @@ cssu::Reference< css::io::XInputStream > * xInputStream - the XInputStream interface ******************************************************************************/ { - cssu::Reference< css::io::XInputStream > xObjectInputStream; + css::uno::Reference< css::io::XInputStream > xObjectInputStream; SAL_WARN_IF( !m_xUriBinding.is(), "xmlsecurity.helper", "Need XUriBinding!" ); @@ -435,7 +431,7 @@ sal_Int32 XSecController::getNewSecurityId( ) return nId; } -void XSecController::startMission(const rtl::Reference<UriBindingHelper>& xUriBinding, const cssu::Reference< cssxc::XXMLSecurityContext >& xSecurityContext ) +void XSecController::startMission(const rtl::Reference<UriBindingHelper>& xUriBinding, const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& xSecurityContext ) /****** XSecController/startMission ******************************************* * * NAME @@ -461,7 +457,7 @@ void XSecController::startMission(const rtl::Reference<UriBindingHelper>& xUriBi m_bVerifyCurrentSignature = false; } -void XSecController::setSAXChainConnector(const cssu::Reference< cssl::XInitialization >& xInitialization) +void XSecController::setSAXChainConnector(const css::uno::Reference< css::lang::XInitialization >& xInitialization) /****** XSecController/setSAXChainConnector *********************************** * * NAME @@ -512,8 +508,8 @@ void XSecController::endMission() * ResolvedListener only exist when the security components are created. */ { - cssu::Reference< cssxc::sax::XMissionTaker > xMissionTaker - ( m_vInternalSignatureInformations[i].xReferenceResolvedListener, cssu::UNO_QUERY ); + css::uno::Reference< css::xml::crypto::sax::XMissionTaker > xMissionTaker + ( m_vInternalSignatureInformations[i].xReferenceResolvedListener, css::uno::UNO_QUERY ); /* * asks the SignatureCreator/SignatureVerifier to release @@ -572,7 +568,7 @@ void writeUnsignedProperties( } void XSecController::exportSignature( - const cssu::Reference<cssxs::XDocumentHandler>& xDocumentHandler, + const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, const SignatureInformation& signatureInfo, bool bXAdESCompliantIfODF ) /****** XSecController/exportSignature **************************************** @@ -606,19 +602,19 @@ void XSecController::exportSignature( signatureInfo.ouSignatureId); } - xDocumentHandler->startElement( "Signature", cssu::Reference< cssxs::XAttributeList > (pAttributeList)); + xDocumentHandler->startElement( "Signature", css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); { /* Write SignedInfo element */ xDocumentHandler->startElement( "SignedInfo", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); { /* Write CanonicalizationMethod element */ pAttributeList = new SvXMLAttributeList(); pAttributeList->AddAttribute( "Algorithm", ALGO_C14N); - xDocumentHandler->startElement( "CanonicalizationMethod", cssu::Reference< cssxs::XAttributeList > (pAttributeList) ); + xDocumentHandler->startElement( "CanonicalizationMethod", css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList) ); xDocumentHandler->endElement( "CanonicalizationMethod" ); /* Write SignatureMethod element */ @@ -632,7 +628,7 @@ void XSecController::exportSignature( pAttributeList->AddAttribute( "Algorithm", getSignatureURI(signatureInfo.eAlgorithmID, vReferenceInfors[0].nDigestID)); - xDocumentHandler->startElement( "SignatureMethod", cssu::Reference< cssxs::XAttributeList > (pAttributeList) ); + xDocumentHandler->startElement( "SignatureMethod", css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList) ); xDocumentHandler->endElement( "SignatureMethod" ); /* Write Reference element */ @@ -671,7 +667,7 @@ void XSecController::exportSignature( } } - xDocumentHandler->startElement( "Reference", cssu::Reference< cssxs::XAttributeList > (pAttributeList) ); + xDocumentHandler->startElement( "Reference", css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList) ); { /* Write Transforms element */ if (refInfor.nType == SignatureReferenceType::XMLSTREAM) @@ -681,7 +677,7 @@ void XSecController::exportSignature( { xDocumentHandler->startElement( "Transforms", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); { pAttributeList = new SvXMLAttributeList(); pAttributeList->AddAttribute( @@ -689,7 +685,7 @@ void XSecController::exportSignature( ALGO_C14N); xDocumentHandler->startElement( "Transform", - cssu::Reference< cssxs::XAttributeList > (pAttributeList) ); + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList) ); xDocumentHandler->endElement( "Transform" ); } xDocumentHandler->endElement( "Transforms" ); @@ -702,13 +698,13 @@ void XSecController::exportSignature( getDigestURI(refInfor.nDigestID)); xDocumentHandler->startElement( "DigestMethod", - cssu::Reference< cssxs::XAttributeList > (pAttributeList) ); + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList) ); xDocumentHandler->endElement( "DigestMethod" ); /* Write DigestValue element */ xDocumentHandler->startElement( "DigestValue", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); xDocumentHandler->characters( refInfor.ouDigestValue ); xDocumentHandler->endElement( "DigestValue" ); } @@ -720,14 +716,14 @@ void XSecController::exportSignature( /* Write SignatureValue element */ xDocumentHandler->startElement( "SignatureValue", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); xDocumentHandler->characters( signatureInfo.ouSignatureValue ); xDocumentHandler->endElement( "SignatureValue" ); /* Write KeyInfo element */ xDocumentHandler->startElement( "KeyInfo", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); { // GPG or X509 key? if (!signatureInfo.ouGpgCertificate.isEmpty()) @@ -737,13 +733,13 @@ void XSecController::exportSignature( /* Write PGPData element */ xDocumentHandler->startElement( "PGPData", - cssu::Reference< cssxs::XAttributeList > (pAttributeList)); + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); { /* Write keyid element */ xDocumentHandler->startElement( "PGPKeyID", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); - xDocumentHandler->characters( signatureInfo.ouCertDigest ); + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters(signatureInfo.ouGpgKeyID); xDocumentHandler->endElement( "PGPKeyID" ); /* Write PGPKeyPacket element */ @@ -751,7 +747,7 @@ void XSecController::exportSignature( { xDocumentHandler->startElement( "PGPKeyPacket", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); xDocumentHandler->characters( signatureInfo.ouGpgCertificate ); xDocumentHandler->endElement( "PGPKeyPacket" ); } @@ -759,7 +755,7 @@ void XSecController::exportSignature( /* Write PGPOwner element */ xDocumentHandler->startElement( "loext:PGPOwner", - cssu::Reference< cssxs::XAttributeList >(new SvXMLAttributeList())); + css::uno::Reference< css::xml::sax::XAttributeList >(new SvXMLAttributeList())); xDocumentHandler->characters( signatureInfo.ouGpgOwner ); xDocumentHandler->endElement( "loext:PGPOwner" ); } @@ -767,43 +763,50 @@ void XSecController::exportSignature( } else { - /* Write X509Data element */ - xDocumentHandler->startElement( - "X509Data", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + assert(signatureInfo.GetSigningCertificate()); + for (auto const& rData : signatureInfo.X509Datas) { - /* Write X509IssuerSerial element */ + /* Write X509Data element */ xDocumentHandler->startElement( - "X509IssuerSerial", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); - { - /* Write X509IssuerName element */ - xDocumentHandler->startElement( - "X509IssuerName", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); - xDocumentHandler->characters( signatureInfo.ouX509IssuerName ); - xDocumentHandler->endElement( "X509IssuerName" ); - - /* Write X509SerialNumber element */ - xDocumentHandler->startElement( - "X509SerialNumber", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); - xDocumentHandler->characters( signatureInfo.ouX509SerialNumber ); - xDocumentHandler->endElement( "X509SerialNumber" ); - } - xDocumentHandler->endElement( "X509IssuerSerial" ); - - /* Write X509Certificate element */ - if (!signatureInfo.ouX509Certificate.isEmpty()) + "X509Data", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); { - xDocumentHandler->startElement( - "X509Certificate", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); - xDocumentHandler->characters( signatureInfo.ouX509Certificate ); - xDocumentHandler->endElement( "X509Certificate" ); + for (auto const& it : rData) + { + /* Write X509IssuerSerial element */ + xDocumentHandler->startElement( + "X509IssuerSerial", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + /* Write X509IssuerName element */ + xDocumentHandler->startElement( + "X509IssuerName", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters(it.X509IssuerName); + xDocumentHandler->endElement( "X509IssuerName" ); + + /* Write X509SerialNumber element */ + xDocumentHandler->startElement( + "X509SerialNumber", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters(it.X509SerialNumber); + xDocumentHandler->endElement( "X509SerialNumber" ); + } + xDocumentHandler->endElement( "X509IssuerSerial" ); + + /* Write X509Certificate element */ + if (!it.X509Certificate.isEmpty()) + { + xDocumentHandler->startElement( + "X509Certificate", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters(it.X509Certificate); + xDocumentHandler->endElement( "X509Certificate" ); + } + } } + xDocumentHandler->endElement( "X509Data" ); } - xDocumentHandler->endElement( "X509Data" ); } } xDocumentHandler->endElement( "KeyInfo" ); @@ -813,24 +816,24 @@ void XSecController::exportSignature( /* Write Object element */ xDocumentHandler->startElement( "Object", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); { /* Write SignatureProperties element */ xDocumentHandler->startElement( "SignatureProperties", - cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); { /* Write SignatureProperty element */ pAttributeList = new SvXMLAttributeList(); pAttributeList->AddAttribute( "Id", - signatureInfo.ouPropertyId); + signatureInfo.ouDateTimePropertyId); pAttributeList->AddAttribute( "Target", "#" + signatureInfo.ouSignatureId); xDocumentHandler->startElement( "SignatureProperty", - cssu::Reference< cssxs::XAttributeList > (pAttributeList)); + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); { /* Write timestamp element */ @@ -841,7 +844,7 @@ void XSecController::exportSignature( xDocumentHandler->startElement( "dc:date", - cssu::Reference< cssxs::XAttributeList > (pAttributeList)); + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); OUStringBuffer buffer; //If the xml signature was already contained in the document, @@ -899,13 +902,13 @@ void XSecController::exportSignature( pAttributeList->AddAttribute("xmlns:xd", NS_XD); xDocumentHandler->startElement( "Object", - cssu::Reference< cssxs::XAttributeList > (pAttributeList)); + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); { pAttributeList = new SvXMLAttributeList(); pAttributeList->AddAttribute("Target", "#" + signatureInfo.ouSignatureId); xDocumentHandler->startElement( "xd:QualifyingProperties", - cssu::Reference< cssxs::XAttributeList > (pAttributeList)); + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); DocumentSignatureHelper::writeSignedProperties(xDocumentHandler, signatureInfo, sDate, true); writeUnsignedProperties(xDocumentHandler, signatureInfo); xDocumentHandler->endElement( "xd:QualifyingProperties" ); @@ -922,6 +925,15 @@ void XSecController::exportOOXMLSignature(const uno::Reference<embed::XStorage>& aExporter.writeSignature(); } +void XSecController::UpdateSignatureInformation(sal_Int32 const nSecurityId, + std::vector<SignatureInformation::X509Data> const& rDatas) +{ + SignatureInformation aInf( 0 ); + int const nIndex = findSignatureInfor(nSecurityId); + assert(nIndex != -1); // nothing should touch this between parsing and verify + m_vInternalSignatureInformations[nIndex].signatureInfor.X509Datas = rDatas; +} + SignatureInformation XSecController::getSignatureInformation( sal_Int32 nSecurityId ) const { SignatureInformation aInf( 0 ); diff --git a/xmlsecurity/source/helper/xsecparser.cxx b/xmlsecurity/source/helper/xsecparser.cxx index 532ba07a0298..1c8bf28ab287 100644 --- a/xmlsecurity/source/helper/xsecparser.cxx +++ b/xmlsecurity/source/helper/xsecparser.cxx @@ -20,136 +20,476 @@ #include "xsecparser.hxx" #include <xmlsignaturehelper.hxx> + +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmlimp.hxx> + #include <com/sun/star/xml/sax/SAXException.hpp> #include <cppuhelper/exc_hlp.hxx> #include <sal/log.hxx> #include <string.h> -namespace cssu = com::sun::star::uno; -namespace cssxc = com::sun::star::xml::crypto; -namespace cssxs = com::sun::star::xml::sax; - -XSecParser::XSecParser(XMLSignatureHelper& rXMLSignatureHelper, - XSecController* pXSecController) - : m_bInX509IssuerName(false) - , m_bInX509SerialNumber(false) - , m_bInX509Certificate(false) - , m_bInGpgCertificate(false) - , m_bInGpgKeyID(false) - , m_bInGpgOwner(false) - , m_bInCertDigest(false) - , m_bInEncapsulatedX509Certificate(false) - , m_bInSigningTime(false) - , m_bInDigestValue(false) - , m_bInSignatureValue(false) - , m_bInDate(false) - , m_bInDescription(false) - , m_bInSignatureLineId(false) - , m_bInSignatureLineValidImage(false) - , m_bInSignatureLineInvalidImage(false) - , m_pXSecController(pXSecController) - , m_bReferenceUnresolved(false) - , m_nReferenceDigestID(cssxc::DigestID::SHA1) - , m_rXMLSignatureHelper(rXMLSignatureHelper) +class XSecParser::Context { -} + protected: + friend class XSecParser; + XSecParser & m_rParser; + private: + std::unique_ptr<SvXMLNamespaceMap> m_pOldNamespaceMap; + + public: + Context(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : m_rParser(rParser) + , m_pOldNamespaceMap(std::move(pOldNamespaceMap)) + { + } + + virtual ~Context() = default; + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) + { + } + + virtual void EndElement() + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/); -OUString XSecParser::getIdAttr(const cssu::Reference< cssxs::XAttributeList >& xAttribs ) + virtual void Characters(OUString const& /*rChars*/) + { + } +}; + +// it's possible that an unsupported element has an Id attribute and a +// ds:Reference digesting it - probably this means XSecController needs to know +// about it. (For known elements, the Id attribute is only processed according +// to the schema.) +class XSecParser::UnknownContext + : public XSecParser::Context { - OUString ouIdAttr = xAttribs->getValueByName("id"); + public: + UnknownContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } - if (ouIdAttr.isEmpty()) - { - ouIdAttr = xAttribs->getValueByName("Id"); - } + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } +}; - return ouIdAttr; +auto XSecParser::Context::CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/) +-> std::unique_ptr<Context> +{ + // default: create new base context + return std::make_unique<UnknownContext>(m_rParser, std::move(pOldNamespaceMap)); } -/* - * XDocumentHandler +/** +note: anything in ds:Object should be trusted *only* if there is a ds:Reference + to it so it is signed (exception: the xades:EncapsulatedX509Certificate). + ds:SignedInfo precedes all ds:Object. + + There may be multiple ds:Signature for purpose of counter-signatures + but the way XAdES describes these, only the ds:SignatureValue element + would be referenced, so requiring a ds:Reference for anything in + ds:Object shouldn't cause issues. */ -void SAL_CALL XSecParser::startDocument( ) +class XSecParser::ReferencedContextImpl + : public XSecParser::Context { - m_bInX509IssuerName = false; - m_bInX509SerialNumber = false; - m_bInX509Certificate = false; - m_bInGpgCertificate = false; - m_bInGpgKeyID = false; - m_bInGpgOwner = false; - m_bInSignatureValue = false; - m_bInDigestValue = false; - m_bInDate = false; - m_bInDescription = false; + protected: + bool m_isReferenced; - if (m_xNextHandler.is()) - { - m_xNextHandler->startDocument(); - } -} + public: + ReferencedContextImpl(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_isReferenced(isReferenced) + { + } -void SAL_CALL XSecParser::endDocument( ) + OUString CheckIdAttrReferenced(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) + { + OUString const id(m_rParser.HandleIdAttr(xAttrs)); + if (!id.isEmpty() && m_rParser.m_pXSecController->haveReferenceForId(id)) + { + m_isReferenced = true; + } + return id; + } +}; + +class XSecParser::LoPGPOwnerContext + : public XSecParser::Context { - if (m_xNextHandler.is()) - { - m_xNextHandler->endDocument(); - } -} + private: + OUString m_Value; -void SAL_CALL XSecParser::startElement( - const OUString& aName, - const cssu::Reference< cssxs::XAttributeList >& xAttribs ) + public: + LoPGPOwnerContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setGpgOwner(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::DsPGPKeyPacketContext + : public XSecParser::Context { - try - { - OUString ouIdAttr = getIdAttr(xAttribs); - if (!ouIdAttr.isEmpty()) + private: + OUString m_Value; + + public: + DsPGPKeyPacketContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) { - m_pXSecController->collectToVerify( ouIdAttr ); } - if ( aName == "Signature" ) + virtual void EndElement() override { - m_rXMLSignatureHelper.StartVerifySignatureElement(); - m_pXSecController->addSignature(); - if (!ouIdAttr.isEmpty()) + m_rParser.m_pXSecController->setGpgCertificate(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::DsPGPKeyIDContext + : public XSecParser::Context +{ + private: + OUString m_Value; + + public: + DsPGPKeyIDContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setGpgKeyID(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::DsPGPDataContext + : public XSecParser::Context +{ + public: + DsPGPDataContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override + { + m_rParser.m_pXSecController->switchGpgSignature(); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyID") + { + return std::make_unique<DsPGPKeyIDContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyPacket") { - m_pXSecController->setId( ouIdAttr ); + return std::make_unique<DsPGPKeyPacketContext>(m_rParser, std::move(pOldNamespaceMap)); } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "PGPOwner") + { + return std::make_unique<LoPGPOwnerContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); } - else if (aName == "SignatureMethod") +}; + +class XSecParser::DsX509CertificateContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509CertificateContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) { - OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); - if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 - || ouAlgorithm == ALGO_ECDSASHA512) - m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); } - else if ( aName == "Reference" ) + + virtual void Characters(OUString const& rChars) override { - OUString ouUri = xAttribs->getValueByName("URI"); - SAL_WARN_IF( ouUri.isEmpty(), "xmlsecurity.helper", "URI is empty" ); - // Remember the type of this reference. - OUString ouType = xAttribs->getValueByName("Type"); - if (ouUri.startsWith("#")) + m_rValue += rChars; + } +}; + +class XSecParser::DsX509SerialNumberContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509SerialNumberContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class XSecParser::DsX509IssuerNameContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509IssuerNameContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class XSecParser::DsX509IssuerSerialContext + : public XSecParser::Context +{ + private: + OUString & m_rX509IssuerName; + OUString & m_rX509SerialNumber; + + public: + DsX509IssuerSerialContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rIssuerName, OUString & rSerialNumber) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rX509IssuerName(rIssuerName) + , m_rX509SerialNumber(rSerialNumber) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName") { - /* - * remove the first character '#' from the attribute value - */ - m_pXSecController->addReference( ouUri.copy(1), m_nReferenceDigestID, ouType ); + return std::make_unique<DsX509IssuerNameContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName); } - else + if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber") { - /* - * remember the uri - */ - m_currentReferenceURI = ouUri; - m_bReferenceUnresolved = true; + return std::make_unique<DsX509SerialNumberContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509SerialNumber); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +/// can't be sure what is supposed to happen here because the spec is clear as mud +class XSecParser::DsX509DataContext + : public XSecParser::Context +{ + private: + // sigh... "No ordering is implied by the above constraints." + // so store the ball of mud in vectors and try to figure it out later. + std::vector<std::pair<OUString, OUString>> m_X509IssuerSerials; + std::vector<OUString> m_X509Certificates; + + public: + DsX509DataContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial") + { + m_X509IssuerSerials.emplace_back(); + return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerSerials.back().first, m_X509IssuerSerials.back().second); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Certificate") + { + m_X509Certificates.emplace_back(); + return std::make_unique<DsX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_X509Certificates.back()); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsKeyInfoContext + : public XSecParser::Context +{ + public: + DsKeyInfoContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data") + { + return std::make_unique<DsX509DataContext>(m_rParser, std::move(pOldNamespaceMap)); } + if (nNamespace == XML_NAMESPACE_DS && rName == "PGPData") + { + return std::make_unique<DsPGPDataContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:KeyName, ds:KeyValue, ds:RetrievalMethod, ds:SPKIData, ds:MgmtData + // (old code would read ds:Transform inside ds:RetrievalMethod but + // presumably that was a bug) + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + +}; + +class XSecParser::DsSignatureValueContext + : public XSecParser::Context +{ + private: + OUString m_Value; + + public: + DsSignatureValueContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setSignatureValue(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::DsDigestValueContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsDigestValueContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override + { + m_rValue.clear(); + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; } - else if (aName == "DigestMethod") +}; + +class XSecParser::DsDigestMethodContext + : public XSecParser::Context +{ + private: + sal_Int32 & m_rReferenceDigestID; + + public: + DsDigestMethodContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_Int32 & rReferenceDigestID) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override { - OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" ); if (!ouAlgorithm.isEmpty()) @@ -159,342 +499,1102 @@ void SAL_CALL XSecParser::startElement( && ouAlgorithm != ALGO_XMLDSIGSHA512, "xmlsecurity.helper", "Algorithm neither SHA1, SHA256 nor SHA512"); if (ouAlgorithm == ALGO_XMLDSIGSHA1) - m_nReferenceDigestID = cssxc::DigestID::SHA1; + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA1; else if (ouAlgorithm == ALGO_XMLDSIGSHA256) - m_nReferenceDigestID = cssxc::DigestID::SHA256; + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA256; else if (ouAlgorithm == ALGO_XMLDSIGSHA512) - m_nReferenceDigestID = cssxc::DigestID::SHA512; + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA512; else - m_nReferenceDigestID = 0; + m_rReferenceDigestID = 0; } } - else if (aName == "Transform") +}; + +class XSecParser::DsTransformContext + : public XSecParser::Context +{ + private: + bool & m_rIsC14N; + + public: + DsTransformContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool & rIsC14N) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + + if (ouAlgorithm == ALGO_C14N) + /* + * a xml stream + */ + { + m_rIsC14N = true; + } + } +}; + +class XSecParser::DsTransformsContext + : public XSecParser::Context +{ + private: + bool & m_rIsC14N; + + public: + DsTransformsContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool & rIsC14N) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override { - if ( m_bReferenceUnresolved ) + if (nNamespace == XML_NAMESPACE_DS && rName == "Transform") { - OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); + return std::make_unique<DsTransformContext>(m_rParser, std::move(pOldNamespaceMap), m_rIsC14N); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; - if (ouAlgorithm == ALGO_C14N) - /* - * a xml stream - */ +class XSecParser::DsReferenceContext + : public XSecParser::Context +{ + private: + OUString m_URI; + OUString m_Type; + OUString m_DigestValue; + bool m_IsC14N = false; + // Relevant for ODF. The digest algorithm selected by the DigestMethod + // element's Algorithm attribute. @see css::xml::crypto::DigestID. + sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; + + public: + DsReferenceContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + + m_URI = xAttrs->getValueByName("URI"); + SAL_WARN_IF(m_URI.isEmpty(), "xmlsecurity.helper", "URI is empty"); + // Remember the type of this reference. + m_Type = xAttrs->getValueByName("Type"); + } + + virtual void EndElement() override + { + if (m_URI.startsWith("#")) + { + /* + * remove the first character '#' from the attribute value + */ + m_rParser.m_pXSecController->addReference(m_URI.copy(1), m_nReferenceDigestID, m_Type); + } + else + { + if (m_IsC14N) // this is determined by nested ds:Transform { - m_pXSecController->addStreamReference( m_currentReferenceURI, false, m_nReferenceDigestID ); - m_bReferenceUnresolved = false; + m_rParser.m_pXSecController->addStreamReference(m_URI, false, m_nReferenceDigestID); + } + else + /* + * it must be an octet stream + */ + { + m_rParser.m_pXSecController->addStreamReference(m_URI, true, m_nReferenceDigestID); } } + + m_rParser.m_pXSecController->setDigestValue(m_nReferenceDigestID, m_DigestValue); } - else if (aName == "X509IssuerName") + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override { - m_ouX509IssuerName.clear(); - m_bInX509IssuerName = true; + if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms") + { + return std::make_unique<DsTransformsContext>(m_rParser, std::move(pOldNamespaceMap), m_IsC14N); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_DigestValue); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); } - else if (aName == "X509SerialNumber") +}; + +class XSecParser::DsSignatureMethodContext + : public XSecParser::Context +{ + public: + DsSignatureMethodContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) { - m_ouX509SerialNumber.clear(); - m_bInX509SerialNumber = true; } - else if (aName == "X509Certificate") + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override { - m_ouX509Certificate.clear(); - m_bInX509Certificate = true; + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 + || ouAlgorithm == ALGO_ECDSASHA512) + { + m_rParser.m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); + } } - else if (aName == "PGPData") +}; + +class XSecParser::DsSignedInfoContext + : public XSecParser::Context +{ + public: + DsSignedInfoContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) { - m_pXSecController->switchGpgSignature(); } - else if (aName == "PGPKeyID") + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override { - m_ouGpgKeyID.clear(); - m_bInGpgKeyID = true; + m_rParser.HandleIdAttr(xAttrs); } - else if (aName == "PGPKeyPacket") + + virtual void EndElement() override { - m_ouGpgCertificate.clear(); - m_bInGpgCertificate = true; + m_rParser.m_pXSecController->setReferenceCount(); } - else if (aName == "loext:PGPOwner") + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override { - m_ouGpgOwner.clear(); - m_bInGpgOwner = true; + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod") + { + return std::make_unique<DsSignatureMethodContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:CanonicalizationMethod + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); } - else if (aName == "SignatureValue") +}; + +class XSecParser::XadesEncapsulatedX509CertificateContext + : public XSecParser::Context +{ + private: + OUString m_Value; + + public: + XadesEncapsulatedX509CertificateContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) { - m_ouSignatureValue.clear(); - m_bInSignatureValue = true; } - else if (aName == "DigestValue" && !m_bInCertDigest) + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override { - m_ouDigestValue.clear(); - m_bInDigestValue = true; + m_rParser.HandleIdAttr(xAttrs); } - else if (aName == "xd:CertDigest") + + virtual void EndElement() override + { + m_rParser.m_pXSecController->addEncapsulatedX509Certificate(m_Value); + } + + virtual void Characters(OUString const& rChars) override { - m_ouCertDigest.clear(); - m_bInCertDigest = true; + m_Value += rChars; } - // FIXME: Existing code here in xmlsecurity uses "xd" as the namespace prefix for XAdES, - // while the sample document attached to tdf#76142 uses "xades". So accept either here. Of - // course this is idiotic and wrong, the right thing would be to use a proper way to parse - // XML that would handle namespaces correctly. I have no idea how substantial re-plumbing of - // this code that would require. - else if (aName == "xd:EncapsulatedX509Certificate" || aName == "xades:EncapsulatedX509Certificate") +}; + +class XSecParser::XadesCertificateValuesContext + : public XSecParser::Context +{ + public: + XadesCertificateValuesContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) { - m_ouEncapsulatedX509Certificate.clear(); - m_bInEncapsulatedX509Certificate = true; } - else if (aName == "xd:SigningTime" || aName == "xades:SigningTime") + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override { - m_ouDate.clear(); - m_bInSigningTime = true; + m_rParser.HandleIdAttr(xAttrs); } - else if ( aName == "SignatureProperty" ) + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override { - if (!ouIdAttr.isEmpty()) + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "EncapsulatedX509Certificate") { - m_pXSecController->setPropertyId( ouIdAttr ); + return std::make_unique<XadesEncapsulatedX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap)); } + // missing: xades:OtherCertificate + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); } - else if (aName == "dc:date") +}; + +class XSecParser::XadesUnsignedSignaturePropertiesContext + : public XSecParser::Context +{ + public: + XadesUnsignedSignaturePropertiesContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) { - if (m_ouDate.isEmpty()) - m_bInDate = true; } - else if (aName == "dc:description") + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override { - m_ouDescription.clear(); - m_bInDescription = true; + m_rParser.HandleIdAttr(xAttrs); } - else if (aName == "loext:SignatureLineId") + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override { - m_ouSignatureLineId.clear(); - m_bInSignatureLineId = true; + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertificateValues") + { + return std::make_unique<XadesCertificateValuesContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: + // xades:CounterSignature + // ^ old code would read a ds:Signature inside it? + // xades:SignatureTimeStamp + // xades:CompleteCertificateRefs + // xades:CompleteRevocationRefs + // xades:AttributeCertificateRefs + // xades:AttributeRevocationRefs + // xades:SigAndRefsTimeStamp + // xades:RefsOnlyTimeStamp + // xades:RevocationValues + // xades:AttrAuthoritiesCertValues + // ^ old code: was equivalent to CertificateValues ??? + // xades:AttributeRevocationValues + // xades:ArchiveTimeStamp + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); } - else if (aName == "loext:SignatureLineValidImage") +}; + +class XSecParser::XadesUnsignedPropertiesContext + : public XSecParser::Context +{ + public: + XadesUnsignedPropertiesContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) { - m_ouSignatureLineValidImage.clear(); - m_bInSignatureLineValidImage = true; } - else if (aName == "loext:SignatureLineInvalidImage") + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override { - m_ouSignatureLineInvalidImage.clear(); - m_bInSignatureLineInvalidImage = true; + m_rParser.HandleIdAttr(xAttrs); } - if (m_xNextHandler.is()) + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override { - m_xNextHandler->startElement(aName, xAttribs); + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedSignatureProperties") + { + return std::make_unique<XadesUnsignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: xades:UnsignedDataObjectProperties + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); } - } - catch (cssu::Exception& ) - {//getCaughtException MUST be the first line in the catch block - cssu::Any exc = cppu::getCaughtException(); - throw cssxs::SAXException( - "xmlsecurity: Exception in XSecParser::startElement", - nullptr, exc); - } - catch (...) - { - throw cssxs::SAXException( - "xmlsecurity: unexpected exception in XSecParser::startElement", nullptr, - cssu::Any()); - } -} +}; -void SAL_CALL XSecParser::endElement( const OUString& aName ) +class XSecParser::LoSignatureLineIdContext + : public XSecParser::ReferencedContextImpl { - try - { - if (aName == "DigestValue" && !m_bInCertDigest) + private: + OUString m_Value; + + public: + LoSignatureLineIdContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) { - m_bInDigestValue = false; } - else if ( aName == "Reference" ) + + virtual void EndElement() override { - if ( m_bReferenceUnresolved ) - /* - * it must be a octet stream - */ + if (m_isReferenced) { - m_pXSecController->addStreamReference( m_currentReferenceURI, true, m_nReferenceDigestID ); - m_bReferenceUnresolved = false; + m_rParser.m_pXSecController->setSignatureLineId(m_Value); } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineId"); + } + } - m_pXSecController->setDigestValue( m_nReferenceDigestID, m_ouDigestValue ); + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; } - else if ( aName == "SignedInfo" ) +}; + +class XSecParser::LoSignatureLineValidImageContext + : public XSecParser::ReferencedContextImpl +{ + private: + OUString m_Value; + + public: + LoSignatureLineValidImageContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) { - m_pXSecController->setReferenceCount(); } - else if ( aName == "SignatureValue" ) + + virtual void EndElement() override { - m_pXSecController->setSignatureValue( m_ouSignatureValue ); - m_bInSignatureValue = false; + if (m_isReferenced) + { + m_rParser.m_pXSecController->setValidSignatureImage(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineValidImage"); + } } - else if (aName == "X509IssuerName") + + virtual void Characters(OUString const& rChars) override { - m_pXSecController->setX509IssuerName( m_ouX509IssuerName ); - m_bInX509IssuerName = false; + m_Value += rChars; } - else if (aName == "X509SerialNumber") +}; + +class XSecParser::LoSignatureLineInvalidImageContext + : public XSecParser::ReferencedContextImpl +{ + private: + OUString m_Value; + + public: + LoSignatureLineInvalidImageContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) { - m_pXSecController->setX509SerialNumber( m_ouX509SerialNumber ); - m_bInX509SerialNumber = false; } - else if (aName == "X509Certificate") + + virtual void EndElement() override { - m_pXSecController->setX509Certificate( m_ouX509Certificate ); - m_bInX509Certificate = false; + if (m_isReferenced) + { + m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineInvalidImage"); + } } - else if (aName == "PGPKeyID") + + virtual void Characters(OUString const& rChars) override { - m_pXSecController->setGpgKeyID( m_ouGpgKeyID ); - m_bInGpgKeyID = false; + m_Value += rChars; } - else if (aName == "PGPKeyPacket") +}; + +class XSecParser::LoSignatureLineContext + : public XSecParser::ReferencedContextImpl +{ + public: + LoSignatureLineContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) { - m_pXSecController->setGpgCertificate( m_ouGpgCertificate ); - m_bInGpgCertificate = false; } - else if (aName == "loext:PGPOwner") + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override { - m_pXSecController->setGpgOwner( m_ouGpgOwner ); - m_bInGpgOwner = false; + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineId") + { + return std::make_unique<LoSignatureLineIdContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineValidImage") + { + return std::make_unique<LoSignatureLineValidImageContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineInvalidImage") + { + return std::make_unique<LoSignatureLineInvalidImageContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); } - else if (aName == "xd:CertDigest") +}; + +class XSecParser::XadesCertDigestContext + : public XSecParser::Context +{ + private: + OUString & m_rDigestValue; + sal_Int32 & m_rReferenceDigestID; + + public: + XadesCertDigestContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rDigestValue, sal_Int32 & rReferenceDigestID) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rDigestValue(rDigestValue) + , m_rReferenceDigestID(rReferenceDigestID) { - m_pXSecController->setCertDigest( m_ouCertDigest ); - m_bInCertDigest = false; } - else if (aName == "xd:EncapsulatedX509Certificate" || aName == "xades:EncapsulatedX509Certificate") + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override { - m_pXSecController->addEncapsulatedX509Certificate( m_ouEncapsulatedX509Certificate ); - m_bInEncapsulatedX509Certificate = false; + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rDigestValue); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); } - else if (aName == "xd:SigningTime" || aName == "xades:SigningTime") +}; + +class XSecParser::XadesCertContext + : public XSecParser::ReferencedContextImpl +{ + private: + sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; + OUString m_CertDigest; + OUString m_X509IssuerName; + OUString m_X509SerialNumber; + + public: + XadesCertContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) { - m_pXSecController->setDate( m_ouDate ); - m_bInSigningTime = false; } - else if (aName == "dc:date") + + virtual void EndElement() override { - if (m_bInDate) + if (m_isReferenced) { - m_pXSecController->setDate( m_ouDate ); - m_bInDate = false; + m_rParser.m_pXSecController->setX509CertDigest(m_CertDigest, m_nReferenceDigestID, m_X509IssuerName, m_X509SerialNumber); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned xades:Cert"); } } - else if (aName == "dc:description") + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override { - m_pXSecController->setDescription( m_ouDescription ); - m_bInDescription = false; + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest") + { + return std::make_unique<XadesCertDigestContext>(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial") + { + return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerName, m_X509SerialNumber); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); } - else if (aName == "loext:SignatureLineId") +}; + +class XSecParser::XadesSigningCertificateContext + : public XSecParser::ReferencedContextImpl +{ + public: + XadesSigningCertificateContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) { - m_pXSecController->setSignatureLineId( m_ouSignatureLineId ); - m_bInSignatureLineId = false; } - else if (aName == "loext:SignatureLineValidImage") + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override { - m_pXSecController->setValidSignatureImage( m_ouSignatureLineValidImage ); - m_bInSignatureLineValidImage = false; + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert") + { + return std::make_unique<XadesCertContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); } - else if (aName == "loext:SignatureLineInvalidImage") +}; + +class XSecParser::XadesSigningTimeContext + : public XSecParser::ReferencedContextImpl +{ + private: + OUString m_Value; + + public: + XadesSigningTimeContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) { - m_pXSecController->setInvalidSignatureImage( m_ouSignatureLineInvalidImage ); - m_bInSignatureLineInvalidImage = false; } - if (m_xNextHandler.is()) + virtual void EndElement() override { - m_xNextHandler->endElement(aName); + if (m_isReferenced) + { + m_rParser.m_pXSecController->setDate("", m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SigningTime"); + } } - } - catch (cssu::Exception& ) - {//getCaughtException MUST be the first line in the catch block - cssu::Any exc = cppu::getCaughtException(); - throw cssxs::SAXException( - "xmlsecurity: Exception in XSecParser::endElement", - nullptr, exc); - } - catch (...) - { - throw cssxs::SAXException( - "xmlsecurity: unexpected exception in XSecParser::endElement", nullptr, - cssu::Any()); - } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::XadesSignedSignaturePropertiesContext + : public XSecParser::ReferencedContextImpl +{ + public: + XadesSignedSignaturePropertiesContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime") + { + return std::make_unique<XadesSigningTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate") + { + return std::make_unique<XadesSigningCertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLine") + { + return std::make_unique<LoSignatureLineContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignaturePolicyIdentifier, xades:SignatureProductionPlace, xades:SignerRole + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesSignedPropertiesContext + : public XSecParser::ReferencedContextImpl +{ + public: + XadesSignedPropertiesContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties") + { + return std::make_unique<XadesSignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignedDataObjectProperties + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesQualifyingPropertiesContext + : public XSecParser::ReferencedContextImpl +{ + public: + XadesQualifyingPropertiesContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties") + { + return std::make_unique<XadesSignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedProperties") + { + return std::make_unique<XadesUnsignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DcDateContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DcDateContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class XSecParser::DcDescriptionContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DcDescriptionContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class XSecParser::DsSignaturePropertyContext + : public XSecParser::ReferencedContextImpl +{ + private: + enum class SignatureProperty { Unknown, Date, Description }; + SignatureProperty m_Property = SignatureProperty::Unknown; + OUString m_Id; + OUString m_Value; + + public: + DsSignaturePropertyContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_Id = CheckIdAttrReferenced(xAttrs); + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + switch (m_Property) + { + case SignatureProperty::Unknown: + SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored"); + break; + case SignatureProperty::Date: + m_rParser.m_pXSecController->setDate(m_Id, m_Value); + break; + case SignatureProperty::Description: + m_rParser.m_pXSecController->setDescription(m_Id, m_Value); + break; + } + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureProperty"); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DC && rName == "date") + { + m_Property = SignatureProperty::Date; + return std::make_unique<DcDateContext>(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + if (nNamespace == XML_NAMESPACE_DC && rName == "description") + { + m_Property = SignatureProperty::Description; + return std::make_unique<DcDescriptionContext>(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsSignaturePropertiesContext + : public XSecParser::ReferencedContextImpl +{ + public: + DsSignaturePropertiesContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty") + { + return std::make_unique<DsSignaturePropertyContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsObjectContext + : public XSecParser::ReferencedContextImpl +{ + public: + DsObjectContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + // init with "false" here - the Signature element can't be referenced by its child + : XSecParser::ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), false) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties") + { + return std::make_unique<DsSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties") + { + return std::make_unique<XadesQualifyingPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: ds:Manifest + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsSignatureContext + : public XSecParser::Context +{ + public: + DsSignatureContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString const ouIdAttr(m_rParser.HandleIdAttr(xAttrs)); + m_rParser.m_rXMLSignatureHelper.StartVerifySignatureElement(); + m_rParser.m_pXSecController->addSignature(); + if (!ouIdAttr.isEmpty()) + { + m_rParser.m_pXSecController->setId( ouIdAttr ); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo") + { + return std::make_unique<DsSignedInfoContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue") + { + return std::make_unique<DsSignatureValueContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo") + { + return std::make_unique<DsKeyInfoContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Object") + { + return std::make_unique<DsObjectContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsigSignaturesContext + : public XSecParser::Context +{ + public: + DsigSignaturesContext(XSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Signature") + { + return std::make_unique<DsSignatureContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + + +XSecParser::XSecParser(XMLSignatureHelper& rXMLSignatureHelper, + XSecController* pXSecController) + : m_pNamespaceMap(new SvXMLNamespaceMap) + , m_pXSecController(pXSecController) + , m_rXMLSignatureHelper(rXMLSignatureHelper) +{ + using namespace xmloff::token; + m_pNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML ); + m_pNamespaceMap->Add( "_dsig_ooo", GetXMLToken(XML_N_DSIG_OOO), XML_NAMESPACE_DSIG_OOO ); + m_pNamespaceMap->Add( "_dsig", GetXMLToken(XML_N_DSIG), XML_NAMESPACE_DSIG ); + m_pNamespaceMap->Add( "_ds", GetXMLToken(XML_N_DS), XML_NAMESPACE_DS ); + m_pNamespaceMap->Add( "_xades132", GetXMLToken(XML_N_XADES132), XML_NAMESPACE_XADES132); + m_pNamespaceMap->Add( "_xades141", GetXMLToken(XML_N_XADES141), XML_NAMESPACE_XADES141); + m_pNamespaceMap->Add( "_dc", GetXMLToken(XML_N_DC), XML_NAMESPACE_DC ); + m_pNamespaceMap->Add( "_office_libo", + GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT); } -void SAL_CALL XSecParser::characters( const OUString& aChars ) +OUString XSecParser::HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) { - if (m_bInX509IssuerName) - { - m_ouX509IssuerName += aChars; - } - else if (m_bInX509SerialNumber) - { - m_ouX509SerialNumber += aChars; - } - else if (m_bInX509Certificate) + OUString ouIdAttr = getIdAttr(xAttrs); + if (!ouIdAttr.isEmpty()) { - m_ouX509Certificate += aChars; + m_pXSecController->collectToVerify( ouIdAttr ); } - else if (m_bInGpgCertificate) - { - m_ouGpgCertificate += aChars; - } - else if (m_bInGpgKeyID) + return ouIdAttr; +} + +OUString XSecParser::getIdAttr(const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) +{ + OUString ouIdAttr = xAttribs->getValueByName("id"); + + if (ouIdAttr.isEmpty()) { - m_ouGpgKeyID += aChars; + ouIdAttr = xAttribs->getValueByName("Id"); } - else if (m_bInGpgOwner) + + return ouIdAttr; +} + +/* + * XDocumentHandler + */ +void SAL_CALL XSecParser::startDocument( ) +{ + if (m_xNextHandler.is()) { - m_ouGpgOwner += aChars; + m_xNextHandler->startDocument(); } - else if (m_bInSignatureValue) +} + +void SAL_CALL XSecParser::endDocument( ) +{ + if (m_xNextHandler.is()) { - m_ouSignatureValue += aChars; + m_xNextHandler->endDocument(); } - else if (m_bInDigestValue && !m_bInCertDigest) +} + +void SAL_CALL XSecParser::startElement( + const OUString& rName, + const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) +{ + assert(m_pNamespaceMap); + std::unique_ptr<SvXMLNamespaceMap> pRewindMap( + SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs)); + + OUString localName; + sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName)); + + std::unique_ptr<Context> pContext; + + if (m_ContextStack.empty()) { - m_ouDigestValue += aChars; + if ((nPrefix == XML_NAMESPACE_DSIG || nPrefix == XML_NAMESPACE_DSIG_OOO) + && localName == "document-signatures") + { + pContext.reset(new DsigSignaturesContext(*this, std::move(pRewindMap))); + } + else + { + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected root element", nullptr, + css::uno::Any()); + } } - else if (m_bInDate) + else { - m_ouDate += aChars; + pContext = m_ContextStack.top()->CreateChildContext( + std::move(pRewindMap), nPrefix, localName); } - else if (m_bInDescription) + + m_ContextStack.push(std::move(pContext)); + assert(!pRewindMap); + + try { - m_ouDescription += aChars; + m_ContextStack.top()->StartElement(xAttribs); + + if (m_xNextHandler.is()) + { + m_xNextHandler->startElement(rName, xAttribs); + } } - else if (m_bInCertDigest) - { - m_ouCertDigest += aChars; + catch (css::uno::Exception& ) + {//getCaughtException MUST be the first line in the catch block + css::uno::Any exc = cppu::getCaughtException(); + throw css::xml::sax::SAXException( + "xmlsecurity: Exception in XSecParser::startElement", + nullptr, exc); } - else if (m_bInEncapsulatedX509Certificate) + catch (...) { - m_ouEncapsulatedX509Certificate += aChars; + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected exception in XSecParser::startElement", nullptr, + css::uno::Any()); } - else if (m_bInSigningTime) +} + +void SAL_CALL XSecParser::endElement(const OUString& rName) +{ + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + + try { - m_ouDate += aChars; + m_ContextStack.top()->EndElement(); + + if (m_xNextHandler.is()) + { + m_xNextHandler->endElement(rName); + } } - else if (m_bInSignatureLineId) - { - m_ouSignatureLineId += aChars; + catch (css::uno::Exception& ) + {//getCaughtException MUST be the first line in the catch block + css::uno::Any exc = cppu::getCaughtException(); + throw css::xml::sax::SAXException( + "xmlsecurity: Exception in XSecParser::endElement", + nullptr, exc); } - else if (m_bInSignatureLineValidImage) + catch (...) { - m_ouSignatureLineValidImage += aChars; + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected exception in XSecParser::endElement", nullptr, + css::uno::Any()); } - else if (m_bInSignatureLineInvalidImage) + + if (m_ContextStack.top()->m_pOldNamespaceMap) { - m_ouSignatureLineInvalidImage += aChars; + m_pNamespaceMap = std::move(m_ContextStack.top()->m_pOldNamespaceMap); } + m_ContextStack.pop(); +} + +void SAL_CALL XSecParser::characters(const OUString& rChars) +{ + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + m_ContextStack.top()->Characters(rChars); if (m_xNextHandler.is()) { - m_xNextHandler->characters(aChars); + m_xNextHandler->characters(rChars); } } @@ -514,7 +1614,7 @@ void SAL_CALL XSecParser::processingInstruction( const OUString& aTarget, const } } -void SAL_CALL XSecParser::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator ) +void SAL_CALL XSecParser::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) { if (m_xNextHandler.is()) { @@ -526,7 +1626,7 @@ void SAL_CALL XSecParser::setDocumentLocator( const cssu::Reference< cssxs::XLoc * XInitialization */ void SAL_CALL XSecParser::initialize( - const cssu::Sequence< cssu::Any >& aArguments ) + const css::uno::Sequence< css::uno::Any >& aArguments ) { aArguments[0] >>= m_xNextHandler; } diff --git a/xmlsecurity/source/helper/xsecparser.hxx b/xmlsecurity/source/helper/xsecparser.hxx index 42b63975ecb9..1b0d3f08eeab 100644 --- a/xmlsecurity/source/helper/xsecparser.hxx +++ b/xmlsecurity/source/helper/xsecparser.hxx @@ -29,6 +29,10 @@ #include <cppuhelper/implbase.hxx> +#include <xmloff/nmspmap.hxx> + +#include <stack> + class XSecParser: public cppu::WeakImplHelper < css::xml::sax::XDocumentHandler, @@ -49,47 +53,54 @@ class XSecParser: public cppu::WeakImplHelper ******************************************************************************/ { friend class XSecController; +public: + class Context; private: - /* - * the following members are used to reserve the signature information, - * including X509IssuerName, X509SerialNumber, and X509Certificate,etc. - */ - OUString m_ouX509IssuerName; - OUString m_ouX509SerialNumber; - OUString m_ouX509Certificate; - OUString m_ouGpgCertificate; - OUString m_ouGpgKeyID; - OUString m_ouGpgOwner; - OUString m_ouCertDigest; - OUString m_ouEncapsulatedX509Certificate; - OUString m_ouDigestValue; - OUString m_ouSignatureValue; - OUString m_ouDate; - /// Characters of a <dc:description> element, as just read from XML. - OUString m_ouDescription; - OUString m_ouSignatureLineId; - OUString m_ouSignatureLineValidImage; - OUString m_ouSignatureLineInvalidImage; - - /* - * whether inside a particular element - */ - bool m_bInX509IssuerName; - bool m_bInX509SerialNumber; - bool m_bInX509Certificate; - bool m_bInGpgCertificate; - bool m_bInGpgKeyID; - bool m_bInGpgOwner; - bool m_bInCertDigest; - bool m_bInEncapsulatedX509Certificate; - bool m_bInSigningTime; - bool m_bInDigestValue; - bool m_bInSignatureValue; - bool m_bInDate; - bool m_bInDescription; - bool m_bInSignatureLineId; - bool m_bInSignatureLineValidImage; - bool m_bInSignatureLineInvalidImage; + class UnknownContext; + class ReferencedContextImpl; + class LoPGPOwnerContext; + class DsPGPKeyPacketContext; + class DsPGPKeyIDContext; + class DsPGPDataContext; + class DsX509CertificateContext; + class DsX509SerialNumberContext; + class DsX509IssuerNameContext; + class DsX509IssuerSerialContext; + class DsX509DataContext; + class DsKeyInfoContext; + class DsSignatureValueContext; + class DsDigestValueContext; + class DsDigestMethodContext; + class DsTransformContext; + class DsTransformsContext; + class DsReferenceContext; + class DsSignatureMethodContext; + class DsSignedInfoContext; + class XadesEncapsulatedX509CertificateContext; + class XadesCertificateValuesContext; + class XadesUnsignedSignaturePropertiesContext; + class XadesUnsignedPropertiesContext; + class LoSignatureLineIdContext; + class LoSignatureLineValidImageContext; + class LoSignatureLineInvalidImageContext; + class LoSignatureLineContext; + class XadesCertDigestContext; + class XadesCertContext; + class XadesSigningCertificateContext; + class XadesSigningTimeContext; + class XadesSignedSignaturePropertiesContext; + class XadesSignedPropertiesContext; + class XadesQualifyingPropertiesContext; + class DcDateContext; + class DcDescriptionContext; + class DsSignaturePropertyContext; + class DsSignaturePropertiesContext; + class DsObjectContext; + class DsSignatureContext; + class DsigSignaturesContext; + + std::stack<std::unique_ptr<Context>> m_ContextStack; + std::unique_ptr<SvXMLNamespaceMap> m_pNamespaceMap; /* * the XSecController collaborating with XSecParser @@ -102,22 +113,9 @@ private: css::uno::Reference< css::xml::sax::XDocumentHandler > m_xNextHandler; - /* - * this string is used to remember the current handled reference's URI, - * - * because it can be decided whether a stream reference is xml based or binary based - * only after the Transforms element is read in, so we have to reserve the reference's - * URI when the startElement event is met. - */ - OUString m_currentReferenceURI; - bool m_bReferenceUnresolved; - - // Relevant for ODF. The digest algorithm selected by the current DigestMethod element's - // Algorithm attribute in the current Reference element. From css::xml::crypto::DigestID. - sal_Int32 m_nReferenceDigestID; XMLSignatureHelper& m_rXMLSignatureHelper; -private: + OUString HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs); static OUString getIdAttr(const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ); diff --git a/xmlsecurity/source/helper/xsecsign.cxx b/xmlsecurity/source/helper/xsecsign.cxx index d8089b1773b3..fd6d5c9c8f24 100644 --- a/xmlsecurity/source/helper/xsecsign.cxx +++ b/xmlsecurity/source/helper/xsecsign.cxx @@ -38,10 +38,6 @@ using namespace css; using namespace css::uno; using namespace css::graphic; -namespace cssu = com::sun::star::uno; -namespace cssl = com::sun::star::lang; -namespace cssxc = com::sun::star::xml::crypto; -namespace cssxs = com::sun::star::xml::sax; /* protected: for signature generation */ OUString XSecController::createId() @@ -59,7 +55,7 @@ OUString XSecController::createId() return OUString::createFromAscii(str); } -cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite( +css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite( InternalSignatureInformation& internalSignatureInfor, sal_Int32 nStorageFormat, bool bXAdESCompliantIfODF) @@ -70,13 +66,13 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar sal_Int32 nIdOfSignatureElementCollector; nIdOfSignatureElementCollector = - m_xSAXEventKeeper->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_AFTERMODIFY, true ); + m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY, true ); m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); rtl::Reference<SignatureCreatorImpl> xSignatureCreator(new SignatureCreatorImpl); - cssu::Sequence<cssu::Any> args(5); + css::uno::Sequence<css::uno::Any> args(5); args[0] <<= OUString::number(nSecurityId); args[1] <<= uno::Reference<xml::crypto::sax::XSecuritySAXEventKeeper>(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()), uno::UNO_QUERY); args[2] <<= OUString::number(nIdOfSignatureElementCollector); @@ -121,7 +117,7 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar { const SignatureReferenceInformation& refInfor = vReferenceInfors[i]; - cssu::Reference< css::io::XInputStream > xInputStream + css::uno::Reference< css::io::XInputStream > xInputStream = getObjectInputStream( refInfor.ouURI ); if (xInputStream.is()) @@ -132,13 +128,13 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar // use sha512 for gpg signing unconditionally const sal_Int32 digestID = !internalSignatureInfor.signatureInfor.ouGpgCertificate.isEmpty()? - cssxc::DigestID::SHA512 : (bXAdESCompliantIfODF ? cssxc::DigestID::SHA256 : cssxc::DigestID::SHA1); + css::xml::crypto::DigestID::SHA512 : (bXAdESCompliantIfODF ? css::xml::crypto::DigestID::SHA256 : css::xml::crypto::DigestID::SHA1); if (nStorageFormat != embed::StorageFormats::OFOPXML) { internalSignatureInfor.signatureInfor.ouSignatureId = createId(); - internalSignatureInfor.signatureInfor.ouPropertyId = createId(); - internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouPropertyId, -1, OUString() ); + internalSignatureInfor.signatureInfor.ouDateTimePropertyId = createId(); + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDateTimePropertyId, -1, OUString() ); size++; if (bXAdESCompliantIfODF) @@ -183,7 +179,7 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar void XSecController::signAStream( sal_Int32 securityId, const OUString& uri, bool isBinary, bool bXAdESCompliantIfODF) { const SignatureReferenceType type = isBinary ? SignatureReferenceType::BINARYSTREAM : SignatureReferenceType::XMLSTREAM; - sal_Int32 digestID = bXAdESCompliantIfODF ? cssxc::DigestID::SHA256 : cssxc::DigestID::SHA1; + sal_Int32 digestID = bXAdESCompliantIfODF ? css::xml::crypto::DigestID::SHA256 : css::xml::crypto::DigestID::SHA1; int index = findSignatureInfor( securityId ); @@ -197,11 +193,12 @@ void XSecController::signAStream( sal_Int32 securityId, const OUString& uri, boo { // use sha512 for gpg signing unconditionally if (!m_vInternalSignatureInformations[index].signatureInfor.ouGpgCertificate.isEmpty()) - digestID = cssxc::DigestID::SHA512; + digestID = css::xml::crypto::DigestID::SHA512; m_vInternalSignatureInformations[index].addReference(type, digestID, uri, -1, OUString()); } } +// note: this is called when creating a new signature from scratch void XSecController::setX509Certificate( sal_Int32 nSecurityId, const OUString& ouX509IssuerName, @@ -215,10 +212,13 @@ void XSecController::setX509Certificate( if ( index == -1 ) { InternalSignatureInformation isi(nSecurityId, nullptr); - isi.signatureInfor.ouX509IssuerName = ouX509IssuerName; - isi.signatureInfor.ouX509SerialNumber = ouX509SerialNumber; - isi.signatureInfor.ouX509Certificate = ouX509Cert; - isi.signatureInfor.ouCertDigest = ouX509CertDigest; + isi.signatureInfor.X509Datas.clear(); + isi.signatureInfor.X509Datas.emplace_back(); + isi.signatureInfor.X509Datas.back().emplace_back(); + isi.signatureInfor.X509Datas.back().back().X509IssuerName = ouX509IssuerName; + isi.signatureInfor.X509Datas.back().back().X509SerialNumber = ouX509SerialNumber; + isi.signatureInfor.X509Datas.back().back().X509Certificate = ouX509Cert; + isi.signatureInfor.X509Datas.back().back().CertDigest = ouX509CertDigest; isi.signatureInfor.eAlgorithmID = eAlgorithmID; m_vInternalSignatureInformations.push_back( isi ); } @@ -226,16 +226,19 @@ void XSecController::setX509Certificate( { SignatureInformation &si = m_vInternalSignatureInformations[index].signatureInfor; - si.ouX509IssuerName = ouX509IssuerName; - si.ouX509SerialNumber = ouX509SerialNumber; - si.ouX509Certificate = ouX509Cert; - si.ouCertDigest = ouX509CertDigest; + si.X509Datas.clear(); + si.X509Datas.emplace_back(); + si.X509Datas.back().emplace_back(); + si.X509Datas.back().back().X509IssuerName = ouX509IssuerName; + si.X509Datas.back().back().X509SerialNumber = ouX509SerialNumber; + si.X509Datas.back().back().X509Certificate = ouX509Cert; + si.X509Datas.back().back().CertDigest = ouX509CertDigest; } } void XSecController::setGpgCertificate( sal_Int32 nSecurityId, - const OUString& ouCertDigest, + const OUString& ouKeyDigest, const OUString& ouCert, const OUString& ouOwner) { @@ -246,16 +249,17 @@ void XSecController::setGpgCertificate( InternalSignatureInformation isi(nSecurityId, nullptr); isi.signatureInfor.ouGpgCertificate = ouCert; isi.signatureInfor.ouGpgOwner = ouOwner; - isi.signatureInfor.ouCertDigest = ouCertDigest; + isi.signatureInfor.ouGpgKeyID = ouKeyDigest; m_vInternalSignatureInformations.push_back( isi ); } else { SignatureInformation &si = m_vInternalSignatureInformations[index].signatureInfor; + si.X509Datas.clear(); // it is a PGP signature now si.ouGpgCertificate = ouCert; si.ouGpgOwner = ouOwner; - si.ouCertDigest = ouCertDigest; + si.ouGpgKeyID = ouKeyDigest; } } @@ -352,7 +356,7 @@ void XSecController::setSignatureLineInvalidGraphic( } bool XSecController::WriteSignature( - const cssu::Reference<cssxs::XDocumentHandler>& xDocumentHandler, + const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, bool bXAdESCompliantIfODF ) { bool rc = false; @@ -378,7 +382,7 @@ bool XSecController::WriteSignature( /* * export the signature template */ - cssu::Reference<cssxs::XDocumentHandler> xSEKHandler(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()),cssu::UNO_QUERY); + css::uno::Reference<css::xml::sax::XDocumentHandler> xSEKHandler(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()),css::uno::UNO_QUERY); int i; int sigNum = m_vInternalSignatureInformations.size(); @@ -399,7 +403,7 @@ bool XSecController::WriteSignature( rc = true; } - catch( cssu::Exception& ) + catch( css::uno::Exception& ) { } @@ -427,7 +431,7 @@ bool XSecController::WriteOOXMLSignature(const uno::Reference<embed::XStorage>& try { // Export the signature template. - cssu::Reference<xml::sax::XDocumentHandler> xSEKHandler(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()), uno::UNO_QUERY); + css::uno::Reference<xml::sax::XDocumentHandler> xSEKHandler(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()), uno::UNO_QUERY); for (InternalSignatureInformation & rInformation : m_vInternalSignatureInformations) { diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx index 305e5aa28128..eca94d82c768 100644 --- a/xmlsecurity/source/helper/xsecverify.cxx +++ b/xmlsecurity/source/helper/xsecverify.cxx @@ -22,6 +22,7 @@ #include <xsecctl.hxx> #include "xsecparser.hxx" #include "ooxmlsecparser.hxx" +#include <biginteger.hxx> #include <framework/signatureverifierimpl.hxx> #include <framework/saxeventkeeperimpl.hxx> #include <gpg/xmlsignature_gpgimpl.hxx> @@ -47,13 +48,9 @@ using namespace css; using namespace css::uno; using namespace css::beans; -namespace cssu = com::sun::star::uno; -namespace cssl = com::sun::star::lang; -namespace cssxc = com::sun::star::xml::crypto; -namespace cssxs = com::sun::star::xml::sax; /* protected: for signature verify */ -cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepareSignatureToRead( +css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToRead( sal_Int32 nSecurityId) { if ( m_eStatusOfSecurityComponents != InitializationState::INITIALIZED ) @@ -62,10 +59,10 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar } sal_Int32 nIdOfSignatureElementCollector; - cssu::Reference< cssxc::sax::XReferenceResolvedListener > xReferenceResolvedListener; + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener; nIdOfSignatureElementCollector = - m_xSAXEventKeeper->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_BEFOREMODIFY, false); + m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false); m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); @@ -74,9 +71,9 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar */ xReferenceResolvedListener = new SignatureVerifierImpl; - cssu::Reference<cssl::XInitialization> xInitialization(xReferenceResolvedListener, cssu::UNO_QUERY); + css::uno::Reference<css::lang::XInitialization> xInitialization(xReferenceResolvedListener, css::uno::UNO_QUERY); - cssu::Sequence<cssu::Any> args(5); + css::uno::Sequence<css::uno::Any> args(5); args[0] <<= OUString::number(nSecurityId); args[1] <<= uno::Reference<xml::crypto::sax::XSecuritySAXEventKeeper>(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()), uno::UNO_QUERY); args[2] <<= OUString::number(nIdOfSignatureElementCollector); @@ -84,8 +81,8 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar args[4] <<= m_xXMLSignature; xInitialization->initialize(args); - cssu::Reference< cssxc::sax::XSignatureVerifyResultBroadcaster > - signatureVerifyResultBroadcaster(xReferenceResolvedListener, cssu::UNO_QUERY); + css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultBroadcaster > + signatureVerifyResultBroadcaster(xReferenceResolvedListener, css::uno::UNO_QUERY); signatureVerifyResultBroadcaster->addSignatureVerifyResultListener( this ); @@ -93,7 +90,7 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar nIdOfSignatureElementCollector, xReferenceResolvedListener); - cssu::Reference<cssxc::sax::XKeyCollector> keyCollector (xReferenceResolvedListener, cssu::UNO_QUERY); + css::uno::Reference<css::xml::crypto::sax::XKeyCollector> keyCollector (xReferenceResolvedListener, css::uno::UNO_QUERY); keyCollector->setKeyId(0); return xReferenceResolvedListener; @@ -101,7 +98,7 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar void XSecController::addSignature() { - cssu::Reference< cssxc::sax::XReferenceResolvedListener > xReferenceResolvedListener; + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener; sal_Int32 nSignatureId = 0; @@ -148,6 +145,25 @@ void XSecController::switchGpgSignature() #endif } +bool XSecController::haveReferenceForId(OUString const& rId) const +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::haveReferenceForId: no signature"); + return false; + } + InternalSignatureInformation const& rIsi(m_vInternalSignatureInformations.back()); + for (SignatureReferenceInformation const& rSri : rIsi.signatureInfor.vSignatureReferenceInfors) + { + if (rSri.nType == SignatureReferenceType::SAMEDOCUMENT + && rSri.ouURI == rId) // ouUri has # stripped + { + return true; + } + } + return false; +} + void XSecController::addReference( const OUString& ouUri, sal_Int32 nDigestID, const OUString& ouType ) { if (m_vInternalSignatureInformations.empty()) @@ -178,13 +194,13 @@ void XSecController::addStreamReference( /* * get the input stream */ - cssu::Reference< css::io::XInputStream > xObjectInputStream + css::uno::Reference< css::io::XInputStream > xObjectInputStream = getObjectInputStream( ouUri ); if ( xObjectInputStream.is() ) { - cssu::Reference<cssxc::XUriBinding> xUriBinding - (isi.xReferenceResolvedListener, cssu::UNO_QUERY); + css::uno::Reference<css::xml::crypto::XUriBinding> xUriBinding + (isi.xReferenceResolvedListener, css::uno::UNO_QUERY); xUriBinding->setUriBinding(ouUri, xObjectInputStream); } } @@ -220,13 +236,15 @@ void XSecController::setReferenceCount() const } } - cssu::Reference<cssxc::sax::XReferenceCollector> xReferenceCollector - (isi.xReferenceResolvedListener, cssu::UNO_QUERY); + css::uno::Reference<css::xml::crypto::sax::XReferenceCollector> xReferenceCollector + (isi.xReferenceResolvedListener, css::uno::UNO_QUERY); xReferenceCollector->setReferenceCount( referenceCount ); } } -void XSecController::setX509IssuerName( OUString const & ouX509IssuerName ) +void XSecController::setX509Data( + std::vector<std::pair<OUString, OUString>> & rX509IssuerSerials, + std::vector<OUString> const& rX509Certificates) { if (m_vInternalSignatureInformations.empty()) { @@ -234,29 +252,52 @@ void XSecController::setX509IssuerName( OUString const & ouX509IssuerName ) return; } InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); - isi.signatureInfor.ouX509IssuerName = ouX509IssuerName; -} - -void XSecController::setX509SerialNumber( OUString const & ouX509SerialNumber ) -{ - if (m_vInternalSignatureInformations.empty()) + SignatureInformation::X509Data data; + // due to the excessive flexibility of the spec it's possible that there + // is both a reference to a cert and the cert itself in one X509Data + for (OUString const& it : rX509Certificates) { - SAL_INFO("xmlsecurity.helper","XSecController::setX509SerialNumber: no signature"); - return; + try + { + data.emplace_back(); + data.back().X509Certificate = it; + uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv(m_xSecurityContext->getSecurityEnvironment()); + uno::Reference<security::XCertificate> const xCert(xSecEnv->createCertificateFromAscii(it)); + if (!xCert.is()) + { + SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); + continue; // will be handled in CheckX509Data + } + OUString const issuerName(xCert->getIssuerName()); + OUString const serialNumber(xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber())); + auto const iter = std::find_if(rX509IssuerSerials.begin(), rX509IssuerSerials.end(), + [&](auto const& rX509IssuerSerial) { + return xmlsecurity::EqualDistinguishedNames(issuerName, rX509IssuerSerial.first) + && serialNumber == rX509IssuerSerial.second; + }); + if (iter != rX509IssuerSerials.end()) + { + data.back().X509IssuerName = iter->first; + data.back().X509SerialNumber = iter->second; + rX509IssuerSerials.erase(iter); + } + } + catch (uno::Exception const&) + { + SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); + } } - InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); - isi.signatureInfor.ouX509SerialNumber = ouX509SerialNumber; -} - -void XSecController::setX509Certificate( OUString const & ouX509Certificate ) -{ - if (m_vInternalSignatureInformations.empty()) + // now handle any that are left... + for (auto const& it : rX509IssuerSerials) { - SAL_INFO("xmlsecurity.helper","XSecController::setX509Certificate: no signature"); - return; + data.emplace_back(); + data.back().X509IssuerName = it.first; + data.back().X509SerialNumber = it.second; + } + if (!data.empty()) + { + isi.signatureInfor.X509Datas.push_back(data); } - InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); - isi.signatureInfor.ouX509Certificate = ouX509Certificate; } void XSecController::setSignatureValue( OUString const & ouSignatureValue ) @@ -322,7 +363,7 @@ void XSecController::setGpgOwner( OUString const & ouGpgOwner ) isi.signatureInfor.ouGpgOwner = ouGpgOwner; } -void XSecController::setDate( OUString const & ouDate ) +void XSecController::setDate(OUString const& rId, OUString const& ouDate) { if (m_vInternalSignatureInformations.empty()) { @@ -330,17 +371,31 @@ void XSecController::setDate( OUString const & ouDate ) return; } InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + // there may be multiple timestamps in a signature - check them for consistency + if (!isi.signatureInfor.ouDateTime.isEmpty() + && isi.signatureInfor.ouDateTime != ouDate) + { + isi.signatureInfor.hasInconsistentSigningTime = true; + } (void)utl::ISO8601parseDateTime( ouDate, isi.signatureInfor.stDateTime); isi.signatureInfor.ouDateTime = ouDate; + if (!rId.isEmpty()) + { + isi.signatureInfor.ouDateTimePropertyId = rId; + } } -void XSecController::setDescription(const OUString& rDescription) +void XSecController::setDescription(OUString const& rId, OUString const& rDescription) { if (m_vInternalSignatureInformations.empty()) return; InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); rInformation.signatureInfor.ouDescription = rDescription; + if (!rId.isEmpty()) + { + rInformation.signatureInfor.ouDescriptionPropertyId = rId; + } } void XSecController::setSignatureBytes(const uno::Sequence<sal_Int8>& rBytes) @@ -352,13 +407,67 @@ void XSecController::setSignatureBytes(const uno::Sequence<sal_Int8>& rBytes) rInformation.signatureInfor.aSignatureBytes = rBytes; } -void XSecController::setCertDigest(const OUString& rCertDigest) +void XSecController::setX509CertDigest( + OUString const& rCertDigest, sal_Int32 const /*TODO nReferenceDigestID*/, + OUString const& rX509IssuerName, OUString const& rX509SerialNumber) { if (m_vInternalSignatureInformations.empty()) return; InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); - rInformation.signatureInfor.ouCertDigest = rCertDigest; + for (auto & rData : rInformation.signatureInfor.X509Datas) + { + for (auto & it : rData) + { + if (xmlsecurity::EqualDistinguishedNames(it.X509IssuerName, rX509IssuerName) + && it.X509SerialNumber == rX509SerialNumber) + { + it.CertDigest = rCertDigest; + return; + } + } + } + // fall-back: read the actual certificates + for (auto & rData : rInformation.signatureInfor.X509Datas) + { + for (auto & it : rData) + { + if (!it.X509Certificate.isEmpty()) + { + try + { + uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv(m_xSecurityContext->getSecurityEnvironment()); + uno::Reference<security::XCertificate> const xCert(xSecEnv->createCertificateFromAscii(it.X509Certificate)); + if (!xCert.is()) + { + SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); + } + else if (xmlsecurity::EqualDistinguishedNames(xCert->getIssuerName(),rX509IssuerName) + && xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()) == rX509SerialNumber) + { + it.CertDigest = rCertDigest; + // note: testInsertCertificate_PEM_DOCX requires these! + it.X509SerialNumber = rX509SerialNumber; + it.X509IssuerName = rX509IssuerName; + return; + } + } + catch (uno::Exception const&) + { + SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); + } + } + } + } + if (!rInformation.signatureInfor.ouGpgCertificate.isEmpty()) + { + SAL_INFO_IF(rCertDigest != rInformation.signatureInfor.ouGpgKeyID, + "xmlsecurity.helper", "PGPKeyID vs CertDigest mismatch"); + } + else + { + SAL_INFO("xmlsecurity.helper", "cannot find X509Data for CertDigest"); + } } namespace { @@ -434,27 +543,6 @@ void XSecController::setId( OUString const & ouId ) isi.signatureInfor.ouSignatureId = ouId; } -void XSecController::setPropertyId( OUString const & ouPropertyId ) -{ - if (m_vInternalSignatureInformations.empty()) - { - SAL_INFO("xmlsecurity.helper","XSecController::setPropertyId: no signature"); - return; - } - InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); - - if (isi.signatureInfor.ouPropertyId.isEmpty()) - { - // <SignatureProperty> ID attribute is for the date. - isi.signatureInfor.ouPropertyId = ouPropertyId; - } - else - { - // <SignatureProperty> ID attribute is for the description. - isi.signatureInfor.ouDescriptionPropertyId = ouPropertyId; - } -} - /* public: for signature verify */ void XSecController::collectToVerify( const OUString& referenceId ) { @@ -466,7 +554,7 @@ void XSecController::collectToVerify( const OUString& referenceId ) */ { bool bJustChainingOn = false; - cssu::Reference< cssxs::XDocumentHandler > xHandler; + css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler; int i,j; int sigNum = m_vInternalSignatureInformations.size(); @@ -490,10 +578,10 @@ void XSecController::collectToVerify( const OUString& referenceId ) } sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector( - cssxc::sax::ElementMarkPriority_BEFOREMODIFY, false ); + css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false ); - cssu::Reference<cssxc::sax::XReferenceCollector> xReferenceCollector - ( isi.xReferenceResolvedListener, cssu::UNO_QUERY ); + css::uno::Reference<css::xml::crypto::sax::XReferenceCollector> xReferenceCollector + ( isi.xReferenceResolvedListener, css::uno::UNO_QUERY ); m_xSAXEventKeeper->setSecurityId(nKeeperId, isi.signatureInfor.nSecurityId); m_xSAXEventKeeper->addReferenceResolvedListener( nKeeperId, isi.xReferenceResolvedListener); @@ -507,7 +595,6 @@ void XSecController::collectToVerify( const OUString& referenceId ) if ( bJustChainingOn ) { - cssu::Reference< cssxs::XDocumentHandler > xSEKHandler(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()), cssu::UNO_QUERY); m_xSAXEventKeeper->setNextHandler(xHandler); } } @@ -521,13 +608,13 @@ void XSecController::addSignature( sal_Int32 nSignatureId ) m_bVerifyCurrentSignature = true; } -cssu::Reference< cssxs::XDocumentHandler > const & XSecController::createSignatureReader(XMLSignatureHelper& rXMLSignatureHelper, sal_Int32 nType) +css::uno::Reference< css::xml::sax::XDocumentHandler > const & XSecController::createSignatureReader(XMLSignatureHelper& rXMLSignatureHelper, sal_Int32 nType) { if (nType == embed::StorageFormats::OFOPXML) m_xSecParser = new OOXMLSecParser(rXMLSignatureHelper, this); else m_xSecParser = new XSecParser(rXMLSignatureHelper, this); - cssu::Reference< cssl::XInitialization > xInitialization(m_xSecParser, uno::UNO_QUERY); + css::uno::Reference< css::lang::XInitialization > xInitialization(m_xSecParser, uno::UNO_QUERY); setSAXChainConnector(xInitialization); diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx index 2a8ab3603de1..f339c1be480d 100644 --- a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx +++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx @@ -782,7 +782,7 @@ sal_Int32 SecurityEnvironment_MSCryptImpl::verifyCertificate( const uno::Reference< css::security::XCertificate >& aCert, const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts) { - sal_Int32 validity = 0; + sal_Int32 validity = css::security::CertificateValidity::INVALID; PCCERT_CHAIN_CONTEXT pChainContext = nullptr; PCCERT_CONTEXT pCertContext = nullptr; @@ -927,7 +927,7 @@ sal_Int32 SecurityEnvironment_MSCryptImpl::verifyCertificate( } else { - SAL_INFO("xmlsecurity.xmlsec", "CertGetCertificateChaine failed."); + SAL_INFO("xmlsecurity.xmlsec", "CertGetCertificateChain failed."); } } diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx index d44d093641c1..b5f779db3029 100644 --- a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx @@ -26,6 +26,7 @@ #include <cppuhelper/supportsservice.hxx> #include "x509certificate_mscryptimpl.hxx" #include <certificateextension_xmlsecimpl.hxx> +#include <biginteger.hxx> #include "sanextension_mscryptimpl.hxx" #include "oid.hxx" @@ -674,4 +675,50 @@ Sequence<OUString> SAL_CALL X509Certificate_MSCryptImpl::getSupportedServiceName return { OUString() }; } +namespace xmlsecurity { + +static bool EncodeDistinguishedName(OUString const& rName, CERT_NAME_BLOB & rBlob) +{ + LPCWSTR pszError; + if (!CertStrToNameW(X509_ASN_ENCODING, + reinterpret_cast<LPCWSTR>(rName.getStr()), CERT_X500_NAME_STR, + nullptr, nullptr, &rBlob.cbData, &pszError)) + { + SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << reinterpret_cast<char16_t const*>(pszError)); + return false; + } + rBlob.pbData = new BYTE[rBlob.cbData]; + if (!CertStrToNameW(X509_ASN_ENCODING, + reinterpret_cast<LPCWSTR>(rName.getStr()), CERT_X500_NAME_STR, + nullptr, rBlob.pbData, &rBlob.cbData, &pszError)) + { + SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << reinterpret_cast<char16_t const*>(pszError)); + return false; + } + return true; +} + +bool EqualDistinguishedNames( + OUString const& rName1, OUString const& rName2) +{ + CERT_NAME_BLOB blob1; + if (!EncodeDistinguishedName(rName1, blob1)) + { + return false; + } + CERT_NAME_BLOB blob2; + if (!EncodeDistinguishedName(rName2, blob2)) + { + delete[] blob1.pbData; + return false; + } + bool const ret(CertCompareCertificateName(X509_ASN_ENCODING, + &blob1, &blob2) == TRUE); + delete[] blob2.pbData; + delete[] blob1.pbData; + return ret; +} + +} // namespace xmlsecurity + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx index dfa9c4ad494b..a3a04b5c1241 100644 --- a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx +++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx @@ -18,6 +18,7 @@ */ #include <sal/config.h> +#include <sal/log.hxx> #include <rtl/uuid.h> #include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp> @@ -228,6 +229,10 @@ SAL_CALL XMLSignature_MSCryptImpl::validate( // We do certificate verification ourselves. pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS; + // limit possible key data to valid X509 certificates only, no KeyValues + if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecMSCngKeyDataX509GetKlass()) < 0) + throw RuntimeException("failed to limit allowed key data"); + //Verify signature //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0) //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if @@ -250,6 +255,7 @@ SAL_CALL XMLSignature_MSCryptImpl::validate( ++nReferenceGood; } } + SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify status " << pDsigCtx->status << ", references good " << nReferenceGood << " of " << nReferenceCount); if (rs == 0 && nReferenceCount == nReferenceGood) { diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx index 180ef6558d38..cfa4ed65a049 100644 --- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx +++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx @@ -32,6 +32,7 @@ #include <rtl/ref.hxx> #include "x509certificate_nssimpl.hxx" +#include <biginteger.hxx> #include <certificateextension_xmlsecimpl.hxx> #include "sanextension_nssimpl.hxx" @@ -534,4 +535,28 @@ sal_Bool SAL_CALL X509Certificate_NssImpl::supportsService(const OUString& servi /* XServiceInfo */ Sequence<OUString> SAL_CALL X509Certificate_NssImpl::getSupportedServiceNames() { return { OUString() }; } +namespace xmlsecurity { + +bool EqualDistinguishedNames( + OUString const& rName1, OUString const& rName2) +{ + CERTName *const pName1(CERT_AsciiToName(OUStringToOString(rName1, RTL_TEXTENCODING_UTF8).getStr())); + if (pName1 == nullptr) + { + return false; + } + CERTName *const pName2(CERT_AsciiToName(OUStringToOString(rName2, RTL_TEXTENCODING_UTF8).getStr())); + if (pName2 == nullptr) + { + CERT_DestroyName(pName1); + return false; + } + bool const ret(CERT_CompareName(pName1, pName2) == SECEqual); + CERT_DestroyName(pName2); + CERT_DestroyName(pName1); + return ret; +} + +} // namespace xmlsecurity + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx index 311ce6aeb69f..1108d8fd8661 100644 --- a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx +++ b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx @@ -28,6 +28,9 @@ #include "securityenvironment_nssimpl.hxx" #include <xmlsec-wrapper.h> + +#include <sal/log.hxx> + #include <com/sun/star/xml/crypto/XXMLSignature.hpp> #include <memory> @@ -244,6 +247,10 @@ SAL_CALL XMLSignature_NssImpl::validate( // We do certificate verification ourselves. pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS; + // limit possible key data to valid X509 certificates only, no KeyValues + if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecNssKeyDataX509GetKlass()) < 0) + throw RuntimeException("failed to limit allowed key data"); + //Verify signature int rs = xmlSecDSigCtxVerify( pDsigCtx.get() , pNode ); @@ -260,6 +267,7 @@ SAL_CALL XMLSignature_NssImpl::validate( ++nReferenceGood; } } + SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify status " << pDsigCtx->status << ", references good " << nReferenceGood << " of " << nReferenceCount); if (rs == 0 && pDsigCtx->status == xmlSecDSigStatusSucceeded && nReferenceCount == nReferenceGood) { |