2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 09:57:41 +00:00

logserver option to disable certificate verification on server side and server authentication on client side

This commit is contained in:
Laszlo Orban 2020-01-23 09:53:27 +01:00 committed by Todd C. Miller
parent 9935a7e2ff
commit 24c9438486
8 changed files with 115 additions and 50 deletions

View File

@ -28,16 +28,26 @@
# By default, server connections are not encrypted.
#tls = true
# If set, server certificate will be verified at server startup and
# also connecting clients will perform server authentication by
# verifying the server's certificate and identity.
#tls_verify = true
# Whether to verify client certificates for TLS connections.
# By default client certs are not checked.
#tls_checkpeer = false
# Path to the certificate authority bundle file in PEM format.
# Required if 'tls_verify' or 'tls_checkpeer' is set.
#tls_cacert = /etc/ssl/sudo/cacert.pem
# Path to the server's certificate file in PEM format.
# Required for TLS connections.
#tls_cert = /etc/ssl/sudo/logsrvd_cert.pem
# Whether to verify client certificates for TLS connections.
# By default client certs are not checked.
#tls_checkpeer = false
# Path to the server's private key file in PEM format.
# Required for TLS connections.
#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
# NOTE that this setting is only effective if the negotiated protocol
@ -53,10 +63,6 @@
# If not set, the server will use the OpenSSL defaults.
#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
# Path to the server's private key file in PEM format.
# Required for TLS connections.
#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
[iolog]
# The top-level directory to use when constructing the path name for the
# I/O log directory. The session sequence number, if any, is stored here.

View File

@ -409,6 +409,10 @@ struct _ServerHello
* true if server uses tls protocol
*/
protobuf_c_boolean tls;
/*
* true if server auth has to be performed
*/
protobuf_c_boolean tls_server_auth;
/*
* true if client auth is required with signed cert
*/
@ -416,7 +420,7 @@ struct _ServerHello
};
#define SERVER_HELLO__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&server_hello__descriptor) \
, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0,NULL, 0, 0 }
, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0,NULL, 0, 0, 0 }
/* ClientMessage methods */

View File

