"Fossies" - the Fresh Open Source Software Archive

Member "freeradius-server-3.0.23/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c" (10 Jun 2021, 19047 Bytes) of package /linux/misc/freeradius-server-3.0.23.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rlm_eap_fast.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.0.22_vs_3.0.23.

    1 /*
    2  * rlm_eap_fast.c  contains the interfaces that are called from eap
    3  *
    4  * Version:     $Id: 02ea77f3c220daf7284e8d3e970d8ce9f1acad64 $
    5  *
    6  *   This program is free software; you can redistribute it and/or modify
    7  *   it under the terms of the GNU General Public License as published by
    8  *   the Free Software Foundation; either version 2 of the License, or
    9  *   (at your option) any later version.
   10  *
   11  *   This program is distributed in the hope that it will be useful,
   12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  *   GNU General Public License for more details.
   15  *
   16  *   You should have received a copy of the GNU General Public License
   17  *   along with this program; if not, write to the Free Software
   18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
   19  *
   20  * Copyright 2016 Alan DeKok <aland@freeradius.org>
   21  * Copyright 2016 The FreeRADIUS server project
   22  */
   23 
   24 RCSID("$Id: 02ea77f3c220daf7284e8d3e970d8ce9f1acad64 $")
   25 USES_APPLE_DEPRECATED_API   /* OpenSSL API has been deprecated by Apple */
   26 
   27 
   28 #include "eap_fast.h"
   29 #include "eap_fast_crypto.h"
   30 
   31 
   32 #include <freeradius-devel/md5.h>
   33 
   34 /*
   35  *  An instance of EAP-FAST
   36  */
   37 typedef struct rlm_eap_fast_t {
   38     char const      *tls_conf_name;             //!< Name of shared TLS config.
   39     fr_tls_server_conf_t *tls_conf;
   40 
   41     char const      *default_method_name;
   42     int         default_method;
   43 
   44     char const      *virtual_server;            //!< Virtual server to use for processing
   45                                     //!< inner EAP method.
   46     char const      *cipher_list;               //!< cipher list specific to EAP-FAST
   47     bool            req_client_cert;            //!< Whether we require a client cert
   48                                     //!< in the outer tunnel.
   49 
   50     int         stage;                  //!< Processing stage.
   51 
   52     uint32_t pac_lifetime;              //!< seconds to add to current time to describe PAC lifetime
   53     char const      *authority_identity;            //!< The identity we present in the EAP-TLS
   54     uint8_t         a_id[PAC_A_ID_LENGTH];          //!< The identity we present in the EAP-TLS
   55     char const      *pac_opaque_key;            //!< The key used to encrypt PAC-Opaque
   56     bool use_tunneled_reply;        //!< Use the reply attributes from the tunneled session in
   57                         //!< the non-tunneled reply to the client.
   58 
   59     bool copy_request_to_tunnel;        //!< Use SOME of the request attributes from outside of the
   60 } rlm_eap_fast_t;
   61 
   62 
   63 static CONF_PARSER module_config[] = {
   64     { "tls", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_fast_t, tls_conf_name), NULL },
   65 
   66     { "default_eap_type", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_fast_t, default_method_name), "mschapv2" },
   67 
   68     { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED | PW_TYPE_NOT_EMPTY, rlm_eap_fast_t, virtual_server) , NULL},
   69     { "cipher_list", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_fast_t, cipher_list) , NULL},
   70 
   71     { "require_client_cert", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_fast_t, req_client_cert), "no" },
   72 
   73     { "pac_lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_eap_fast_t, pac_lifetime), "604800" },
   74     { "authority_identity", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED, rlm_eap_fast_t, authority_identity), NULL },
   75     { "pac_opaque_key", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED, rlm_eap_fast_t, pac_opaque_key), NULL },
   76     { "copy_request_to_tunnel", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_fast_t, copy_request_to_tunnel), "no" },
   77 
   78     { "use_tunneled_reply", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_fast_t, use_tunneled_reply), "no" },
   79 
   80     CONF_PARSER_TERMINATOR
   81 };
   82 
   83 /*
   84  *  Attach the module.
   85  */
   86 static int mod_instantiate(CONF_SECTION *cs, void **instance)
   87 {
   88     rlm_eap_fast_t *inst;
   89 
   90     *instance = inst = talloc_zero(cs, rlm_eap_fast_t);
   91     if (!inst) return -1;
   92 
   93     /*
   94      *  Parse the configuration attributes.
   95      */
   96     if (cf_section_parse(cs, inst, module_config) < 0) {
   97         return -1;
   98     }
   99 
  100     if (!cf_section_sub_find_name2(main_config.config, "server", inst->virtual_server)) {
  101         ERROR("rlm_eap_fast.virtual_server: Unknown virtual server '%s'", inst->virtual_server);
  102         return -1;
  103     }
  104 
  105     inst->default_method = eap_name2type(inst->default_method_name);
  106     if (!inst->default_method) {
  107         ERROR("rlm_eap_fast.default_provisioning_eap_type: "
  108               "Unknown EAP type %s",
  109                    inst->default_method_name);
  110         return -1;
  111     }
  112 
  113     /*
  114      *  Read tls configuration, either from group given by 'tls'
  115      *  option, or from the eap-tls configuration.
  116      */
  117     inst->tls_conf = eaptls_conf_parse(cs, "tls");
  118 
  119     if (!inst->tls_conf) {
  120         ERROR("rlm_eap_fast.tls: Failed initializing SSL context");
  121         return -1;
  122     }
  123 
  124     if (talloc_array_length(inst->pac_opaque_key) - 1 != 32) {
  125         ERROR("rlm_eap_fast.pac_opaque_key: Must be 32 bytes long");
  126         return -1;
  127     }
  128 
  129     if (!inst->pac_lifetime) {
  130         ERROR("rlm_eap_fast.pac_lifetime: must be non-zero");
  131         return -1;
  132     }
  133 
  134 #ifdef TLS1_3_VERSION
  135     if (inst->tls_conf->min_version == TLS1_3_VERSION) {
  136         ERROR("There are no standards for using TLS 1.3 with EAP-FAST.");
  137         ERROR("You MUST enable TLS 1.2 for EAP-FAST to work.");
  138         return -1;
  139     }
  140 
  141     if ((inst->tls_conf->max_version == TLS1_3_VERSION) ||
  142         (inst->tls_conf->min_version == TLS1_3_VERSION)) {
  143         WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
  144         WARN("!! There is no standard for using EAP-FAST with TLS 1.3");
  145         WARN("!! Please set tls_max_version = \"1.2\"");
  146         WARN("!! FreeRADIUS only supports TLS 1.3 for special builds of wpa_supplicant and Windows");
  147         WARN("!! This limitation is likely to change in late 2021.");
  148         WARN("!! If you are using this version of FreeRADIUS after 2021, you will probably need to upgrade");
  149         WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
  150     }
  151 #endif
  152 
  153     rad_assert(PAC_A_ID_LENGTH == MD5_DIGEST_LENGTH);
  154     FR_MD5_CTX ctx;
  155     fr_md5_init(&ctx);
  156     fr_md5_update(&ctx, inst->authority_identity, talloc_array_length(inst->authority_identity) - 1);
  157     fr_md5_final(inst->a_id, &ctx);
  158 
  159     return 0;
  160 }
  161 
  162 /** Allocate the FAST per-session data
  163  *
  164  */
  165 static eap_fast_tunnel_t *eap_fast_alloc(TALLOC_CTX *ctx, rlm_eap_fast_t *inst)
  166 {
  167     eap_fast_tunnel_t *t = talloc_zero(ctx, eap_fast_tunnel_t);
  168 
  169     t->mode = EAP_FAST_UNKNOWN;
  170     t->stage = TLS_SESSION_HANDSHAKE;
  171 
  172     t->default_method = inst->default_method;
  173     t->copy_request_to_tunnel = inst->copy_request_to_tunnel;
  174     t->use_tunneled_reply = inst->use_tunneled_reply;
  175 
  176     t->pac_lifetime = inst->pac_lifetime;
  177     t->authority_identity = inst->authority_identity;
  178     t->a_id = inst->a_id;
  179     t->pac_opaque_key = (const uint8_t *)inst->pac_opaque_key;
  180 
  181     t->virtual_server = inst->virtual_server;
  182 
  183     return t;
  184 }
  185 
  186 static void eap_fast_session_ticket(tls_session_t *tls_session, uint8_t *client_random,
  187                     uint8_t *server_random, uint8_t *secret, int *secret_len)
  188 {
  189     eap_fast_tunnel_t   *t = (eap_fast_tunnel_t *) tls_session->opaque;
  190     uint8_t         seed[2 * SSL3_RANDOM_SIZE];
  191 
  192     rad_assert(t->pac.key);
  193 
  194     memcpy(seed, server_random, SSL3_RANDOM_SIZE);
  195     memcpy(&seed[SSL3_RANDOM_SIZE], client_random, SSL3_RANDOM_SIZE);
  196 
  197     T_PRF(t->pac.key, PAC_KEY_LENGTH, "PAC to master secret label hash",
  198           seed, sizeof(seed), secret, SSL_MAX_MASTER_KEY_LENGTH);
  199     *secret_len = SSL_MAX_MASTER_KEY_LENGTH;
  200 }
  201 
  202 // hostap:src/crypto/tls_openssl.c:tls_sess_sec_cb()
  203 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  204 static int _session_secret(SSL *s, void *secret, int *secret_len,
  205                UNUSED STACK_OF(SSL_CIPHER) *peer_ciphers,
  206                UNUSED SSL_CIPHER **cipher, void *arg)
  207 #else
  208 static int _session_secret(SSL *s, void *secret, int *secret_len,
  209                UNUSED STACK_OF(SSL_CIPHER) *peer_ciphers,
  210                UNUSED const SSL_CIPHER **cipher, void *arg)
  211 #endif
  212 {
  213     // FIXME enforce non-anon cipher
  214 
  215     REQUEST     *request = (REQUEST *)SSL_get_ex_data(s, FR_TLS_EX_INDEX_REQUEST);
  216     tls_session_t   *tls_session = arg;
  217     eap_fast_tunnel_t   *t;
  218 
  219     if (!tls_session) return 0;
  220 
  221     t = (eap_fast_tunnel_t *) tls_session->opaque;
  222 
  223     if (!t->pac.key) return 0;
  224 
  225     RDEBUG("processing PAC-Opaque");
  226 
  227 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  228     eap_fast_session_ticket(tls_session, s->s3->client_random, s->s3->server_random, secret, secret_len);
  229 #else
  230     uint8_t client_random[SSL3_RANDOM_SIZE];
  231     uint8_t server_random[SSL3_RANDOM_SIZE];
  232 
  233     SSL_get_client_random(s, client_random, sizeof(client_random));
  234     SSL_get_server_random(s, server_random, sizeof(server_random));
  235 
  236     eap_fast_session_ticket(tls_session, client_random, server_random, secret, secret_len);
  237 #endif
  238 
  239     memset(t->pac.key, 0, PAC_KEY_LENGTH);
  240     talloc_free(t->pac.key);
  241     t->pac.key = NULL;
  242 
  243     return 1;
  244 }
  245 
  246 /*
  247  * hints from hostap:src/crypto/tls_openssl.c:tls_session_ticket_ext_cb()
  248  *
  249  * N.B. we actually always tell OpenSSL we have digested the ticket so that
  250  *      it does not cause a fail loop and enables us to update the PAC easily
  251  *
  252  */
  253 static int _session_ticket(SSL *s, uint8_t const *data, int len, void *arg)
  254 {
  255     tls_session_t       *tls_session = arg;
  256     REQUEST         *request = (REQUEST *)SSL_get_ex_data(s, FR_TLS_EX_INDEX_REQUEST);
  257     eap_fast_tunnel_t   *t;
  258     VALUE_PAIR      *fast_vps = NULL;
  259     vp_cursor_t     cursor;
  260     DICT_ATTR const *fast_da;
  261     char const      *errmsg;
  262     int         dlen, plen;
  263     uint16_t        length;
  264     eap_fast_attr_pac_opaque_t const    *opaque = (eap_fast_attr_pac_opaque_t const *) data;
  265     eap_fast_attr_pac_opaque_t      opaque_plaintext;
  266 
  267     if (!tls_session) return 0;
  268 
  269     t = (eap_fast_tunnel_t *) tls_session->opaque;
  270 
  271     RDEBUG("PAC provided via ClientHello SessionTicket extension");
  272 
  273     if ((ntohs(opaque->hdr.type) & EAP_FAST_TLV_TYPE) != PAC_INFO_PAC_OPAQUE) {
  274         errmsg = "PAC is not of type Opaque";
  275 error:
  276         RERROR("%s, sending alert to client", errmsg);
  277         /*
  278         if (tls_session_handshake_alert(request, tls_session, SSL3_AL_FATAL, SSL_AD_BAD_CERTIFICATE)) {
  279             RERROR("too many alerts");
  280             return 0;
  281         }
  282         */
  283         if (t->pac.key) talloc_free(t->pac.key);
  284 
  285         memset(&t->pac, 0, sizeof(t->pac));
  286         if (fast_vps) fr_pair_list_free(&fast_vps);
  287         return 1;
  288     }
  289 
  290     /*
  291      * we would like to use the length of the SessionTicket
  292      * but Cisco hates everyone and sends a zero padding payload
  293      * so we have to use the length in the PAC-Opaque header
  294      */
  295     length = ntohs(opaque->hdr.length);
  296     if (len - sizeof(opaque->hdr) < length) {
  297         errmsg = "PAC has bad length in header";
  298         goto error;
  299     }
  300 
  301     if (length < PAC_A_ID_LENGTH + EVP_MAX_IV_LENGTH + EVP_GCM_TLS_TAG_LEN + 1) {
  302         errmsg = "PAC file too short";
  303         goto error;
  304     }
  305 
  306     if (memcmp(opaque->aad, t->a_id, PAC_A_ID_LENGTH)) {
  307         errmsg = "PAC has incorrect A_ID";
  308         goto error;
  309     }
  310 
  311     dlen = length - sizeof(opaque->aad) - sizeof(opaque->iv) - sizeof(opaque->tag);
  312     plen = eap_fast_decrypt(opaque->data, dlen, opaque->aad, PAC_A_ID_LENGTH,
  313                     (uint8_t const *) opaque->tag, t->pac_opaque_key, opaque->iv,
  314                     (uint8_t *)&opaque_plaintext);
  315     if (plen == -1) {
  316         errmsg = "PAC failed to decrypt";
  317         goto error;
  318     }
  319 
  320     fast_da = dict_attrbyname("FreeRADIUS-EAP-FAST-PAC-Opaque-TLV");
  321     rad_assert(fast_da != NULL);
  322 
  323     fast_vps = eap_fast_fast2vp((REQUEST *)tls_session, s, (uint8_t *)&opaque_plaintext, plen, fast_da, NULL);
  324     if (!fast_vps) return 0;
  325 
  326     for (VALUE_PAIR *vp = fr_cursor_init(&cursor, &fast_vps); vp; vp = fr_cursor_next(&cursor)) {
  327         char *value;
  328 
  329         switch ((vp->da->attr >> fr_attr_shift[3]) & fr_attr_mask[3]) {
  330         case PAC_INFO_PAC_TYPE:
  331             rad_assert(t->pac.type == 0);
  332             t->pac.type = vp->vp_integer;
  333             break;
  334         case PAC_INFO_PAC_LIFETIME:
  335             rad_assert(t->pac.expires == 0);
  336             t->pac.expires = vp->vp_integer;
  337             t->pac.expired = (vp->vp_integer <= time(NULL));
  338             break;
  339         case PAC_INFO_PAC_KEY:
  340             rad_assert(t->pac.key == NULL);
  341             rad_assert(vp->vp_length == PAC_KEY_LENGTH);
  342             t->pac.key = talloc_size(t, PAC_KEY_LENGTH);
  343             rad_assert(t->pac.key != NULL);
  344             memcpy(t->pac.key, vp->vp_octets, PAC_KEY_LENGTH);
  345             break;
  346         default:
  347             value = vp_aprints(tls_session, vp, '"');
  348             RERROR("unknown TLV: %s", value);
  349             talloc_free(value);
  350             errmsg = "unknown TLV";
  351             goto error;
  352         }
  353     }
  354 
  355     fr_pair_list_free(&fast_vps);
  356 
  357     if (!t->pac.type) {
  358         errmsg = "PAC missing type TLV";
  359         goto error;
  360     }
  361 
  362     if (t->pac.type != PAC_TYPE_TUNNEL) {
  363         errmsg = "PAC is of not of tunnel type";
  364         goto error;
  365     }
  366 
  367     if (!t->pac.expires) {
  368         errmsg = "PAC missing lifetime TLV";
  369         goto error;
  370     }
  371 
  372     if (!t->pac.key) {
  373         errmsg = "PAC missing key TLV";
  374         goto error;
  375     }
  376 
  377     if (!SSL_set_session_secret_cb(tls_session->ssl, _session_secret, tls_session)) {
  378         RERROR("Failed setting SSL session secret callback");
  379         return 0;
  380     }
  381 
  382     return 1;
  383 }
  384 
  385 
  386 /*
  387  *  Do authentication, by letting EAP-TLS do most of the work.
  388  */
  389 static int mod_process(void *arg, eap_handler_t *handler)
  390 {
  391     int rcode;
  392     int ret = 0;
  393     fr_tls_status_t status;
  394     rlm_eap_fast_t *inst = (rlm_eap_fast_t *) arg;
  395     tls_session_t *tls_session = (tls_session_t *) handler->opaque;
  396     eap_fast_tunnel_t *t = (eap_fast_tunnel_t *) tls_session->opaque;
  397     REQUEST *request = handler->request;
  398 
  399     RDEBUG2("Authenticate");
  400 
  401     /*
  402      *  We need FAST data associated with the session, so
  403      *  allocate it here, if it wasn't already alloacted.
  404      */
  405     if (!t) t = tls_session->opaque = eap_fast_alloc(tls_session, inst);
  406 
  407     /*
  408      *  Process TLS layer until done.
  409      */
  410     status = eaptls_process(handler);
  411     if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
  412         REDEBUG("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
  413     } else {
  414         RDEBUG3("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
  415     }
  416 
  417     /*
  418      *  Make request available to any SSL callbacks
  419      */
  420     SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request);
  421     switch (status) {
  422     /*
  423      *  EAP-TLS handshake was successful, tell the
  424      *  client to keep talking.
  425      *
  426      *  If this was EAP-TLS, we would just return
  427      *  an EAP-TLS-Success packet here.
  428      */
  429     case FR_TLS_SUCCESS:
  430         tls_handshake_send(request, tls_session);
  431         rad_assert(t != NULL);
  432         break;
  433 
  434     /*
  435      *  The TLS code is still working on the TLS
  436      *  exchange, and it's a valid TLS request.
  437      *  do nothing.
  438      */
  439     case FR_TLS_HANDLED:
  440         ret = 1;
  441         goto done;
  442 
  443     /*
  444      *  Handshake is done, proceed with decoding tunneled
  445      *  data.
  446      */
  447     case FR_TLS_OK:
  448         break;
  449 
  450     /*
  451      *  Anything else: fail.
  452      */
  453     default:
  454         ret = 0;
  455         goto done;
  456     }
  457 
  458     /*
  459      *  Session is established, proceed with decoding
  460      *  tunneled data.
  461      */
  462     RDEBUG2("Session established.  Proceeding to decode tunneled attributes");
  463 
  464     /*
  465      *  Process the FAST portion of the request.
  466      */
  467     rcode = eap_fast_process(handler, tls_session);
  468 
  469     switch (rcode) {
  470     case PW_CODE_ACCESS_REJECT:
  471         RDEBUG("Reject");
  472         eaptls_fail(handler, EAP_FAST_VERSION);
  473         ret = 0;
  474         goto done;
  475 
  476         /*
  477          *  Access-Challenge, continue tunneled conversation.
  478          */
  479     case PW_CODE_ACCESS_CHALLENGE:
  480         RDEBUG("Challenge");
  481         tls_handshake_send(request, tls_session);
  482         eaptls_request(handler->eap_ds, tls_session);
  483         ret = 1;
  484         goto done;
  485 
  486         /*
  487          *  Success: Automatically return MPPE keys.
  488          */
  489     case PW_CODE_ACCESS_ACCEPT:
  490         if (t->accept_vps) {
  491             RDEBUG2("Using saved attributes from the original Access-Accept");
  492             rdebug_pair_list(L_DBG_LVL_2, request, t->accept_vps, NULL);
  493             fr_pair_list_mcopy_by_num(handler->request->reply,
  494                   &handler->request->reply->vps,
  495                   &t->accept_vps, 0, 0, TAG_ANY);
  496         } else if (t->use_tunneled_reply) {
  497             RDEBUG2("No saved attributes in the original Access-Accept");
  498         }
  499         ret = eaptls_success(handler, EAP_FAST_VERSION);
  500         goto done;
  501 
  502         /*
  503          *  No response packet, MUST be proxying it.
  504          *  The main EAP module will take care of discovering
  505          *  that the request now has a "proxy" packet, and
  506          *  will proxy it, rather than returning an EAP packet.
  507          */
  508     case PW_CODE_STATUS_CLIENT:
  509 #ifdef WITH_PROXY
  510         rad_assert(handler->request->proxy != NULL);
  511 #endif
  512         ret = 1;
  513         goto done;
  514 
  515     default:
  516         break;
  517     }
  518 
  519     /*
  520      *  Something we don't understand: Reject it.
  521      */
  522     eaptls_fail(handler, EAP_FAST_VERSION);
  523 
  524 done:
  525     SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL);
  526 
  527     return ret;
  528 }
  529 
  530 static int eap_fast_tls_start(EAP_DS * eap_ds,tls_session_t *tls_session)
  531 {
  532     EAPTLS_PACKET   reply;
  533 
  534     reply.code = FR_TLS_START;
  535     reply.length = TLS_HEADER_LEN + 1 + tls_session->clean_in.used;/*flags*/
  536 
  537     reply.flags = tls_session->peap_flag;
  538     reply.flags = SET_START(reply.flags);
  539 
  540     reply.data = tls_session->clean_in.data;
  541     reply.dlen = tls_session->clean_in.used;
  542 
  543     eaptls_compose(eap_ds, &reply);
  544 
  545     return 1;
  546 }
  547 
  548 
  549 /*
  550  *  Send an initial eap-tls request to the peer, using the libeap functions.
  551  */
  552 static int mod_session_init(void *type_arg, eap_handler_t *handler)
  553 {
  554     int         rcode;
  555     tls_session_t       *tls_session;
  556     rlm_eap_fast_t      *inst;
  557     VALUE_PAIR      *vp;
  558     bool            client_cert;
  559     REQUEST         *request = handler->request;
  560 
  561     inst = type_arg;
  562 
  563     handler->tls = true;
  564 
  565     /*
  566      *  EAP-TLS-Require-Client-Cert attribute will override
  567      *  the require_client_cert configuration option.
  568      */
  569     vp = fr_pair_find_by_num(handler->request->config, PW_EAP_TLS_REQUIRE_CLIENT_CERT, 0, TAG_ANY);
  570     if (vp) {
  571         client_cert = vp->vp_integer ? true : false;
  572     } else {
  573         client_cert = inst->req_client_cert;
  574     }
  575 
  576     /*
  577      *  Don't allow TLS 1.3 for us, even if it's allowed
  578      *  elsewhere.
  579      */
  580     handler->opaque = tls_session = eaptls_session(handler, inst->tls_conf, client_cert, false);
  581 
  582     if (!tls_session) return 0;
  583 
  584     if (inst->cipher_list) {
  585         RDEBUG("Over-riding main cipher list with '%s'", inst->cipher_list);
  586 
  587         if (!SSL_set_cipher_list(tls_session->ssl, inst->cipher_list)) {
  588             REDEBUG("Failed over-riding cipher list to '%s'.  EAP-FAST will likely not work",
  589                 inst->cipher_list);
  590         }
  591     }
  592 
  593 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
  594     {
  595         int i;
  596         for (i = 0; ; i++) {
  597             const char *cipher = SSL_get_cipher_list(tls_session->ssl, i);
  598             if (!cipher) break;
  599             if (!strstr(cipher, "ADH-")) continue;
  600             RDEBUG("Setting security level to 0 to allow anonymous cipher suites");
  601             SSL_set_security_level(tls_session->ssl, 0);
  602             break;
  603         }
  604     }
  605 #endif
  606 
  607 #ifdef SSL_OP_NO_TLSv1_3
  608     /*
  609      *  Forcibly disable TLSv1.3
  610      *
  611      *  TLSv1.3 does not support opaque session tickets, which
  612      *  are needed for EAP-FAST.
  613      */
  614     SSL_set_options(tls_session->ssl, SSL_OP_NO_TLSv1_3);
  615 #endif
  616 
  617     /*
  618      *  Push TLV of authority_identity into tls_record
  619      *  call eap_tls_compose() with args
  620      *
  621      *  RFC 4851 section 4.1.1
  622      *  N.B. mandatory/reserved flags are not applicable here
  623      */
  624     eap_fast_tlv_append(tls_session, PAC_INFO_A_ID, false, PAC_A_ID_LENGTH, inst->a_id);
  625     tls_session->peap_flag = EAP_FAST_VERSION;
  626     tls_session->length_flag = false;
  627     rcode = eap_fast_tls_start(handler->eap_ds, tls_session);
  628 
  629     if (rcode < 0) {
  630         talloc_free(tls_session);
  631         return 0;
  632     }
  633 
  634     tls_session->record_init(&tls_session->clean_in);
  635 
  636     if (!SSL_set_session_ticket_ext_cb(tls_session->ssl, _session_ticket, tls_session)) {
  637         RERROR("Failed setting SSL session ticket callback");
  638         return 0;
  639     }
  640 
  641     handler->stage = PROCESS;
  642 
  643     return 1;
  644 }
  645 
  646 
  647 /*
  648  *  The module name should be the only globally exported symbol.
  649  *  That is, everything else should be 'static'.
  650  */
  651 extern rlm_eap_module_t rlm_eap_fast;
  652 rlm_eap_module_t rlm_eap_fast = {
  653     .name       = "eap_fast",
  654     .instantiate    = mod_instantiate,  /* Create new submodule instance */
  655     .session_init   = mod_session_init, /* Initialise a new EAP session */
  656     .process    = mod_process       /* Process next round of EAP method */
  657 };