mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 00:37:00 +08:00
Added option to allow sending a cookie without the corresponding certificate.
This option is required for the cisco clients, that do not always use the client certificate. When this option is set to false it means that the cookie itself is sufficient for authentication. This is bad practice of smart cards are in use.
This commit is contained in:
@@ -10,7 +10,13 @@ auth = "pam"
|
||||
# Client config xml. The variable $GROUP will be replaced by
|
||||
# the user's group name. This file must be accessible from inside
|
||||
# the worker's chroot. It is not used by the openconnect client.
|
||||
user-profile = ../doc/profile.xml
|
||||
#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
|
||||
|
||||
# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
|
||||
#listen-host = [IP|HOSTNAME]
|
||||
|
||||
22
src/config.c
22
src/config.c
@@ -28,6 +28,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <ocserv-args.h>
|
||||
#include <autoopts/options.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <tlslib.h>
|
||||
@@ -124,7 +125,7 @@ unsigned j;
|
||||
#endif
|
||||
} else if (strcasecmp(auth[j], "certificate") == 0) {
|
||||
config->auth_types |= AUTH_TYPE_CERTIFICATE;
|
||||
config->cert_req = GNUTLS_CERT_REQUIRE;
|
||||
config->cert_req = GNUTLS_CERT_REQUEST;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown auth method: %s\n", auth[j]);
|
||||
exit(1);
|
||||
@@ -161,6 +162,7 @@ unsigned j;
|
||||
READ_STRING("pid-file", pid_file, 0);
|
||||
|
||||
READ_STRING("banner", config->banner, 0);
|
||||
READ_TF("always-require-cert", config->force_cert_auth, 0, 1);
|
||||
READ_TF("use-utmp", config->use_utmp, 0, 1);
|
||||
READ_TF("try-mtu-discovery", config->try_mtu, 0, 0);
|
||||
|
||||
@@ -237,9 +239,27 @@ static void check_cfg( struct cfg_st *config)
|
||||
if (config->cert) {
|
||||
config->cert_hash = calc_sha1_hash(config->cert, 1);
|
||||
}
|
||||
|
||||
if (config->force_cert_auth)
|
||||
config->cert_req = GNUTLS_CERT_REQUIRE;
|
||||
|
||||
if (config->xml_config_file) {
|
||||
config->xml_config_hash = calc_sha1_hash(config->xml_config_file, 0);
|
||||
if (config->xml_config_hash == NULL && config->chroot_dir != NULL) {
|
||||
char path[_POSIX_PATH_MAX];
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", config->chroot_dir, config->xml_config_file);
|
||||
config->xml_config_hash = calc_sha1_hash(path, 0);
|
||||
|
||||
if (config->xml_config_hash == NULL) {
|
||||
fprintf(stderr, "Cannot open file '%s'\n", path);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (config->xml_config_hash == NULL) {
|
||||
fprintf(stderr, "Cannot open file '%s'\n", config->xml_config_file);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (config->keepalive == 0)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.c)
|
||||
*
|
||||
* It has been AutoGen-ed March 1, 2013 at 07:46:59 PM by AutoGen 5.16
|
||||
* It has been AutoGen-ed March 1, 2013 at 09:44:33 PM by AutoGen 5.16
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
@@ -87,6 +87,12 @@ auth = "pam"
|
||||
# It is not used by the openconnect client.
|
||||
#user-profile = /path/to/file.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
|
||||
|
||||
# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
|
||||
#listen-host = [IP|HOSTNAME]
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.h)
|
||||
*
|
||||
* It has been AutoGen-ed March 1, 2013 at 07:46:59 PM by AutoGen 5.16
|
||||
* It has been AutoGen-ed March 1, 2013 at 09:44:33 PM by AutoGen 5.16
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
18
src/tlslib.c
18
src/tlslib.c
@@ -196,13 +196,15 @@ static int verify_certificate_cb(gnutls_session_t session)
|
||||
if (session == ws->dtls_session) /* no certificate is verified in DTLS */
|
||||
return 0;
|
||||
|
||||
ws->cert_auth_ok = 0;
|
||||
|
||||
/* This verification function uses the trusted CAs in the credentials
|
||||
* structure. So you must have installed one or more CA certificates.
|
||||
*/
|
||||
ret = gnutls_certificate_verify_peers2(session, &status);
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_ERR, "error verifying client certificate");
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (status != 0) {
|
||||
@@ -214,7 +216,7 @@ static int verify_certificate_cb(gnutls_session_t session)
|
||||
gnutls_certificate_verification_status_print(status, type,
|
||||
&out, 0);
|
||||
if (ret < 0)
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
goto fail;
|
||||
|
||||
oclog(ws, LOG_INFO, "client certificate verification failed: %s", out.data);
|
||||
|
||||
@@ -223,13 +225,20 @@ static int verify_certificate_cb(gnutls_session_t session)
|
||||
oclog(ws, LOG_INFO, "client certificate verification failed.");
|
||||
#endif
|
||||
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
goto fail;
|
||||
} else {
|
||||
ws->cert_auth_ok = 1;
|
||||
oclog(ws, LOG_INFO, "client certificate verification succeeded");
|
||||
}
|
||||
|
||||
/* notify gnutls to continue handshake normally */
|
||||
return 0;
|
||||
fail:
|
||||
if (ws->config->force_cert_auth != 0)
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int pin_callback (void *user, int attempt, const char *token_url,
|
||||
@@ -479,8 +488,7 @@ gnutls_x509_crt_t crt;
|
||||
|
||||
ret = gnutls_load_file(file, &data);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Cannot open file '%s': %s\n", file, gnutls_strerror(ret));
|
||||
exit(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cert != 0) {
|
||||
|
||||
@@ -83,6 +83,7 @@ struct cfg_st {
|
||||
unsigned max_same_clients;
|
||||
unsigned use_utmp;
|
||||
unsigned try_mtu; /* MTU discovery enabled */
|
||||
unsigned force_cert_auth; /* always require client certificate */
|
||||
|
||||
/* if gdbm is there */
|
||||
char* cookie_db_name;
|
||||
|
||||
@@ -292,6 +292,11 @@ static int auth_user(worker_st *ws, struct cmd_auth_req_st* areq)
|
||||
int ret;
|
||||
|
||||
if (ws->config->auth_types & AUTH_TYPE_CERTIFICATE) {
|
||||
if (ws->cert_auth_ok == 0) {
|
||||
oclog(ws, LOG_INFO, "no certificate provided for authentication");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = get_cert_info(ws, areq->cert_user, sizeof(areq->cert_user),
|
||||
areq->cert_group, sizeof(areq->cert_group));
|
||||
if (ret < 0)
|
||||
@@ -322,7 +327,12 @@ struct cmd_auth_cookie_req_st areq;
|
||||
if (cookie_size != sizeof(areq.cookie))
|
||||
return -1;
|
||||
|
||||
if (ws->config->auth_types & AUTH_TYPE_CERTIFICATE) {
|
||||
if ((ws->config->auth_types & AUTH_TYPE_CERTIFICATE) && ws->config->force_cert_auth != 0) {
|
||||
if (ws->cert_auth_ok == 0) {
|
||||
oclog(ws, LOG_INFO, "no certificate provided for cookie authentication");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = get_cert_info(ws, areq.cert_user, sizeof(areq.cert_user),
|
||||
areq.cert_group, sizeof(areq.cert_group));
|
||||
if (ret < 0)
|
||||
|
||||
@@ -87,6 +87,7 @@ typedef struct worker_st {
|
||||
uint8_t master_secret[TLS_MASTER_SIZE];
|
||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
||||
unsigned auth_ok;
|
||||
unsigned cert_auth_ok;
|
||||
int tun_fd;
|
||||
|
||||
struct http_req_st req;
|
||||
|
||||
Reference in New Issue
Block a user