@ -1578,7 +1578,7 @@ const ProtobufCMessageDescriptor server_message__descriptor =
(ProtobufCMessageInit) server_message__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor server_hello__field_descriptors[5] =
static const ProtobufCFieldDescriptor server_hello__field_descriptors[6] =
{
{
"server_id",
@ -1629,11 +1629,23 @@ static const ProtobufCFieldDescriptor server_hello__field_descriptors[5] =
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"tls_reqcert",
"tls_server_auth",
5,
PROTOBUF_C_LABEL_NONE,
PROTOBUF_C_TYPE_BOOL,
0, /* quantifier_offset */
offsetof(ServerHello, tls_server_auth),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"tls_reqcert",
6,
PROTOBUF_C_LABEL_NONE,
PROTOBUF_C_TYPE_BOOL,
0, /* quantifier_offset */
offsetof(ServerHello, tls_reqcert),
NULL,
NULL,
@ -1646,12 +1658,13 @@ static const unsigned server_hello__field_indices_by_name[] = {
0, /* field[0] = server_id */
2, /* field[2] = servers */
3, /* field[3] = tls */
4, /* field[4] = tls_reqcert */
5, /* field[5] = tls_reqcert */
4, /* field[4] = tls_server_auth */
};
static const ProtobufCIntRange server_hello__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 5 }
{ 0, 6 }
};
const ProtobufCMessageDescriptor server_hello__descriptor =
{
@ -1661,7 +1674,7 @@ const ProtobufCMessageDescriptor server_hello__descriptor =
"ServerHello",
"",
sizeof(ServerHello),
5,
6,
server_hello__field_descriptors,
server_hello__field_indices_by_name,
1, server_hello__number_ranges,

View File

@ -126,5 +126,6 @@ message ServerHello {
string redirect = 2; /* optional redirect if busy */
repeated string servers = 3; /* optional list of known servers */
bool tls = 4; /* true if server uses tls protocol */
bool tls_reqcert = 5; /* true if client auth is required with signed cert */
bool tls_server_auth = 5; /* true if server auth has to be performed */
bool tls_reqcert = 6; /* true if client auth is required with signed cert */
}

View File

@ -178,9 +178,11 @@ fmt_hello_message(struct connection_buffer *buf)
hello.server_id = (char *)server_id;
#if defined(HAVE_OPENSSL)
hello.tls = logsrvd_conf_get_tls_opt();
hello.tls_server_auth = logsrvd_get_tls_config()->verify;
hello.tls_reqcert = logsrvd_get_tls_config()->check_peer;
#else
hello.tls = false;
hello.tls_server_auth = false;
hello.tls_reqcert = false;
#endif
msg.hello = &hello;
@ -970,9 +972,11 @@ verify_peer_identity(int preverify_ok, X509_STORE_CTX *ctx)
switch(result)
{
case MatchFound:
debug_return_int(1);
debug_return_int(1);
default:
debug_return_int(0);
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
"hostname validation failed");
debug_return_int(0);
}
}
@ -1101,6 +1105,7 @@ init_tls_server_context(void)
const SSL_METHOD *method;
SSL_CTX *ctx = NULL;
const struct logsrvd_tls_config *tls_config = logsrvd_get_tls_config();
bool ca_bundle_required = tls_config->verify | tls_config->check_peer;
debug_decl(init_tls_server_context, SUDO_DEBUG_UTIL);
SSL_library_init();
@ -1127,29 +1132,39 @@ init_tls_server_context(void)
goto bad;
}
if (tls_config->cacert_path != NULL) {
STACK_OF(X509_NAME) *cacerts =
SSL_load_client_CA_file(tls_config->cacert_path);
if (cacerts == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"calling SSL_load_client_CA_file() failed: %s",
ERR_error_string(ERR_get_error(), NULL));
goto bad;
} else {
SSL_CTX_set_client_CA_list(ctx, cacerts);
/* set the location of the CA bundle file for verification */
if (SSL_CTX_load_verify_locations(ctx, tls_config->cacert_path, NULL) <= 0) {
/* if server or client authentication is required, CA bundle file has to be prepared */
if (ca_bundle_required) {
if (tls_config->cacert_path != NULL) {
STACK_OF(X509_NAME) *cacerts =
SSL_load_client_CA_file(tls_config->cacert_path);
if (cacerts == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"calling SSL_CTX_load_verify_locations() failed: %s",
"calling SSL_load_client_CA_file() failed: %s",
ERR_error_string(ERR_get_error(), NULL));
goto bad;
} else {
SSL_CTX_set_client_CA_list(ctx, cacerts);
/* set the location of the CA bundle file for verification */
if (SSL_CTX_load_verify_locations(ctx, tls_config->cacert_path, NULL) <= 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"calling SSL_CTX_load_verify_locations() failed: %s",
ERR_error_string(ERR_get_error(), NULL));
goto bad;
}
}
}
}
if (!verify_server_cert(ctx, tls_config)) {
goto bad;
/* only verify server cert if it is set in the configuration */
if (tls_config->verify) {
if (!verify_server_cert(ctx, tls_config)) {
goto bad;
}
} else {
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
"skipping server cert check");
}
}
/* if peer authentication is enabled, verify client cert during TLS handshake
@ -1303,6 +1318,11 @@ tls_handshake_cb(int fd, int what, void *v)
sudo_warn(U_("unable to add event to queue"));
}
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
"TLS version: %s, negotiated cipher suite: %s",
SSL_get_version(closure->ssl),
SSL_get_cipher(closure->ssl));
debug_return;
bad:
connection_closure_free(closure);

View File

@ -136,6 +136,7 @@ struct logsrvd_tls_config {
char *dhparams_path;
char *ciphers_v12;
char *ciphers_v13;
bool verify;
bool check_peer;
};

View File

@ -526,6 +526,19 @@ cb_tls_ciphers13(struct logsrvd_config *config, const char *str)
debug_return_bool(true);
}
static bool
cb_tls_verify(struct logsrvd_config *config, const char *str)
{
int val;
debug_decl(cb_tls_verify, SUDO_DEBUG_UTIL);
if ((val = sudo_strtobool(str)) == -1)
debug_return_bool(false);
config->server.tls_config.verify = val;
debug_return_bool(true);
}
static bool
cb_tls_checkpeer(struct logsrvd_config *config, const char *str)
{
@ -706,6 +719,7 @@ static struct logsrvd_config_entry server_conf_entries[] = {
{ "tls_ciphers_v12", cb_tls_ciphers12 },
{ "tls_ciphers_v13", cb_tls_ciphers13 },
{ "tls_checkpeer", cb_tls_checkpeer },
{ "tls_verify", cb_tls_verify },
#endif
{ NULL }
};
@ -882,6 +896,8 @@ logsrvd_conf_alloc(void)
#if defined(HAVE_OPENSSL)
config->server.tls_config.cacert_path = strdup(DEFAULT_CA_CERT_PATH);
config->server.tls_config.cert_path = strdup(DEFAULT_SERVER_CERT_PATH);
config->server.tls_config.verify = true;
config->server.tls_config.check_peer = false;
#endif
/* I/O log defaults */

