linuxdeployqt icon indicating copy to clipboard operation
linuxdeployqt copied to clipboard

AppImage built with lnuxdeployqt can't get work SSL connection

Open u2fly opened this issue 1 year ago • 9 comments

LeoCAD uses linuxdeployqt for AppImage builds, but resulted AppImages can't work with SSL:

  • YAML: https://github.com/leozide/leocad/blob/5772688318f8b7df41c2b8ae5b5659f8c4b2c1e5/appveyor.yml#L88
  • Builds: https://github.com/leozide/leocad/releases/tag/continuous

Error output when trying to connect:

$ ./LeoCAD-Linux-8eec5756-x86_64.AppImage
qt.network.ssl: QSslSocket: cannot resolve EVP_PKEY_base_id
qt.network.ssl: QSslSocket: cannot resolve SSL_get_peer_certificate
qt.network.ssl: QSslSocket: cannot call unresolved function SSL_get_peer_certificate

How to solve it in YAML?

Note: there was the same issue described for other AppImages built with linuxdeploy/linuxdeploy:

  • https://discourse.appimage.org/t/app-diverting-to-host-oss-openssl-libraries-in-runtime/2701

u2fly avatar Oct 14 '24 15:10 u2fly

Thanks for reporting this @app4soft. We need some OpenSSL and/or Qt experts to explain what is going on and how to fix this. I don't know the answer unfortunately.

probonopd avatar Oct 14 '24 22:10 probonopd

Related OpenSSL issue:

  • https://github.com/openssl/openssl/issues/7481

@probonopd, is there a way to setup AppImage build to not bundle any connection related libs at all and set AppImage to use all the connection related libs from the system? (not only SSL).

I mean, is there a way to exclude Qt 6 networking module from AppImage and set it to use libQt6Network.so.6 from the system? (and how to do that with YAML build script)

Same way as AppImage already did for the core Linux libs, which are not included, but used from the system.

u2fly avatar Oct 15 '24 04:10 u2fly

I think that would crash badly as soon as the target system has even a slightly different Qt version installed locally than what is in the bundle.

probonopd avatar Oct 18 '24 18:10 probonopd

Here is a solution used in FreeCAD's AppImage:

  • https://github.com/FreeCAD/FreeCAD-Bundle/commit/9db09e470163bfc7e36d4a1f00da6c54fe5ef483

AppRun entry code:

...
# SSL
# https://forum.freecadweb.org/viewtopic.php?f=4&t=34873&start=20#p327416
export SSL_CERT_FILE=$PREFIX/ssl/cacert.pem
# https://github.com/FreeCAD/FreeCAD-AppImage/pull/20
export GIT_SSL_CAINFO=$HERE/usr/ssl/cacert.pem
...

I tried it with LeoCAD's AppImages, but it does not solves the issue:

$ export SSL_CERT_FILE=$PREFIX/ssl/cacert.pem
$ ~/AppImages/LeoCAD*.AppImage
qt.network.ssl: QSslSocket: cannot resolve EVP_PKEY_base_id
qt.network.ssl: QSslSocket: cannot resolve SSL_get_peer_certificate
qt.network.ssl: QSslSocket: cannot call unresolved function SSL_get_peer_certificate

Is it due to SSL_CERT_FILE is a custom FreeCAD's variable?

If so, how to workaround this solution and make it universal for Qt5/Qt6 apps AppImages?

REFERENCE

  • https://stackoverflow.com/questions/14681012/how-to-include-openssl-in-a-qt-project
    • https://stackoverflow.com/a/22103277

From George at "Unable to use AES files of OpenSSL in Qt Creator": https://stackoverflow.com/questions/22093148/unable-to-use-aes-files-of-openssl-in-qt-creator

If this is on Linux, add the following into your .pro file:

PKGCONFIG += openssl

It will handle all necessary header paths, compile-linker options and the libraries.

And make sure you have the openssl-devel package installed in your system.

  • https://doc.qt.io/qt-6/ssl.html#enabling-and-disabling-ssl-support-when-building-qt-from-source

When building a version of Qt linked against OpenSSL, Qt's build system will use CMake's FindOpenSSL command to find OpenSSL in several standard locations. You can set the CMake variable OPENSSL_ROOT_DIR to force a specific location.

For example:

configure -openssl-linked -- -D OPENSSL_ROOT_DIR=<openssl_dir>

To disable SSL support in a Qt build, configure Qt with the -no-openssl option.

u2fly avatar Oct 18 '24 23:10 u2fly

I have the same issue before. I found linuxdeployqt does not bundle ssl plugin for some reason. So I have to add -extra-plugins=tls to fix this issue, and also add the environment variables to AppRun for some Linux distributions compatibility:

this_dir="\$(readlink -f "\$(dirname "\$0")")"
export XDG_DATA_DIRS="\${this_dir}/usr/share:\${XDG_DATA_DIRS}:/usr/share:/usr/local/share"
export QT_QPA_PLATFORMTHEME=gtk3
unset QT_STYLE_OVERRIDE

# Force set openssl config directory to an invalid directory to fallback to use default openssl config.
# This can avoid some distributions (mainly Fedora) having some strange patches or configurations
# for openssl that make the libssl in Appimage bundle unavailable.
export OPENSSL_CONF="\${this_dir}"

