Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package openfortivpn for openSUSE:Factory checked in at 2026-03-17 19:04:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openfortivpn (Old) and /work/SRC/openSUSE:Factory/.openfortivpn.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openfortivpn" Tue Mar 17 19:04:00 2026 rev:32 rq:1339418 version:1.24.1 Changes: -------- --- /work/SRC/openSUSE:Factory/openfortivpn/openfortivpn.changes 2025-02-19 15:59:47.123170403 +0100 +++ /work/SRC/openSUSE:Factory/.openfortivpn.new.8177/openfortivpn.changes 2026-03-17 19:05:41.223629436 +0100 @@ -1,0 +2,18 @@ +Mon Mar 16 15:00:59 UTC 2026 - Martin Hauke <[email protected]> + +- Update to version 1.24.1 + * fix regression where the plugin was not passed to pppd. +- Update to version 1.24.0 + * add OpenSSL 3.0+ PKCS#11 support using OSSL_STORE API. + * add OpenSSL Engine support (with OpenSSL < 3.0). + * update package links for distros in README. + * remove deprecated option --plugin. + * increase the maximum size of the proxy response. + * route: always remove wrong pppd route to self. + * fix several Coverity warnings. + * fix a memory leak in new ipv4_drop_wrong_route method. + * HTTP: fixes missing '\0' in debug. + * IO: fixes a RC use after free. + * SSL: Avoid leaking SSL context. + +------------------------------------------------------------------- Old: ---- openfortivpn-1.23.1.tar.gz New: ---- openfortivpn-1.24.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openfortivpn.spec ++++++ --- /var/tmp/diff_new_pack.aKUCJJ/_old 2026-03-17 19:05:41.747651152 +0100 +++ /var/tmp/diff_new_pack.aKUCJJ/_new 2026-03-17 19:05:41.747651152 +0100 @@ -1,7 +1,7 @@ # # spec file for package openfortivpn # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: openfortivpn -Version: 1.23.1 +Version: 1.24.1 Release: 0 Summary: Client for PPP+SSL VPN tunnel services License: GPL-3.0-or-later ++++++ openfortivpn-1.23.1.tar.gz -> openfortivpn-1.24.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/.github/workflows/codeql-analysis.yml new/openfortivpn-1.24.1/.github/workflows/codeql-analysis.yml --- old/openfortivpn-1.23.1/.github/workflows/codeql-analysis.yml 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/.github/workflows/codeql-analysis.yml 2026-01-11 13:11:14.000000000 +0100 @@ -33,11 +33,11 @@ steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 # Override language selection by uncommenting this and choosing your languages # with: # languages: go, javascript, csharp, python, cpp, java @@ -48,7 +48,7 @@ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below). - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@v4 # âšī¸ Command-line programs to run using the OS shell. # đ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -62,4 +62,4 @@ # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/.github/workflows/codespell.yml new/openfortivpn-1.24.1/.github/workflows/codespell.yml --- old/openfortivpn-1.23.1/.github/workflows/codespell.yml 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/.github/workflows/codespell.yml 2026-01-11 13:11:14.000000000 +0100 @@ -14,7 +14,7 @@ runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: codespell-project/actions-codespell@master with: skip: .git,checkpatch.pl,spelling.txt,LICENSE.OpenSSL diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/.github/workflows/coverity-scan.yml new/openfortivpn-1.24.1/.github/workflows/coverity-scan.yml --- old/openfortivpn-1.23.1/.github/workflows/coverity-scan.yml 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/.github/workflows/coverity-scan.yml 2026-01-11 13:11:14.000000000 +0100 @@ -12,7 +12,7 @@ steps: - name: Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Download the Coverity Scan Build Tool run: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/.github/workflows/openfortivpn.yml new/openfortivpn-1.24.1/.github/workflows/openfortivpn.yml --- old/openfortivpn-1.23.1/.github/workflows/openfortivpn.yml 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/.github/workflows/openfortivpn.yml 2026-01-11 13:11:14.000000000 +0100 @@ -18,7 +18,7 @@ steps: - name: Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Install Dependencies run: sudo apt-get install -y astyle @@ -41,7 +41,7 @@ steps: - name: Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Install Dependencies run: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/CHANGELOG.md new/openfortivpn-1.24.1/CHANGELOG.md --- old/openfortivpn-1.23.1/CHANGELOG.md 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/CHANGELOG.md 2026-01-11 13:11:14.000000000 +0100 @@ -14,16 +14,34 @@ This high level changelog is usually updated when a release is tagged. On the master branch there may be changes that are not (yet) described here. +### 1.24.1 + +* [-] fix regression where the `plugin` was not passed to pppd + +### 1.24.0 + +* [+] add OpenSSL 3.0+ PKCS#11 support using OSSL_STORE API +* [+] add OpenSSL Engine support (with OpenSSL < 3.0) +* [+] update package links for distros in README +* [~] remove deprecated option `--plugin` +* [~] increase the maximum size of the proxy response +* [~] route: always remove wrong pppd route to self +* [-] fix several Coverity warnings +* [-] fix a memory leak in new ipv4_drop_wrong_route method +* [-] HTTP: fixes missing '\0' in debug +* [-] IO: fixes a RC use after free +* [-] SSL: Avoid leaking SSL context + ### 1.23.1 * [-] fix a few coverity warnings ### 1.23.0 -* [-] Support older mac0S versions that lack vdprintf() -* [-] Patch certificate login error for FortiOS 7.4.4 -* [-] Clear OTP after run -* [+] Support SAML login authentication +* [-] support older mac0S versions that lack vdprintf() +* [-] patch certificate login error for FortiOS 7.4.4 +* [-] clear OTP after run +* [+] support SAML login authentication ### 1.22.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/README.md new/openfortivpn-1.24.1/README.md --- old/openfortivpn-1.23.1/README.md 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/README.md 2026-01-11 13:11:14.000000000 +0100 @@ -76,6 +76,11 @@ Check [#464](https://github.com/adrienverge/openfortivpn/issues/464) for a discussion of known issues in this area. +Building on Fedora since [this +update](https://src.fedoraproject.org/rpms/openssl/c/13b583a535e62d12521cfeb5088a68e5811eb6e6?branch=rawhide) +will NOT include engine support unless `openssl-devel-engine` is installed. Try +first to use `pkcs11-provider` on OpenSSL >= 3.0. + To make use of your smartcard put at least `pkcs11:` to the user-cert config or commandline option. It takes the full or a partial PKCS#11 token URI. @@ -105,11 +110,11 @@ * [Fedora / CentOS](https://packages.fedoraproject.org/pkgs/openfortivpn) * [openSUSE / SLE](https://software.opensuse.org/package/openfortivpn) * [Gentoo](https://packages.gentoo.org/packages/net-vpn/openfortivpn) -* [NixOS](https://github.com/NixOS/nixpkgs/tree/master/pkgs/tools/networking/openfortivpn) +* [NixOS](https://github.com/NixOS/nixpkgs/tree/master/pkgs/by-name/op/openfortivpn) * [Arch Linux](https://archlinux.org/packages/extra/x86_64/openfortivpn) * [Debian](https://packages.debian.org/stable/openfortivpn) * [Ubuntu](https://packages.ubuntu.com/search?keywords=openfortivpn) -* [Solus](https://dev.getsol.us/source/openfortivpn/) +* [Solus](https://github.com/getsolus/packages/tree/main/packages/o/openfortivpn) * [Alpine Linux](https://pkgs.alpinelinux.org/package/edge/testing/x86_64/openfortivpn) On macOS both [Homebrew](https://formulae.brew.sh/formula/openfortivpn) and diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/configure.ac new/openfortivpn-1.24.1/configure.ac --- old/openfortivpn-1.23.1/configure.ac 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/configure.ac 2026-01-11 13:11:14.000000000 +0100 @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.63]) -AC_INIT([openfortivpn], [1.23.1]) +AC_INIT([openfortivpn], [1.24.1]) AC_CONFIG_SRCDIR([src/main.c]) AM_INIT_AUTOMAKE([foreign subdir-objects]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/src/http.c new/openfortivpn-1.24.1/src/http.c --- old/openfortivpn-1.23.1/src/http.c 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/src/http.c 2026-01-11 13:11:14.000000000 +0100 @@ -178,6 +178,7 @@ return ERR_HTTP_TLS; } bytes_read += n; + buffer[bytes_read] = '\0'; log_debug_details("%s:\n%s\n", __func__, buffer); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/src/io.c new/openfortivpn-1.24.1/src/io.c --- old/openfortivpn-1.23.1/src/io.c 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/src/io.c 2026-01-11 13:11:14.000000000 +0100 @@ -36,7 +36,9 @@ #include <arpa/inet.h> #include <netinet/tcp.h> +#include <assert.h> #include <errno.h> +#include <limits.h> #include <signal.h> #include <string.h> @@ -126,6 +128,10 @@ * Warning: for performance reasons, this function does not check if the packet * is already present in the list. If it is, there will be a loop in the list * and this will result in an unpredictable behavior. + * + * Warning: Once a packet is added with pool_push, consider it to be freed from + * your perspective! You don't know when it will be really released by the + * thread which pool_pop it in parallel. */ static void pool_push(struct ppp_packet_pool *pool, struct ppp_packet *new) { @@ -405,9 +411,10 @@ memcpy(buffer, header, 6 * sizeof(uint8_t)); - size = safe_ssl_read(tunnel->ssl_handle, &buffer[6], 256 - 6); + size = safe_ssl_read(tunnel->ssl_handle, &buffer[6], sizeof(buffer) - 6); if (size < 0) return; + assert(size <= INT_MAX - 6); size += 6; // Print hex dump @@ -487,7 +494,6 @@ log_debug("gateway ---> %s (%lu bytes)\n", PPP_DAEMON, packet->len); log_packet("gtw: ", packet->len, pkt_data(packet)); - pool_push(&tunnel->ssl_to_pty_pool, packet); if (tunnel->state == STATE_CONNECTING) { if (packet_is_ip_plus_dns(packet)) { @@ -513,6 +519,8 @@ SEM_POST(&sem_if_config); } } + + pool_push(&tunnel->ssl_to_pty_pool, packet); } // Send message to main thread to stop other threads diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/src/ipv4.c new/openfortivpn-1.24.1/src/ipv4.c --- old/openfortivpn-1.23.1/src/ipv4.c 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/src/ipv4.c 2026-01-11 13:11:14.000000000 +0100 @@ -26,14 +26,16 @@ #include <fcntl.h> #include <sys/ioctl.h> #include <sys/stat.h> +#include <sys/types.h> +#include <assert.h> #include <errno.h> #include <limits.h> +#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> -#include <assert.h> #define IPV4_GET_ROUTE_BUFFER_CHUNK_SIZE 65536 #define SHOW_ROUTE_BUFFER_SIZE 128 @@ -161,10 +163,11 @@ route_mask(route).s_addr = inet_addr("0.0.0.0"); route_gtw(route).s_addr = inet_addr("0.0.0.0"); + size_t total_bytes_read = 0; #if HAVE_PROC_NET_ROUTE /* this is not present on Mac OS X and FreeBSD */ int fd; - uint32_t total_bytes_read = 0; + ssize_t bytes_read; // Cannot stat, mmap not lseek this special /proc file fd = open("/proc/net/route", O_RDONLY); @@ -173,13 +176,14 @@ goto end; } - int bytes_read; - while ((bytes_read = read(fd, buffer + total_bytes_read, buffer_size - total_bytes_read - 1)) > 0) { + assert(buffer_size - total_bytes_read > bytes_read); total_bytes_read += bytes_read; if ((buffer_size - total_bytes_read) < 1) { + assert(SIZE_MAX - buffer_size + >= IPV4_GET_ROUTE_BUFFER_CHUNK_SIZE); buffer_size += IPV4_GET_ROUTE_BUFFER_CHUNK_SIZE; realloc_buffer = realloc(buffer, buffer_size); @@ -206,7 +210,6 @@ #else FILE *fp; - uint32_t total_bytes_read = 0; char *saveptr3 = NULL; int have_ref = 0; @@ -230,11 +233,14 @@ line = buffer; // Read the output a line at a time while (fgets(line, buffer_size - total_bytes_read - 1, fp) != NULL) { - uint32_t bytes_read = strlen(line); + size_t bytes_read = strlen(line); + assert(SIZE_MAX - total_bytes_read >= bytes_read); total_bytes_read += bytes_read; if (bytes_read > 0 && line[bytes_read - 1] != '\n') { + assert(SIZE_MAX - buffer_size + >= IPV4_GET_ROUTE_BUFFER_CHUNK_SIZE); buffer_size += IPV4_GET_ROUTE_BUFFER_CHUNK_SIZE; realloc_buffer = realloc(buffer, buffer_size); @@ -726,6 +732,47 @@ return 0; } +/* + * This is a workaround for wrongly configured pppd with ip-accept-remote + * If the FortiGate is configured to send its own external address + * pppd will create a route to self for it, killing everything ... + * So this method tests this and drops the wrongly configured route. + * And no more silently to help troubleshooting! + */ +int ipv4_drop_wrong_route(struct tunnel *tunnel) +{ + struct rtentry *gtw_rt = &tunnel->ipv4.gtw_rt; + int ret; + + route_init(gtw_rt); + // Set up a route to the tunnel gateway + route_dest(gtw_rt).s_addr = tunnel->config->gateway_ip.s_addr; + route_mask(gtw_rt).s_addr = inet_addr("255.255.255.255"); + route_iface(gtw_rt) = malloc(strlen(tunnel->ppp_iface) + 2); + if (!route_iface(gtw_rt)) { + log_error("malloc: %s\n", strerror(errno)); + return ERR_IPV4_SEE_ERRNO; + } + sprintf(route_iface(gtw_rt), "%s", tunnel->ppp_iface); + ret = ipv4_get_route(gtw_rt); + /* The route is not here, all is fine */ + if (ret == ERR_IPV4_NO_SUCH_ROUTE) { + ret = 0; + goto cleanandout; + } + + if ((ret == 0) + && (route_dest(gtw_rt).s_addr == tunnel->config->gateway_ip.s_addr) + && (route_mask(gtw_rt).s_addr == inet_addr("255.255.255.255"))) { + log_warn("Removing wrong route to vpn server...\n"); + log_debug("ip route show %s\n", ipv4_show_route(gtw_rt)); + ret = ipv4_del_route(gtw_rt); + } +cleanandout: + route_destroy(gtw_rt); + return ret; +} + int ipv4_protect_tunnel_route(struct tunnel *tunnel) { struct rtentry *gtw_rt = &tunnel->ipv4.gtw_rt; @@ -761,15 +808,6 @@ log_error("malloc: %s\n", strerror(errno)); return ERR_IPV4_SEE_ERRNO; } - sprintf(route_iface(gtw_rt), "%s", tunnel->ppp_iface); - ret = ipv4_get_route(gtw_rt); - if ((ret == 0) - && (route_dest(gtw_rt).s_addr == tunnel->config->gateway_ip.s_addr) - && (route_mask(gtw_rt).s_addr == inet_addr("255.255.255.255"))) { - log_debug("Removing wrong route to vpn server...\n"); - log_debug("ip route show %s\n", ipv4_show_route(gtw_rt)); - ipv4_del_route(gtw_rt); - } sprintf(route_iface(gtw_rt), "!%s", tunnel->ppp_iface); ret = ipv4_get_route(gtw_rt); if (ret != 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/src/ipv4.h new/openfortivpn-1.24.1/src/ipv4.h --- old/openfortivpn-1.23.1/src/ipv4.h 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/src/ipv4.h 2026-01-11 13:11:14.000000000 +0100 @@ -85,6 +85,7 @@ struct tunnel; +int ipv4_drop_wrong_route(struct tunnel *tunnel); int ipv4_add_split_vpn_route(struct tunnel *tunnel, char *dest, char *mask, char *gateway); int ipv4_set_tunnel_routes(struct tunnel *tunnel); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/src/main.c new/openfortivpn-1.24.1/src/main.c --- old/openfortivpn-1.23.1/src/main.c 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/src/main.c 2026-01-11 13:11:14.000000000 +0100 @@ -289,7 +289,7 @@ {"username", required_argument, NULL, 'u'}, {"password", required_argument, NULL, 'p'}, {"cookie", required_argument, NULL, 0}, - {"cookie-on-stdin", no_argument, NULL, 0}, + {"cookie-on-stdin", no_argument, NULL, 0}, {"saml-login", optional_argument, NULL, 0}, {"otp", required_argument, NULL, 'o'}, {"otp-prompt", required_argument, NULL, 0}, @@ -322,7 +322,6 @@ {"pppd-ifname", required_argument, NULL, 0}, {"pppd-call", required_argument, NULL, 0}, {"pppd-accept-remote", optional_argument, NULL, 0}, - {"plugin", required_argument, NULL, 0}, // deprecated #endif #if HAVE_USR_SBIN_PPP {"ppp-system", required_argument, NULL, 0}, @@ -348,7 +347,7 @@ switch (c) { case 0: - /* If this option set a flag, do nothing else now. */ + /* If this option sets a flag, do nothing else now. */ if (long_options[option_index].flag != 0) break; if (strcmp(long_options[option_index].name, @@ -418,16 +417,6 @@ } break; } - // --plugin is deprecated, use --pppd-plugin - if (cli_cfg.pppd_plugin == NULL && - strcmp(long_options[option_index].name, - "plugin") == 0) { - log_warn("Option --%s is deprecated, use --pppd-plugin\n", - long_options[option_index].name); - free(cli_cfg.pppd_plugin); - cli_cfg.pppd_plugin = strdup(optarg); - break; - } #endif #if HAVE_USR_SBIN_PPP if (strcmp(long_options[option_index].name, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/src/tunnel.c new/openfortivpn-1.24.1/src/tunnel.c --- old/openfortivpn-1.23.1/src/tunnel.c 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/src/tunnel.c 2026-01-11 13:11:14.000000000 +0100 @@ -32,9 +32,13 @@ #include "userinput.h" #include <openssl/err.h> +#if OPENSSL_VERSION_NUMBER < 0x30000000L #ifndef OPENSSL_NO_ENGINE #include <openssl/engine.h> -#endif +#endif // OPENSSL_NO_ENGINE +#else // OPENSSL_VERSION_NUMBER >= 0x30000000L +#include <openssl/store.h> +#endif // OPENSSL_VERSION_NUMBER #include <openssl/ui.h> #include <openssl/x509v3.h> #if HAVE_SYSTEMD @@ -109,6 +113,14 @@ { log_info("Interface %s is UP.\n", tunnel->ppp_iface); + { + /* Drop invalid route by pppd (or tun) in all cases. */ + int ret = ipv4_drop_wrong_route(tunnel); + + if (ret != 0) + log_warn("Issue occurs while checking for wrong route, continuing anyway.\n"); + } + if (tunnel->config->set_routes) { int ret; @@ -751,7 +763,7 @@ } if (env_proxy != NULL) { - char request[128]; + char request[4096]; // https://tools.ietf.org/html/rfc7231#section-4.3.6 sprintf(request, "CONNECT %s:%u HTTP/1.1\r\nHost: %s:%u\r\n\r\n", @@ -775,8 +787,8 @@ memset(&(request), 0, sizeof(request)); for (size_t j = 0; response == NULL; j++) { if (j >= ARRAY_SIZE(request) - 1) { - log_error("Proxy response is unexpectedly large and cannot fit in the %lu-bytes buffer.\n", - ARRAY_SIZE(request)); + log_error("Proxy response is unexpectedly large (%lu bytes) and cannot fit in the %lu-bytes buffer.\n", + j, ARRAY_SIZE(request)); goto err_proxy_response; } @@ -1092,6 +1104,7 @@ } #endif +#if OPENSSL_VERSION_NUMBER < 0x30000000L #ifndef OPENSSL_NO_ENGINE /* Use PKCS11 engine for PIV if user-cert config starts with pkcs11 URI: */ if (tunnel->config->use_engine > 0) { @@ -1153,7 +1166,101 @@ goto err_ssl_context; } } else { /* end PKCS11 engine */ -#endif +#endif // OPENSSL_NO_ENGINE +#else // OPENSSL_VERSION_NUMBER >= 0x30000000L + /* OpenSSL 3.0+ provider-based PKCS#11 support */ + if (tunnel->config->use_engine > 0) { + // Debug: Print the certificate path/URI being used + log_debug_details("Attempting to load certificate from: %s\n", + tunnel->config->user_cert); + + // Use OSSL_STORE to load certificate and private key from PKCS#11 + OSSL_STORE_CTX *store_ctx = OSSL_STORE_open(tunnel->config->user_cert, + NULL, NULL, NULL, NULL); + + if (!store_ctx) { + log_error("PKCS11 OSSL_STORE_open failed: %s\n", + ERR_error_string(ERR_peek_last_error(), NULL)); + goto err_ssl_context; + } + + X509 *cert = NULL; + EVP_PKEY *pkey = NULL; + OSSL_STORE_INFO *info; + + // Load all objects from the store + while ((info = OSSL_STORE_load(store_ctx)) != NULL) { + int type = OSSL_STORE_INFO_get_type(info); + + if (type == OSSL_STORE_INFO_CERT) { + if (!cert) { + cert = OSSL_STORE_INFO_get1_CERT(info); + log_debug_details("Loaded certificate from PKCS#11 store\n"); + } else { + // Second certificate - indicates multiple certs + log_error("PKCS11: Multiple certificates found in store. Please specify more specific URL parameters (e.g., ?id=... or ?label=...) to select the desired certificate.\n"); + OSSL_STORE_INFO_free(info); + goto err_ssl_context; + } + } else if (type == OSSL_STORE_INFO_PKEY) { + if (!pkey) { + pkey = OSSL_STORE_INFO_get1_PKEY(info); + log_debug_details("Loaded private key from PKCS#11 store\n"); + } else { + // Second private key - indicates multiple keys + log_error("PKCS11: Multiple private keys found in store. Please specify more specific URL parameters (e.g., ?id=... or ?label=...) to select the desired private key.\n"); + OSSL_STORE_INFO_free(info); + goto err_ssl_context; + } + } + + OSSL_STORE_INFO_free(info); + } + + OSSL_STORE_close(store_ctx); + + // Check if we successfully loaded both certificate and private key + if (!cert) { + log_error("PKCS11: Could not load certificate from store\n"); + EVP_PKEY_free(pkey); // Free pkey if it was loaded but cert failed + goto err_ssl_context; + } + if (!pkey) { + log_error("PKCS11: Could not load private key from store\n"); + X509_free(cert); // Free cert if it was loaded but pkey failed + goto err_ssl_context; + } + + // Use the loaded certificate and private key + if (!SSL_CTX_use_certificate(tunnel->ssl_context, cert)) { + log_error("PKCS11 SSL_CTX_use_certificate failed: %s\n", + ERR_error_string(ERR_peek_last_error(), NULL)); + X509_free(cert); + EVP_PKEY_free(pkey); + goto err_ssl_context; + } + + if (!SSL_CTX_use_PrivateKey(tunnel->ssl_context, pkey)) { + log_error("PKCS11 SSL_CTX_use_PrivateKey failed: %s\n", + ERR_error_string(ERR_peek_last_error(), NULL)); + X509_free(cert); + EVP_PKEY_free(pkey); + goto err_ssl_context; + } + + if (!SSL_CTX_check_private_key(tunnel->ssl_context)) { + log_error("PKCS11 SSL_CTX_check_private_key: %s\n", + ERR_error_string(ERR_peek_last_error(), NULL)); + X509_free(cert); + EVP_PKEY_free(pkey); + goto err_ssl_context; + } + + // Clean up + X509_free(cert); + EVP_PKEY_free(pkey); + } else { /* end PKCS11 engine */ +#endif // OPENSSL_VERSION_NUMBER >= 0x30000000L if (tunnel->config->user_cert) { if (!SSL_CTX_use_certificate_chain_file( tunnel->ssl_context, tunnel->config->user_cert)) { @@ -1180,9 +1287,7 @@ goto err_ssl_context; } } -#ifndef OPENSSL_NO_ENGINE } -#endif tunnel->ssl_handle = SSL_new(tunnel->ssl_context); if (tunnel->ssl_handle == NULL) { @@ -1352,6 +1457,7 @@ } else { auth_log_out(&tunnel); log_info("Logged out.\n"); + ssl_disconnect(&tunnel); } // explicitly free the buffer allocated for split routes of the ipv4 configuration diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openfortivpn-1.23.1/src/userinput.c new/openfortivpn-1.24.1/src/userinput.c --- old/openfortivpn-1.23.1/src/userinput.c 2025-02-13 10:20:00.000000000 +0100 +++ new/openfortivpn-1.24.1/src/userinput.c 2026-01-11 13:11:14.000000000 +0100 @@ -24,8 +24,10 @@ #include <sys/wait.h> #include <termios.h> +#include <assert.h> #include <ctype.h> #include <errno.h> +#include <limits.h> #include <stdarg.h> #include <stddef.h> #include <stdio.h> @@ -368,22 +370,19 @@ char *read_from_stdin(size_t count) { char *buf; - char *output; - int bytes_read; + ssize_t bytes_read; + assert(count < SIZE_MAX - 1); buf = malloc(count + 1); if (buf == NULL) return NULL; bytes_read = read(STDIN_FILENO, buf, count); - if (bytes_read == -1) { + if (bytes_read < 0) { free(buf); return NULL; } buf[bytes_read] = '\0'; - output = realloc(buf, bytes_read + 1); - - // Just keep using the larger buffer if realloc() fails. - return output ? output : buf; + return buf; }
