From 359b914554f4c01831ab9ee1a2ae3473a844c6a0 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 15 Nov 2022 01:37:32 -0500 Subject: [PATCH] import freeradius-3.0.21-34.el9 --- .../freeradius-Backport-OpenSSL3-fixes.patch | 1625 ++++++++++++----- ...pass-noenc-to-certificate-generation.patch | 136 ++ SOURCES/freeradius.sysusers | 3 + SPECS/freeradius.spec | 54 +- 4 files changed, 1333 insertions(+), 485 deletions(-) create mode 100644 SOURCES/freeradius-bootstrap-pass-noenc-to-certificate-generation.patch create mode 100644 SOURCES/freeradius.sysusers diff --git a/SOURCES/freeradius-Backport-OpenSSL3-fixes.patch b/SOURCES/freeradius-Backport-OpenSSL3-fixes.patch index ac6d783..3632b82 100644 --- a/SOURCES/freeradius-Backport-OpenSSL3-fixes.patch +++ b/SOURCES/freeradius-Backport-OpenSSL3-fixes.patch @@ -1,59 +1,61 @@ -From: Antonio Torres Date: Tue, 11 Jan 2022 -Subject: [PATCH] Backport OpenSSL3 fixes from 3.0.26 +Subject: [PATCH] Backport OpenSSL3 fixes from 3.0.x -Backport TLS and OpenSSL3 fixes from the future 3.0.26 FreeRADIUS release. - -Additionally include checks to avoid segfault when trying to use MD4 algorithm -while having OpenSSL legacy provider disabled. +Backport TLS and OpenSSL3 fixes from the 3.0.x branch as of May 24th, 2022. Related: rhbz#1978216 +Related: rhbz#2083699 Signed-off-by: Antonio Torres + +[antorres@redhat.com]: these changes include the macro WITH_FIPS, which allows FreeRADIUS +to work on top of OpenSSL 3.0 when the system is in FIPS mode. We enable this macro on the specfile. --- - share/dictionary.freeradius.internal | 50 +- + share/dictionary.freeradius.internal | 54 +- src/include/build.h | 25 +- src/include/libradius.h | 23 +- - src/include/listen.h | 24 +- - src/include/md4.h | 49 +- - src/include/md5.h | 29 +- + src/include/listen.h | 26 +- + src/include/md4.h | 50 +- + src/include/md5.h | 33 +- src/include/openssl3.h | 109 ++ src/include/tls-h | 32 +- src/include/token.h | 7 +- - src/lib/hmacmd5.c | 4 +- + src/lib/dict.c | 150 +- + src/lib/hmacmd5.c | 6 +- src/lib/hmacsha1.c | 5 +- src/lib/md4.c | 1 + src/lib/md5.c | 1 + src/lib/pair.c | 97 +- src/lib/print.c | 19 +- - src/lib/radius.c | 300 +++- + src/lib/radius.c | 300 ++- src/lib/token.c | 24 +- - src/main/cb.c | 118 +- + src/main/cb.c | 121 +- src/main/map.c | 54 +- - src/main/tls.c | 1819 ++++++++++++++++---- - src/main/tls_listen.c | 171 +- + src/main/radclient.c | 77 +- + src/main/tls.c | 1912 ++++++++++++++++---- + src/main/tls_listen.c | 177 +- src/modules/proto_dhcp/rlm_dhcp.c | 2 +- src/modules/rlm_eap/libeap/eap_tls.c | 178 +- src/modules/rlm_eap/libeap/eap_tls.h | 10 +- - src/modules/rlm_eap/libeap/mppe_keys.c | 161 +- + src/modules/rlm_eap/libeap/mppe_keys.c | 211 ++- src/modules/rlm_eap/radeapclient.c | 8 + src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c | 51 +- - .../rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c | 60 +- + .../rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c | 64 +- src/modules/rlm_eap/types/rlm_eap_peap/peap.c | 22 +- - .../rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c | 41 +- + .../rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c | 21 +- src/modules/rlm_eap/types/rlm_eap_pwd/const_time.h | 190 ++ - src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.c | 719 +++++--- + src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.c | 779 +++++--- src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.h | 16 +- .../rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.c | 508 +++++- .../rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.h | 2 + .../rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c | 52 +- .../rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h | 5 + - .../rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c | 40 +- + .../rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c | 20 +- src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c | 25 +- src/modules/rlm_exec/rlm_exec.c | 4 +- src/modules/rlm_expr/rlm_expr.c | 115 ++ src/modules/rlm_files/rlm_files.c | 2 +- - src/modules/rlm_ldap/ldap.h | 1 + - src/modules/rlm_mschap/rlm_mschap.c | 97 +- + src/modules/rlm_ldap/ldap.h | 4 + + src/modules/rlm_mschap/rlm_mschap.c | 99 +- src/modules/rlm_otp/otp_mppe.c | 16 +- src/modules/rlm_otp/otp_pwe.c | 8 - src/modules/rlm_otp/otp_radstate.c | 9 +- @@ -64,12 +66,30 @@ Signed-off-by: Antonio Torres src/modules/rlm_wimax/milenage.h | 128 ++ src/modules/rlm_wimax/rlm_wimax.c | 429 ++++- src/tests/keywords/md4 | 58 + - 54 files changed, 5583 insertions(+), 1114 deletions(-) + 56 files changed, 5913 insertions(+), 1205 deletions(-) diff --git a/share/dictionary.freeradius.internal b/share/dictionary.freeradius.internal -index 724e1f7ff6..53dd04ec9a 100644 +index 724e1f7ff6..347e3e59f3 100644 --- a/share/dictionary.freeradius.internal +++ b/share/dictionary.freeradius.internal +@@ -148,7 +148,7 @@ VALUE EAP-IKEv2-IDType DER_ASN1_GN 10 + VALUE EAP-IKEv2-IDType KEY_ID 11 + + ATTRIBUTE EAP-IKEv2-ID 1104 string +-ATTRIBUTE EAP-IKEv2-Secret 1105 string ++ATTRIBUTE EAP-IKEv2-Secret 1105 string secret + ATTRIBUTE EAP-IKEv2-AuthType 1106 integer + + VALUE EAP-IKEv2-AuthType none 0 +@@ -196,7 +196,7 @@ ATTRIBUTE FreeRADIUS-Client-Require-MA 1122 integer + VALUE FreeRADIUS-Client-Require-MA no 0 + VALUE FreeRADIUS-Client-Require-MA yes 1 + +-ATTRIBUTE FreeRADIUS-Client-Secret 1123 string ++ATTRIBUTE FreeRADIUS-Client-Secret 1123 string secret + ATTRIBUTE FreeRADIUS-Client-Shortname 1124 string + ATTRIBUTE FreeRADIUS-Client-NAS-Type 1125 string + ATTRIBUTE FreeRADIUS-Client-Virtual-Server 1126 string @@ -254,6 +254,7 @@ ATTRIBUTE FreeRADIUS-Response-Delay-USec 1155 integer ATTRIBUTE REST-HTTP-Header 1160 string @@ -316,7 +336,7 @@ index ce2f713de1..757828f070 100644 unsigned int attr, unsigned int vendor, int8_t tag); void fr_pair_list_mcopy_by_num(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from, diff --git a/src/include/listen.h b/src/include/listen.h -index 4f50bbf808..b395aeb046 100644 +index 4f50bbf808..e8222a3f02 100644 --- a/src/include/listen.h +++ b/src/include/listen.h @@ -45,6 +45,8 @@ typedef enum RAD_LISTEN_TYPE { @@ -328,11 +348,14 @@ index 4f50bbf808..b395aeb046 100644 RAD_LISTEN_STATUS_FROZEN, RAD_LISTEN_STATUS_EOL, RAD_LISTEN_STATUS_REMOVE_NOW -@@ -70,9 +72,10 @@ struct rad_listen { +@@ -68,11 +70,12 @@ struct rad_listen { + int fd; + char const *server; int status; - #ifdef WITH_TCP +-#ifdef WITH_TCP int count; - bool dual; ++#ifdef WITH_TCP rbtree_t *children; rad_listen_t *parent; + @@ -380,10 +403,21 @@ index 4f50bbf808..b395aeb046 100644 RADCLIENT_LIST *clients; diff --git a/src/include/md4.h b/src/include/md4.h -index b7bdd6a15e..f3801728c8 100644 +index b7bdd6a15e..1492bd4a5c 100644 --- a/src/include/md4.h +++ b/src/include/md4.h -@@ -71,14 +71,61 @@ void fr_md4_final(uint8_t out[MD4_DIGEST_LENGTH], FR_MD4_CTX *ctx) +@@ -26,6 +26,10 @@ RCSIDH(md4_h, "$Id$") + + #include + ++#ifdef WITH_FIPS ++#undef HAVE_OPENSSL_MD4_H ++#endif ++ + #ifdef HAVE_OPENSSL_MD4_H + # include + #endif +@@ -71,14 +75,58 @@ void fr_md4_final(uint8_t out[MD4_DIGEST_LENGTH], FR_MD4_CTX *ctx) void fr_md4_transform(uint32_t buf[4], uint8_t const inc[MD4_BLOCK_LENGTH]) CC_BOUNDED(__size__, 1, 4, 4) CC_BOUNDED(__minbytes__, 2, MD4_BLOCK_LENGTH); @@ -419,10 +453,7 @@ index b7bdd6a15e..f3801728c8 100644 + ctx->len = MD4_DIGEST_LENGTH; + + EVP_MD_CTX_set_flags(ctx->ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); -+ if (EVP_DigestInit_ex(ctx->ctx, ctx->md, NULL) != 1) { -+ fprintf(stderr, "Couldn't init MD4 algorithm. Enable OpenSSL legacy provider.\n"); -+ exit(EXIT_FAILURE); -+ } ++ EVP_DigestInit_ex(ctx->ctx, ctx->md, NULL); +} + +static inline void fr_md4_update(FR_MD4_CTX *ctx, uint8_t const *in, size_t inlen) @@ -447,10 +478,21 @@ index b7bdd6a15e..f3801728c8 100644 /* md4.c */ void fr_md4_calc(uint8_t out[MD4_DIGEST_LENGTH], uint8_t const *in, size_t inlen); diff --git a/src/include/md5.h b/src/include/md5.h -index a44584564f..64025f4a4d 100644 +index a44584564f..b7d571ac7b 100644 --- a/src/include/md5.h +++ b/src/include/md5.h -@@ -68,14 +68,41 @@ void fr_md5_final(uint8_t out[MD5_DIGEST_LENGTH], FR_MD5_CTX *ctx) +@@ -26,6 +26,10 @@ RCSIDH(md5_h, "$Id$") + + # include + ++#ifdef WITH_FIPS ++#undef HAVE_OPENSSL_MD5_H ++#endif ++ + #ifdef HAVE_OPENSSL_MD5_H + # include + #endif +@@ -68,14 +72,41 @@ void fr_md5_final(uint8_t out[MD5_DIGEST_LENGTH], FR_MD5_CTX *ctx) void fr_md5_transform(uint32_t state[4], uint8_t const block[MD5_BLOCK_LENGTH]) CC_BOUNDED(__size__, 1, 4, 4) CC_BOUNDED(__minbytes__, 2, MD5_BLOCK_LENGTH); @@ -609,7 +651,7 @@ index 0000000000..4423ee538a +#endif +#endif /* FR_OPENSSL3_H */ diff --git a/src/include/tls-h b/src/include/tls-h -index 62f57c4715..67835881a7 100644 +index 62f57c4715..206f55db79 100644 --- a/src/include/tls-h +++ b/src/include/tls-h @@ -94,7 +94,7 @@ typedef struct _record_t { @@ -621,7 +663,15 @@ index 62f57c4715..67835881a7 100644 int content_type; uint8_t handshake_type; uint8_t alert_level; -@@ -139,6 +139,9 @@ typedef struct _tls_session_t { +@@ -103,7 +103,6 @@ typedef struct _tls_info_t { + + char info_description[256]; + size_t record_len; +- int version; + } tls_info_t; + + #if OPENSSL_VERSION_NUMBER < 0x10001000L +@@ -139,6 +138,9 @@ typedef struct _tls_session_t { bool invalid_hb_used; //!< Whether heartbleed attack was detected. bool connected; //!< whether the outgoing socket is connected bool is_init_finished; //!< whether or not init is finished @@ -631,7 +681,7 @@ index 62f57c4715..67835881a7 100644 /* * Framed-MTU attribute in RADIUS, if present, can also be used to set this -@@ -160,8 +163,11 @@ typedef struct _tls_session_t { +@@ -160,8 +162,11 @@ typedef struct _tls_session_t { void *opaque; void (*free_opaque)(void *opaque); @@ -644,7 +694,7 @@ index 62f57c4715..67835881a7 100644 } tls_session_t; /* -@@ -309,16 +315,17 @@ int tls_error_io_log(REQUEST *request, tls_session_t *session, int ret, char co +@@ -309,16 +314,17 @@ int tls_error_io_log(REQUEST *request, tls_session_t *session, int ret, char co CC_HINT(format (printf, 4, 5)); void tls_global_cleanup(void); @@ -664,11 +714,10 @@ index 62f57c4715..67835881a7 100644 /* * Low-level TLS stuff -@@ -360,6 +367,11 @@ struct fr_tls_server_conf_t { +@@ -360,6 +366,10 @@ struct fr_tls_server_conf_t { bool disable_tlsv1; bool disable_tlsv1_1; bool disable_tlsv1_2; -+ bool tls13_enable_magic; + bool disallow_untrusted; //!< allow untrusted CAs to issue client certificates + + int min_version; @@ -676,7 +725,7 @@ index 62f57c4715..67835881a7 100644 char const *tls_min_version; char const *tls_max_version; -@@ -371,16 +383,20 @@ struct fr_tls_server_conf_t { +@@ -371,16 +381,20 @@ struct fr_tls_server_conf_t { bool check_crl; bool check_all_crl; bool allow_expired_crl; @@ -698,7 +747,7 @@ index 62f57c4715..67835881a7 100644 fr_hash_table_t *cache_ht; char session_context_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; -@@ -389,6 +405,8 @@ struct fr_tls_server_conf_t { +@@ -389,6 +403,8 @@ struct fr_tls_server_conf_t { char const *verify_client_cert_cmd; bool require_client_cert; @@ -707,7 +756,7 @@ index 62f57c4715..67835881a7 100644 #ifdef HAVE_OPENSSL_OCSP_H /* * OCSP Configuration -@@ -414,6 +432,10 @@ struct fr_tls_server_conf_t { +@@ -414,6 +430,10 @@ struct fr_tls_server_conf_t { char const *psk_query; #endif @@ -743,18 +792,289 @@ index 6cbd05217a..c8bb748702 100644 typedef struct FR_NAME_NUMBER { char const *name; +diff --git a/src/lib/dict.c b/src/lib/dict.c +index 96e06b5287..479bf1104e 100644 +--- a/src/lib/dict.c ++++ b/src/lib/dict.c +@@ -725,7 +725,8 @@ int dict_addattr(char const *name, int attr, unsigned int vendor, PW_TYPE type, + { + size_t namelen; + DICT_ATTR const *parent; +- DICT_ATTR *n; ++ DICT_ATTR *n; ++ DICT_ATTR const *old; + static int max_attr = 0; + + namelen = strlen(name); +@@ -882,6 +883,8 @@ int dict_addattr(char const *name, int attr, unsigned int vendor, PW_TYPE type, + return -1; + } + ++ if (flags.encrypt) flags.secret = 1; ++ + if (flags.length && (type != PW_TYPE_OCTETS)) { + fr_strerror_printf("The \"length\" flag can only be set for attributes of type \"octets\""); + return -1; +@@ -1080,6 +1083,18 @@ int dict_addattr(char const *name, int attr, unsigned int vendor, PW_TYPE type, + n->type = type; + n->flags = flags; + ++ /* ++ * Allow old-style names, but they always end up as ++ * new-style names. ++ */ ++ old = dict_attrbyvalue(n->attr, n->vendor); ++ if (old && (old->type == n->type)) { ++ DICT_ATTR *mutable; ++ ++ memcpy(&mutable, &old, sizeof(old)); /* const issues */ ++ mutable->flags.is_dup = true; ++ } ++ + /* + * Insert the attribute, only if it's not a duplicate. + */ +@@ -1258,6 +1273,8 @@ int dict_addvalue(char const *namestr, char const *attrstr, int value) + fr_int2str(dict_attr_types, da->type, "?Unknown?")); + return -1; + } ++ /* in v4 this is done with the UNCONST #define */ ++ ((DICT_ATTR *)((uintptr_t)(da)))->flags.has_value = 1; + } else { + value_fixup_t *fixup; + +@@ -1742,6 +1759,10 @@ static int process_attribute(char const* fn, int const line, + "\"encrypt=3\" flag set", fn, line); + return -1; + } ++ flags.secret = 1; ++ ++ } else if (strncmp(key, "secret", 6) == 0) { ++ flags.secret = 1; + + } else if (strncmp(key, "array", 6) == 0) { + flags.array = 1; +@@ -2022,7 +2043,7 @@ static int process_value_alias(char const* fn, int const line, char **argv, + } + + +-static int parse_format(char const *fn, int line, char const *format, int *pvalue, int *ptype, int *plength, bool *pcontinuation) ++static int parse_format(char const *fn, int line, char const *format, int *ptype, int *plength, bool *pcontinuation) + { + char const *p; + int type, length; +@@ -2075,9 +2096,8 @@ static int parse_format(char const *fn, int line, char const *format, int *pvalu + } + continuation = true; + +- if ((*pvalue != VENDORPEC_WIMAX) || +- (type != 1) || (length != 1)) { +- fr_strerror_printf("dict_init: %s[%d]: Only WiMAX VSAs can have continuations", ++ if ((type != 1) || (length != 1)) { ++ fr_strerror_printf("dict_init: %s[%d]: Only 'format=1,1' VSAs can have continuations", + fn, line); + return -1; + } +@@ -2132,7 +2152,7 @@ static int process_vendor(char const* fn, int const line, char **argv, + * Look for a format statement. Allow it to over-ride the hard-coded formats below. + */ + if (argc == 3) { +- if (parse_format(fn, line, argv[2], &value, &type, &length, &continuation) < 0) { ++ if (parse_format(fn, line, argv[2], &type, &length, &continuation) < 0) { + return -1; + } + +@@ -2409,7 +2429,8 @@ static int my_dict_init(char const *parent, char const *filename, + /* + * Optionally include a dictionary + */ +- if (strcasecmp(argv[0], "$INCLUDE-") == 0) { ++ if ((strcasecmp(argv[0], "$INCLUDE-") == 0) || ++ (strcasecmp(argv[0], "$-INCLUDE") == 0)) { + int rcode = my_dict_init(dir, argv[1], fn, line); + + if (rcode == -2) continue; +@@ -2783,45 +2804,72 @@ int dict_init(char const *dir, char const *fn) + return 0; + } + +-static size_t print_attr_oid(char *buffer, size_t size, unsigned int attr, +- int dv_type) ++static size_t print_attr_oid(char *buffer, size_t bufsize, unsigned int attr, unsigned int vendor) + { +- int nest; +- size_t outlen; ++ int nest, dv_type = 1; + size_t len; ++ char *p = buffer; ++ ++ if (vendor > FR_MAX_VENDOR) { ++ len = snprintf(p, bufsize, "%u.", vendor / FR_MAX_VENDOR); ++ p += len; ++ bufsize -= len; ++ vendor &= (FR_MAX_VENDOR) - 1; ++ } ++ ++ if (vendor) { ++ DICT_VENDOR *dv; ++ ++ /* ++ * dv_type is the length of the vendor's type field ++ * RFC 2865 never defined a mandatory length, so ++ * different vendors have different length type fields. ++ */ ++ dv = dict_vendorbyvalue(vendor); ++ if (dv) dv_type = dv->type; ++ ++ len = snprintf(p, bufsize, "26.%u.", vendor); ++ ++ p += len; ++ bufsize -= len; ++ } ++ + + switch (dv_type) { + default: + case 1: +- len = snprintf(buffer, size, "%u", attr & 0xff); ++ len = snprintf(p, bufsize, "%u", attr & 0xff); ++ p += len; ++ bufsize -= len; ++ if ((attr >> 8) == 0) return p - buffer; + break; + +- case 4: +- return snprintf(buffer, size, "%u", attr); +- + case 2: +- return snprintf(buffer, size, "%u", attr & 0xffff); +- +- } ++ len = snprintf(p, bufsize, "%u", attr & 0xffff); ++ p += len; ++ return p - buffer; + +- if ((attr >> 8) == 0) return len; ++ case 4: ++ len = snprintf(p, bufsize, "%u", attr); ++ p += len; ++ return p - buffer; + +- outlen = len; +- buffer += len; +- size -= len; ++ } + ++ /* ++ * "attr" is a sequence of packed numbers. Unpack them. ++ */ + for (nest = 1; nest <= fr_attr_max_tlv; nest++) { + if (((attr >> fr_attr_shift[nest]) & fr_attr_mask[nest]) == 0) break; + +- len = snprintf(buffer, size, ".%u", ++ len = snprintf(p, bufsize, ".%u", + (attr >> fr_attr_shift[nest]) & fr_attr_mask[nest]); + +- outlen = len; +- buffer += len; +- size -= len; ++ p += len; ++ bufsize -= len; + } + +- return outlen; ++ return p - buffer; + } + + /** Free dynamically allocated (unknown attributes) +@@ -2862,7 +2910,6 @@ void dict_attr_free(DICT_ATTR const **da) + int dict_unknown_from_fields(DICT_ATTR *da, unsigned int attr, unsigned int vendor) + { + char *p; +- int dv_type = 1; + size_t len = 0; + size_t bufsize = DICT_ATTR_MAX_NAME_LEN; + +@@ -2888,32 +2935,7 @@ int dict_unknown_from_fields(DICT_ATTR *da, unsigned int attr, unsigned int vend + p += len; + bufsize -= len; + +- if (vendor > FR_MAX_VENDOR) { +- len = snprintf(p, bufsize, "%u.", vendor / FR_MAX_VENDOR); +- p += len; +- bufsize -= len; +- vendor &= (FR_MAX_VENDOR) - 1; +- } +- +- if (vendor) { +- DICT_VENDOR *dv; +- +- /* +- * dv_type is the length of the vendor's type field +- * RFC 2865 never defined a mandatory length, so +- * different vendors have different length type fields. +- */ +- dv = dict_vendorbyvalue(vendor); +- if (dv) { +- dv_type = dv->type; +- } +- len = snprintf(p, bufsize, "26.%u.", vendor); +- +- p += len; +- bufsize -= len; +- } +- +- print_attr_oid(p, bufsize , attr, dv_type); ++ print_attr_oid(p, bufsize , attr, vendor); + + return 0; + } +@@ -3270,7 +3292,15 @@ DICT_ATTR const *dict_attrbyname(char const *name) + da = (DICT_ATTR *) buffer; + strlcpy(da->name, name, DICT_ATTR_MAX_NAME_LEN + 1); + +- return fr_hash_table_finddata(attributes_byname, da); ++ da = fr_hash_table_finddata(attributes_byname, da); ++ if (!da) return NULL; ++ ++ if (!da->flags.is_dup) return da; ++ ++ /* ++ * This MUST exist if the dup flag is set. ++ */ ++ return dict_attrbyvalue(da->attr, da->vendor); + } + + /** Look up a dictionary attribute by name embedded in another string +@@ -3464,3 +3494,13 @@ DICT_ATTR const *dict_unknown_add(DICT_ATTR const *old) + da = dict_attrbyvalue(old->attr, old->vendor); + return da; + } ++ ++size_t dict_print_oid(char *buffer, size_t buflen, DICT_ATTR const *da) ++{ ++ return print_attr_oid(buffer, buflen, da->attr, da->vendor); ++} ++ ++int dict_walk(fr_hash_table_walk_t callback, void *context) ++{ ++ return fr_hash_table_walk(attributes_byname, callback, context); ++} diff --git a/src/lib/hmacmd5.c b/src/lib/hmacmd5.c -index 1cca00fa2a..88ba171aa0 100644 +index 1cca00fa2a..2aad490e30 100644 --- a/src/lib/hmacmd5.c +++ b/src/lib/hmacmd5.c -@@ -34,6 +34,7 @@ RCSID("$Id$") +@@ -34,8 +34,9 @@ RCSID("$Id$") #include #include +#include - #ifdef HAVE_OPENSSL_EVP_H +-#ifdef HAVE_OPENSSL_EVP_H ++#if defined(HAVE_OPENSSL_EVP_H) && !defined(WITH_FIPS) /** Calculate HMAC using OpenSSL's MD5 implementation + * + * @param digest Caller digest to be filled in. @@ -49,6 +50,7 @@ void fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *text, size_t uint8_t const *key, size_t key_len) { @@ -1644,7 +1964,7 @@ index 8ae41b392f..a7978622e6 100644 true, /* `foo` */ false diff --git a/src/main/cb.c b/src/main/cb.c -index 4ae14e575b..0796914b41 100644 +index 4ae14e575b..f8b2edbecc 100644 --- a/src/main/cb.c +++ b/src/main/cb.c @@ -29,45 +29,94 @@ USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ @@ -1751,20 +2071,22 @@ index 4ae14e575b..0796914b41 100644 } } } -@@ -83,18 +132,18 @@ void cbtls_msg(int write_p, int msg_version, int content_type, - tls_session_t *state = (tls_session_t *)arg; - - /* -- * OpenSSL 1.0.2 calls this function with 'pseudo' -- * content types. Which breaks our tracking of -- * the SSL Session state. -+ * OpenSSL calls this function with 'pseudo' content -+ * types. Which breaks our tracking of the SSL Session -+ * state. +@@ -87,14 +136,24 @@ void cbtls_msg(int write_p, int msg_version, int content_type, + * content types. Which breaks our tracking of + * the SSL Session state. */ -- if ((msg_version == 0) && (content_type > UINT8_MAX)) { ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + if ((msg_version == 0) && (content_type > UINT8_MAX)) { - DEBUG4("Ignoring cbtls_msg call with pseudo content type %i, version %i", -+ if ((msg_version == 0) || (content_type >= UINT8_MAX)) { ++#else ++ /* ++ * "...we do not see the need to resolve application breakage ++ * just because the documentation now is incorrect." ++ * ++ * https://github.com/openssl/openssl/issues/17262 ++ */ ++ if ((content_type > UINT8_MAX) && (content_type != SSL3_RT_INNER_CONTENT_TYPE)) { ++#endif + DEBUG4("(TLS) Ignoring cbtls_msg call with pseudo content type %i, version %i", content_type, msg_version); return; @@ -1776,7 +2098,7 @@ index 4ae14e575b..0796914b41 100644 return; } -@@ -104,6 +153,25 @@ void cbtls_msg(int write_p, int msg_version, int content_type, +@@ -104,6 +163,25 @@ void cbtls_msg(int write_p, int msg_version, int content_type, */ if (!state) return; @@ -1802,7 +2124,15 @@ index 4ae14e575b..0796914b41 100644 /* * 0 - received (from peer) * 1 - sending (to peer) -@@ -124,6 +192,12 @@ void cbtls_msg(int write_p, int msg_version, int content_type, +@@ -111,7 +189,6 @@ void cbtls_msg(int write_p, int msg_version, int content_type, + state->info.origin = write_p; + state->info.content_type = content_type; + state->info.record_len = len; +- state->info.version = msg_version; + state->info.initialized = true; + + if (content_type == SSL3_RT_ALERT) { +@@ -124,6 +201,12 @@ void cbtls_msg(int write_p, int msg_version, int content_type, state->info.alert_level = 0x00; state->info.alert_description = 0x00; @@ -1815,7 +2145,7 @@ index 4ae14e575b..0796914b41 100644 #ifdef SSL3_RT_HEARTBEAT } else if (content_type == TLS1_RT_HEARTBEAT) { uint8_t *p = buf; -@@ -141,16 +215,24 @@ void cbtls_msg(int write_p, int msg_version, int content_type, +@@ -141,16 +224,24 @@ void cbtls_msg(int write_p, int msg_version, int content_type, } #endif } @@ -1939,8 +2269,148 @@ index 6275ba124d..17988d27f9 100644 /* * += - Add all src_list attributes to the destination */ +diff --git a/src/main/radclient.c b/src/main/radclient.c +index 52d2872b13..09d27c8711 100644 +--- a/src/main/radclient.c ++++ b/src/main/radclient.c +@@ -28,6 +28,10 @@ RCSID("$Id$") + #include + #include + #include ++#ifdef HAVE_OPENSSL_SSL_H ++#include ++#include ++#endif + #include + + #ifdef HAVE_GETOPT_H +@@ -36,6 +40,8 @@ RCSID("$Id$") + + #include + ++USES_APPLE_DEPRECATED_API ++ + typedef struct REQUEST REQUEST; /* to shut up warnings about mschap.h */ + + #include "smbdes.h" +@@ -155,9 +161,60 @@ static int _rc_request_free(rc_request_t *request) + return 0; + } + ++#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L ++# include ++ ++static OSSL_PROVIDER *openssl_default_provider = NULL; ++static OSSL_PROVIDER *openssl_legacy_provider = NULL; ++ ++static int openssl3_init(void) ++{ ++ /* ++ * Load the default provider for most algorithms ++ */ ++ openssl_default_provider = OSSL_PROVIDER_load(NULL, "default"); ++ if (!openssl_default_provider) { ++ ERROR("(TLS) Failed loading default provider"); ++ return -1; ++ } ++ ++ /* ++ * Needed for MD4 ++ * ++ * https://www.openssl.org/docs/man3.0/man7/migration_guide.html#Legacy-Algorithms ++ */ ++ openssl_legacy_provider = OSSL_PROVIDER_load(NULL, "legacy"); ++ if (!openssl_legacy_provider) { ++ ERROR("(TLS) Failed loading legacy provider"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void openssl3_free(void) ++{ ++ if (openssl_default_provider && !OSSL_PROVIDER_unload(openssl_default_provider)) { ++ ERROR("Failed unloading default provider"); ++ } ++ openssl_default_provider = NULL; ++ ++ if (openssl_legacy_provider && !OSSL_PROVIDER_unload(openssl_legacy_provider)) { ++ ERROR("Failed unloading legacy provider"); ++ } ++ openssl_legacy_provider = NULL; ++} ++#else ++#define openssl3_init() ++#define openssl3_free() ++#endif ++ ++ ++ + static int mschapv1_encode(RADIUS_PACKET *packet, VALUE_PAIR **request, + char const *password) + { ++ int rcode; + unsigned int i; + uint8_t *p; + VALUE_PAIR *challenge, *reply; +@@ -190,9 +247,8 @@ static int mschapv1_encode(RADIUS_PACKET *packet, VALUE_PAIR **request, + + p[1] = 0x01; /* NT hash */ + +- if (mschap_ntpwdhash(nthash, password) < 0) { +- return 0; +- } ++ rcode = mschap_ntpwdhash(nthash, password); ++ if (rcode < 0) return 0; + + smbdes_mschap(nthash, challenge->vp_octets, p + 26); + return 1; +@@ -960,8 +1016,8 @@ static int send_one_packet(rc_request_t *request) + */ + fr_packet_list_yank(pl, request->packet); + +- REDEBUG("No reply from server for ID %d socket %d", +- request->packet->id, request->packet->sockfd); ++ RDEBUG("No reply from server for ID %d socket %d", ++ request->packet->id, request->packet->sockfd); + deallocate_id(request); + + /* +@@ -1197,9 +1253,11 @@ int main(int argc, char **argv) + break; + + case 'c': +- if (!isdigit((int) *optarg)) +- usage(); ++ if (!isdigit((int) *optarg)) usage(); ++ + resend_count = atoi(optarg); ++ ++ if (resend_count < 1) usage(); + break; + + case 'D': +@@ -1421,6 +1479,8 @@ int main(int argc, char **argv) + exit(1); + } + ++ openssl3_init(); ++ + /* + * Bind to the first specified IP address and port. + * This means we ignore later ones. +@@ -1637,5 +1697,8 @@ int main(int argc, char **argv) + if ((stats.lost > 0) || (stats.failed > 0)) { + exit(1); + } ++ ++ openssl3_free(); ++ + exit(0); + } diff --git a/src/main/tls.c b/src/main/tls.c -index 78c7370a63..cc8dc53178 100644 +index 78c7370a63..118978b52a 100644 --- a/src/main/tls.c +++ b/src/main/tls.c @@ -27,6 +27,7 @@ USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ @@ -1962,7 +2432,7 @@ index 78c7370a63..cc8dc53178 100644 #ifdef HAVE_UTIME_H #include #endif -@@ -56,8 +61,19 @@ USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ +@@ -56,8 +61,25 @@ USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ # endif # include @@ -1977,12 +2447,18 @@ index 78c7370a63..cc8dc53178 100644 +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#define ERR_get_error_line(_file, _line) ERR_get_error_all(_file, _line, NULL, NULL, NULL) ++ ++#define FIPS_mode(_x) EVP_default_properties_is_fips_enabled(NULL) ++#define PEM_read_bio_DHparams(_bio, _x, _y, _z) PEM_read_bio_Parameters(_bio, &dh) ++#define SSL_CTX_set0_tmp_dh_pkey(_ctx, _dh) SSL_CTX_set_tmp_dh(_ctx, _dh) ++#define DH EVP_PKEY ++#define DH_free(_dh) +#endif + #ifdef ENABLE_OPENSSL_VERSION_CHECK typedef struct libssl_defect { uint64_t high; -@@ -153,6 +169,11 @@ static unsigned int record_plus(record_t *buf, void const *ptr, +@@ -153,6 +175,11 @@ static unsigned int record_plus(record_t *buf, void const *ptr, static unsigned int record_minus(record_t *buf, void *ptr, unsigned int size); @@ -1994,7 +2470,7 @@ index 78c7370a63..cc8dc53178 100644 DIAG_OFF(format-nonliteral) /** Print errors in the TLS thread local error stack * -@@ -191,9 +212,9 @@ static int tls_verror_log(REQUEST *request, char const *msg, va_list ap) +@@ -191,9 +218,9 @@ static int tls_verror_log(REQUEST *request, char const *msg, va_list ap) /* Extra verbose */ if ((request && RDEBUG_ENABLED3) || DEBUG_ENABLED3) { @@ -2006,7 +2482,7 @@ index 78c7370a63..cc8dc53178 100644 } talloc_free(p); -@@ -205,7 +226,7 @@ static int tls_verror_log(REQUEST *request, char const *msg, va_list ap) +@@ -205,7 +232,7 @@ static int tls_verror_log(REQUEST *request, char const *msg, va_list ap) * Print the error we were given, irrespective * of whether there were any OpenSSL errors. */ @@ -2015,7 +2491,7 @@ index 78c7370a63..cc8dc53178 100644 talloc_free(p); } -@@ -217,9 +238,9 @@ static int tls_verror_log(REQUEST *request, char const *msg, va_list ap) +@@ -217,9 +244,9 @@ static int tls_verror_log(REQUEST *request, char const *msg, va_list ap) ERR_error_string_n(error, buffer, sizeof(buffer)); /* Extra verbose */ if ((request && RDEBUG_ENABLED3) || DEBUG_ENABLED3) { @@ -2027,7 +2503,7 @@ index 78c7370a63..cc8dc53178 100644 } in_stack++; } while ((error = ERR_get_error_line(&file, &line))); -@@ -309,11 +330,11 @@ int tls_error_io_log(REQUEST *request, tls_session_t *session, int ret, char con +@@ -309,11 +336,11 @@ int tls_error_io_log(REQUEST *request, tls_session_t *session, int ret, char con * being regarded as "dead". */ case SSL_ERROR_SYSCALL: @@ -2041,7 +2517,7 @@ index 78c7370a63..cc8dc53178 100644 return 0; /* -@@ -323,7 +344,7 @@ int tls_error_io_log(REQUEST *request, tls_session_t *session, int ret, char con +@@ -323,7 +350,7 @@ int tls_error_io_log(REQUEST *request, tls_session_t *session, int ret, char con * the code needs updating here. */ default: @@ -2050,7 +2526,7 @@ index 78c7370a63..cc8dc53178 100644 return 0; } -@@ -376,7 +397,7 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity, +@@ -376,7 +403,7 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity, * The passed identity is weird. Deny it. */ if (!identity_is_safe(identity)) { @@ -2059,7 +2535,7 @@ index 78c7370a63..cc8dc53178 100644 return 0; } -@@ -386,7 +407,7 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity, +@@ -386,7 +413,7 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity, hex_len = radius_xlat(buffer, sizeof(buffer), request, conf->psk_query, NULL, NULL); if (!hex_len) { @@ -2068,7 +2544,7 @@ index 78c7370a63..cc8dc53178 100644 return 0; } -@@ -396,7 +417,7 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity, +@@ -396,7 +423,7 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity, * the truncation, and complain about it. */ if (hex_len > (2 * max_psk_len)) { @@ -2077,7 +2553,7 @@ index 78c7370a63..cc8dc53178 100644 (unsigned int) hex_len, 2 * max_psk_len); return 0; } -@@ -419,7 +440,7 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity, +@@ -419,7 +446,7 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity, * static identity. */ if (strcmp(identity, conf->psk_identity) != 0) { @@ -2086,7 +2562,7 @@ index 78c7370a63..cc8dc53178 100644 identity); return 0; } -@@ -475,8 +496,6 @@ void tls_session_id(SSL_SESSION *ssn, char *buffer, size_t bufsize) +@@ -475,8 +502,6 @@ void tls_session_id(SSL_SESSION *ssn, char *buffer, size_t bufsize) #endif } @@ -2095,7 +2571,7 @@ index 78c7370a63..cc8dc53178 100644 static int _tls_session_free(tls_session_t *ssn) { /* -@@ -492,6 +511,52 @@ static int _tls_session_free(tls_session_t *ssn) +@@ -492,6 +517,52 @@ static int _tls_session_free(tls_session_t *ssn) return 0; } @@ -2148,7 +2624,7 @@ index 78c7370a63..cc8dc53178 100644 tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, int fd, VALUE_PAIR **certs) { int ret; -@@ -506,6 +571,7 @@ tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *con +@@ -506,6 +577,7 @@ tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *con ssn->ctx = conf->ctx; ssn->mtu = conf->fragment_size; @@ -2156,7 +2632,17 @@ index 78c7370a63..cc8dc53178 100644 SSL_CTX_set_mode(ssn->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_AUTO_RETRY); -@@ -537,15 +603,14 @@ tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *con +@@ -516,6 +588,9 @@ tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *con + } + + request = request_alloc(ssn); ++ request->packet = rad_alloc(request, false); ++ request->reply = rad_alloc(request, false); ++ + SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_REQUEST, (void *)request); + + /* +@@ -537,15 +612,14 @@ tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *con SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf); SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_SSN, (void *)ssn); if (certs) SSL_set_ex_data(ssn->ssl, fr_tls_ex_index_certs, (void *)certs); @@ -2176,7 +2662,7 @@ index 78c7370a63..cc8dc53178 100644 case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: -@@ -555,7 +620,7 @@ tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *con +@@ -555,7 +629,7 @@ tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *con } if (ret <= 0) { @@ -2185,7 +2671,7 @@ index 78c7370a63..cc8dc53178 100644 talloc_free(ssn); return NULL; -@@ -575,18 +640,61 @@ tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *con +@@ -575,18 +649,61 @@ tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *con * @param conf to use to configure the tls session. * @param request The current #REQUEST. * @param client_cert Whether to require a client_cert. @@ -2249,7 +2735,7 @@ index 78c7370a63..cc8dc53178 100644 new_tls = SSL_new(conf->ctx); if (new_tls == NULL) { -@@ -594,11 +702,36 @@ tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQU +@@ -594,11 +711,35 @@ tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQU return NULL; } @@ -2264,11 +2750,10 @@ index 78c7370a63..cc8dc53178 100644 + WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + WARN("!! FORCING MAXIMUM TLS VERSION TO TLS 1.2 !!"); + WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); -+ WARN("!! There is no standard for using this EAP method with TLS 1.3"); -+ WARN("!! Please set tls_max_version = \"1.2\""); -+ WARN("!! FreeRADIUS only supports TLS 1.3 for special builds of wpa_supplicant and Windows"); -+ WARN("!! This limitation is likely to change in late 2021."); -+ WARN("!! If you are using this version of FreeRADIUS after 2021, you will probably need to upgrade"); ++ WARN("!! There is either no standard for using this EAP method with TLS 1.3,"); ++ WARN("!! or FreeRADIUS does not fully support TLS 1.3 for this EAP method."); ++ WARN("!!"); ++ WARN("!! This message can be removed by setting tls_max_version = \"1.2\""); + WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + + if (SSL_set_max_proto_version(new_tls, TLS1_2_VERSION) == 0) { @@ -2287,7 +2772,7 @@ index 78c7370a63..cc8dc53178 100644 return NULL; } session_init(state); -@@ -606,6 +739,14 @@ tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQU +@@ -606,6 +747,14 @@ tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQU state->ctx = conf->ctx; state->ssl = new_tls; @@ -2302,7 +2787,7 @@ index 78c7370a63..cc8dc53178 100644 /* * Initialize callbacks -@@ -637,6 +778,85 @@ tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQU +@@ -637,6 +786,85 @@ tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQU SSL_set_msg_callback_arg(new_tls, state); SSL_set_info_callback(new_tls, cbtls_info); @@ -2388,7 +2873,7 @@ index 78c7370a63..cc8dc53178 100644 /* * In Server mode we only accept. */ -@@ -646,7 +866,7 @@ tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQU +@@ -646,7 +874,7 @@ tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQU * Verify the peer certificate, if asked. */ if (client_cert) { @@ -2397,7 +2882,7 @@ index 78c7370a63..cc8dc53178 100644 verify_mode = SSL_VERIFY_PEER; verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; verify_mode |= SSL_VERIFY_CLIENT_ONCE; -@@ -670,10 +890,41 @@ tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQU +@@ -670,10 +898,41 @@ tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQU * just too much. */ state->mtu = conf->fragment_size; @@ -2441,7 +2926,7 @@ index 78c7370a63..cc8dc53178 100644 if (conf->session_cache_enable) state->allow_session_resumption = true; /* otherwise it's false */ -@@ -697,12 +948,15 @@ int tls_handshake_recv(REQUEST *request, tls_session_t *ssn) +@@ -697,12 +956,15 @@ int tls_handshake_recv(REQUEST *request, tls_session_t *ssn) { int err; @@ -2459,7 +2944,7 @@ index 78c7370a63..cc8dc53178 100644 record_init(&ssn->dirty_in); return 0; } -@@ -716,21 +970,23 @@ int tls_handshake_recv(REQUEST *request, tls_session_t *ssn) +@@ -716,24 +978,26 @@ int tls_handshake_recv(REQUEST *request, tls_session_t *ssn) return 1; } @@ -2484,8 +2969,12 @@ index 78c7370a63..cc8dc53178 100644 + REXDENT(); } - switch (ssn->info.version) { -@@ -767,13 +1023,15 @@ int tls_handshake_recv(REQUEST *request, tls_session_t *ssn) +- switch (ssn->info.version) { ++ switch (SSL_version(ssn->ssl)) { + case SSL2_VERSION: + str_version = "SSL 2.0"; + break; +@@ -767,13 +1031,15 @@ int tls_handshake_recv(REQUEST *request, tls_session_t *ssn) if (vp) { fr_pair_value_strcpy(vp, str_version); fr_pair_add(&request->state, vp); @@ -2505,7 +2994,7 @@ index 78c7370a63..cc8dc53178 100644 #if OPENSSL_VERSION_NUMBER >= 0x10001000L /* -@@ -791,7 +1049,7 @@ int tls_handshake_recv(REQUEST *request, tls_session_t *ssn) +@@ -791,7 +1057,7 @@ int tls_handshake_recv(REQUEST *request, tls_session_t *ssn) * to get the session is a hard fail. */ if (!ssn->ssl_session && ssn->is_init_finished) { @@ -2514,7 +3003,7 @@ index 78c7370a63..cc8dc53178 100644 return 0; } } -@@ -805,23 +1063,21 @@ int tls_handshake_recv(REQUEST *request, tls_session_t *ssn) +@@ -805,25 +1071,25 @@ int tls_handshake_recv(REQUEST *request, tls_session_t *ssn) err = BIO_read(ssn->from_ssl, ssn->dirty_out.data, sizeof(ssn->dirty_out.data)); if (err > 0) { @@ -2538,11 +3027,16 @@ index 78c7370a63..cc8dc53178 100644 } else { - - RDEBUG2("TLS - Application data."); +- /* Its clean application data, do whatever we want */ + RDEBUG2("(TLS) Application data."); - /* Its clean application data, do whatever we want */ ++ /* Its clean application data, leave whatever is in the buffer */ ++#if 0 record_init(&ssn->clean_out); ++#endif } -@@ -855,13 +1111,12 @@ int tls_handshake_send(REQUEST *request, tls_session_t *ssn) + + /* We are done with dirty_in, reinitialize it */ +@@ -855,13 +1121,12 @@ int tls_handshake_send(REQUEST *request, tls_session_t *ssn) record_minus(&ssn->clean_in, NULL, written); /* Get the dirty data from Bio to send it */ @@ -2560,7 +3054,7 @@ index 78c7370a63..cc8dc53178 100644 return 0; } } -@@ -963,7 +1218,10 @@ void tls_session_information(tls_session_t *tls_session) +@@ -963,7 +1228,10 @@ void tls_session_information(tls_session_t *tls_session) { char const *str_write_p, *str_version, *str_content_type = ""; char const *str_details1 = "", *str_details2= ""; @@ -2571,7 +3065,7 @@ index 78c7370a63..cc8dc53178 100644 char buffer[32]; /* -@@ -972,7 +1230,18 @@ void tls_session_information(tls_session_t *tls_session) +@@ -972,9 +1240,20 @@ void tls_session_information(tls_session_t *tls_session) */ if (rad_debug_lvl == 0) return; @@ -2589,9 +3083,18 @@ index 78c7370a63..cc8dc53178 100644 + +#define FROM_CLIENT (tls_session->info.origin == 0) - switch (tls_session->info.version) { +- switch (tls_session->info.version) { ++ switch (SSL_version(tls_session->ssl)) { case SSL2_VERSION: -@@ -1006,8 +1275,7 @@ void tls_session_information(tls_session_t *tls_session) + str_version = "SSL 2.0 "; + break; +@@ -1001,13 +1280,12 @@ void tls_session_information(tls_session_t *tls_session) + #endif + + default: +- sprintf(buffer, "UNKNOWN TLS VERSION '%04X'", tls_session->info.version); ++ sprintf(buffer, "UNKNOWN TLS VERSION '%04X'", SSL_version(tls_session->ssl)); + str_version = buffer; break; } @@ -2601,7 +3104,7 @@ index 78c7370a63..cc8dc53178 100644 switch (tls_session->info.content_type) { case SSL3_RT_CHANGE_CIPHER_SPEC: str_content_type = "ChangeCipherSpec"; -@@ -1026,7 +1294,8 @@ void tls_session_information(tls_session_t *tls_session) +@@ -1026,7 +1304,8 @@ void tls_session_information(tls_session_t *tls_session) break; default: @@ -2611,7 +3114,7 @@ index 78c7370a63..cc8dc53178 100644 break; } -@@ -1045,9 +1314,12 @@ void tls_session_information(tls_session_t *tls_session) +@@ -1045,9 +1324,12 @@ void tls_session_information(tls_session_t *tls_session) } str_details2 = " ???"; @@ -2624,7 +3127,7 @@ index 78c7370a63..cc8dc53178 100644 break; case SSL3_AD_UNEXPECTED_MESSAGE: -@@ -1074,24 +1346,34 @@ void tls_session_information(tls_session_t *tls_session) +@@ -1074,24 +1356,34 @@ void tls_session_information(tls_session_t *tls_session) str_details2 = " handshake_failure"; break; @@ -2659,7 +3162,7 @@ index 78c7370a63..cc8dc53178 100644 break; case SSL3_AD_ILLEGAL_PARAMETER: -@@ -1100,6 +1382,7 @@ void tls_session_information(tls_session_t *tls_session) +@@ -1100,6 +1392,7 @@ void tls_session_information(tls_session_t *tls_session) case TLS1_AD_UNKNOWN_CA: str_details2 = " unknown_ca"; @@ -2667,7 +3170,7 @@ index 78c7370a63..cc8dc53178 100644 break; case TLS1_AD_ACCESS_DENIED: -@@ -1120,6 +1403,18 @@ void tls_session_information(tls_session_t *tls_session) +@@ -1120,6 +1413,18 @@ void tls_session_information(tls_session_t *tls_session) case TLS1_AD_PROTOCOL_VERSION: str_details2 = " protocol_version"; @@ -2677,7 +3180,7 @@ index 78c7370a63..cc8dc53178 100644 + /* + * Complain about OpenSSL bugs. + */ -+ if ((tls_session->info.version > tls_session->conf->max_version) && ++ if ((SSL_version(tls_session->ssl) > tls_session->conf->max_version) && + (rad_debug_lvl > 0)) { + WARN("TLS 1.3 has been negotiated even though it was disabled. This is an OpenSSL Bug."); + WARN("Please set: cipher_list = \"DEFAULT@SECLEVEL=1\" in the tls {...} section."); @@ -2686,7 +3189,7 @@ index 78c7370a63..cc8dc53178 100644 break; case TLS1_AD_INSUFFICIENT_SECURITY: -@@ -1137,12 +1432,69 @@ void tls_session_information(tls_session_t *tls_session) +@@ -1137,12 +1442,69 @@ void tls_session_information(tls_session_t *tls_session) case TLS1_AD_NO_RENEGOTIATION: str_details2 = " no_renegotiation"; break; @@ -2757,7 +3260,7 @@ index 78c7370a63..cc8dc53178 100644 if (tls_session->info.record_len > 0) switch (tls_session->info.handshake_type) { case SSL3_MT_HELLO_REQUEST: -@@ -1157,6 +1509,18 @@ void tls_session_information(tls_session_t *tls_session) +@@ -1157,6 +1519,18 @@ void tls_session_information(tls_session_t *tls_session) str_details1 = ", ServerHello"; break; @@ -2776,7 +3279,7 @@ index 78c7370a63..cc8dc53178 100644 case SSL3_MT_CERTIFICATE: str_details1 = ", Certificate"; break; -@@ -1184,31 +1548,52 @@ void tls_session_information(tls_session_t *tls_session) +@@ -1184,31 +1558,52 @@ void tls_session_information(tls_session_t *tls_session) case SSL3_MT_FINISHED: str_details1 = ", Finished"; break; @@ -2834,7 +3337,7 @@ index 78c7370a63..cc8dc53178 100644 CONF_PARSER_TERMINATOR }; -@@ -1256,6 +1641,7 @@ static CONF_PARSER tls_server_config[] = { +@@ -1256,6 +1651,7 @@ static CONF_PARSER tls_server_config[] = { #ifdef X509_V_FLAG_CRL_CHECK_ALL { "check_all_crl", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, check_all_crl), "no" }, #endif @@ -2842,7 +3345,7 @@ index 78c7370a63..cc8dc53178 100644 { "allow_expired_crl", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, allow_expired_crl), NULL }, { "check_cert_cn", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, check_cert_cn), NULL }, { "cipher_list", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, cipher_list), NULL }, -@@ -1263,6 +1649,10 @@ static CONF_PARSER tls_server_config[] = { +@@ -1263,6 +1659,10 @@ static CONF_PARSER tls_server_config[] = { { "check_cert_issuer", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, check_cert_issuer), NULL }, { "require_client_cert", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, require_client_cert), NULL }, @@ -2853,7 +3356,7 @@ index 78c7370a63..cc8dc53178 100644 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH { "ecdh_curve", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, ecdh_curve), "prime256v1" }, -@@ -1281,9 +1671,23 @@ static CONF_PARSER tls_server_config[] = { +@@ -1281,9 +1681,19 @@ static CONF_PARSER tls_server_config[] = { { "disable_tlsv1_2", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, disable_tlsv1_2), NULL }, #endif @@ -2869,17 +3372,13 @@ index 78c7370a63..cc8dc53178 100644 + "1.0" +#endif + }, -+ -+#ifdef TLS1_3_VERSION -+ { "tls13_enable", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, tls13_enable_magic), NULL }, -+#endif - { "tls_min_version", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, tls_min_version), "1.0" }, + { "realm_dir", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, realm_dir), NULL }, { "cache", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) cache_config }, -@@ -1312,6 +1716,7 @@ static CONF_PARSER tls_client_config[] = { +@@ -1312,6 +1722,7 @@ static CONF_PARSER tls_client_config[] = { { "check_cert_cn", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, check_cert_cn), NULL }, { "cipher_list", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, cipher_list), NULL }, { "check_cert_issuer", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, check_cert_issuer), NULL }, @@ -2887,13 +3386,14 @@ index 78c7370a63..cc8dc53178 100644 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH -@@ -1331,14 +1736,25 @@ static CONF_PARSER tls_client_config[] = { +@@ -1331,9 +1742,19 @@ static CONF_PARSER tls_client_config[] = { { "disable_tlsv1_2", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, disable_tlsv1_2), NULL }, #endif - { "tls_max_version", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, tls_max_version), "" }, + { "tls_max_version", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, tls_max_version), NULL }, -+ + +- { "tls_min_version", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, tls_min_version), "1.0" }, + { "tls_min_version", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, tls_min_version), +#if defined(TLS1_2_VERSION) + "1.2" @@ -2903,22 +3403,16 @@ index 78c7370a63..cc8dc53178 100644 + "1.0" +#endif + }, - -- { "tls_min_version", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, tls_min_version), "1.0" }, ++ + { "hostname", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, client_hostname), NULL }, CONF_PARSER_TERMINATOR }; +@@ -1347,7 +1768,44 @@ static int load_dh_params(SSL_CTX *ctx, char *file) + DH *dh = NULL; + BIO *bio; - -+#if OPENSSL_VERSION_NUMBER < 0x30000000L - /* - * TODO: Check for the type of key exchange * like conf->dh_key - */ -@@ -1349,6 +1765,23 @@ static int load_dh_params(SSL_CTX *ctx, char *file) - - if (!file) return 0; - +- if (!file) return 0; + /* + * Prior to trying to load the file, check what OpenSSL will do with it. + * @@ -2932,22 +3426,35 @@ index 78c7370a63..cc8dc53178 100644 +#if OPENSSL_VERSION_NUMBER >= 0x10101000L + if (FIPS_mode() > 0) { + WARN(LOG_PREFIX ": Ignoring user-selected DH parameters in FIPS mode. Using defaults."); ++ file = NULL; ++ } ++ ++ /* ++ * No dh file, set auto context. ++ */ ++ if (!file) { ++ if (!SSL_CTX_set_dh_auto(ctx, 1)) { ++ ERROR(LOG_PREFIX ": Unable to set DH parameters"); ++ return -1; ++ } ++ ++ return 0; ++ } ++ ++ WARN(LOG_PREFIX ": Setting DH parameters from %s - this is no longer necessary.", file); ++ WARN(LOG_PREFIX ": You should comment out the 'dh_file' configuration item."); ++ ++#else ++ if (!file) { ++ WARN(LOG_PREFIX ": Cannot set DH parameters. DH cipher suites may not work."); + return 0; + } +#endif + + if ((bio = BIO_new_file(file, "r")) == NULL) { ERROR(LOG_PREFIX ": Unable to open DH file - %s", file); - return -1; -@@ -1371,6 +1804,7 @@ static int load_dh_params(SSL_CTX *ctx, char *file) - DH_free(dh); - return 0; - } -+#endif - - - /* -@@ -1422,7 +1856,7 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) +@@ -1422,7 +1880,7 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) conf = (fr_tls_server_conf_t *)SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_CONF); if (!conf) { @@ -2956,7 +3463,7 @@ index 78c7370a63..cc8dc53178 100644 return 0; } -@@ -1439,7 +1873,7 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) +@@ -1439,7 +1897,7 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) blob_len = i2d_SSL_SESSION(sess, NULL); if (blob_len < 1) { /* something went wrong */ @@ -2965,7 +3472,7 @@ index 78c7370a63..cc8dc53178 100644 return 0; } -@@ -1447,14 +1881,14 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) +@@ -1447,14 +1905,14 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) /* alloc and convert to ASN.1 */ sess_blob = malloc(blob_len); if (!sess_blob) { @@ -2982,7 +3489,7 @@ index 78c7370a63..cc8dc53178 100644 goto error; } -@@ -1463,7 +1897,7 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) +@@ -1463,7 +1921,7 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) conf->session_cache_path, FR_DIR_SEP, buffer); fd = open(filename, O_RDWR|O_CREAT|O_EXCL, S_IWUSR); if (fd < 0) { @@ -2991,7 +3498,7 @@ index 78c7370a63..cc8dc53178 100644 filename, fr_syserror(errno)); goto error; } -@@ -1486,7 +1920,7 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) +@@ -1486,7 +1944,7 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) while (todo > 0) { rv = write(fd, p, todo); if (rv < 1) { @@ -3000,7 +3507,7 @@ index 78c7370a63..cc8dc53178 100644 close(fd); goto error; } -@@ -1494,7 +1928,7 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) +@@ -1494,7 +1952,7 @@ static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess) todo -= rv; } close(fd); @@ -3009,7 +3516,7 @@ index 78c7370a63..cc8dc53178 100644 } error: -@@ -1595,7 +2029,7 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l +@@ -1595,7 +2053,7 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l conf = (fr_tls_server_conf_t *)SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_CONF); if (!conf) { @@ -3018,7 +3525,7 @@ index 78c7370a63..cc8dc53178 100644 return NULL; } -@@ -1617,20 +2051,20 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l +@@ -1617,20 +2075,20 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l snprintf(filename, sizeof(filename), "%s%c%s.asn1", conf->session_cache_path, FR_DIR_SEP, buffer); fd = open(filename, O_RDONLY); if (fd < 0) { @@ -3042,7 +3549,7 @@ index 78c7370a63..cc8dc53178 100644 close(fd); goto error; } -@@ -1640,7 +2074,7 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l +@@ -1640,7 +2098,7 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l while (todo > 0) { rv = read(fd, q, todo); if (rv < 1) { @@ -3051,7 +3558,7 @@ index 78c7370a63..cc8dc53178 100644 close(fd); goto error; } -@@ -1664,7 +2098,7 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l +@@ -1664,7 +2122,7 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l memcpy(&o, &p, sizeof(o)); sess = d2i_SSL_SESSION(NULL, o, st.st_size); if (!sess) { @@ -3060,7 +3567,7 @@ index 78c7370a63..cc8dc53178 100644 goto error; } -@@ -1674,7 +2108,7 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l +@@ -1674,7 +2132,7 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l rv = pairlist_read(talloc_ctx, filename, &pairlist, 1); if (rv < 0) { /* not safe to un-persist a session w/o VPs */ @@ -3069,7 +3576,7 @@ index 78c7370a63..cc8dc53178 100644 SSL_SESSION_free(sess); sess = NULL; goto error; -@@ -1708,12 +2142,27 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l +@@ -1708,12 +2166,27 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l if (vp) { if ((request->timestamp + vp->vp_integer) > expires) { vp->vp_integer = expires - request->timestamp; @@ -3098,7 +3605,7 @@ index 78c7370a63..cc8dc53178 100644 /* move the cached VPs into the session */ fr_pair_list_mcopy_by_num(talloc_ctx, &vps, &pairlist->reply, 0, 0, TAG_ANY); -@@ -1733,46 +2182,390 @@ error: +@@ -1733,34 +2206,378 @@ error: return sess; } @@ -3140,23 +3647,15 @@ index 78c7370a63..cc8dc53178 100644 - for (i = 0; i < sk_ACCESS_DESCRIPTION_num(aia); i++) { - ad = sk_ACCESS_DESCRIPTION_value(aia, i); - if (OBJ_obj2nid(ad->method) != NID_ad_OCSP) continue; -- if (ad->location->type != GEN_URI) continue; -- found_uri = true; + p = SSL_SESSION_get_id(ssn, &size); + if (size > bufsize) size = bufsize; - -- if (OCSP_parse_url((char *) ad->location->d.ia5->data, host_out, -- port_out, path_out, is_https)) return 1; -- } -- return found_uri ? -1 : 0; ++ + memcpy(buffer, p, size); + return size; +#endif - } - - /* -- * This function sends a OCSP request to a defined OCSP responder -- * and checks the OCSP response for correctness. ++} ++ ++/* + * From TLS-Cache-Method + * + * All of the save / clear / load callbacks are done with any @@ -3506,22 +4005,10 @@ index 78c7370a63..cc8dc53178 100644 + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(aia); i++) { + ad = sk_ACCESS_DESCRIPTION_value(aia, i); + if (OBJ_obj2nid(ad->method) != NID_ad_OCSP) continue; -+ if (ad->location->type != GEN_URI) continue; -+ found_uri = true; -+ -+ if (OCSP_parse_url((char *) ad->location->d.ia5->data, host_out, -+ port_out, path_out, is_https)) return 1; -+ } -+ return found_uri ? -1 : 0; -+} -+ -+/* -+ * This function sends a OCSP request to a defined OCSP responder -+ * and checks the OCSP response for correctness. - */ + if (ad->location->type != GEN_URI) continue; + found_uri = true; - /* Maximum leeway in validity period: default 5 minutes */ -@@ -1811,7 +2604,7 @@ static ocsp_status_t ocsp_check(REQUEST *request, X509_STORE *store, X509 *issue +@@ -1811,7 +2628,7 @@ static ocsp_status_t ocsp_check(REQUEST *request, X509_STORE *store, X509 *issue VALUE_PAIR *vp; if (issuer_cert == NULL) { @@ -3530,7 +4017,7 @@ index 78c7370a63..cc8dc53178 100644 goto skipped; } -@@ -1836,7 +2629,7 @@ static ocsp_status_t ocsp_check(REQUEST *request, X509_STORE *store, X509 *issue +@@ -1836,7 +2653,7 @@ static ocsp_status_t ocsp_check(REQUEST *request, X509_STORE *store, X509 *issue /* Reading the libssl src, they do a strdup on the URL, so it could of been const *sigh* */ OCSP_parse_url(url, &host, &port, &path, &use_ssl); if (!host || !port || !path) { @@ -3539,7 +4026,7 @@ index 78c7370a63..cc8dc53178 100644 goto skipped; } } else { -@@ -1845,15 +2638,15 @@ static ocsp_status_t ocsp_check(REQUEST *request, X509_STORE *store, X509 *issue +@@ -1845,15 +2662,15 @@ static ocsp_status_t ocsp_check(REQUEST *request, X509_STORE *store, X509 *issue ret = ocsp_parse_cert_url(client_cert, &host, &port, &path, &use_ssl); switch (ret) { case -1: @@ -3558,7 +4045,7 @@ index 78c7370a63..cc8dc53178 100644 goto skipped; case 1: -@@ -1865,7 +2658,7 @@ static ocsp_status_t ocsp_check(REQUEST *request, X509_STORE *store, X509 *issue +@@ -1865,7 +2682,7 @@ static ocsp_status_t ocsp_check(REQUEST *request, X509_STORE *store, X509 *issue /* Check host and port length are sane, then create Host: HTTP header */ if ((strlen(host) + strlen(port) + 2) > sizeof(hostheader)) { @@ -3567,7 +4054,7 @@ index 78c7370a63..cc8dc53178 100644 goto skipped; } snprintf(hostheader, sizeof(hostheader), "%s:%s", host, port); -@@ -2038,15 +2831,15 @@ ocsp_end: +@@ -2038,15 +2855,15 @@ ocsp_end: vp = pair_make_request("TLS-OCSP-Cert-Valid", NULL, T_OP_SET); vp->vp_integer = 2; /* skipped */ if (conf->ocsp_softfail) { @@ -3586,7 +4073,7 @@ index 78c7370a63..cc8dc53178 100644 ocsp_status = OCSP_STATUS_FAILED; } break; -@@ -2054,7 +2847,7 @@ ocsp_end: +@@ -2054,7 +2871,7 @@ ocsp_end: default: vp = pair_make_request("TLS-OCSP-Cert-Valid", NULL, T_OP_SET); vp->vp_integer = 0; /* no */ @@ -3595,7 +4082,7 @@ index 78c7370a63..cc8dc53178 100644 break; } -@@ -2087,6 +2880,10 @@ static char const *cert_attr_names[9][2] = { +@@ -2087,6 +2904,10 @@ static char const *cert_attr_names[9][2] = { #define FR_TLS_SAN_UPN (7) #define FR_TLS_VALID_SINCE (8) @@ -3606,7 +4093,7 @@ index 78c7370a63..cc8dc53178 100644 /* * Before trusting a certificate, you must make sure that the * certificate is 'valid'. There are several steps that your -@@ -2183,8 +2980,8 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) +@@ -2183,8 +3004,8 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) buf[0] = '\0'; sn = X509_get_serialNumber(client_cert); @@ -3617,7 +4104,7 @@ index 78c7370a63..cc8dc53178 100644 /* * For this next bit, we create the attributes *only* if -@@ -2328,8 +3125,14 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) +@@ -2328,8 +3149,14 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) if (!my_ok) { char const *p = X509_verify_cert_error_string(err); @@ -3633,7 +4120,7 @@ index 78c7370a63..cc8dc53178 100644 return my_ok; } -@@ -2405,7 +3208,6 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) +@@ -2405,7 +3232,6 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) fr_bin2hex(value + 2, srcp, asn1len); } @@ -3641,7 +4128,7 @@ index 78c7370a63..cc8dc53178 100644 vp = fr_pair_make(talloc_ctx, certs, attribute, value, T_OP_ADD); if (!vp) { RDEBUG3("Skipping %s += '%s'. Please check that both the " -@@ -2446,20 +3248,28 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) +@@ -2446,20 +3272,28 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) switch (X509_STORE_CTX_get_error(ctx)) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: @@ -3673,7 +4160,7 @@ index 78c7370a63..cc8dc53178 100644 #if 0 ASN1_TIME_print(bio_err, X509_get_notAfter(ctx->current_cert)); #endif -@@ -2471,12 +3281,49 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) +@@ -2471,12 +3305,49 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) * checks. */ if (depth == 0) { @@ -3724,7 +4211,7 @@ index 78c7370a63..cc8dc53178 100644 (strcmp(issuer, conf->check_cert_issuer) != 0)) { AUTH(LOG_PREFIX ": Certificate issuer (%s) does not match specified value (%s)!", issuer, conf->check_cert_issuer); -@@ -2595,45 +3442,54 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) +@@ -2595,45 +3466,54 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx) unlink(filename); break; } @@ -3791,7 +4278,7 @@ index 78c7370a63..cc8dc53178 100644 return NULL; } -@@ -2647,36 +3503,58 @@ static X509_STORE *init_revocation_store(fr_tls_server_conf_t *conf) +@@ -2647,36 +3527,58 @@ static X509_STORE *init_revocation_store(fr_tls_server_conf_t *conf) #endif return store; } @@ -3803,18 +4290,25 @@ index 78c7370a63..cc8dc53178 100644 { - int nid; - EC_KEY *ecdh; -+ if (!disable_single_dh_use) { -+ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); -+ } - +- - if (!ecdh_curve || !*ecdh_curve) return 0; -+ if (!ecdh_curve) return 0; - +- - nid = OBJ_sn2nid(ecdh_curve); - if (!nid) { - ERROR(LOG_PREFIX ": Unknown ecdh_curve \"%s\"", ecdh_curve); - return -1; ++ if (!disable_single_dh_use) { ++ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); + } + +- ecdh = EC_KEY_new_by_curve_name(nid); +- if (!ecdh) { +- ERROR(LOG_PREFIX ": Unable to create new curve \"%s\"", ecdh_curve); +- return -1; - } ++ if (!ecdh_curve) return 0; + +- SSL_CTX_set_tmp_ecdh(ctx, ecdh); +#if OPENSSL_VERSION_NUMBER >= 0x1000200fL + /* + * A colon-separated list of curves. @@ -3822,10 +4316,8 @@ index 78c7370a63..cc8dc53178 100644 + if (*ecdh_curve) { + char *list; -- ecdh = EC_KEY_new_by_curve_name(nid); -- if (!ecdh) { -- ERROR(LOG_PREFIX ": Unable to create new curve \"%s\"", ecdh_curve); -- return -1; +- if (!disable_single_dh_use) { +- SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); + memcpy(&list, &ecdh_curve, sizeof(list)); /* const issues */ + + if (SSL_CTX_set1_curves_list(ctx, list) == 0) { @@ -3834,7 +4326,7 @@ index 78c7370a63..cc8dc53178 100644 + } } -- SSL_CTX_set_tmp_ecdh(ctx, ecdh); +- EC_KEY_free(ecdh); + (void) SSL_CTX_set_ecdh_auto(ctx, 1); +#else + /* @@ -3857,26 +4349,22 @@ index 78c7370a63..cc8dc53178 100644 + } + + SSL_CTX_set_tmp_ecdh(ctx, ecdh); - -- if (!disable_single_dh_use) { -- SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); ++ + EC_KEY_free(ecdh); - } -- -- EC_KEY_free(ecdh); ++ } +#endif return 0; } -@@ -2708,9 +3586,31 @@ int tls_global_init(bool spawn_flag, bool check) +@@ -2708,10 +3610,32 @@ int tls_global_init(bool spawn_flag, bool check) * and we don't want to have tls.c depend on globals. */ if (spawn_flag && !check && (tls_mutexes_init() < 0)) { - ERROR("FATAL: Failed to set up SSL mutexes"); + ERROR("(TLS) FATAL: Failed to set up SSL mutexes"); -+ return -1; -+ } -+ + return -1; + } + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + /* + * Load the default provider for most algorithms @@ -3895,13 +4383,14 @@ index 78c7370a63..cc8dc53178 100644 + openssl_legacy_provider = OSSL_PROVIDER_load(NULL, "legacy"); + if (!openssl_legacy_provider) { + ERROR("(TLS) Failed loading legacy provider"); - return -1; - } ++ return -1; ++ } +#endif - ++ return 0; } -@@ -2777,6 +3677,19 @@ void tls_global_cleanup(void) + +@@ -2777,6 +3701,19 @@ void tls_global_cleanup(void) #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif @@ -3921,7 +4410,7 @@ index 78c7370a63..cc8dc53178 100644 CONF_modules_unload(1); ERR_free_strings(); EVP_cleanup(); -@@ -2797,9 +3710,6 @@ static const FR_NAME_NUMBER version2int[] = { +@@ -2797,9 +3734,6 @@ static const FR_NAME_NUMBER version2int[] = { #endif #ifdef TLS1_3_VERSION { "1.3", TLS1_3_VERSION }, @@ -3931,7 +4420,7 @@ index 78c7370a63..cc8dc53178 100644 #endif { NULL, 0 } }; -@@ -2816,18 +3726,18 @@ static const FR_NAME_NUMBER version2int[] = { +@@ -2816,18 +3750,18 @@ static const FR_NAME_NUMBER version2int[] = { * - Load the Private key & the certificate * - Set the Context options & Verify options */ @@ -3954,7 +4443,7 @@ index 78c7370a63..cc8dc53178 100644 /* * SHA256 is in all versions of OpenSSL, but isn't -@@ -2840,7 +3750,7 @@ SSL_CTX *tls_init_ctx(fr_tls_server_conf_t *conf, int client) +@@ -2840,7 +3774,7 @@ SSL_CTX *tls_init_ctx(fr_tls_server_conf_t *conf, int client) ctx = SSL_CTX_new(SSLv23_method()); /* which is really "all known SSL / TLS methods". Idiots. */ if (!ctx) { @@ -3963,7 +4452,7 @@ index 78c7370a63..cc8dc53178 100644 return NULL; } -@@ -3033,39 +3943,55 @@ SSL_CTX *tls_init_ctx(fr_tls_server_conf_t *conf, int client) +@@ -3033,39 +3967,55 @@ SSL_CTX *tls_init_ctx(fr_tls_server_conf_t *conf, int client) * the cert chain needs to be given in PEM from * openSSL.org */ @@ -4033,7 +4522,7 @@ index 78c7370a63..cc8dc53178 100644 return NULL; } -@@ -3088,6 +4014,18 @@ post_ca: +@@ -3088,6 +4038,18 @@ post_ca: ctx_options |= SSL_OP_NO_SSLv2; ctx_options |= SSL_OP_NO_SSLv3; @@ -4052,7 +4541,7 @@ index 78c7370a63..cc8dc53178 100644 /* * SSL_CTX_set_(min|max)_proto_version was included in OpenSSL 1.1.0 * -@@ -3095,168 +4033,213 @@ post_ca: +@@ -3095,168 +4057,250 @@ post_ca: * below, so we don't need to check for them explicitly. * * TLS1_3_VERSION is available in OpenSSL 1.1.1. @@ -4266,11 +4755,11 @@ index 78c7370a63..cc8dc53178 100644 -#ifdef SSL_OP_NO_TLSv1 - insecure_tls_version |= (conf->disable_tlsv1 == false); --#endif --#ifdef SSL_OP_NO_TLSv1_1 -- insecure_tls_version |= (conf->disable_tlsv1_1 == false); + ctx_available |= SSL_OP_NO_TLSv1_1; #endif +-#ifdef SSL_OP_NO_TLSv1_1 +- insecure_tls_version |= (conf->disable_tlsv1_1 == false); +-#endif -#endif /* OpenSSL version ? 1.1.0 */ - if (rad_debug_lvl && insecure_tls_version) { @@ -4284,11 +4773,11 @@ index 78c7370a63..cc8dc53178 100644 + if (min_version <= TLS1_2_VERSION) { + ERROR(LOG_PREFIX ": 'disable_tlsv1_2' is set, but 'min_version <= 1.2'. These cannot both be true."); + return NULL; - } ++ } + if (max_version == TLS1_2_VERSION) { + ERROR(LOG_PREFIX ": 'disable_tlsv1_1' is set, but 'max_version = 1.2'. These cannot both be true."); + return NULL; -+ } + } + ctx_options |= SSL_OP_NO_TLSv1_2; } + ctx_available |= SSL_OP_NO_TLSv1_2; @@ -4306,10 +4795,13 @@ index 78c7370a63..cc8dc53178 100644 /* - * For historical config compatibility, we also allow - * these, but complain if the admin uses them. -+ * Tell OpenSSL PRETTY PLEASE MAY WE USE TLS 1.1. -+ * -+ * Because saying "use TLS 1.1" isn't enough. We have to -+ * send it flowers and cake. ++ * Set the cipher list if we were told to do so. We do ++ * this before setting min/max TLS version. In a sane ++ * world, OpenSSL would error out if we set the max TLS ++ * version to something which was unsupported by the ++ * current security level. However, this is OpenSSL. If ++ * you set conflicting options, it doesn't give an error. ++ * Instead, it just picks something to do. */ -#ifdef SSL_OP_NO_TLSv1 - if (conf->disable_tlsv1) { @@ -4317,9 +4809,11 @@ index 78c7370a63..cc8dc53178 100644 -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - WARN("Please use tls_min_version and tls_max_version instead of disable_tlsv1"); -#endif -+ if ((min_version <= TLS1_1_VERSION) && conf->cipher_list && -+ !strstr(conf->cipher_list, "DEFAULT@SECLEVEL=1")) { -+ WARN(LOG_PREFIX ": In order to use TLS 1.0 and/or TLS 1.1, you likely need to set: cipher_list = \"DEFAULT@SECLEVEL=1\""); ++ if (conf->cipher_list) { ++ if (!SSL_CTX_set_cipher_list(ctx, conf->cipher_list)) { ++ tls_error_log(NULL, "Failed setting cipher list"); ++ return NULL; ++ } } - ctx_tls_versions |= SSL_OP_NO_TLSv1; @@ -4327,6 +4821,45 @@ index 78c7370a63..cc8dc53178 100644 -#ifdef SSL_OP_NO_TLSv1_1 - if (conf->disable_tlsv1_1) { - ctx_options |= SSL_OP_NO_TLSv1_1; +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L +- WARN("Please use tls_min_version and tls_max_version instead of disable_tlsv1_2"); ++ /* ++ * Tell OpenSSL PRETTY PLEASE MAY WE USE TLS 1.1. ++ * ++ * Because saying "use TLS 1.1" isn't enough. We have to ++ * send it flowers and cake. ++ */ ++ if (min_version <= TLS1_1_VERSION) { ++#if OPENSSL_VERSION_NUMBER >= 0x10101000L ++ int seclevel = SSL_CTX_get_security_level(ctx); ++ int required;; ++ ++#if OPENSSL_VERSION_NUMBER >= 0x30000000L ++ required = 0; ++#else ++ required = 1; + #endif +- } + +- ctx_tls_versions |= SSL_OP_NO_TLSv1_1; ++ if (seclevel != required) { ++ WARN(LOG_PREFIX ": In order to use TLS 1.0 and/or TLS 1.1, you likely need to set: cipher_list = \"DEFAULT@SECLEVEL=%d\"", required); ++ } ++ ++#else ++ /* ++ * No API to get the security level. Just guess based on the string in the cipher_list. ++ */ ++ if (conf->cipher_list && ++ !strstr(conf->cipher_list, "DEFAULT@SECLEVEL=1")) { ++ WARN(LOG_PREFIX ": In order to use TLS 1.0 and/or TLS 1.1, you likely need to set: cipher_list = \"DEFAULT@SECLEVEL=1\""); ++ } + #endif +-#ifdef SSL_OP_NO_TLSv1_2 ++ } + +- if (conf->disable_tlsv1_2) { +- ctx_options |= SSL_OP_NO_TLSv1_2; #if OPENSSL_VERSION_NUMBER >= 0x10100000L - WARN("Please use tls_min_version and tls_max_version instead of disable_tlsv1_2"); -#endif @@ -4335,17 +4868,8 @@ index 78c7370a63..cc8dc53178 100644 + } + if (conf->disable_tlsv1_1) { + WARN(LOG_PREFIX ": Please use 'tls_min_version' and 'tls_max_version' instead of 'disable_tlsv1_1'"); - } -- -- ctx_tls_versions |= SSL_OP_NO_TLSv1_1; --#endif --#ifdef SSL_OP_NO_TLSv1_2 -- - if (conf->disable_tlsv1_2) { -- ctx_options |= SSL_OP_NO_TLSv1_2; --#if OPENSSL_VERSION_NUMBER >= 0x10100000L -- WARN("Please use tls_min_version and tls_max_version instead of disable_tlsv1_2"); --#endif ++ } ++ if (conf->disable_tlsv1_2) { + WARN(LOG_PREFIX ": Please use 'tls_min_version' and 'tls_max_version' instead of 'disable_tlsv1_2'"); } @@ -4381,7 +4905,7 @@ index 78c7370a63..cc8dc53178 100644 #ifdef SSL_OP_NO_TICKET ctx_options |= SSL_OP_NO_TICKET; #endif -@@ -3291,6 +4274,19 @@ post_ca: +@@ -3291,6 +4335,19 @@ post_ca: SSL_CTX_set_options(ctx, ctx_options); @@ -4401,7 +4925,7 @@ index 78c7370a63..cc8dc53178 100644 /* * TODO: Set the RSA & DH * SSL_CTX_set_tmp_rsa_callback(ctx, cbtls_rsa); -@@ -3336,12 +4332,21 @@ post_ca: +@@ -3336,12 +4393,21 @@ post_ca: /* * Cache sessions on disk if requested. */ @@ -4424,7 +4948,7 @@ index 78c7370a63..cc8dc53178 100644 SSL_CTX_set_quiet_shutdown(ctx, 1); if (fr_tls_ex_index_vps < 0) fr_tls_ex_index_vps = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, NULL); -@@ -3359,6 +4364,17 @@ post_ca: +@@ -3359,6 +4425,17 @@ post_ca: } X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); @@ -4442,7 +4966,24 @@ index 78c7370a63..cc8dc53178 100644 #ifdef X509_V_FLAG_CRL_CHECK_ALL if (conf->check_all_crl) X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK_ALL); -@@ -3424,9 +4440,9 @@ post_ca: +@@ -3389,16 +4466,6 @@ post_ca: + } + #endif + +- /* +- * Set the cipher list if we were told to +- */ +- if (conf->cipher_list) { +- if (!SSL_CTX_set_cipher_list(ctx, conf->cipher_list)) { +- tls_error_log(NULL, "Failed setting cipher list"); +- return NULL; +- } +- } +- + /* + * Setup session caching + */ +@@ -3424,9 +4491,9 @@ post_ca: (unsigned int) strlen(conf->session_context_id)); /* @@ -4454,7 +4995,7 @@ index 78c7370a63..cc8dc53178 100644 /* * Set the maximum number of entries in the -@@ -3468,11 +4484,15 @@ static int _tls_server_conf_free(fr_tls_server_conf_t *conf) +@@ -3468,11 +4535,15 @@ static int _tls_server_conf_free(fr_tls_server_conf_t *conf) if (conf->cache_ht) fr_hash_table_free(conf->cache_ht); @@ -4470,7 +5011,7 @@ index 78c7370a63..cc8dc53178 100644 #ifndef NDEBUG memset(conf, 0, sizeof(*conf)); #endif -@@ -3505,9 +4525,105 @@ static int store_cmp(void const *a, void const *b) +@@ -3505,9 +4576,109 @@ static int store_cmp(void const *a, void const *b) DICT_ATTR const *one = a; DICT_ATTR const *two = b; @@ -4491,8 +5032,8 @@ index 78c7370a63..cc8dc53178 100644 + fr_realm_ctx_t const *two = b; + + return strcmp(one->name, two->name); -+} -+ + } + +static void realm_free(void *data) +{ + fr_realm_ctx_t *r = data; @@ -4515,6 +5056,7 @@ index 78c7370a63..cc8dc53178 100644 + if (!dir) { + ERROR("Error reading directory %s: %s", conf->realm_dir, fr_syserror(errno)); + error: ++ if (dir) closedir(dir); + fr_hash_table_free(ht); + return -1; + } @@ -4570,14 +5112,17 @@ index 78c7370a63..cc8dc53178 100644 + } + } + ++ conf->realms = ht; ++ closedir(dir); ++ + return 0; - } - ++} ++ + fr_tls_server_conf_t *tls_server_conf_parse(CONF_SECTION *cs) { fr_tls_server_conf_t *conf; -@@ -3535,6 +4651,16 @@ fr_tls_server_conf_t *tls_server_conf_parse(CONF_SECTION *cs) +@@ -3535,6 +4706,16 @@ fr_tls_server_conf_t *tls_server_conf_parse(CONF_SECTION *cs) */ if (conf->fragment_size < 100) conf->fragment_size = 100; @@ -4594,7 +5139,7 @@ index 78c7370a63..cc8dc53178 100644 /* * Only check for certificate things if we don't have a * PSK query. -@@ -3563,10 +4689,15 @@ fr_tls_server_conf_t *tls_server_conf_parse(CONF_SECTION *cs) +@@ -3563,10 +4744,15 @@ fr_tls_server_conf_t *tls_server_conf_parse(CONF_SECTION *cs) } } @@ -4611,7 +5156,7 @@ index 78c7370a63..cc8dc53178 100644 if (conf->ctx == NULL) { goto error; } -@@ -3633,10 +4764,12 @@ skip_list: +@@ -3633,10 +4819,11 @@ skip_list: * Initialize OCSP Revocation Store */ if (conf->ocsp_enable) { @@ -4621,21 +5166,19 @@ index 78c7370a63..cc8dc53178 100644 } #endif /*HAVE_OPENSSL_OCSP_H*/ + -+#if OPENSSL_VERSION_NUMBER < 0x30000000L { char *dh_file; -@@ -3645,6 +4778,9 @@ skip_list: - goto error; - } +@@ -3655,7 +4842,7 @@ skip_list: } -+#else -+ if (!SSL_CTX_set_dh_auto(conf->ctx, 1)) goto error; -+#endif - if (conf->verify_tmp_dir) { - if (chmod(conf->verify_tmp_dir, S_IRWXU) < 0) { -@@ -3663,12 +4799,17 @@ skip_list: + if (conf->verify_client_cert_cmd && !conf->verify_tmp_dir) { +- ERROR(LOG_PREFIX ": You MUST set the verify directory in order to use verify_client_cmd"); ++ ERROR(LOG_PREFIX ": You MUST set the 'tmpdir' directory in order to use '%s' cmd", conf->verify_client_cert_cmd); + goto error; + } + +@@ -3663,12 +4850,17 @@ skip_list: /* * OpenSSL 1.0.1f and 1.0.1g get the MS-MPPE keys wrong. */ @@ -4654,7 +5197,7 @@ index 78c7370a63..cc8dc53178 100644 /* * Cache conf in cs in case we're asked to parse this again. */ -@@ -3703,11 +4844,12 @@ fr_tls_server_conf_t *tls_client_conf_parse(CONF_SECTION *cs) +@@ -3703,7 +4895,7 @@ fr_tls_server_conf_t *tls_client_conf_parse(CONF_SECTION *cs) /* * Initialize TLS */ @@ -4663,22 +5206,7 @@ index 78c7370a63..cc8dc53178 100644 if (conf->ctx == NULL) { goto error; } - -+#if OPENSSL_VERSION_NUMBER < 0x30000000L - { - char *dh_file; - -@@ -3716,6 +4858,9 @@ fr_tls_server_conf_t *tls_client_conf_parse(CONF_SECTION *cs) - goto error; - } - } -+#else -+ if (!SSL_CTX_set_dh_auto(conf->ctx, 1)) goto error; -+#endif - - cf_data_add(cs, "tls-conf", conf, NULL); - -@@ -3755,7 +4900,7 @@ int tls_success(tls_session_t *ssn, REQUEST *request) +@@ -3755,7 +4947,7 @@ int tls_success(tls_session_t *ssn, REQUEST *request) * not allowed, */ if (SSL_session_reused(ssn->ssl)) { @@ -4687,7 +5215,7 @@ index 78c7370a63..cc8dc53178 100644 return -1; } -@@ -3763,12 +4908,14 @@ int tls_success(tls_session_t *ssn, REQUEST *request) +@@ -3763,12 +4955,14 @@ int tls_success(tls_session_t *ssn, REQUEST *request) * Else resumption IS allowed, so we store the * user data in the cache. */ @@ -4703,7 +5231,7 @@ index 78c7370a63..cc8dc53178 100644 vp = fr_pair_list_copy_by_num(talloc_ctx, request->reply->vps, PW_USER_NAME, 0, TAG_ANY); if (vp) fr_pair_add(&vps, vp); -@@ -3778,6 +4925,9 @@ int tls_success(tls_session_t *ssn, REQUEST *request) +@@ -3778,6 +4972,9 @@ int tls_success(tls_session_t *ssn, REQUEST *request) vp = fr_pair_list_copy_by_num(talloc_ctx, request->packet->vps, PW_STRIPPED_USER_DOMAIN, 0, TAG_ANY); if (vp) fr_pair_add(&vps, vp); @@ -4713,7 +5241,7 @@ index 78c7370a63..cc8dc53178 100644 vp = fr_pair_list_copy_by_num(talloc_ctx, request->reply->vps, PW_CHARGEABLE_USER_IDENTITY, 0, TAG_ANY); if (vp) fr_pair_add(&vps, vp); -@@ -3836,7 +4986,7 @@ int tls_success(tls_session_t *ssn, REQUEST *request) +@@ -3836,7 +5033,7 @@ int tls_success(tls_session_t *ssn, REQUEST *request) if (vp) { if ((request->timestamp + vp->vp_integer) > expires) { vp->vp_integer = expires - request->timestamp; @@ -4722,7 +5250,7 @@ index 78c7370a63..cc8dc53178 100644 vp->vp_integer); } } -@@ -3858,7 +5008,7 @@ int tls_success(tls_session_t *ssn, REQUEST *request) +@@ -3858,7 +5055,7 @@ int tls_success(tls_session_t *ssn, REQUEST *request) FR_DIR_SEP, buffer); vp_file = fopen(filename, "w"); if (vp_file == NULL) { @@ -4731,7 +5259,7 @@ index 78c7370a63..cc8dc53178 100644 fr_syserror(errno)); } else { VALUE_PAIR *prev = NULL; -@@ -3889,6 +5039,10 @@ int tls_success(tls_session_t *ssn, REQUEST *request) +@@ -3889,6 +5086,10 @@ int tls_success(tls_session_t *ssn, REQUEST *request) fprintf(vp_file, "\n"); fclose(vp_file); } @@ -4742,7 +5270,7 @@ index 78c7370a63..cc8dc53178 100644 } else { RDEBUG("Failed to find 'persist_dir' in TLS configuration. Session will not be cached on disk."); } -@@ -3901,15 +5055,27 @@ int tls_success(tls_session_t *ssn, REQUEST *request) +@@ -3901,15 +5102,27 @@ int tls_success(tls_session_t *ssn, REQUEST *request) * Else the session WAS allowed. Copy the cached reply. */ } else { @@ -4764,7 +5292,7 @@ index 78c7370a63..cc8dc53178 100644 + * OpenSSL frees the underlying session out from + * under us in TLS 1.3. + */ -+ if (ssn->info.version == TLS1_3_VERSION) ssn->ssl_session = SSL_get_session(ssn->ssl); ++ if (SSL_version(ssn->ssl) == TLS1_3_VERSION) ssn->ssl_session = SSL_get_session(ssn->ssl); +#endif +#endif + @@ -4773,7 +5301,7 @@ index 78c7370a63..cc8dc53178 100644 /* "touch" the cached session/vp file */ char filename[3 * MAX_SESSION_SIZE + 1]; -@@ -3921,6 +5087,10 @@ int tls_success(tls_session_t *ssn, REQUEST *request) +@@ -3921,6 +5134,10 @@ int tls_success(tls_session_t *ssn, REQUEST *request) utime(filename, NULL); } @@ -4784,23 +5312,68 @@ index 78c7370a63..cc8dc53178 100644 /* * Mark the request as resumed. */ -@@ -3975,27 +5145,30 @@ fr_tls_status_t tls_application_data(tls_session_t *ssn, REQUEST *request) +@@ -3953,49 +5170,69 @@ fr_tls_status_t tls_application_data(tls_session_t *ssn, REQUEST *request) + err = BIO_write(ssn->into_ssl, ssn->dirty_in.data, + ssn->dirty_in.used); + if (err != (int) ssn->dirty_in.used) { ++ REDEBUG("(TLS) Failed writing %zd bytes to SSL BIO: %d", ssn->dirty_in.used, err); + record_init(&ssn->dirty_in); +- RDEBUG("Failed writing %zd bytes to SSL BIO: %d", ssn->dirty_in.used, err); + return FR_TLS_FAIL; + } ++ ++ record_init(&ssn->dirty_in); + } + + /* +- * Clear the dirty buffer now that we are done with it +- * and init the clean_out buffer to store decrypted data ++ * tls_handshake_recv() may read application data. So ++ * don't touch clean_out. But only if the BIO_write() ++ * above didn't do anything. + */ +- record_init(&ssn->dirty_in); +- record_init(&ssn->clean_out); ++ else if (ssn->clean_out.used > 0) { ++ RDEBUG("(TLS) We already have %zd bytes of application data, processing it.", ++ (ssn->clean_out.used)); ++ goto add_certs; ++ } + + /* + * Read (and decrypt) the tunneled data from the + * SSL session, and put it into the decrypted + * data buffer. + */ +- err = SSL_read(ssn->ssl, ssn->clean_out.data, sizeof(ssn->clean_out.data)); ++ err = SSL_read(ssn->ssl, ssn->clean_out.data + ssn->clean_out.used, ++ sizeof(ssn->clean_out.data) - ssn->clean_out.used); if (err <= 0) { int code; - RDEBUG("SSL_read Error"); -+ RDEBUG3("SSL_read Error"); ++ RDEBUG3("(TLS) SSL_read Error"); code = SSL_get_error(ssn->ssl, err); switch (code) { case SSL_ERROR_WANT_READ: - RDEBUG("Error in fragmentation logic: SSL_WANT_READ"); ++ if (ssn->clean_out.used > 0) { /* just process what application data we have */ ++ err = 0; ++ break; ++ } ++ + RDEBUG("(TLS) OpenSSL says that it needs to read more data."); return FR_TLS_MORE_FRAGMENTS; case SSL_ERROR_WANT_WRITE: - RDEBUG("Error in fragmentation logic: SSL_WANT_WRITE"); -+ RDEBUG("(TLS) Error in fragmentation logic: SSL_WANT_WRITE"); ++ if (ssn->clean_out.used > 0) { /* just process what application data we have */ ++ err = 0; ++ break; ++ } ++ ++ REDEBUG("(TLS) Error in fragmentation logic: SSL_WANT_WRITE"); return FR_TLS_FAIL; case SSL_ERROR_NONE: @@ -4822,7 +5395,18 @@ index 78c7370a63..cc8dc53178 100644 return FR_TLS_FAIL; } } -@@ -4026,27 +5199,27 @@ fr_tls_status_t tls_application_data(tls_session_t *ssn, REQUEST *request) +@@ -4003,8 +5240,9 @@ fr_tls_status_t tls_application_data(tls_session_t *ssn, REQUEST *request) + /* + * Passed all checks, successfully decrypted data + */ +- ssn->clean_out.used = err; ++ ssn->clean_out.used += err; + ++add_certs: + /* + * Add the certificates to intermediate packets, so that + * the inner tunnel policies can use them. +@@ -4026,27 +5264,27 @@ fr_tls_status_t tls_application_data(tls_session_t *ssn, REQUEST *request) fr_tls_status_t tls_ack_handler(tls_session_t *ssn, REQUEST *request) { if (ssn == NULL){ @@ -4855,7 +5439,7 @@ index 78c7370a63..cc8dc53178 100644 /* * From now on all the content is -@@ -4057,12 +5230,12 @@ fr_tls_status_t tls_ack_handler(tls_session_t *ssn, REQUEST *request) +@@ -4057,12 +5295,12 @@ fr_tls_status_t tls_ack_handler(tls_session_t *ssn, REQUEST *request) return FR_TLS_SUCCESS; } /* else more data to send */ @@ -4870,7 +5454,7 @@ index 78c7370a63..cc8dc53178 100644 return FR_TLS_REQUEST; /* -@@ -4070,7 +5243,7 @@ fr_tls_status_t tls_ack_handler(tls_session_t *ssn, REQUEST *request) +@@ -4070,7 +5308,7 @@ fr_tls_status_t tls_ack_handler(tls_session_t *ssn, REQUEST *request) * to the default section below. */ default: @@ -4880,7 +5464,7 @@ index 78c7370a63..cc8dc53178 100644 } } diff --git a/src/main/tls_listen.c b/src/main/tls_listen.c -index 0eed87b64f..c846507492 100644 +index 0eed87b64f..c3c40d17ea 100644 --- a/src/main/tls_listen.c +++ b/src/main/tls_listen.c @@ -81,7 +81,7 @@ static void tls_socket_close(rad_listen_t *listener) @@ -5009,15 +5593,21 @@ index 0eed87b64f..c846507492 100644 goto do_close; } -@@ -252,10 +262,49 @@ static int tls_socket_recv(rad_listen_t *listener) +@@ -252,10 +262,55 @@ static int tls_socket_recv(rad_listen_t *listener) } /* - * FIXME: Run the request through a virtual - * server in order to see if we like the - * certificate presented by the client. -+ * Else we MUST be finished the SSL setup. ++ * If SSL handshake still isn't finished, then there ++ * is more data to read. Release the mutex and ++ * return so this function will be called again + */ ++ if (!SSL_is_init_finished(sock->ssn->ssl)) { ++ PTHREAD_MUTEX_UNLOCK(&sock->mutex); ++ return 0; ++ } + } + + /* @@ -5043,7 +5633,7 @@ index 0eed87b64f..c846507492 100644 + * Fake out a Status-Server packet, which + * does NOT have a Message-Authenticator, + * or any other contents. -+ */ + */ + request->packet->code = PW_CODE_STATUS_SERVER; + request->packet->data = talloc_zero_array(request->packet, uint8_t, 20); + request->packet->data[0] = PW_CODE_STATUS_SERVER; @@ -5054,7 +5644,7 @@ index 0eed87b64f..c846507492 100644 + /* + * Don't read from the socket until the request + * returns. - */ ++ */ + listener->status = RAD_LISTEN_STATUS_PAUSE; + radius_update_listener(listener); + @@ -5062,7 +5652,7 @@ index 0eed87b64f..c846507492 100644 } /* -@@ -263,7 +312,7 @@ static int tls_socket_recv(rad_listen_t *listener) +@@ -263,7 +318,7 @@ static int tls_socket_recv(rad_listen_t *listener) */ get_application_data: status = tls_application_data(sock->ssn, request); @@ -5071,7 +5661,7 @@ index 0eed87b64f..c846507492 100644 if (status == FR_TLS_MORE_FRAGMENTS) { PTHREAD_MUTEX_UNLOCK(&sock->mutex); -@@ -275,6 +324,16 @@ get_application_data: +@@ -275,6 +330,16 @@ get_application_data: return 0; } @@ -5088,7 +5678,7 @@ index 0eed87b64f..c846507492 100644 /* * We now have a bunch of application data. */ -@@ -286,7 +345,7 @@ get_application_data: +@@ -286,7 +351,7 @@ get_application_data: */ if ((sock->ssn->clean_out.used < 20) || (((sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]) != (int) sock->ssn->clean_out.used)) { @@ -5097,7 +5687,7 @@ index 0eed87b64f..c846507492 100644 sock->ssn->clean_out.used, (sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]); goto do_close; -@@ -301,7 +360,7 @@ get_application_data: +@@ -301,7 +366,7 @@ get_application_data: if (!rad_packet_ok(packet, 0, NULL)) { if (DEBUG_ENABLED) ERROR("Receive - %s", fr_strerror()); @@ -5106,7 +5696,7 @@ index 0eed87b64f..c846507492 100644 PTHREAD_MUTEX_LOCK(&sock->mutex); tls_socket_close(listener); PTHREAD_MUTEX_UNLOCK(&sock->mutex); -@@ -315,7 +374,7 @@ get_application_data: +@@ -315,7 +380,7 @@ get_application_data: char host_ipaddr[128]; if (is_radius_code(packet->code)) { @@ -5115,7 +5705,7 @@ index 0eed87b64f..c846507492 100644 fr_packet_codes[packet->code], inet_ntop(packet->src_ipaddr.af, &packet->src_ipaddr.ipaddr, -@@ -323,7 +382,7 @@ get_application_data: +@@ -323,7 +388,7 @@ get_application_data: packet->src_port, packet->id, (int) packet->data_len); } else { @@ -5124,7 +5714,7 @@ index 0eed87b64f..c846507492 100644 inet_ntop(packet->src_ipaddr.af, &packet->src_ipaddr.ipaddr, host_ipaddr, sizeof(host_ipaddr)), -@@ -359,6 +418,7 @@ redo: +@@ -359,6 +424,7 @@ redo: rad_assert(client != NULL); packet = talloc_steal(NULL, sock->packet); @@ -5132,7 +5722,7 @@ index 0eed87b64f..c846507492 100644 sock->packet = NULL; /* -@@ -391,8 +451,26 @@ redo: +@@ -391,8 +457,26 @@ redo: break; #endif @@ -5160,7 +5750,7 @@ index 0eed87b64f..c846507492 100644 FR_STATS_INC(auth, total_unknown_types); WARN("Ignoring Status-Server request due to security configuration"); rad_free(&packet); -@@ -405,7 +483,7 @@ redo: +@@ -405,7 +489,7 @@ redo: bad_packet: FR_STATS_INC(auth, total_unknown_types); @@ -5169,7 +5759,7 @@ index 0eed87b64f..c846507492 100644 packet->code, client->shortname, packet->src_port); rad_free(&packet); return 0; -@@ -432,7 +510,7 @@ redo: +@@ -432,7 +516,7 @@ redo: int peek = SSL_peek(sock->ssn->ssl, buf, 1); if (peek > 0) { @@ -5178,7 +5768,7 @@ index 0eed87b64f..c846507492 100644 goto redo; } } -@@ -455,6 +533,34 @@ int dual_tls_send(rad_listen_t *listener, REQUEST *request) +@@ -455,6 +539,34 @@ int dual_tls_send(rad_listen_t *listener, REQUEST *request) if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0; @@ -5213,7 +5803,7 @@ index 0eed87b64f..c846507492 100644 /* * Accounting reject's are silently dropped. * -@@ -727,6 +833,15 @@ int proxy_tls_recv(rad_listen_t *listener) +@@ -727,6 +839,15 @@ int proxy_tls_recv(rad_listen_t *listener) break; #endif @@ -5229,7 +5819,7 @@ index 0eed87b64f..c846507492 100644 default: /* * FIXME: Update MIB for packet types? -@@ -765,8 +880,8 @@ int proxy_tls_send(rad_listen_t *listener, REQUEST *request) +@@ -765,8 +886,8 @@ int proxy_tls_send(rad_listen_t *listener, REQUEST *request) * if there's no packet, encode it here. */ if (!request->proxy->data) { @@ -5254,7 +5844,7 @@ index 9fed166e62..1cd73ff246 100644 /* Free any unmoved pairs */ fr_pair_list_free(&head); diff --git a/src/modules/rlm_eap/libeap/eap_tls.c b/src/modules/rlm_eap/libeap/eap_tls.c -index 83e7252fa8..76c38c6d3f 100644 +index 83e7252fa8..2f37663df1 100644 --- a/src/modules/rlm_eap/libeap/eap_tls.c +++ b/src/modules/rlm_eap/libeap/eap_tls.c @@ -1,3 +1,4 @@ @@ -5303,7 +5893,7 @@ index 83e7252fa8..76c38c6d3f 100644 + uint8_t const context_tls13[] = { handler->type }; +#endif + -+ switch (tls_session->info.version) { ++ switch (SSL_version(tls_session->ssl)) { +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + context = context_tls13; @@ -5535,7 +6125,7 @@ index 83e7252fa8..76c38c6d3f 100644 + * data to be sent. So this is done always for EAP-TLS but + * notibly not for PEAP even on resumption. + */ -+ if ((tls_session->info.version == TLS1_3_VERSION) && ++ if ((SSL_version(tls_session->ssl) == TLS1_3_VERSION) && + (tls_session->client_cert_ok || tls_session->authentication_success || SSL_session_reused(tls_session->ssl))) { + if ((handler->type == PW_EAP_TLS) || SSL_session_reused(tls_session->ssl)) { + tls_session->authentication_success = true; @@ -5710,25 +6300,28 @@ index 73c7fdd53b..8e5fc773d6 100644 int eaptls_compose(EAP_DS *eap_ds, EAPTLS_PACKET *reply); diff --git a/src/modules/rlm_eap/libeap/mppe_keys.c b/src/modules/rlm_eap/libeap/mppe_keys.c -index 3a9e864104..e16756583c 100644 +index 3a9e864104..385441c62f 100644 --- a/src/modules/rlm_eap/libeap/mppe_keys.c +++ b/src/modules/rlm_eap/libeap/mppe_keys.c -@@ -26,11 +26,12 @@ RCSID("$Id$") +@@ -26,11 +26,16 @@ RCSID("$Id$") USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ #include "eap_tls.h" +#include #include -- +#include ++#if OPENSSL_VERSION_NUMBER >= 0x30000000L ++#include ++#endif + /* - * TLS PRF from RFC 2246 + * TLS P_hash from RFC 2246/5246 section 5 */ static void P_hash(EVP_MD const *evp_md, unsigned char const *secret, unsigned int secret_len, -@@ -38,8 +39,9 @@ static void P_hash(EVP_MD const *evp_md, +@@ -38,23 +43,18 @@ static void P_hash(EVP_MD const *evp_md, unsigned char *out, unsigned int out_len) { HMAC_CTX *ctx_a, *ctx_out; @@ -5740,7 +6333,10 @@ index 3a9e864104..e16756583c 100644 ctx_a = HMAC_CTX_new(); ctx_out = HMAC_CTX_new(); -@@ -50,11 +52,9 @@ static void P_hash(EVP_MD const *evp_md, +-#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW +- HMAC_CTX_set_flags(ctx_a, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); +- HMAC_CTX_set_flags(ctx_out, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); +-#endif HMAC_Init_ex(ctx_a, secret, secret_len, evp_md, NULL); HMAC_Init_ex(ctx_out, secret, secret_len, evp_md, NULL); @@ -5781,7 +6377,7 @@ index 3a9e864104..e16756583c 100644 } HMAC_CTX_free(ctx_a); -@@ -85,6 +88,38 @@ static void P_hash(EVP_MD const *evp_md, +@@ -85,6 +88,82 @@ static void P_hash(EVP_MD const *evp_md, memset(a, 0, sizeof(a)); } @@ -5799,12 +6395,56 @@ index 3a9e864104..e16756583c 100644 + uint8_t const *s1 = secret; + uint8_t const *s2 = secret + (secret_len - len); + -+ P_hash(EVP_md5(), s1, len, seed, seed_len, out, out_len); ++ EVP_MD const *md5 = NULL; ++ ++#if OPENSSL_VERSION_NUMBER >= 0x30000000L ++ EVP_MD *md5_to_free = NULL; ++ ++ /* ++ * If we are using OpenSSL >= 3.0 and FIPS mode is ++ * enabled, we need to load the default provider in a ++ * standalone context in order to access MD5. ++ */ ++ OSSL_LIB_CTX *libctx = NULL; ++ OSSL_PROVIDER *default_provider = NULL; ++ ++ if (EVP_default_properties_is_fips_enabled(NULL)) { ++ libctx = OSSL_LIB_CTX_new(); ++ default_provider = OSSL_PROVIDER_load(libctx, "default"); ++ ++ if (!default_provider) { ++ ERROR("Failed loading OpenSSL default provider."); ++ return; ++ } ++ ++ md5_to_free = EVP_MD_fetch(libctx, "MD5", NULL); ++ if (!md5_to_free) { ++ ERROR("Failed loading OpenSSL MD5 function."); ++ return; ++ } ++ ++ md5 = md5_to_free; ++ } else { ++ md5 = EVP_md5(); ++ } ++#else ++ md5 = EVP_md5(); ++#endif ++ ++ P_hash(md5, s1, len, seed, seed_len, out, out_len); + P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len); + + for (i = 0; i < out_len; i++) { + out[i] ^= buf[i]; + } ++ ++#if OPENSSL_VERSION_NUMBER >= 0x30000000L ++ if (libctx) { ++ OSSL_PROVIDER_unload(default_provider); ++ OSSL_LIB_CTX_free(libctx); ++ EVP_MD_free(md5_to_free); ++ } ++#endif +} + +/* @@ -5820,7 +6460,7 @@ index 3a9e864104..e16756583c 100644 /* EAP-FAST Pseudo-Random Function (T-PRF): RFC 4851, Section 5.5 */ void T_PRF(unsigned char const *secret, unsigned int secret_len, char const *prf_label, -@@ -128,60 +163,55 @@ void T_PRF(unsigned char const *secret, unsigned int secret_len, +@@ -128,60 +207,55 @@ void T_PRF(unsigned char const *secret, unsigned int secret_len, talloc_free(buf); } @@ -5903,7 +6543,7 @@ index 3a9e864104..e16756583c 100644 } #endif -@@ -195,7 +225,7 @@ void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *prf_label) +@@ -195,7 +269,7 @@ void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *prf_label) } @@ -5912,7 +6552,7 @@ index 3a9e864104..e16756583c 100644 /* * Generate the TTLS challenge -@@ -206,9 +236,10 @@ void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *prf_label) +@@ -206,9 +280,10 @@ void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *prf_label) void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size) { #if OPENSSL_VERSION_NUMBER >= 0x10001000L @@ -5926,7 +6566,7 @@ index 3a9e864104..e16756583c 100644 #else uint8_t out[32], buf[32]; uint8_t seed[sizeof(FR_TLS_PRF_CHALLENGE)-1 + 2*SSL3_RANDOM_SIZE]; -@@ -226,14 +257,20 @@ void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size) +@@ -226,14 +301,20 @@ void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size) #endif } @@ -5948,7 +6588,7 @@ index 3a9e864104..e16756583c 100644 vp = fr_pair_afrom_num(packet, PW_EAP_SESSION_ID, 0); if (!vp) return; -@@ -241,11 +278,33 @@ void eaptls_gen_eap_key(RADIUS_PACKET *packet, SSL *ssl, uint32_t header) +@@ -241,11 +322,33 @@ void eaptls_gen_eap_key(RADIUS_PACKET *packet, SSL *ssl, uint32_t header) vp->vp_length = 1 + 2 * SSL3_RANDOM_SIZE; buff = p = talloc_array(vp, uint8_t, vp->vp_length); @@ -5958,7 +6598,7 @@ index 3a9e864104..e16756583c 100644 - SSL_get_client_random(ssl, p, SSL3_RANDOM_SIZE); - p += SSL3_RANDOM_SIZE; - SSL_get_server_random(ssl, p, SSL3_RANDOM_SIZE); -+ switch (tls_session->info.version) { ++ switch (SSL_version(tls_session->ssl)) { + case TLS1_VERSION: + case TLS1_1_VERSION: + case TLS1_2_VERSION: @@ -5986,7 +6626,7 @@ index 3a9e864104..e16756583c 100644 vp->vp_octets = buff; fr_pair_add(&packet->vps, vp); -@@ -254,7 +313,7 @@ void eaptls_gen_eap_key(RADIUS_PACKET *packet, SSL *ssl, uint32_t header) +@@ -254,7 +357,7 @@ void eaptls_gen_eap_key(RADIUS_PACKET *packet, SSL *ssl, uint32_t header) /* * Same as before, but for EAP-FAST the order of {server,client}_random is flipped */ @@ -5995,7 +6635,7 @@ index 3a9e864104..e16756583c 100644 { uint8_t *p; size_t len, master_key_len; -@@ -273,7 +332,9 @@ void eap_fast_tls_gen_challenge(SSL *s, uint8_t *buffer, uint8_t *scratch, size_ +@@ -273,7 +376,9 @@ void eap_fast_tls_gen_challenge(SSL *s, uint8_t *buffer, uint8_t *scratch, size_ p += SSL3_RANDOM_SIZE; master_key_len = SSL_SESSION_get_master_key(SSL_get_session(s), master_key, sizeof(master_key)); @@ -6028,7 +6668,7 @@ index 553a6a6a57..cd504a8363 100644 static void NEVER_RETURNS usage(void) { diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c -index b0953aa1d4..8c63498586 100644 +index b0953aa1d4..bbb5a03c95 100644 --- a/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c +++ b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c @@ -61,33 +61,51 @@ static int openssl_get_keyblock_size(REQUEST *request, SSL *ssl) @@ -6110,7 +6750,7 @@ index b0953aa1d4..8c63498586 100644 t->keyblock = talloc(t, eap_fast_keyblock_t); - eap_fast_tls_gen_challenge(tls_session->ssl, buf, scratch, ksize + sizeof(*t->keyblock), "key expansion"); -+ eap_fast_tls_gen_challenge(tls_session->ssl, tls_session->info.version, buf, ksize + sizeof(*t->keyblock), "key expansion"); ++ eap_fast_tls_gen_challenge(tls_session->ssl, SSL_version(tls_session->ssl), buf, ksize + sizeof(*t->keyblock), "key expansion"); memcpy(t->keyblock, &buf[ksize], sizeof(*t->keyblock)); memset(buf, 0, ksize + sizeof(*t->keyblock)); @@ -6153,7 +6793,7 @@ index b0953aa1d4..8c63498586 100644 eap_fast_init_keys(request, tls_session); diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c -index 2ce2dd0c3b..7c91d34050 100644 +index 2ce2dd0c3b..093dc868cd 100644 --- a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c +++ b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c @@ -131,6 +131,25 @@ static int mod_instantiate(CONF_SECTION *cs, void **instance) @@ -6229,7 +6869,7 @@ index 2ce2dd0c3b..7c91d34050 100644 } /* -@@ -553,7 +572,12 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) +@@ -553,7 +572,13 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) } else { client_cert = inst->req_client_cert; } @@ -6237,13 +6877,14 @@ index 2ce2dd0c3b..7c91d34050 100644 + + /* + * Don't allow TLS 1.3 for us, even if it's allowed -+ * elsewhere. ++ * elsewhere. We haven't implemented the necessary ++ * changes, so we don't allow it. + */ + handler->opaque = tls_session = eaptls_session(handler, inst->tls_conf, client_cert, false); if (!tls_session) return 0; -@@ -566,16 +590,20 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) +@@ -566,16 +591,20 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) } } @@ -6273,6 +6914,23 @@ index 2ce2dd0c3b..7c91d34050 100644 #ifdef SSL_OP_NO_TLSv1_3 /* * Forcibly disable TLSv1.3 +@@ -599,6 +628,7 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) + rcode = eap_fast_tls_start(handler->eap_ds, tls_session); + + if (rcode < 0) { ++ error: + talloc_free(tls_session); + return 0; + } +@@ -607,7 +637,7 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) + + if (!SSL_set_session_ticket_ext_cb(tls_session->ssl, _session_ticket, tls_session)) { + RERROR("Failed setting SSL session ticket callback"); +- return 0; ++ goto error; + } + + handler->stage = PROCESS; diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/peap.c b/src/modules/rlm_eap/types/rlm_eap_peap/peap.c index deaf702d61..5647f613af 100644 --- a/src/modules/rlm_eap/types/rlm_eap_peap/peap.c @@ -6337,49 +6995,22 @@ index deaf702d61..5647f613af 100644 /* diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c b/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c -index 3d23322663..4bbf57330f 100644 +index 3d23322663..d9f850cef2 100644 --- a/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c +++ b/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c -@@ -135,6 +135,25 @@ static int mod_instantiate(CONF_SECTION *cs, void **instance) - inst->auth_type_eap = dv->value; - } - -+#ifdef TLS1_3_VERSION -+ if ((inst->tls_conf->min_version == TLS1_3_VERSION) && !inst->tls_conf->tls13_enable_magic) { -+ ERROR("There are no standards for using TLS 1.3 with PEAP."); -+ ERROR("You MUST enable TLS 1.2 for PEAP to work."); -+ return -1; -+ } -+ -+ if ((inst->tls_conf->max_version == TLS1_3_VERSION) || -+ (inst->tls_conf->min_version == TLS1_3_VERSION)) { -+ WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); -+ WARN("!! There is no standard for using PEAP with TLS 1.3"); -+ WARN("!! Please set tls_max_version = \"1.2\""); -+ WARN("!! FreeRADIUS only supports TLS 1.3 for special builds of wpa_supplicant and Windows"); -+ WARN("!! This limitation is likely to change in late 2021."); -+ WARN("!! If you are using this version of FreeRADIUS after 2021, you will probably need to upgrade"); -+ WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); -+} -+#endif -+ - return 0; - } - -@@ -192,7 +211,11 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) +@@ -192,7 +192,10 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) client_cert = inst->req_client_cert; } - ssn = eaptls_session(handler, inst->tls_conf, client_cert); + /* -+ * Don't allow TLS 1.3 for us, even if it's allowed -+ * elsewhere. ++ * Allow TLS 1.3, it works. + */ -+ ssn = eaptls_session(handler, inst->tls_conf, client_cert, inst->tls_conf->tls13_enable_magic); ++ ssn = eaptls_session(handler, inst->tls_conf, client_cert, true); if (!ssn) { return 0; } -@@ -200,9 +223,13 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) +@@ -200,9 +203,13 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) handler->opaque = ((void *)ssn); /* @@ -6395,7 +7026,7 @@ index 3d23322663..4bbf57330f 100644 /* * As it is a poorly designed protocol, PEAP uses -@@ -230,7 +257,7 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) +@@ -230,7 +237,7 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) { REDEBUG("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "")); } else { @@ -6404,7 +7035,7 @@ index 3d23322663..4bbf57330f 100644 } if (status == 0) return 0; -@@ -274,7 +301,7 @@ static int mod_process(void *arg, eap_handler_t *handler) +@@ -274,7 +281,7 @@ static int mod_process(void *arg, eap_handler_t *handler) if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) { REDEBUG("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "")); } else { @@ -6413,7 +7044,7 @@ index 3d23322663..4bbf57330f 100644 } /* -@@ -311,6 +338,10 @@ static int mod_process(void *arg, eap_handler_t *handler) +@@ -311,6 +318,10 @@ static int mod_process(void *arg, eap_handler_t *handler) * data. */ case FR_TLS_OK: @@ -6621,7 +7252,7 @@ index 0000000000..b717dd51b3 + +#endif /* CONST_TIME_H */ diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.c b/src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.c -index d94851c3aa..d428644539 100644 +index d94851c3aa..26260527a5 100644 --- a/src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.c +++ b/src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.c @@ -1,7 +1,5 @@ @@ -6634,7 +7265,7 @@ index d94851c3aa..d428644539 100644 * and binary forms, with or without modification, provided that the * following conditions are met: * 1. Redistribution of source code must retain the above copyright -@@ -29,94 +27,233 @@ +@@ -29,100 +27,237 @@ * This license and distribution terms cannot be changed. In other words, * this code cannot simply be copied and put under a different distribution * license (including the GNU public license). @@ -6740,8 +7371,7 @@ index d94851c3aa..d428644539 100644 + BN_free(res); + return -2; + } - -- HMAC_Final(ctx, digest, &mdlen); ++ + symbol = -1; + mask = const_time_eq(BN_is_word(res, 1), 1); + symbol = const_time_select_int(mask, 1, symbol); @@ -6750,7 +7380,8 @@ index d94851c3aa..d428644539 100644 + + BN_free(pm1over2); + BN_free(res); -+ + +- HMAC_Final(ctx, digest, &mdlen); + return symbol; } @@ -6909,18 +7540,29 @@ index d94851c3aa..d428644539 100644 uint32_t *token) { - BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL; -+ BIGNUM *x_candidate = NULL, *rnd = NULL, *y_sqrd = NULL, *qr = NULL, *qnr = NULL; - HMAC_CTX *ctx = NULL; +- HMAC_CTX *ctx = NULL; - uint8_t pwe_digest[SHA256_DIGEST_LENGTH], *prfbuf = NULL, ctr; - int nid, is_odd, primebitlen, primebytelen, ret = 0; -+ uint8_t pwe_digest[SHA256_DIGEST_LENGTH], *prfbuf = NULL, *xbuf = NULL, *pm1buf = NULL, ctr; -+ int nid, is_odd, primebitlen, primebytelen, ret = 0, found = 0, mask; -+ int save, i, rbits, qr_or_qnr, save_is_odd = 0, cmp; -+ unsigned int skip; +- +- ctx = HMAC_CTX_new(); +- if (ctx == NULL) { +- DEBUG("failed allocating HMAC context"); +- goto fail; +- } ++ BIGNUM *x_candidate = NULL, *rnd = NULL, *y_sqrd = NULL, *qr = NULL, *qnr = NULL, *y1 = NULL, *y2 = NULL, *y = NULL, *exp = NULL; ++ EVP_MD_CTX *hmac_ctx; ++ EVP_PKEY *hmac_pkey; ++ uint8_t pwe_digest[SHA256_DIGEST_LENGTH], *prfbuf = NULL, *xbuf = NULL, *pm1buf = NULL, *y1buf = NULL, *y2buf = NULL, *ybuf = NULL, ctr; ++ int nid, is_odd, primebitlen, primebytelen, ret = 0, found = 0, mask; ++ int save, i, rbits, qr_or_qnr, save_is_odd = 0, cmp; ++ unsigned int skip; ++ ++ MEM(hmac_ctx = EVP_MD_CTX_new()); ++ MEM(hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, allzero, sizeof(allzero))); - ctx = HMAC_CTX_new(); - if (ctx == NULL) { -@@ -159,17 +296,19 @@ int compute_password_element (pwd_session_t *session, uint16_t grp_num, + switch (grp_num) { /* from IANA registry for IKE D-H groups */ + case 19: +@@ -159,17 +294,23 @@ int compute_password_element (pwd_session_t *session, uint16_t grp_num, goto fail; } @@ -6936,7 +7578,11 @@ index d94851c3aa..d428644539 100644 + ((qr = consttime_BN()) == NULL) || + ((qnr = consttime_BN()) == NULL) || + ((x_candidate = consttime_BN()) == NULL) || -+ ((y_sqrd = consttime_BN()) == NULL)) { ++ ((y_sqrd = consttime_BN()) == NULL) || ++ ((y1 = consttime_BN()) == NULL) || ++ ((y2 = consttime_BN()) == NULL) || ++ ((y = consttime_BN()) == NULL) || ++ ((exp = consttime_BN()) == NULL)) { DEBUG("unable to create bignums"); goto fail; } @@ -6946,7 +7592,7 @@ index d94851c3aa..d428644539 100644 DEBUG("unable to get prime for GFp curve"); goto fail; } -@@ -179,46 +318,61 @@ int compute_password_element (pwd_session_t *session, uint16_t grp_num, +@@ -179,46 +320,80 @@ int compute_password_element (pwd_session_t *session, uint16_t grp_num, goto fail; } @@ -6969,6 +7615,19 @@ index d94851c3aa..d428644539 100644 + DEBUG("unable to alloc space for pm1 buffer"); + goto fail; + } ++ if ((y1buf = talloc_zero_array(request, uint8_t, primebytelen)) == NULL) { ++ DEBUG("unable to alloc space for y1 buffer"); ++ goto fail; ++ } ++ if ((y2buf = talloc_zero_array(request, uint8_t, primebytelen)) == NULL) { ++ DEBUG("unable to alloc space for y2 buffer"); ++ goto fail; ++ } ++ if ((ybuf = talloc_zero_array(request, uint8_t, primebytelen)) == NULL) { ++ DEBUG("unable to alloc space for y buffer"); ++ goto fail; ++ } ++ + + /* + * derive random quadradic residue and quadratic non-residue @@ -7012,13 +7671,19 @@ index d94851c3aa..d428644539 100644 - H_Update(ctx, (uint8_t const *)password, password_len); - H_Update(ctx, (uint8_t *)&ctr, sizeof(ctr)); - H_Final(ctx, pwe_digest); -+ HMAC_Init_ex(ctx, allzero, SHA256_DIGEST_LENGTH, EVP_sha256(),NULL); -+ HMAC_Update(ctx, (uint8_t *)token, sizeof(*token)); -+ HMAC_Update(ctx, (uint8_t const *)id_peer, id_peer_len); -+ HMAC_Update(ctx, (uint8_t const *)id_server, id_server_len); -+ HMAC_Update(ctx, (uint8_t const *)password, password_len); -+ HMAC_Update(ctx, (uint8_t *)&ctr, sizeof(ctr)); -+ pwd_hmac_final(ctx, pwe_digest); ++ EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey); ++ EVP_DigestSignUpdate(hmac_ctx, (uint8_t *)token, sizeof(*token)); ++ EVP_DigestSignUpdate(hmac_ctx, (uint8_t const *)id_peer, id_peer_len); ++ EVP_DigestSignUpdate(hmac_ctx, (uint8_t const *)id_server, id_server_len); ++ EVP_DigestSignUpdate(hmac_ctx, (uint8_t const *)password, password_len); ++ EVP_DigestSignUpdate(hmac_ctx, (uint8_t *)&ctr, sizeof(ctr)); ++ ++ { ++ size_t mdlen = SHA256_DIGEST_LENGTH; ++ ++ EVP_DigestSignFinal(hmac_ctx, pwe_digest, &mdlen); ++ EVP_MD_CTX_reset(hmac_ctx); ++ } BN_bin2bn(pwe_digest, SHA256_DIGEST_LENGTH, rnd); - if (eap_pwd_kdf(pwe_digest, SHA256_DIGEST_LENGTH, "EAP-pwd Hunting And Pecking", @@ -7033,7 +7698,7 @@ index d94851c3aa..d428644539 100644 /* * eap_pwd_kdf() returns a string of bits 0..primebitlen but * BN_bin2bn will treat that string of bits as a big endian -@@ -226,49 +380,73 @@ int compute_password_element (pwd_session_t *session, uint16_t grp_num, +@@ -226,49 +401,86 @@ int compute_password_element (pwd_session_t *session, uint16_t grp_num, * then excessive bits-- those _after_ primebitlen-- so now * we have to shift right the amount we masked off. */ @@ -7052,18 +7717,13 @@ index d94851c3aa..d428644539 100644 - * need to unambiguously identify the solution, if there is - * one... - */ +- is_odd = BN_is_odd(rnd) ? 1 : 0; + * it would've been better if the spec reduced the candidate + * modulo the prime but it didn't. So if the candidate >= prime + * we need to skip it but still run through the operations below + */ + cmp = const_time_memcmp(pm1buf, prfbuf, primebytelen); + skip = const_time_fill_msb((unsigned int)cmp); -+ -+ /* -+ * need to unambiguously identify the solution, if there is -+ * one.. -+ */ - is_odd = BN_is_odd(rnd) ? 1 : 0; /* - * solve the quadratic equation, if it's not solvable then we @@ -7072,13 +7732,10 @@ index d94851c3aa..d428644539 100644 - if (!EC_POINT_set_compressed_coordinates_GFp(session->group, session->pwe, x_candidate, is_odd, NULL)) { - continue; - } -+ * check whether x^3 + a*x + b is a quadratic residue -+ * -+ * save the first quadratic residue we find in the loop but do -+ * it in constant time. ++ * need to unambiguously identify the solution, if there is ++ * one.. + */ -+ do_equation(session->group, y_sqrd, x_candidate, session->bnctx); -+ qr_or_qnr = is_quadratic_residue(y_sqrd, session->prime, qr, qnr, session->bnctx); ++ is_odd = BN_is_odd(rnd); /* - * If there's a solution to the equation then the point must be @@ -7090,9 +7747,13 @@ index d94851c3aa..d428644539 100644 - DEBUG("EAP-pwd: point is not on curve"); - continue; - } -+ * if the candidate >= prime then we want to skip it ++ * check whether x^3 + a*x + b is a quadratic residue ++ * ++ * save the first quadratic residue we find in the loop but do ++ * it in constant time. + */ -+ qr_or_qnr = const_time_select(skip, 0, qr_or_qnr); ++ do_equation(session->group, y_sqrd, x_candidate, session->bnctx); ++ qr_or_qnr = is_quadratic_residue(y_sqrd, session->prime, qr, qnr, session->bnctx); - if (BN_cmp(cofactor, BN_value_one())) { - /* make sure the point is not in a small sub-group */ @@ -7102,10 +7763,9 @@ index d94851c3aa..d428644539 100644 - continue; - } + /* -+ * if we haven't found PWE yet (found = 0) then mask will be true, -+ * if we have found PWE then mask will be false ++ * if the candidate >= prime then we want to skip it + */ -+ mask = const_time_select(found, 0, -1); ++ qr_or_qnr = const_time_select(skip, 0, qr_or_qnr); - if (EC_POINT_is_at_infinity(session->group, session->pwe)) { - DEBUG("EAP-pwd: point is at infinity"); @@ -7115,6 +7775,12 @@ index d94851c3aa..d428644539 100644 - /* if we got here then we have a new generator. */ - break; + /* ++ * if we haven't found PWE yet (found = 0) then mask will be true, ++ * if we have found PWE then mask will be false ++ */ ++ mask = const_time_select(found, 0, -1); ++ ++ /* + * save will be 1 if we want to save this value-- i.e. we haven't + * found PWE yet and this is a quadratic residue-- and 0 otherwise + */ @@ -7135,13 +7801,26 @@ index d94851c3aa..d428644539 100644 + * now we can savely construct PWE + */ + BN_bin2bn(xbuf, primebytelen, x_candidate); -+ if (!EC_POINT_set_compressed_coordinates(session->group, session->pwe, -+ x_candidate, save_is_odd, NULL)) { ++ do_equation(session->group, y_sqrd, x_candidate, session->bnctx); ++ if ( !BN_add(exp, session->prime, BN_value_one()) || ++ !BN_rshift(exp, exp, 2) || ++ !BN_mod_exp_mont_consttime(y1, y_sqrd, exp, session->prime, session->bnctx, NULL) || ++ !BN_sub(y2, session->prime, y1) || ++ !BN_bn2bin(y1, y1buf) || ++ !BN_bn2bin(y2, y2buf)) { ++ DEBUG("unable to compute y"); ++ goto fail; ++ } ++ mask = const_time_eq(save_is_odd, BN_is_odd(y1)); ++ const_time_select_bin(mask, y1buf, y2buf, primebytelen, ybuf); ++ if (BN_bin2bn(ybuf, primebytelen, y) == NULL || ++ !EC_POINT_set_affine_coordinates(session->group, session->pwe, x_candidate, y, session->bnctx)) { ++ DEBUG("unable to set point coordinate"); + goto fail; } session->group_num = grp_num; -@@ -278,78 +456,81 @@ int compute_password_element (pwd_session_t *session, uint16_t grp_num, +@@ -278,78 +490,89 @@ int compute_password_element (pwd_session_t *session, uint16_t grp_num, } /* cleanliness and order.... */ @@ -7152,12 +7831,21 @@ index d94851c3aa..d428644539 100644 + BN_clear_free(qnr); BN_clear_free(rnd); - talloc_free(prfbuf); +- HMAC_CTX_free(ctx); ++ BN_clear_free(y1); ++ BN_clear_free(y2); ++ BN_clear_free(y); ++ BN_clear_free(exp); + + if (prfbuf) talloc_free(prfbuf); + if (xbuf) talloc_free(xbuf); + if (pm1buf) talloc_free(pm1buf); ++ if (y1buf) talloc_free(y1buf); ++ if (y2buf) talloc_free(y2buf); ++ if (ybuf) talloc_free(ybuf); + - HMAC_CTX_free(ctx); ++ EVP_MD_CTX_free(hmac_ctx); ++ EVP_PKEY_free(hmac_pkey); return ret; } @@ -7264,7 +7952,7 @@ index d94851c3aa..d428644539 100644 goto finish; } -@@ -361,7 +542,7 @@ int process_peer_commit (pwd_session_t *session, uint8_t *in, size_t in_len, BN_ +@@ -361,7 +584,7 @@ int process_peer_commit (pwd_session_t *session, uint8_t *in, size_t in_len, BN_ * Did the peer send enough data? */ if (in_len < (2 * data_len + BN_num_bytes(session->order))) { @@ -7273,7 +7961,7 @@ index d94851c3aa..d428644539 100644 goto finish; } -@@ -377,54 +558,54 @@ int process_peer_commit (pwd_session_t *session, uint8_t *in, size_t in_len, BN_ +@@ -377,54 +600,54 @@ int process_peer_commit (pwd_session_t *session, uint8_t *in, size_t in_len, BN_ if (BN_is_zero(session->peer_scalar) || BN_is_one(session->peer_scalar) || BN_cmp(session->peer_scalar, session->order) >= 0) { @@ -7342,7 +8030,7 @@ index d94851c3aa..d428644539 100644 goto finish; } } -@@ -436,15 +617,15 @@ int process_peer_commit (pwd_session_t *session, uint8_t *in, size_t in_len, BN_ +@@ -436,15 +659,15 @@ int process_peer_commit (pwd_session_t *session, uint8_t *in, size_t in_len, BN_ * sure" so let's be safe. */ if (EC_POINT_is_at_infinity(session->group, K)) { @@ -7362,7 +8050,7 @@ index d94851c3aa..d428644539 100644 finish: EC_POINT_clear_free(K); -@@ -453,36 +634,29 @@ finish: +@@ -453,36 +676,29 @@ finish: BN_clear_free(x); BN_clear_free(y); @@ -7410,7 +8098,7 @@ index d94851c3aa..d428644539 100644 /* * Zero the memory each time because this is mod prime math and some -@@ -492,24 +666,24 @@ int compute_server_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) +@@ -492,24 +708,24 @@ int compute_server_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) */ offset = BN_num_bytes(session->prime) - BN_num_bytes(session->k); BN_bn2bin(session->k, cruft + offset); @@ -7440,7 +8128,7 @@ index d94851c3aa..d428644539 100644 /* * and server scalar -@@ -517,25 +691,25 @@ int compute_server_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) +@@ -517,25 +733,25 @@ int compute_server_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) memset(cruft, 0, BN_num_bytes(session->prime)); offset = BN_num_bytes(session->order) - BN_num_bytes(session->my_scalar); BN_bn2bin(session->my_scalar, cruft + offset); @@ -7471,7 +8159,7 @@ index d94851c3aa..d428644539 100644 /* * and peer scalar -@@ -543,52 +717,46 @@ int compute_server_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) +@@ -543,52 +759,46 @@ int compute_server_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) memset(cruft, 0, BN_num_bytes(session->prime)); offset = BN_num_bytes(session->order) - BN_num_bytes(session->peer_scalar); BN_bn2bin(session->peer_scalar, cruft + offset); @@ -7539,7 +8227,7 @@ index d94851c3aa..d428644539 100644 /* * Zero the memory each time because this is mod prime math and some -@@ -598,25 +766,25 @@ int compute_peer_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) +@@ -598,25 +808,25 @@ int compute_peer_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) */ offset = BN_num_bytes(session->prime) - BN_num_bytes(session->k); BN_bn2bin(session->k, cruft + offset); @@ -7570,7 +8258,7 @@ index d94851c3aa..d428644539 100644 /* * and peer scalar -@@ -624,24 +792,24 @@ int compute_peer_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) +@@ -624,24 +834,24 @@ int compute_peer_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) memset(cruft, 0, BN_num_bytes(session->prime)); offset = BN_num_bytes(session->order) - BN_num_bytes(session->peer_scalar); BN_bn2bin(session->peer_scalar, cruft + offset); @@ -7600,7 +8288,7 @@ index d94851c3aa..d428644539 100644 /* * and server scalar -@@ -649,94 +817,75 @@ int compute_peer_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) +@@ -649,94 +859,75 @@ int compute_peer_confirm (pwd_session_t *session, uint8_t *out, BN_CTX *bnctx) memset(cruft, 0, BN_num_bytes(session->prime)); offset = BN_num_bytes(session->order) - BN_num_bytes(session->my_scalar); BN_bn2bin(session->my_scalar, cruft + offset); @@ -8554,49 +9242,22 @@ index cebcb92f57..550cbbdce3 100644 #endif /* _RLM_EAP_TLS_H */ diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c -index a3c575bceb..3c77aa4877 100644 +index a3c575bceb..4e53c92244 100644 --- a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c +++ b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c -@@ -130,6 +130,25 @@ static int mod_instantiate(CONF_SECTION *cs, void **instance) - return -1; - } - -+#ifdef TLS1_3_VERSION -+ if ((inst->tls_conf->min_version == TLS1_3_VERSION) && !inst->tls_conf->tls13_enable_magic) { -+ ERROR("There are no standards for using TLS 1.3 with TTLS."); -+ ERROR("You MUST enable TLS 1.2 for TTLS to work."); -+ return -1; -+ } -+ -+ if ((inst->tls_conf->max_version == TLS1_3_VERSION) || -+ (inst->tls_conf->min_version == TLS1_3_VERSION)) { -+ WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); -+ WARN("!! There is no standard for using TTLS with TLS 1.3"); -+ WARN("!! Please set tls_max_version = \"1.2\""); -+ WARN("!! FreeRADIUS only supports TLS 1.3 for special builds of wpa_supplicant and Windows"); -+ WARN("!! This limitation is likely to change in late 2021."); -+ WARN("!! If you are using this version of FreeRADIUS after 2021, you will probably need to upgrade"); -+ WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); -+ } -+#endif -+ - return 0; - } - -@@ -181,7 +200,11 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) +@@ -181,7 +181,10 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) client_cert = inst->req_client_cert; } - ssn = eaptls_session(handler, inst->tls_conf, client_cert); + /* -+ * Don't allow TLS 1.3 for us, even if it's allowed -+ * elsewhere. ++ * Allow TLS 1.3, it works. + */ -+ ssn = eaptls_session(handler, inst->tls_conf, client_cert, inst->tls_conf->tls13_enable_magic); ++ ssn = eaptls_session(handler, inst->tls_conf, client_cert, true); if (!ssn) { return 0; } -@@ -189,9 +212,13 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) +@@ -189,9 +192,13 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) handler->opaque = ((void *)ssn); /* @@ -8612,7 +9273,7 @@ index a3c575bceb..3c77aa4877 100644 /* * TLS session initialization is over. Now handle TLS -@@ -201,7 +228,7 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) +@@ -201,7 +208,7 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) { REDEBUG("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "")); } else { @@ -8621,7 +9282,7 @@ index a3c575bceb..3c77aa4877 100644 } if (status == 0) return 0; -@@ -238,7 +265,7 @@ static int mod_process(void *arg, eap_handler_t *handler) +@@ -238,7 +245,7 @@ static int mod_process(void *arg, eap_handler_t *handler) if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) { REDEBUG("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "")); } else { @@ -8630,7 +9291,7 @@ index a3c575bceb..3c77aa4877 100644 } /* -@@ -342,8 +369,7 @@ static int mod_process(void *arg, eap_handler_t *handler) +@@ -342,8 +349,7 @@ static int mod_process(void *arg, eap_handler_t *handler) * Success: Automatically return MPPE keys. */ case PW_CODE_ACCESS_ACCEPT: @@ -8908,7 +9569,7 @@ index c825a9230b..9e77cd7ff1 100644 /* diff --git a/src/modules/rlm_ldap/ldap.h b/src/modules/rlm_ldap/ldap.h -index 7dc874d35e..bcec9af9dc 100644 +index 7dc874d35e..29e7cfd757 100644 --- a/src/modules/rlm_ldap/ldap.h +++ b/src/modules/rlm_ldap/ldap.h @@ -20,6 +20,7 @@ @@ -8919,8 +9580,18 @@ index 7dc874d35e..bcec9af9dc 100644 #include #include #include "config.h" +@@ -265,6 +266,9 @@ typedef struct ldap_instance { + + int tls_require_cert; //!< OpenLDAP constant representing the require cert string. + ++ char const *tls_min_version_str; //!< Minimum TLS version ++ int tls_min_version; ++ + /* + * Options + */ diff --git a/src/modules/rlm_mschap/rlm_mschap.c b/src/modules/rlm_mschap/rlm_mschap.c -index 83c84a63e2..4e4447a213 100644 +index 83c84a63e2..25bcd9c44e 100644 --- a/src/modules/rlm_mschap/rlm_mschap.c +++ b/src/modules/rlm_mschap/rlm_mschap.c @@ -322,6 +322,56 @@ static ssize_t mschap_xlat(void *instance, REQUEST *request, @@ -8997,7 +9668,7 @@ index 83c84a63e2..4e4447a213 100644 if (!nt_password) { RDEBUG("Local MS-CHAPv2 password change requires NT-Password attribute"); -@@ -951,11 +1000,45 @@ ntlm_auth_err: +@@ -951,11 +1000,47 @@ ntlm_auth_err: RDEBUG("Doing MS-CHAPv2 password change locally"); } @@ -9014,22 +9685,24 @@ index 83c84a63e2..4e4447a213 100644 + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { + REDEBUG("Failed getting RC4 from OpenSSL"); ++ error: ++ if (ctx) EVP_CIPHER_CTX_free(ctx); + return -1; + } + + if (!EVP_CIPHER_CTX_set_key_length(ctx, nt_password->vp_length)) { + REDEBUG("Failed setting key length"); -+ return -1; ++ goto error; + } + + if (!EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, nt_password->vp_octets, NULL)) { + REDEBUG("Failed setting key value"); -+ return -1; ++ goto error;; + } + + if (!EVP_EncryptUpdate(ctx, nt_pass_decrypted, &ntlen, new_nt_password, ntlen)) { + REDEBUG("Failed getting output"); -+ return -1; ++ goto error; + } + + EVP_CIPHER_CTX_free(ctx); diff --git a/SOURCES/freeradius-bootstrap-pass-noenc-to-certificate-generation.patch b/SOURCES/freeradius-bootstrap-pass-noenc-to-certificate-generation.patch new file mode 100644 index 0000000..b3dc68e --- /dev/null +++ b/SOURCES/freeradius-bootstrap-pass-noenc-to-certificate-generation.patch @@ -0,0 +1,136 @@ +From e089777942552c4fe3e58aa328566e7bb745dbf8 Mon Sep 17 00:00:00 2001 +From: Antonio Torres +Date: Fri, 22 Apr 2022 12:27:43 +0200 +Subject: [PATCH] bootstrap: pass -noenc to certificate generation + +Bootstrap script would fail to generate certificates if run on systems +with FIPS enabled. By passing the -noenc option, we can skip the usage +of unsupported algorithms on these systems. + +After generating the certificates, correct permissions are set. + +Signed-off-by: Antonio Torres + +[antorres@redhat.com]: patch adapted to work together with freeradius-bootstrap-create-only.patch. +In bootstrap diff, -f is changed to -e in conditionals. +--- + raddb/certs/Makefile | 20 ++++++++++++++++---- + raddb/certs/bootstrap | 6 +++--- + 2 files changed, 19 insertions(+), 7 deletions(-) + +diff --git a/raddb/certs/Makefile b/raddb/certs/Makefile +index 5cbfd467ce..cb10394ec3 100644 +--- a/raddb/certs/Makefile ++++ b/raddb/certs/Makefile +@@ -60,6 +60,8 @@ passwords.mk: server.cnf ca.cnf client.cnf inner-server.cnf + ###################################################################### + dh: + $(OPENSSL) dhparam -out dh -2 $(DH_KEY_SIZE) ++ chown root:radiusd dh ++ chmod 640 dh + + ###################################################################### + # +@@ -71,8 +73,10 @@ ca.key ca.pem: ca.cnf + @[ -f serial ] || $(MAKE) serial + $(OPENSSL) req -new -x509 -keyout ca.key -out ca.pem \ + -days $(CA_DEFAULT_DAYS) -config ./ca.cnf \ +- -passin pass:$(PASSWORD_CA) -passout pass:$(PASSWORD_CA) ++ -passin pass:$(PASSWORD_CA) -passout pass:$(PASSWORD_CA) -noenc + chmod g+r ca.key ++ chown root:radiusd ca.* ++ chmod 640 ca.* + + ca.der: ca.pem + $(OPENSSL) x509 -inform PEM -outform DER -in ca.pem -out ca.der +@@ -81,6 +85,8 @@ ca.crl: ca.pem + $(OPENSSL) ca -gencrl -keyfile ca.key -cert ca.pem -config ./ca.cnf -out ca-crl.pem -key $(PASSWORD_CA) + $(OPENSSL) crl -in ca-crl.pem -outform der -out ca.crl + rm ca-crl.pem ++ chown root:radiusd ca.* ++ chmod 640 ca.* + + ###################################################################### + # +@@ -88,7 +94,7 @@ ca.crl: ca.pem + # + ###################################################################### + server.csr server.key: server.cnf +- $(OPENSSL) req -new -out server.csr -keyout server.key -config ./server.cnf ++ $(OPENSSL) req -new -out server.csr -keyout server.key -config ./server.cnf -noenc + chmod g+r server.key + + server.crt: server.csr ca.key ca.pem +@@ -101,6 +107,8 @@ server.p12: server.crt + server.pem: server.p12 + $(OPENSSL) pkcs12 -in server.p12 -out server.pem -passin pass:$(PASSWORD_SERVER) -passout pass:$(PASSWORD_SERVER) + chmod g+r server.pem ++ chown root:radiusd server.* ++ chmod 640 server.* + + .PHONY: server.vrfy + server.vrfy: ca.pem +@@ -113,7 +121,7 @@ server.vrfy: ca.pem + # + ###################################################################### + client.csr client.key: client.cnf +- $(OPENSSL) req -new -out client.csr -keyout client.key -config ./client.cnf ++ $(OPENSSL) req -new -out client.csr -keyout client.key -config ./client.cnf -noenc + chmod g+r client.key + + client.crt: client.csr ca.pem ca.key +@@ -127,6 +135,8 @@ client.pem: client.p12 + $(OPENSSL) pkcs12 -in client.p12 -out client.pem -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT) + chmod g+r client.pem + cp client.pem $(USER_NAME).pem ++ chown root:radiusd client.* ++ chmod 640 client.* + + .PHONY: client.vrfy + client.vrfy: ca.pem client.pem +@@ -139,7 +149,7 @@ client.vrfy: ca.pem client.pem + # + ###################################################################### + inner-server.csr inner-server.key: inner-server.cnf +- $(OPENSSL) req -new -out inner-server.csr -keyout inner-server.key -config ./inner-server.cnf ++ $(OPENSSL) req -new -out inner-server.csr -keyout inner-server.key -config ./inner-server.cnf -noenc + chmod g+r inner-server.key + + inner-server.crt: inner-server.csr ca.key ca.pem +@@ -152,6 +162,8 @@ inner-server.p12: inner-server.crt + inner-server.pem: inner-server.p12 + $(OPENSSL) pkcs12 -in inner-server.p12 -out inner-server.pem -passin pass:$(PASSWORD_INNER) -passout pass:$(PASSWORD_INNER) + chmod g+r inner-server.pem ++ chown root:radiusd inner-server.* ++ chmod 640 inner-server.* + + .PHONY: inner-server.vrfy + inner-server.vrfy: ca.pem +diff --git a/raddb/certs/bootstrap b/raddb/certs/bootstrap +index 57de8cf0d7..c258ec45e0 100755 +--- a/raddb/certs/bootstrap ++++ b/raddb/certs/bootstrap +@@ -41,12 +41,12 @@ if [ ! -f dh ]; then + fi + + if [ ! -e server.key ]; then +- openssl req -new -out server.csr -keyout server.key -config ./server.cnf || exit 1 ++ openssl req -new -out server.csr -keyout server.key -config ./server.cnf -noenc || exit 1 + chmod g+r server.key + fi + + if [ ! -e ca.key ]; then +- openssl req -new -x509 -keyout ca.key -out ca.pem -days `grep default_days ca.cnf | sed 's/.*=//;s/^ *//'` -config ./ca.cnf || exit 1 ++ openssl req -new -x509 -keyout ca.key -out ca.pem -days `grep default_days ca.cnf | sed 's/.*=//;s/^ *//'` -config ./ca.cnf -noenc || exit 1 + fi + + if [ ! -e index.txt ]; then +@@ -77,7 +77,7 @@ if [ ! -f ca.der ]; then + fi + + if [ ! -e client.key ]; then +- openssl req -new -out client.csr -keyout client.key -config ./client.cnf ++ openssl req -new -out client.csr -keyout client.key -config ./client.cnf -noenc + chmod g+r client.key + fi + \ No newline at end of file diff --git a/SOURCES/freeradius.sysusers b/SOURCES/freeradius.sysusers new file mode 100644 index 0000000..c0d814e --- /dev/null +++ b/SOURCES/freeradius.sysusers @@ -0,0 +1,3 @@ +#Type Name ID GECOS Home directory Shell +u radiusd 95 "radiusd user" /var/lib/radiusd /sbin/nologin +g radiusd 95 - - - \ No newline at end of file diff --git a/SPECS/freeradius.spec b/SPECS/freeradius.spec index 2a42dea..12a9004 100644 --- a/SPECS/freeradius.spec +++ b/SPECS/freeradius.spec @@ -1,7 +1,7 @@ Summary: High-performance and highly configurable free RADIUS server Name: freeradius Version: 3.0.21 -Release: 26%{?dist} +Release: 34%{?dist} License: GPLv2+ and LGPLv2+ URL: http://www.freeradius.org/ @@ -19,6 +19,7 @@ Source100: radiusd.service Source102: freeradius-logrotate Source103: freeradius-pam-conf Source104: freeradius-tmpfiles.conf +Source105: freeradius.sysusers Patch1: freeradius-Adjust-configuration-to-fit-Red-Hat-specifics.patch Patch2: freeradius-Use-system-crypto-policy-by-default.patch @@ -28,6 +29,7 @@ Patch5: freeradius-bootstrap-make-permissions.patch Patch6: freeradius-Fix-resource-hard-limit-error.patch Patch7: freeradius-ldap-infinite-timeout-on-starttls.patch Patch8: freeradius-Backport-OpenSSL3-fixes.patch +Patch9: freeradius-bootstrap-pass-noenc-to-certificate-generation.patch %global docdir %{?_pkgdocdir}%{!?_pkgdocdir:%{_docdir}/%{name}-%{version}} @@ -47,6 +49,7 @@ BuildRequires: systemd-units BuildRequires: libtalloc-devel BuildRequires: pcre-devel BuildRequires: chrpath +BuildRequires: systemd-rpm-macros %if ! 0%{?rhel} BuildRequires: libyubikey-devel @@ -56,6 +59,7 @@ BuildRequires: ykclient-devel # Require OpenSSL version we built with, or newer, to avoid startup failures # due to runtime OpenSSL version checks. Requires: openssl >= %(rpm -q --queryformat '%%{VERSION}' openssl) +Requires: openssl-perl Requires(pre): shadow-utils glibc-common Requires(post): systemd-sysv Requires(post): systemd-units @@ -213,6 +217,7 @@ This plugin provides the REST support for the FreeRADIUS server project. %patch6 -p1 %patch7 -p1 %patch8 -p1 +%patch9 -p1 %build # Force compile/link options, extra security for network facing daemon @@ -225,6 +230,9 @@ sed 's/rlm_python/rlm_python3/g' src/modules/stable -i export PY3_LIB_DIR="$(python3-config --configdir)" export PY3_INC_DIR="$(python3 -c 'import sysconfig; print(sysconfig.get_config_var("INCLUDEPY"))')" +# Enable FIPS support +%global build_cflags %{build_cflags} -DWITH_FIPS + # In order for the above hack to stick, do a fake configure so # we can run reconfig before cleaning up after ourselves and running # configure for real. @@ -279,6 +287,7 @@ mkdir -p %{buildroot}%{_localstatedir}/run/ install -d -m 0710 %{buildroot}%{_localstatedir}/run/radiusd/ install -d -m 0700 %{buildroot}%{_localstatedir}/run/radiusd/tmp install -m 0644 %{SOURCE104} %{buildroot}%{_tmpfilesdir}/radiusd.conf +install -p -D -m 0644 %{SOURCE105} %{buildroot}%{_sysusersdir}/freeradius.conf # install SNMP MIB files mkdir -p $RPM_BUILD_ROOT%{_datadir}/snmp/mibs/ @@ -362,20 +371,13 @@ EOF # Make sure our user/group is present prior to any package or subpackage installation %pre -getent group radiusd >/dev/null || /usr/sbin/groupadd -r -g 95 radiusd > /dev/null 2>&1 -getent passwd radiusd >/dev/null || /usr/sbin/useradd -r -g radiusd -u 95 -c "radiusd user" -d %{_localstatedir}/lib/radiusd -s /sbin/nologin radiusd > /dev/null 2>&1 -exit 0 +%sysusers_create_compat %{SOURCE105} %preun %systemd_preun radiusd.service %postun %systemd_postun_with_restart radiusd.service -if [ $1 -eq 0 ]; then # uninstall - getent passwd radiusd >/dev/null && /usr/sbin/userdel radiusd > /dev/null 2>&1 - getent group radiusd >/dev/null && /usr/sbin/groupdel radiusd > /dev/null 2>&1 -fi -exit 0 /bin/systemctl try-restart radiusd.service >/dev/null 2>&1 || : @@ -394,6 +396,7 @@ exit 0 %config(noreplace) %{_sysconfdir}/ld.so.conf.d/%{name}-%{_arch}.conf %{_unitdir}/radiusd.service %{_tmpfilesdir}/radiusd.conf +%{_sysusersdir}/freeradius.conf %dir %attr(710,radiusd,radiusd) %{_localstatedir}/run/radiusd %dir %attr(700,radiusd,radiusd) %{_localstatedir}/run/radiusd/tmp %dir %attr(755,radiusd,radiusd) %{_localstatedir}/lib/radiusd @@ -855,6 +858,39 @@ exit 0 %attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-available/rest %changelog +* Wed Jun 29 2022 Antonio Torres - 3.0.21-34 +- Use GID / UID 95 as it's reserved for FreeRADIUS (https://pagure.io/setup/blob/07f8debf03dfb0e5ed36051c13c86c8cd00cd241/f/uidgid#_107) + Resolves: #2095403 + +* Fri Jun 24 2022 Antonio Torres - 3.0.21-33 +- Dynamically allocate users using sysusers.d format + Resolves: #2095403 + +* Mon May 30 2022 Antonio Torres - 3.0.21-32 +- Add WITH_FIPS macro to CFLAGS + Related: rhbz#2083699 + +* Tue May 24 2022 Antonio Torres - 3.0.21-31 +- Update OpenSSL 3.0 support backport to current v3.0.x branch state +- Add "--enable-fips-workaround" to build options + Related: rhbz#2083699 + +* Tue May 10 2022 Antonio Torres - 3.0.21-30 +- Add openssl-perl dependency + Related: rhbz#2078816 + +* Thu Apr 28 2022 Antonio Torres - 3.0.21-29 +- Set correct permissions for certificates generated by bootstrap Makefile + Related: rhbz#2069224 + +* Mon Apr 25 2022 Antonio Torres - 3.0.21-28 +- bootstrap: pass -noenc to certificate generation, do it on script as well + Related: rhbz#2069224 + +* Fri Apr 22 2022 Antonio Torres - 3.0.21-27 +- bootstrap: pass -noenc to certificate generation + Related: rhbz#2069224 + * Mon Jan 31 2022 Antonio Torres - 3.0.21-26 - Move remaining files from /var/run to /run Related: rhbz#2047972