summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/auth/cert.c12
-rw-r--r--lib/gnutls_int.h1
-rw-r--r--lib/includes/gnutls/gnutls.h.in8
-rw-r--r--lib/state.c3
4 files changed, 16 insertions, 8 deletions
diff --git a/lib/auth/cert.c b/lib/auth/cert.c
index 450f9f4d6f..e08e20bd77 100644
--- a/lib/auth/cert.c
+++ b/lib/auth/cert.c
@@ -204,7 +204,8 @@ static int cert_get_issuer_dn(gnutls_pcert_st * cert, gnutls_datum_t * odn)
* CAs and sign algorithms supported by the peer server.
*/
static int
-find_x509_cert(const gnutls_certificate_credentials_t cred,
+find_x509_client_cert(gnutls_session_t session,
+ const gnutls_certificate_credentials_t cred,
uint8_t * _data, size_t _data_size,
const gnutls_pk_algorithm_t * pk_algos,
int pk_algos_length, int *indx)
@@ -221,9 +222,10 @@ find_x509_cert(const gnutls_certificate_credentials_t cred,
/* If peer doesn't send any issuers and we have a single certificate
* then send that one.
*/
- if (data_size == 0 && cred->ncerts == 1) {
- *indx = 0;
- return 0;
+ if (cred->ncerts == 1 &&
+ (data_size == 0 || session->internals.force_client_cert)) {
+ *indx = 0;
+ return 0;
}
do {
@@ -654,7 +656,7 @@ select_client_cert(gnutls_session_t session,
if (session->security_parameters.cert_type == GNUTLS_CRT_X509)
result =
- find_x509_cert(cred, _data, _data_size,
+ find_x509_client_cert(session, cred, _data, _data_size,
pk_algos, pk_algos_length, &indx);
#ifdef ENABLE_OPENPGP
else if (session->security_parameters.cert_type ==
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 6bdfe25980..743e1ba678 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -1000,6 +1000,7 @@ typedef struct {
bool sc_random_set;
bool no_replay_protection; /* DTLS replay protection */
bool allow_cert_change; /* whether the peer is allowed to change certificate */
+ bool force_client_cert;
bool try_ext_master_secret; /* whether to try negotiating the ext master secret */
/* a verify callback to override the verify callback from the credentials
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index aecf7ebc7c..f6afddfc45 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -353,8 +353,9 @@ typedef enum {
* @GNUTLS_NO_SIGNAL: In systems where SIGPIPE is delivered on send, it will be disabled. That flag has effect in systems which support the MSG_NOSIGNAL sockets flag (since 3.4.2).
* @GNUTLS_NO_EXTENSIONS: Do not enable any TLS extensions by default (since 3.1.2).
* @GNUTLS_NO_REPLAY_PROTECTION: Disable any replay protection in DTLS. This must only be used if replay protection is achieved using other means.
- * @GNUTLS_ALLOW_CERT_CHANGE: Allow the peer to replace its certificate during a rehandshake. This change is often used in attacks and thus prohibited by default (since 3.5.0).
- * @GNUTLS_ENABLE_FALSE_START: Enable the TLS false start on client side if the negotiated ciphersuites allow it. This will enable sending data prior to the handshake being complete, and may introduce a risk of crypto failure when combined with certain key exchanged; for that GnuTLS may not enable that option in ciphersuites that are known to be not safe for false start (since 3.5.0).
+ * @GNUTLS_ALLOW_CERT_CHANGE: Allow the peer to replace its certificate during a rehandshake. This change is often used in attacks and thus prohibited by default. Since 3.5.0.
+ * @GNUTLS_ENABLE_FALSE_START: Enable the TLS false start on client side if the negotiated ciphersuites allow it. This will enable sending data prior to the handshake being complete, and may introduce a risk of crypto failure when combined with certain key exchanged; for that GnuTLS may not enable that option in ciphersuites that are known to be not safe for false start. Since 3.5.0.
+ * @GNUTLS_FORCE_CLIENT_CERT: When in client side and only a single cert is specified, send that certificate irrespective of the issuers expectated by the server. Since 3.5.0.
*
* Enumeration of different flags for gnutls_init() function. All the flags
* can be combined except @GNUTLS_SERVER and @GNUTLS_CLIENT which are mutually
@@ -369,7 +370,8 @@ typedef enum {
GNUTLS_NO_REPLAY_PROTECTION = (1<<5),
GNUTLS_NO_SIGNAL = (1<<6),
GNUTLS_ALLOW_CERT_CHANGE = (1<<7),
- GNUTLS_ENABLE_FALSE_START = (1<<8)
+ GNUTLS_ENABLE_FALSE_START = (1<<8),
+ GNUTLS_FORCE_CLIENT_CERT = (1<<9)
} gnutls_init_flags_t;
/**
diff --git a/lib/state.c b/lib/state.c
index 0c6ebf92a1..03dc2d3620 100644
--- a/lib/state.c
+++ b/lib/state.c
@@ -443,6 +443,9 @@ int gnutls_init(gnutls_session_t * session, unsigned int flags)
if (!(flags & GNUTLS_NO_EXTENSIONS))
(*session)->internals.try_ext_master_secret = 1;
+ if (flags & GNUTLS_FORCE_CLIENT_CERT)
+ (*session)->internals.force_client_cert = 1;
+
if (flags & GNUTLS_NO_REPLAY_PROTECTION)
(*session)->internals.no_replay_protection = 1;