View File

@ -281,15 +281,10 @@ verify_peer_identity(int preverify_ok, X509_STORE_CTX *ctx)
}
static bool
tls_init(struct client_closure *closure, bool cert_required)
tls_init(struct client_closure *closure, bool verify, bool cert_required)
{
debug_decl(tls_init, SUDOERS_DEBUG_PLUGIN);
if (closure->log_details->ca_bundle == NULL) {
sudo_warnx(U_("CA bundle file is not set in sudoers"));
goto bad;
}
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
@ -312,18 +307,27 @@ tls_init(struct client_closure *closure, bool cert_required)
SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1);
#endif
/* sets the location of the CA bundle file for verification purposes */
if (SSL_CTX_load_verify_locations(closure->ssl_ctx,
closure->log_details->ca_bundle, NULL) <= 0) {
sudo_warnx(U_("Calling SSL_CTX_load_verify_locations() failed: %s"),
ERR_error_string(ERR_get_error(), NULL));
goto bad;
}
/* turn on server cert verification during the handshake.
hostname matching will be done in a custom callback (verify_peer_identity).
/* if server explicitly requests it, turn on server cert verification
during the handshake. Hostname matching will be done in a custom
callback (verify_peer_identity).
*/
SSL_CTX_set_verify(closure->ssl_ctx, SSL_VERIFY_PEER, verify_peer_identity);
if (verify) {
if (closure->log_details->ca_bundle == NULL) {
sudo_warnx(U_("CA bundle file is not set in sudoers"));
goto bad;
}
/* sets the location of the CA bundle file for verification purposes */
if (SSL_CTX_load_verify_locations(closure->ssl_ctx,
closure->log_details->ca_bundle, NULL) <= 0) {
sudo_warnx(U_("Calling SSL_CTX_load_verify_locations() failed: %s"),
ERR_error_string(ERR_get_error(), NULL));
goto bad;
}
SSL_CTX_set_verify(closure->ssl_ctx, SSL_VERIFY_PEER, verify_peer_identity);
}
/* if the server requests client authentication with signed certificate */
if (cert_required) {
@ -1057,7 +1061,7 @@ handle_server_hello(ServerHello *msg, struct client_closure *closure)
#if defined(HAVE_OPENSSL)
/* if server requested TLS */
if (msg->tls) {
if (!tls_init(closure, msg->tls_reqcert)) {
if (!tls_init(closure, msg->tls_server_auth, msg->tls_reqcert)) {
sudo_warnx(U_("TLS initialization was unsuccessful"));
debug_return_bool(false);
}