Removed unnecessary CA and certificate handlers

This removes certificate and CA handlers not used by the openconnect
client. This is a hardening measure to further reduce the attack surface
of the worker process.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
This commit is contained in:
Nikos Mavrogiannopoulos
2026-05-19 20:11:33 +02:00
parent 2dfb9acec5
commit e567f92e64
8 changed files with 8 additions and 278 deletions
+5
View File
@@ -14,6 +14,11 @@
body limit body limit
- Fix build issue on FreeBSD (#704) - Fix build issue on FreeBSD (#704)
- Build against Nettle 4. - Build against Nettle 4.
- Removed unnecessary for openconnect client handlers to reduce attack surface:
* /cert.pem
* /cert.cer
* /ca.pem
* /ca.cer
* Version 1.4.2 (released 2026-04-16) * Version 1.4.2 (released 2026-04-16)
-154
View File
@@ -90,160 +90,6 @@ static int send_data(worker_st *ws, unsigned int http_ver,
return 0; return 0;
} }
int get_cert_handler(worker_st *ws, unsigned int http_ver)
{
if (ws->conn_type != SOCK_TYPE_UNIX) { /* we have TLS */
const gnutls_datum_t *certs;
gnutls_datum_t out = { NULL, 0 };
int ret;
oclog(ws, LOG_DEBUG, "requested server certificate");
certs = gnutls_certificate_get_ours(ws->session);
if (certs == NULL) {
return -1;
}
ret = gnutls_pem_base64_encode_alloc("CERTIFICATE", &certs[0],
&out);
if (ret < 0)
return -1;
ret = send_data(ws, http_ver, "application/x-pem-file",
(char *)out.data, out.size);
gnutls_free(out.data);
return ret;
} else {
return -1;
}
}
int get_cert_der_handler(worker_st *ws, unsigned int http_ver)
{
if (ws->conn_type != SOCK_TYPE_UNIX) { /* we have TLS */
const gnutls_datum_t *certs;
oclog(ws, LOG_DEBUG, "requested raw server certificate");
certs = gnutls_certificate_get_ours(ws->session);
if (certs == NULL) {
return -1;
}
return send_data(ws, http_ver, "application/pkix-cert",
(char *)certs[0].data, certs[0].size);
} else {
return -1;
}
}
static int ca_handler(worker_st *ws, unsigned int http_ver, unsigned int der)
{
if (ws->conn_type != SOCK_TYPE_UNIX) { /* we have TLS */
const gnutls_datum_t *certs;
gnutls_datum_t out = { NULL, 0 }, tmpca;
unsigned int i;
int ret;
gnutls_x509_crt_t issuer = NULL, crt = NULL;
oclog(ws, LOG_DEBUG, "requested server CA");
certs = gnutls_certificate_get_ours(ws->session);
if (certs == NULL) {
oclog(ws, LOG_DEBUG, "could not obtain our cert");
return -1;
}
ret = gnutls_x509_crt_init(&crt);
if (ret < 0) {
oclog(ws, LOG_DEBUG, "could not initialize cert");
return -1;
}
ret = gnutls_x509_crt_import(crt, &certs[0],
GNUTLS_X509_FMT_DER);
if (ret < 0) {
ret = -1;
oclog(ws, LOG_DEBUG, "could not import our cert");
goto cleanup;
}
for (i = 0; i < 8; i++) {
ret = gnutls_certificate_get_crt_raw(WSCREDS(ws)->xcred,
i, 1, &tmpca);
if (ret < 0) {
goto cleanup;
}
ret = gnutls_x509_crt_init(&issuer);
if (ret < 0) {
ret = -1;
oclog(ws, LOG_DEBUG,
"could not initialize issuer cert");
goto cleanup;
}
ret = gnutls_x509_crt_import(issuer, &tmpca,
GNUTLS_X509_FMT_DER);
if (ret < 0) {
ret = -1;
oclog(ws, LOG_DEBUG,
"could not import issuer cert");
goto cleanup;
}
ret = gnutls_x509_crt_check_issuer(crt, issuer);
if (ret != 0) {
ret = gnutls_x509_crt_export2(
issuer,
der ? GNUTLS_X509_FMT_DER :
GNUTLS_X509_FMT_PEM,
&out);
if (ret < 0) {
ret = -1;
oclog(ws, LOG_DEBUG,
"could not export issuer of cert");
goto cleanup;
}
break;
}
gnutls_x509_crt_deinit(issuer);
issuer = NULL;
}
ret = send_data(ws, http_ver, "application/pkix-cert",
(char *)out.data, out.size);
cleanup:
if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
oclog(ws, LOG_DEBUG,
"could not get CA; does the server cert list contain the CA certificate?");
ret = -1;
}
if (crt)
gnutls_x509_crt_deinit(crt);
if (issuer)
gnutls_x509_crt_deinit(issuer);
gnutls_free(out.data);
return ret;
} else {
return -1;
}
}
int get_ca_handler(worker_st *ws, unsigned int http_ver)
{
return ca_handler(ws, http_ver, 0);
}
int get_ca_der_handler(worker_st *ws, unsigned int http_ver)
{
return ca_handler(ws, http_ver, 1);
}
#ifdef ANYCONNECT_CLIENT_COMPAT #ifdef ANYCONNECT_CLIENT_COMPAT
int get_config_handler(worker_st *ws, unsigned int http_ver) int get_config_handler(worker_st *ws, unsigned int http_ver)
{ {
-4
View File
@@ -61,10 +61,6 @@ static const struct known_urls_st known_urls[] = {
LL("/", get_auth_handler, post_auth_handler), LL("/", get_auth_handler, post_auth_handler),
LL("/auth", get_auth_handler, post_auth_handler), LL("/auth", get_auth_handler, post_auth_handler),
LL("/VPN", get_auth_handler, post_auth_handler), LL("/VPN", get_auth_handler, post_auth_handler),
LL("/cert.pem", get_cert_handler, NULL),
LL("/cert.cer", get_cert_der_handler, NULL),
LL("/ca.pem", get_ca_handler, NULL),
LL("/ca.cer", get_ca_der_handler, NULL),
#ifdef ANYCONNECT_CLIENT_COMPAT #ifdef ANYCONNECT_CLIENT_COMPAT
LL_DIR("/profiles", get_config_handler, NULL), LL_DIR("/profiles", get_config_handler, NULL),
LL("/VPNManifest.xml", get_string_handler, NULL), LL("/VPNManifest.xml", get_string_handler, NULL),
+1 -5
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013-2016 Nikos Mavrogiannopoulos * Copyright (C) 2013-2026 Nikos Mavrogiannopoulos
* *
* Author: Nikos Mavrogiannopoulos * Author: Nikos Mavrogiannopoulos
* *
@@ -348,10 +348,6 @@ int auth_user_deinit(worker_st *ws);
int get_auth_handler(worker_st *server, unsigned int http_ver); int get_auth_handler(worker_st *server, unsigned int http_ver);
int post_auth_handler(worker_st *server, unsigned int http_ver); int post_auth_handler(worker_st *server, unsigned int http_ver);
int post_kkdcp_handler(worker_st *server, unsigned int http_ver); int post_kkdcp_handler(worker_st *server, unsigned int http_ver);
int get_cert_handler(worker_st *ws, unsigned int http_ver);
int get_cert_der_handler(worker_st *ws, unsigned int http_ver);
int get_ca_handler(worker_st *ws, unsigned int http_ver);
int get_ca_der_handler(worker_st *ws, unsigned int http_ver);
int get_svc_handler(worker_st *ws, unsigned int http_ver); int get_svc_handler(worker_st *ws, unsigned int http_ver);
int post_svc_handler(worker_st *ws, unsigned int http_ver); int post_svc_handler(worker_st *ws, unsigned int http_ver);
+1 -1
View File
@@ -116,7 +116,7 @@ if have_cwrap
'test-pass', 'test-pass-cert', 'test-pass-cert-rfc822name', 'test-pass', 'test-pass-cert', 'test-pass-cert-rfc822name',
'test-cert', 'test-group-pass', 'test-pass-group-cert', 'test-cert', 'test-group-pass', 'test-pass-group-cert',
'test-pass-group-cert-no-pass', 'test-sighup', 'test-pass-group-cert-no-pass', 'test-sighup',
'test-enc-key', 'test-sighup-key-change', 'test-get-cert', 'test-enc-key', 'test-sighup-key-change',
'test-san-cert', 'test-pass-opt-cert', 'test-san-cert', 'test-pass-opt-cert',
'test-cert-opt-pass', 'test-cert-opt-pass',
'haproxy-auth', 'test-maintenance', 'resumption', 'haproxy-auth', 'test-maintenance', 'resumption',
+1 -1
View File
@@ -75,7 +75,7 @@ else
fi fi
echo "Checking with CURL that server returns HTTP 200 for user authenticated GET" echo "Checking with CURL that server returns HTTP 200 for user authenticated GET"
http_result=$(curl --insecure https://localhost:${PORT}/cert.pem --output /dev/null --cookie "${HTTP_COOKIE}" --silent --write-out "%{http_code}") http_result=$(curl --insecure https://localhost:${PORT}/svc --output /dev/null --cookie "${HTTP_COOKIE}" --silent --write-out "%{http_code}")
if [ "${http_result}" != "200" ]; then if [ "${http_result}" != "200" ]; then
fail ${PID} "Server returned ${http_result} instead of 200 for GET" fail ${PID} "Server returned ${http_result} instead of 200 for GET"
fi fi
-92
View File
@@ -1,92 +0,0 @@
#!/bin/sh
#
# Copyright (C) 2013 Nikos Mavrogiannopoulos
#
# This file is part of ocserv.
#
# ocserv is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# ocserv is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GnuTLS; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
SERV="${SERV:-../src/ocserv}"
srcdir=${srcdir:-.}
NO_NEED_ROOT=1
TMPFILE=getcert.$$.tmp
TMPFILE2=getcert2.$$.tmp
. `dirname $0`/common.sh
eval "${GETPORT}"
echo "Testing ocserv certificate GET handlers... "
update_config test-user-cert.config
launch_simple_sr_server -d 1 -f -c ${CONFIG}
PID=$!
wait_server $PID
echo -n "Connecting to GET PEM certificate... "
( LD_PRELOAD=libsocket_wrapper.so curl https://$ADDRESS:$PORT/cert.pem --insecure > $TMPFILE 2>/dev/null ) ||
fail $PID "Could not get certificate!"
cmp $TMPFILE "${srcdir}/certs/server-cert.pem"
if test $? != 0;then
fail $PID "failed, certs not match"
fi
echo "ok"
echo -n "Connecting to GET DER certificate... "
( LD_PRELOAD=libsocket_wrapper.so curl https://$ADDRESS:$PORT/cert.cer --insecure > $TMPFILE 2>/dev/null ) ||
fail $PID "Could not get DER certificate!"
certtool --inder -i <"$TMPFILE" >$TMPFILE2
certtool -i <"${srcdir}/certs/server-cert.pem" >$TMPFILE
cmp "$TMPFILE" "$TMPFILE2"
if test $? != 0;then
fail $PID "failed, certs not match"
fi
echo "ok"
echo -n "Connecting to GET CA PEM certificate... "
( LD_PRELOAD=libsocket_wrapper.so curl https://$ADDRESS:$PORT/ca.pem --insecure > $TMPFILE 2>/dev/null ) ||
fail $PID "Could not get certificate!"
cmp $TMPFILE "${srcdir}/certs/ca.pem"
if test $? != 0;then
fail $PID "failed, certs not match"
fi
echo "ok"
echo -n "Connecting to GET CA DER certificate... "
( LD_PRELOAD=libsocket_wrapper.so curl https://$ADDRESS:$PORT/ca.cer --insecure > $TMPFILE 2>/dev/null ) ||
fail $PID "Could not get DER certificate!"
certtool --inder -i <"$TMPFILE" >$TMPFILE2
certtool -i <"${srcdir}/certs/ca.pem" >$TMPFILE
cmp "$TMPFILE" "$TMPFILE2"
if test $? != 0;then
fail $PID "failed, certs not match"
fi
echo "ok"
cleanup
rm -f "$TMPFILE" "$TMPFILE2"
exit 0
-21
View File
@@ -111,27 +111,6 @@ results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PO
CheckHeaders "$results" CheckHeaders "$results"
echo "ok" echo "ok"
echo -n "Testing /cert.pem ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/cert.pem --insecure)
CheckHeaders "$results"
echo "ok"
echo -n "Testing /cert.cer ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/cert.cer --insecure)
CheckHeaders "$results"
echo "ok"
echo -n "Testing /ca.pem ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/ca.pem --insecure)
CheckHeaders "$results"
echo "ok"
echo -n "Testing /ca.cer ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/ca.cer --insecure)
CheckHeaders "$results"
echo "ok"
cleanup cleanup
exit 0 exit 0