diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8e6a1917..58659bd8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -23,7 +23,7 @@ EXTRA_DIST = certs/ca-key.pem certs/ca.pem common.sh certs/server-cert.pem \
certs/server-cert-ed25519.pem certs/server-key-ed25519.pem data/test-ed25519.config \
certs/server-cert-rsa-pss.pem certs/server-key-rsa-pss.pem data/test-rsa-pss.config \
data/test-otp-cert.config data/test-otp.oath test-otp-cert data/test-otp.passwd \
- data/test-otp.config data/test-cert-opt-pass.config
+ data/test-otp.config data/test-cert-opt-pass.config data/test-gssapi-opt-pass.config
SUBDIRS = docker-ocserv docker-kerberos
@@ -52,7 +52,8 @@ if HAVE_CWRAP
dist_check_SCRIPTS += test-pass test-pass-cert test-cert test-group-pass \
test-pass-group-cert test-pass-group-cert-no-pass test-sighup \
test-enc-key test-sighup-key-change test-get-cert test-san-cert \
- test-gssapi test-pass-opt-cert test-cert-opt-pass
+ test-gssapi test-pass-opt-cert test-cert-opt-pass test-gssapi-opt-pass \
+ test-gssapi-opt-cert
if HAVE_CWRAP_PAM
dist_check_SCRIPTS += test-pam test-pam-noauth
diff --git a/tests/data/test-gssapi-opt-cert.config b/tests/data/test-gssapi-opt-cert.config
new file mode 100644
index 00000000..ac165d75
--- /dev/null
+++ b/tests/data/test-gssapi-opt-cert.config
@@ -0,0 +1,189 @@
+# User authentication method. Could be set multiple times and in that case
+# all should succeed.
+# Options: certificate, pam.
+#auth = "certificate"
+#auth = "plain[./data/test1.passwd]"
+auth = "gssapi[require-local-user-map=false]"
+enable-auth = certificate
+
+# A banner to be displayed on clients
+#banner = "Welcome"
+
+# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
+#listen-host = [IP|HOSTNAME]
+
+use-dbus = no
+
+# Limit the number of clients. Unset or set to zero for unlimited.
+#max-clients = 1024
+max-clients = 16
+
+# Limit the number of client connections to one every X milliseconds
+# (X is the provided value). Set to zero for no limit.
+#rate-limit-ms = 100
+
+# Limit the number of identical clients (i.e., users connecting multiple times)
+# Unset or set to zero for unlimited.
+max-same-clients = 2
+
+# TCP and UDP port number
+tcp-port = 4438
+udp-port = 4438
+
+#listen-clear-file = ./ocserv-gssapi-conn.socket
+
+# Keepalive in seconds
+keepalive = 32400
+
+# Dead peer detection in seconds
+dpd = 440
+
+# MTU discovery (DPD must be enabled)
+try-mtu-discovery = false
+
+# The key and the certificates of the server
+# The key may be a file, or any URL supported by GnuTLS (e.g.,
+# tpmkey:uuid=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx;storage=user
+# or pkcs11:object=my-vpn-key;object-type=private)
+#
+# There may be multiple certificate and key pairs and each key
+# should correspond to the preceding certificate.
+server-cert = @SRCDIR@/certs/server-cert.pem
+server-key = @SRCDIR@/certs/server-key.pem
+
+# Diffie-Hellman parameters. Only needed if you require support
+# for the DHE ciphersuites (by default this server supports ECDHE).
+# Can be generated using:
+# certtool --generate-dh-params --outfile /path/to/dh.pem
+#dh-params = /path/to/dh.pem
+
+# If you have a certificate from a CA that provides an OCSP
+# service you may provide a fresh OCSP status response within
+# the TLS handshake. That will prevent the client from connecting
+# independently on the OCSP server.
+# You can update this response periodically using:
+# ocsptool --ask --load-cert=your_cert --load-issuer=your_ca --outfile response
+# Make sure that you replace the following file in an atomic way.
+#ocsp-response = /path/to/ocsp.der
+
+# In case PKCS #11 or TPM keys are used the PINs should be available
+# in files. The srk-pin-file is applicable to TPM keys only (It's the storage
+# root key).
+#pin-file = /path/to/pin.txt
+#srk-pin-file = /path/to/srkpin.txt
+
+# The Certificate Authority that will be used
+# to verify clients if certificate authentication
+# is set.
+ca-cert = @SRCDIR@/certs/ca.pem
+
+# The object identifier that will be used to read the user ID in the client certificate.
+# The object identifier should be part of the certificate's DN
+# Useful OIDs are:
+# CN = 2.5.4.3, UID = 0.9.2342.19200300.100.1.1
+cert-user-oid = 0.9.2342.19200300.100.1.1
+
+# The object identifier that will be used to read the user group in the client
+# certificate. The object identifier should be part of the certificate's DN
+# Useful OIDs are:
+# OU (organizational unit) = 2.5.4.11
+#cert-group-oid = 2.5.4.11
+
+# A revocation list of ca-cert is set
+#crl = /path/to/crl.pem
+
+# GnuTLS priority string
+tls-priorities = "PERFORMANCE:%SERVER_PRECEDENCE:%COMPAT"
+
+# To enforce perfect forward secrecy (PFS) on the main channel.
+#tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA"
+
+# The time (in seconds) that a client is allowed to stay connected prior
+# to authentication
+auth-timeout = 40
+
+# The time (in seconds) that a client is not allowed to reconnect after
+# a failed authentication attempt.
+#min-reauth-time = 2
+
+# Cookie validity time (in seconds)
+# Once a client is authenticated he's provided a cookie with
+# which he can reconnect. This option sets the maximum lifetime
+# of that cookie.
+cookie-validity = 172800
+
+# Script to call when a client connects and obtains an IP
+# Parameters are passed on the environment.
+# REASON, USERNAME, GROUPNAME, HOSTNAME (the hostname selected by client),
+# DEVICE, IP_REAL (the real IP of the client), IP_LOCAL (the local IP
+# in the P-t-P connection), IP_REMOTE (the VPN IP of the client). REASON
+# may be "connect" or "disconnect".
+#connect-script = /usr/bin/myscript
+#disconnect-script = /usr/bin/myscript
+
+# UTMP
+use-utmp = true
+
+# PID file
+pid-file = ./ocserv.pid
+
+# The default server directory. Does not require any devices present.
+#chroot-dir = /path/to/chroot
+
+# socket file used for IPC, will be appended with .PID
+# It must be accessible within the chroot environment (if any)
+socket-file = ./ocserv-gssapi-socket
+
+# The user the worker processes will be run as. It should be
+# unique (no other services run as this user).
+run-as-user = @USERNAME@
+run-as-group = @GROUP@
+#run-as-user = root
+#run-as-group = root
+
+# Network settings
+
+device = vpns
+
+# The default domain to be advertised
+default-domain = example.com
+
+ipv4-network = 192.168.1.0
+ipv4-netmask = 255.255.255.0
+# Use the keywork local to advertize the local P-t-P address as DNS server
+ipv4-dns = 192.168.1.1
+
+# The NBNS server (if any)
+#ipv4-nbns = 192.168.2.3
+
+#ipv6-address =
+#ipv6-mask =
+#ipv6-dns =
+
+# Prior to leasing any IP from the pool ping it to verify that
+# it is not in use by another (unrelated to this server) host.
+ping-leases = false
+
+# Leave empty to assign the default MTU of the device
+# mtu =
+
+route = 192.168.1.0/255.255.255.0
+#route = 192.168.5.0/255.255.255.0
+
+#
+# The following options are for (experimental) AnyConnect client
+# compatibility. They are only available if the server is built
+# with --enable-anyconnect
+#
+
+# Client profile xml. A sample file exists in doc/profile.xml.
+# This file must be accessible from inside the worker's chroot.
+# The profile is ignored by the openconnect client.
+#user-profile = profile.xml
+
+# Unless set to false it is required for clients to present their
+# certificate even if they are authenticating via a previously granted
+# cookie. Legacy CISCO clients do not do that, and thus this option
+# should be set for them.
+#always-require-cert = false
+
diff --git a/tests/data/test-gssapi-opt-pass.config b/tests/data/test-gssapi-opt-pass.config
new file mode 100644
index 00000000..637cad4d
--- /dev/null
+++ b/tests/data/test-gssapi-opt-pass.config
@@ -0,0 +1,189 @@
+# User authentication method. Could be set multiple times and in that case
+# all should succeed.
+# Options: certificate, pam.
+#auth = "certificate"
+#auth = "plain[./data/test1.passwd]"
+auth = "gssapi[require-local-user-map=false]"
+enable-auth = "plain[passwd=@SRCDIR@/data/test1.passwd]"
+
+# A banner to be displayed on clients
+#banner = "Welcome"
+
+# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
+#listen-host = [IP|HOSTNAME]
+
+use-dbus = no
+
+# Limit the number of clients. Unset or set to zero for unlimited.
+#max-clients = 1024
+max-clients = 16
+
+# Limit the number of client connections to one every X milliseconds
+# (X is the provided value). Set to zero for no limit.
+#rate-limit-ms = 100
+
+# Limit the number of identical clients (i.e., users connecting multiple times)
+# Unset or set to zero for unlimited.
+max-same-clients = 2
+
+# TCP and UDP port number
+tcp-port = 4439
+udp-port = 4439
+
+#listen-clear-file = ./ocserv-gssapi-conn.socket
+
+# Keepalive in seconds
+keepalive = 32400
+
+# Dead peer detection in seconds
+dpd = 440
+
+# MTU discovery (DPD must be enabled)
+try-mtu-discovery = false
+
+# The key and the certificates of the server
+# The key may be a file, or any URL supported by GnuTLS (e.g.,
+# tpmkey:uuid=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx;storage=user
+# or pkcs11:object=my-vpn-key;object-type=private)
+#
+# There may be multiple certificate and key pairs and each key
+# should correspond to the preceding certificate.
+server-cert = @SRCDIR@/certs/server-cert.pem
+server-key = @SRCDIR@/certs/server-key.pem
+
+# Diffie-Hellman parameters. Only needed if you require support
+# for the DHE ciphersuites (by default this server supports ECDHE).
+# Can be generated using:
+# certtool --generate-dh-params --outfile /path/to/dh.pem
+#dh-params = /path/to/dh.pem
+
+# If you have a certificate from a CA that provides an OCSP
+# service you may provide a fresh OCSP status response within
+# the TLS handshake. That will prevent the client from connecting
+# independently on the OCSP server.
+# You can update this response periodically using:
+# ocsptool --ask --load-cert=your_cert --load-issuer=your_ca --outfile response
+# Make sure that you replace the following file in an atomic way.
+#ocsp-response = /path/to/ocsp.der
+
+# In case PKCS #11 or TPM keys are used the PINs should be available
+# in files. The srk-pin-file is applicable to TPM keys only (It's the storage
+# root key).
+#pin-file = /path/to/pin.txt
+#srk-pin-file = /path/to/srkpin.txt
+
+# The Certificate Authority that will be used
+# to verify clients if certificate authentication
+# is set.
+#ca-cert = /path/to/ca.pem
+
+# The object identifier that will be used to read the user ID in the client certificate.
+# The object identifier should be part of the certificate's DN
+# Useful OIDs are:
+# CN = 2.5.4.3, UID = 0.9.2342.19200300.100.1.1
+#cert-user-oid = 0.9.2342.19200300.100.1.1
+
+# The object identifier that will be used to read the user group in the client
+# certificate. The object identifier should be part of the certificate's DN
+# Useful OIDs are:
+# OU (organizational unit) = 2.5.4.11
+#cert-group-oid = 2.5.4.11
+
+# A revocation list of ca-cert is set
+#crl = /path/to/crl.pem
+
+# GnuTLS priority string
+tls-priorities = "PERFORMANCE:%SERVER_PRECEDENCE:%COMPAT"
+
+# To enforce perfect forward secrecy (PFS) on the main channel.
+#tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA"
+
+# The time (in seconds) that a client is allowed to stay connected prior
+# to authentication
+auth-timeout = 40
+
+# The time (in seconds) that a client is not allowed to reconnect after
+# a failed authentication attempt.
+#min-reauth-time = 2
+
+# Cookie validity time (in seconds)
+# Once a client is authenticated he's provided a cookie with
+# which he can reconnect. This option sets the maximum lifetime
+# of that cookie.
+cookie-validity = 172800
+
+# Script to call when a client connects and obtains an IP
+# Parameters are passed on the environment.
+# REASON, USERNAME, GROUPNAME, HOSTNAME (the hostname selected by client),
+# DEVICE, IP_REAL (the real IP of the client), IP_LOCAL (the local IP
+# in the P-t-P connection), IP_REMOTE (the VPN IP of the client). REASON
+# may be "connect" or "disconnect".
+#connect-script = /usr/bin/myscript
+#disconnect-script = /usr/bin/myscript
+
+# UTMP
+use-utmp = true
+
+# PID file
+pid-file = ./ocserv.pid
+
+# The default server directory. Does not require any devices present.
+#chroot-dir = /path/to/chroot
+
+# socket file used for IPC, will be appended with .PID
+# It must be accessible within the chroot environment (if any)
+socket-file = ./ocserv-gssapi-socket
+
+# The user the worker processes will be run as. It should be
+# unique (no other services run as this user).
+run-as-user = @USERNAME@
+run-as-group = @GROUP@
+#run-as-user = root
+#run-as-group = root
+
+# Network settings
+
+device = vpns
+
+# The default domain to be advertised
+default-domain = example.com
+
+ipv4-network = 192.168.1.0
+ipv4-netmask = 255.255.255.0
+# Use the keywork local to advertize the local P-t-P address as DNS server
+ipv4-dns = 192.168.1.1
+
+# The NBNS server (if any)
+#ipv4-nbns = 192.168.2.3
+
+#ipv6-address =
+#ipv6-mask =
+#ipv6-dns =
+
+# Prior to leasing any IP from the pool ping it to verify that
+# it is not in use by another (unrelated to this server) host.
+ping-leases = false
+
+# Leave empty to assign the default MTU of the device
+# mtu =
+
+route = 192.168.1.0/255.255.255.0
+#route = 192.168.5.0/255.255.255.0
+
+#
+# The following options are for (experimental) AnyConnect client
+# compatibility. They are only available if the server is built
+# with --enable-anyconnect
+#
+
+# Client profile xml. A sample file exists in doc/profile.xml.
+# This file must be accessible from inside the worker's chroot.
+# The profile is ignored by the openconnect client.
+#user-profile = profile.xml
+
+# Unless set to false it is required for clients to present their
+# certificate even if they are authenticating via a previously granted
+# cookie. Legacy CISCO clients do not do that, and thus this option
+# should be set for them.
+#always-require-cert = false
+
diff --git a/tests/test-gssapi-opt-cert b/tests/test-gssapi-opt-cert
new file mode 100755
index 00000000..40be5e82
--- /dev/null
+++ b/tests/test-gssapi-opt-cert
@@ -0,0 +1,110 @@
+#!/bin/sh
+#
+# Copyright (C) 2013-2018 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 this program. If not, see .
+
+SERV="${SERV:-../src/ocserv}"
+srcdir=${srcdir:-.}
+builddir=${builddir:-.}
+NO_NEED_ROOT=1
+PORT=4438
+OUTFILE=test-gssapi-opt-pass.$$.tmp
+
+connect()
+{
+opts=$1
+pass=$2
+rm -f ${OUTFILE}
+
+echo "$pass" | LD_PRELOAD=libsocket_wrapper.so $OPENCONNECT -q $ADDRESS:$PORT $opts --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 --authenticate >${OUTFILE} 2>&1
+if test $? != 0;then
+ cat ${OUTFILE}
+ return 1
+fi
+
+grep 'COOKIE=' ${OUTFILE}
+if test $? != 0;then
+ cat ${OUTFILE}
+ return 1
+fi
+
+rm -f ${OUTFILE}
+return 0
+}
+
+
+NTLMSSP_CONF=""
+for conf in /etc/gss/mech.d/mech.ntlmssp.conf /etc/gss/mech.d/ntlmssp.conf;do
+ if test -f ${conf};then
+ NTLMSSP_CONF=${conf}
+ fi
+done
+
+if test -z "$NTLMSSP_CONF";then
+ echo "GSS NTLM SSP was not found"
+ exit 77
+fi
+
+echo $NTLMSSP_CONF
+
+$SERV --version 2>&1|grep gssapi >/dev/null 2>&1
+if [ $? != 0 ];then
+ exit 77
+fi
+
+. `dirname $0`/common.sh
+
+echo "Testing local backend with gssapi and password fallback... "
+
+VERBOSE=1
+
+update_config test-gssapi-opt-cert.config
+launch_sr_server -d 1 -f -c ${CONFIG} & PID=$!
+wait_server $PID
+
+echo -n "Connecting to obtain cookie (with certificate)... "
+connect "-u test --sslkey ${srcdir}/certs/user-key.pem -c ${srcdir}/certs/user-cert.pem"
+if test $? != 0;then
+ fail $PID "Failed to connect with certificate!"
+fi
+echo ok
+
+echo -n "Connecting to obtain cookie (with incorrect certificate)... "
+connect "-u test --sslkey ${srcdir}/certs/user-key.pem -c ${srcdir}/certs/user-cert-wrong.pem" ""
+if test $? = 0;then
+ fail $PID "Should not have connected with wrong certificate!"
+fi
+echo ok
+
+# Try GSSAPI
+
+export NTLM_USER_FILE=${builddir}/ntlm.$$.pass.tmp
+echo "TESTINVALID:testinvalid:testpass" >$NTLM_USER_FILE
+
+#CURLOPTS="--cacert ${srcdir}/certs/ca.pem"
+CURLOPTS="--insecure"
+
+echo "Connecting with curl/negotiate... "
+LD_PRELOAD=libsocket_wrapper.so curl https://testinvalid:testpass@$ADDRESS:$PORT ${CURLOPTS} --negotiate -f -v ||
+ fail $PID "Could not connect to server"
+
+kill $PID
+wait
+
+rm -f ${builddir}/ntlm.$$.pass.tmp
+
+exit 0
diff --git a/tests/test-gssapi-opt-pass b/tests/test-gssapi-opt-pass
new file mode 100755
index 00000000..79e19950
--- /dev/null
+++ b/tests/test-gssapi-opt-pass
@@ -0,0 +1,110 @@
+#!/bin/sh
+#
+# Copyright (C) 2013-2018 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 this program. If not, see .
+
+SERV="${SERV:-../src/ocserv}"
+srcdir=${srcdir:-.}
+builddir=${builddir:-.}
+NO_NEED_ROOT=1
+PORT=4439
+OUTFILE=test-gssapi-opt-pass.$$.tmp
+
+connect()
+{
+opts=$1
+pass=$2
+rm -f ${OUTFILE}
+
+echo "$pass" | LD_PRELOAD=libsocket_wrapper.so $OPENCONNECT -q $ADDRESS:$PORT $opts --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 --authenticate >${OUTFILE} 2>&1
+if test $? != 0;then
+ cat ${OUTFILE}
+ return 1
+fi
+
+grep 'COOKIE=' ${OUTFILE}
+if test $? != 0;then
+ cat ${OUTFILE}
+ return 1
+fi
+
+rm -f ${OUTFILE}
+return 0
+}
+
+
+NTLMSSP_CONF=""
+for conf in /etc/gss/mech.d/mech.ntlmssp.conf /etc/gss/mech.d/ntlmssp.conf;do
+ if test -f ${conf};then
+ NTLMSSP_CONF=${conf}
+ fi
+done
+
+if test -z "$NTLMSSP_CONF";then
+ echo "GSS NTLM SSP was not found"
+ exit 77
+fi
+
+echo $NTLMSSP_CONF
+
+$SERV --version 2>&1|grep gssapi >/dev/null 2>&1
+if [ $? != 0 ];then
+ exit 77
+fi
+
+. `dirname $0`/common.sh
+
+echo "Testing local backend with gssapi and password fallback... "
+
+VERBOSE=1
+
+update_config test-gssapi-opt-pass.config
+launch_sr_server -d 1 -f -c ${CONFIG} & PID=$!
+wait_server $PID
+
+echo -n "Connecting to obtain cookie (user with non-gssapi password)... "
+connect "-u test2" "test2"
+if test $? != 0;then
+ fail $PID "Failed to connect with user without gssapi!"
+fi
+echo ok
+
+echo -n "Connecting to obtain cookie (user with non-gssapi password)... "
+connect "-u test" "test"
+if test $? != 0;then
+ fail $PID "Failed to connect with user without gssapi!"
+fi
+echo ok
+
+# Try GSSAPI
+
+export NTLM_USER_FILE=${builddir}/ntlm.$$.pass.tmp
+echo "TESTINVALID:testinvalid:testpass" >$NTLM_USER_FILE
+
+#CURLOPTS="--cacert ${srcdir}/certs/ca.pem"
+CURLOPTS="--insecure"
+
+echo "Connecting with curl/negotiate... "
+LD_PRELOAD=libsocket_wrapper.so curl https://testinvalid:testpass@$ADDRESS:$PORT ${CURLOPTS} --negotiate -f -v ||
+ fail $PID "Could not connect to server"
+
+kill $PID
+wait
+
+rm -f ${builddir}/ntlm.$$.pass.tmp
+
+exit 0