X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Feap-tls.c;h=bfcf199635d7532990cb3a5153cbc3e6269edcb1;hb=d706c95906d996534f13632a747af5dc617f306e;hp=5740f308a89ae6c2e645222474a2ba6497cde9e7;hpb=505ec5cbd15ec23ed84282462ae9e451a1978133;p=ppp.git diff --git a/pppd/eap-tls.c b/pppd/eap-tls.c index 5740f30..bfcf199 100644 --- a/pppd/eap-tls.c +++ b/pppd/eap-tls.c @@ -48,6 +48,8 @@ #include "eap-tls.h" #include "fsm.h" #include "lcp.h" +#include "chap_ms.h" +#include "mppe.h" #include "pathnames.h" typedef struct pw_cb_data @@ -56,15 +58,17 @@ typedef struct pw_cb_data const char *prompt_info; } PW_CB_DATA; +#ifndef OPENSSL_NO_ENGINE /* The openssl configuration file and engines can be loaded only once */ static CONF *ssl_config = NULL; static ENGINE *cert_engine = NULL; static ENGINE *pkey_engine = NULL; +#endif /* TLSv1.3 do we have a session ticket ? */ static int have_session_ticket = 0; -int ssl_verify_callback(int, X509_STORE_CTX *); +int ssl_verify_callback(int, X509_STORE_CTX *); void ssl_msg_callback(int write_p, int version, int ct, const void *buf, size_t len, SSL * ssl, void *arg); int ssl_new_session_cb(SSL *s, SSL_SESSION *sess); @@ -72,10 +76,6 @@ int ssl_new_session_cb(SSL *s, SSL_SESSION *sess); X509 *get_X509_from_file(char *filename); int ssl_cmp_certs(char *filename, X509 * a); -#ifdef MPPE - -#define EAPTLS_MPPE_KEY_LEN 32 - /* * OpenSSL 1.1+ introduced a generic TLS_method() * For older releases we substitute the appropriate method @@ -117,6 +117,8 @@ static inline int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, long tls_ver_max) #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ +#ifdef MPPE +#define EAPTLS_MPPE_KEY_LEN 32 /* * Generate keys according to RFC 2716 and add to reply @@ -159,24 +161,17 @@ void eaptls_gen_mppe_keys(struct eaptls_session *ets, int client) */ if (client) { - p = out; - BCOPY( p, mppe_send_key, sizeof(mppe_send_key) ); - p += EAPTLS_MPPE_KEY_LEN; - BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) ); + mppe_set_keys(out, out + EAPTLS_MPPE_KEY_LEN, EAPTLS_MPPE_KEY_LEN); } else { - p = out; - BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) ); - p += EAPTLS_MPPE_KEY_LEN; - BCOPY( p, mppe_send_key, sizeof(mppe_send_key) ); + mppe_set_keys(out + EAPTLS_MPPE_KEY_LEN, out, EAPTLS_MPPE_KEY_LEN); } - - mppe_keys_set = 1; } #endif /* MPPE */ + void log_ssl_errors( void ) { unsigned long ssl_err = ERR_get_error(); @@ -219,7 +214,9 @@ CONF *eaptls_ssl_load_config( void ) } dbglog( "Loading OpenSSL built-ins" ); +#ifndef OPENSSL_NO_ENGINE ENGINE_load_builtin_engines(); +#endif OPENSSL_load_builtin_modules(); dbglog( "Loading OpenSSL configured modules" ); @@ -233,6 +230,7 @@ CONF *eaptls_ssl_load_config( void ) return config; } +#ifndef OPENSSL_NO_ENGINE ENGINE *eaptls_ssl_load_engine( char *engine_name ) { ENGINE *e = NULL; @@ -277,7 +275,7 @@ ENGINE *eaptls_ssl_load_engine( char *engine_name ) return e; } - +#endif /* @@ -287,10 +285,12 @@ ENGINE *eaptls_ssl_load_engine( char *engine_name ) SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, char *certfile, char *peer_certfile, char *privkeyfile) { +#ifndef OPENSSL_NO_ENGINE char *cert_engine_name = NULL; char *cert_identifier = NULL; char *pkey_engine_name = NULL; char *pkey_identifier = NULL; +#endif SSL_CTX *ctx; SSL *ssl; X509_STORE *certstore; @@ -329,11 +329,13 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, SSL_library_init(); SSL_load_error_strings(); +#ifndef OPENSSL_NO_ENGINE /* load the openssl config file only once and load it before triggering the loading of a global openssl config file via SSL_CTX_new() */ if (!ssl_config) ssl_config = eaptls_ssl_load_config(); +#endif ctx = SSL_CTX_new(TLS_method()); @@ -342,6 +344,7 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, goto fail; } +#ifndef OPENSSL_NO_ENGINE /* if the certificate filename is of the form engine:id. e.g. pkcs11:12345 then we try to load and use this engine. @@ -417,6 +420,7 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, else pkey_engine = eaptls_ssl_load_engine( pkey_engine_name ); } +#endif SSL_CTX_set_default_passwd_cb (ctx, password_callback); @@ -434,6 +438,7 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, if (init_server) SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(cacertfile)); +#ifndef OPENSSL_NO_ENGINE if (cert_engine) { struct @@ -468,6 +473,7 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, } } else +#endif { if (!SSL_CTX_use_certificate_chain_file(ctx, certfile)) { @@ -504,6 +510,7 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, } SSL_free(ssl); +#ifndef OPENSSL_NO_ENGINE if (pkey_engine) { EVP_PKEY *pkey = NULL; @@ -556,6 +563,7 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, } } else +#endif { if (!SSL_CTX_use_PrivateKey_file(ctx, privkeyfile, SSL_FILETYPE_PEM)) { @@ -733,6 +741,7 @@ int eaptls_init_ssl_server(eap_state * esp) if (!esp->es_server.ea_session) fatal("Allocation error"); ets = esp->es_server.ea_session; + ets->client = 0; if (!esp->es_server.ea_peer) { error("EAP-TLS: Error: client name not set (BUG)"); @@ -824,6 +833,7 @@ int eaptls_init_ssl_client(eap_state * esp) if (!esp->es_client.ea_session) fatal("Allocation error"); ets = esp->es_client.ea_session; + ets->client = 1; /* * If available, copy server name in ets; it will be used in cert @@ -1146,6 +1156,7 @@ int ssl_verify_callback(int ok, X509_STORE_CTX * ctx) int err, depth; SSL *ssl; struct eaptls_session *ets; + char *ptr1 = NULL, *ptr2 = NULL; peer_cert = X509_STORE_CTX_get_current_cert(ctx); err = X509_STORE_CTX_get_error(ctx); @@ -1181,34 +1192,71 @@ int ssl_verify_callback(int ok, X509_STORE_CTX * ctx) if (!depth) { - /* This is the peer certificate */ - - X509_NAME_oneline(X509_get_subject_name(peer_cert), - subject, 256); + /* Verify certificate based on certificate type and extended key usage */ + if (tls_verify_key_usage) { + int purpose = ets->client ? X509_PURPOSE_SSL_SERVER : X509_PURPOSE_SSL_CLIENT ; + if (X509_check_purpose(peer_cert, purpose, 0) == 0) { + error("Certificate verification error: nsCertType mismatch"); + return 0; + } - X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert), - NID_commonName, cn_str, 256); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + int flags = ets->client ? XKU_SSL_SERVER : XKU_SSL_CLIENT; + if (!(X509_get_extended_key_usage(peer_cert) & flags)) { + error("Certificate verification error: invalid extended key usage"); + return 0; + } +#endif + info("Certificate key usage: OK"); + } /* * If acting as client and the name of the server wasn't specified * explicitely, we can't verify the server authenticity */ - if (!ets->peer[0]) { - warn("Peer name not specified: no check"); + if (!tls_verify_method) + tls_verify_method = TLS_VERIFY_NONE; + + if (!ets->peer[0] || !strcmp(TLS_VERIFY_NONE, tls_verify_method)) { + warn("Certificate verication disabled or no peer name was specified"); return ok; } - /* - * Check the CN - */ - if (strcmp(cn_str, ets->peer)) { - error - ("Certificate verification error: CN (%s) != peer_name (%s)", - cn_str, ets->peer); + /* This is the peer certificate */ + X509_NAME_oneline(X509_get_subject_name(peer_cert), + subject, 256); + + X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert), + NID_commonName, cn_str, 256); + + /* Verify based on subject name */ + ptr1 = ets->peer; + if (!strcmp(TLS_VERIFY_SUBJECT, tls_verify_method)) { + ptr2 = subject; + } + + /* Verify based on common name (default) */ + if (strlen(tls_verify_method) == 0 || + !strcmp(TLS_VERIFY_NAME, tls_verify_method)) { + ptr2 = cn_str; + } + + /* Match the suffix of common name */ + if (!strcmp(TLS_VERIFY_SUFFIX, tls_verify_method)) { + int len = strlen(ptr1); + int off = strlen(cn_str) - len; + ptr2 = cn_str; + if (off > 0) { + ptr2 = cn_str + off; + } + } + + if (strcmp(ptr1, ptr2)) { + error("Certificate verification error: CN (%s) != %s", ptr1, ptr2); return 0; } - warn("Certificate CN: %s , peer name %s", cn_str, ets->peer); + info("Certificate CN: %s, peer name %s", cn_str, ets->peer); /* * If a peer certificate file was specified, here we check it