2 * Copyright (c) 2021 Eivind Næss. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
16 * 3. The name(s) of the authors of this software must not be used to
17 * endorse or promote products derived from this software without
18 * prior written permission.
20 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
21 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
23 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
24 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
25 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
26 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 #include <openssl/ssl.h>
31 #include <openssl/err.h>
32 #include <openssl/x509v3.h>
38 * Structure used in verifying the peer certificate
48 #if OPENSSL_VERSION_NUMBER < 0x10100000L
51 * OpenSSL 1.1+ introduced a generic TLS_method()
52 * For older releases we substitute the appropriate method
54 #define TLS_method SSLv23_method
56 #ifndef SSL_CTX_set_max_proto_version
57 /** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */
58 static inline int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, long tls_ver_max)
62 if (tls_ver_max < TLS1_VERSION)
64 sslopt |= SSL_OP_NO_TLSv1;
66 #ifdef SSL_OP_NO_TLSv1_1
67 if (tls_ver_max < TLS1_1_VERSION)
69 sslopt |= SSL_OP_NO_TLSv1_1;
72 #ifdef SSL_OP_NO_TLSv1_2
73 if (tls_ver_max < TLS1_2_VERSION)
75 sslopt |= SSL_OP_NO_TLSv1_2;
78 SSL_CTX_set_options(ctx, sslopt);
82 #endif /* SSL_CTX_set_max_proto_version */
84 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
88 * Verify a certificate. Most of the work (signatures and issuer attributes checking)
89 * is done by ssl; we check the CN in the peer certificate against the peer name.
91 static int tls_verify_callback(int ok, X509_STORE_CTX *ctx)
99 char *ptr1 = NULL, *ptr2 = NULL;
101 peer_cert = X509_STORE_CTX_get_current_cert(ctx);
102 err = X509_STORE_CTX_get_error(ctx);
103 depth = X509_STORE_CTX_get_error_depth(ctx);
105 dbglog("certificate verify depth: %d", depth);
107 if (auth_required && !ok) {
108 X509_NAME_oneline(X509_get_subject_name(peer_cert),
111 X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
112 NID_commonName, cn_str, 256);
114 dbglog("Certificate verification error:\n depth: %d CN: %s"
115 "\n err: %d (%s)\n", depth, cn_str, err,
116 X509_verify_cert_error_string(err));
121 ssl = X509_STORE_CTX_get_ex_data(ctx,
122 SSL_get_ex_data_X509_STORE_CTX_idx());
124 inf = (struct tls_info*) SSL_get_ex_data(ssl, 0);
126 error("Error: SSL_get_ex_data returned NULL");
134 /* Verify certificate based on certificate type and extended key usage */
135 if (tls_verify_key_usage) {
136 int purpose = inf->client ? X509_PURPOSE_SSL_SERVER : X509_PURPOSE_SSL_CLIENT ;
137 if (X509_check_purpose(peer_cert, purpose, 0) == 0) {
138 error("Certificate verification error: nsCertType mismatch");
142 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
143 int flags = inf->client ? XKU_SSL_SERVER : XKU_SSL_CLIENT;
144 if (!(X509_get_extended_key_usage(peer_cert) & flags)) {
145 error("Certificate verification error: invalid extended key usage");
149 info("Certificate key usage: OK");
153 * If acting as client and the name of the server wasn't specified
154 * explicitely, we can't verify the server authenticity
156 if (!tls_verify_method)
157 tls_verify_method = TLS_VERIFY_NONE;
159 if (!inf->peer_name || !strcmp(TLS_VERIFY_NONE, tls_verify_method)) {
160 warn("Certificate verication disabled or no peer name was specified");
164 /* This is the peer certificate */
165 X509_NAME_oneline(X509_get_subject_name(peer_cert),
168 X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
169 NID_commonName, cn_str, 256);
171 /* Verify based on subject name */
172 ptr1 = inf->peer_name;
173 if (!strcmp(TLS_VERIFY_SUBJECT, tls_verify_method)) {
177 /* Verify based on common name (default) */
178 if (strlen(tls_verify_method) == 0 ||
179 !strcmp(TLS_VERIFY_NAME, tls_verify_method)) {
183 /* Match the suffix of common name */
184 if (!strcmp(TLS_VERIFY_SUFFIX, tls_verify_method)) {
185 int len = strlen(ptr1);
186 int off = strlen(cn_str) - len;
193 if (strcmp(ptr1, ptr2)) {
194 error("Certificate verification error: CN (%s) != %s", ptr1, ptr2);
198 if (inf->peer_cert) {
199 if (X509_cmp(inf->peer_cert, peer_cert) != 0) {
200 error("Peer certificate doesn't match stored certificate");
205 info("Certificate CN: %s, peer name %s", cn_str, inf->peer_name);
213 #if OPENSSL_VERSION_NUMBER < 0x10100000L
215 SSL_load_error_strings();
220 int tls_set_verify(SSL_CTX *ctx, int depth)
222 SSL_CTX_set_verify_depth(ctx, depth);
223 SSL_CTX_set_verify(ctx,
225 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
226 &tls_verify_callback);
230 int tls_set_verify_info(SSL *ssl, const char *peer_name, const char *peer_cert,
231 bool client, struct tls_info **out)
234 struct tls_info *tmp = calloc(sizeof(struct tls_info), 1);
236 fatal("Allocation error");
239 tmp->client = client;
241 tmp->peer_name = strdup(peer_name);
244 if (peer_cert && strlen(peer_cert) > 0) {
245 FILE *fp = fopen(peer_cert, "r");
247 tmp->peer_cert = PEM_read_X509(fp, NULL, NULL, NULL);
251 if (!tmp->peer_cert) {
252 error("EAP-TLS: Error loading client certificate from file %s",
254 tls_free_verify_info(&tmp);
259 SSL_set_ex_data(ssl, 0, tmp);
267 void tls_free_verify_info(struct tls_info **in) {
269 struct tls_info *tmp = *in;
270 if (tmp->peer_name) {
271 free(tmp->peer_name);
273 if (tmp->peer_cert) {
274 X509_free(tmp->peer_cert);
281 const SSL_METHOD* tls_method() {
285 int tls_set_version(SSL_CTX *ctx, const char *max_version)
287 #if defined(TLS1_2_VERSION)
288 long tls_version = TLS1_2_VERSION;
289 #elif defined(TLS1_1_VERSION)
290 long tls_version = TLS1_1_VERSION;
292 long tls_version = TLS1_VERSION;
295 /* As EAP-TLS+TLSv1.3 is highly experimental we offer the user a chance to override */
297 if (strncmp(max_version, "1.0", 3) == 0) {
298 tls_version = TLS1_VERSION;
300 else if (strncmp(max_version, "1.1", 3) == 0) {
301 tls_version = TLS1_1_VERSION;
303 else if (strncmp(max_version, "1.2", 3) == 0) {
304 #ifdef TLS1_2_VERSION
305 tls_version = TLS1_2_VERSION;
307 warn("TLSv1.2 not available. Defaulting to TLSv1.1");
308 tls_version = TLS_1_1_VERSION;
311 else if (strncmp(max_version, "1.3", 3) == 0) {
312 #ifdef TLS1_3_VERSION
313 tls_version = TLS1_3_VERSION;
315 warn("TLSv1.3 not available.");
320 dbglog("Setting max protocol version to 0x%X", tls_version);
321 if (!SSL_CTX_set_max_proto_version(ctx, tls_version)) {
322 error("Could not set max protocol version");
329 int tls_set_opts(SSL_CTX *ctx) {
331 /* Explicitly set the NO_TICKETS flag to support Win7/Win8 clients */
332 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3
333 #ifdef SSL_OP_NO_TICKET
336 | SSL_OP_NO_COMPRESSION
339 /* OpenSSL 1.1.1+ does not include RC4 ciphers by default.
340 * This causes totally obsolete WinXP clients to fail. If you really
341 * need ppp+EAP-TLS+openssl 1.1.1+WinXP then enable RC4 cipers and
342 * make sure that you use an OpenSSL that supports them
344 SSL_CTX_set_cipher_list(ctx, "RC4");
349 int tls_set_crl(SSL_CTX *ctx, const char *crl_dir, const char *crl_file)
351 X509_STORE *certstore = NULL;
352 X509_LOOKUP *lookup = NULL;
357 if (!(certstore = SSL_CTX_get_cert_store(ctx))) {
358 error("Failed to get certificate store");
363 X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) {
364 error("Store lookup for CRL failed");
368 X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM);
369 X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK);
373 X509_CRL *crl = NULL;
375 fp = fopen(crl_file, "r");
377 error("Cannot open CRL file '%s'", crl_file);
381 crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL);
383 error("Cannot read CRL file '%s'", crl_file);
387 if (!(certstore = SSL_CTX_get_cert_store(ctx))) {
388 error("Failed to get certificate store");
391 if (!X509_STORE_add_crl(certstore, crl)) {
392 error("Cannot add CRL to certificate store");
395 X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK);
409 int tls_set_ca(SSL_CTX *ctx, const char *ca_dir, const char *ca_file)
411 if (ca_file && strlen(ca_file) == 0) {
415 if (ca_dir && strlen(ca_dir) == 0) {
419 if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_dir)) {
421 error("Cannot load verify locations");
423 dbglog("CA certificate file = [%s]", ca_file);
427 dbglog("CA certificate path = [%s]", ca_dir);
436 void tls_log_sslerr( void )
438 unsigned long ssl_err = ERR_get_error();
441 dbglog("EAP-TLS SSL error stack:");
442 while (ssl_err != 0) {
443 dbglog( ERR_error_string( ssl_err, NULL ) );
444 ssl_err = ERR_get_error();