# Find the system certificates location
# https://gitlab.com/probono/platformissues/blob/master/README.md#certificates
possible_locations=(
  "/etc/ssl/certs/ca-certificates.crt"                # Debian/Ubuntu/Gentoo etc.
  "/etc/pki/tls/certs/ca-bundle.crt"                  # Fedora/RHEL
  "/etc/ssl/ca-bundle.pem"                            # OpenSUSE
  "/etc/pki/tls/cacert.pem"                           # OpenELEC
  "/etc/ssl/certs"                                    # SLES10/SLES11, https://golang.org/issue/12139
  "/usr/share/ca-certs/.prebuilt-store/"              # Clear Linux OS; https://github.com/knapsu/plex-media-player-appimage/issues/17#issuecomment-437710032
  "/system/etc/security/cacerts"                      # Android
  "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" # CentOS/RHEL 7
  "/etc/ssl/cert.pem"                                 # Alpine Linux
)

for location in "\${possible_locations[@]}"; do
  if [ -r "\${location}" ]; then
    export SSL_CERT_FILE="\${location}"
    break
  fi
done

Full script can be found: https://github.com/c0re100/qBittorrent-Enhanced-Edition/blob/v5_0_x/.github/workflows/build_appimage.sh#L343

abcfy2 avatar Oct 30 '24 02:10 abcfy2

Full script can be found:

@abcfy2, Thanks.

Could you point me how/where to insert your solution into LeoCAD's YAML?

  • https://github.com/leozide/leocad/blob/master/appveyor.yml

u2fly avatar Oct 30 '24 09:10 u2fly

@app4soft Try to modify these lines: https://github.com/leozide/leocad/blob/bf3f1d5db8ae0eecf194ac5178a5a12db5d3808b/appveyor.yml#L92-L95

before:

      - ./linuxdeployqt*.AppImage ./AppDir/usr/share/applications/*.desktop -bundle-non-qt-libs
      - ./linuxdeployqt*.AppImage --appimage-extract
      - export PATH=$(readlink -f ./squashfs-root/usr/bin/):$PATH
      - ./squashfs-root/usr/bin/appimagetool AppDir/

after:

      - |
        cat > AppDir/AppRun <<EOF
        #!/bin/bash -e

        this_dir="\$(readlink -f "\$(dirname "\$0")")"
        export XDG_DATA_DIRS="\${this_dir}/usr/share:\${XDG_DATA_DIRS}:/usr/share:/usr/local/share"
        export QT_QPA_PLATFORMTHEME=gtk3
        unset QT_STYLE_OVERRIDE

        # Find the system certificates location
        # https://gitlab.com/probono/platformissues/blob/master/README.md#certificates
        possible_locations=(
          "/etc/ssl/certs/ca-certificates.crt"                # Debian/Ubuntu/Gentoo etc.
          "/etc/pki/tls/certs/ca-bundle.crt"                  # Fedora/RHEL
          "/etc/ssl/ca-bundle.pem"                            # OpenSUSE
          "/etc/pki/tls/cacert.pem"                           # OpenELEC
          "/etc/ssl/certs"                                    # SLES10/SLES11, https://golang.org/issue/12139
          "/usr/share/ca-certs/.prebuilt-store/"              # Clear Linux OS; https://github.com/knapsu/plex-media-player-appimage/issues/17#issuecomment-437710032
          "/system/etc/security/cacerts"                      # Android
          "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" # CentOS/RHEL 7
          "/etc/ssl/cert.pem"                                 # Alpine Linux
        )

        for location in "\${possible_locations[@]}"; do
          if [ -r "\${location}" ]; then
            export SSL_CERT_FILE="\${location}"
            break
          fi
        done

        exec "\${this_dir}/usr/bin/leocad" "\$@"
        EOF
      - ./linuxdeployqt*.AppImage ./AppDir/usr/share/applications/*.desktop -appimage -always-overwrite -extra-plugins=tls -no-copy-copyright-files

Key points:

  • generate your own AppRun instead of default soft link to add some environment variables to make better compatibility
  • linuxdeployqt can generate AppImage directly, so just use -appimage is enough. The most important is append -extra-plugins=tls to bundle qt TLS plugin to support https

abcfy2 avatar Oct 31 '24 03:10 abcfy2

@abcfy2, Thanks.

u2fly avatar Nov 02 '24 11:11 u2fly

Here are a few missed considerations regarding the LeoCAD correction:

On Appveyor, LeoCAD is built on Qt5 - see export PATH=$HOME/Qt/5.15/gcc_64/bin:$PATH in the LeoCAD appveyor.yml. However...

The most important is append -extra-plugins=tls to bundle qt TLS plugin to support https

The TLS plugin was introduced in Qt 6.2 so using the -extra-plugins=tls argument will only solicit the message:

WARNING: The plugin "/usr/lib/x86_64-linux-gnu/qt5/plugins/tls" could not be found. Please check spelling and try again!

generate your own AppRun instead of default soft link to add some environment variables to make better compatibility

It is not necessary to remove the appveyor.yml lines suggested above. Simply copy your AppRun file to AppDir before running linuxdeployqt - it will be preserved. Here is the linuxdeployqt source code that creates the AppRun link - if a file does not already exist:

QFile appRun(appDirPath + "/AppRun");
if(appRun.exists()){
    qDebug() << "Keeping existing AppRun";
} else {
    if (!QFile::link(relativeBinPath, appDirPath + "/AppRun")) {
        LogError() << "Could not create AppRun link";
    }
}

In the end the only modification to the LeoCAD appveyor.yml is to copy your AppRun file to the AppDir folder before calling linuxdeployqt. The cat content will be the AppRun file.

- cp tools/setup/AppRun AppDir

Be careful about cutting and pasting. QT_QPA_PLATFORMTHEME=gtk3 and QT_STYLE_OVERRIDE has nothing to do with qt.network.ssl.

Cheers,

trevorsandy avatar Nov 10 '24 09:11 trevorsandy