int eaptls_success(eap_handler_t *handler, int peap_flag) { EAPTLS_PACKET reply; REQUEST *request = handler->request; tls_session_t *tls_session = handler->opaque; handler->finished = true; reply.code = FR_TLS_SUCCESS; reply.length = TLS_HEADER_LEN; reply.flags = peap_flag; reply.data = NULL; reply.dlen = 0; tls_success(tls_session, request); /* * Call compose AFTER checking for cached data. */ eaptls_compose(handler->eap_ds, &reply); /* * Automatically generate MPPE keying material. */ if (tls_session->prf_label) { eaptls_gen_mppe_keys(handler->request, tls_session->ssl, tls_session->prf_label); } else { RWDEBUG("Not adding MPPE keys because there is no PRF label"); } eaptls_gen_eap_key(handler->request->reply, tls_session->ssl, handler->type); return 1; }
/* * Similarly, when the EAP server receives an EAP-Response with * the M bit set, it MUST respond with an EAP-Request with * EAP-Type=EAP-TLS and no data. This serves as a fragment ACK. * * In order to prevent errors in the processing of fragments, the * EAP server MUST use increment the Identifier value for each * fragment ACK contained within an EAP-Request, and the peer * MUST include this Identifier value in the subsequent fragment * contained within an EAP- Reponse. * * EAP server sends an ACK when it determines there are More * fragments to receive to make the complete * TLS-record/TLS-Message */ static int eaptls_send_ack(EAP_DS *eap_ds, int peap_flag) { EAPTLS_PACKET reply; reply.code = FR_TLS_ACK; reply.length = TLS_HEADER_LEN + 1/*flags*/; reply.flags = peap_flag; reply.data = NULL; reply.dlen = 0; eaptls_compose(eap_ds, &reply); return 1; }
/* * Similarly, when the EAP server receives an EAP-Response with * the M bit set, it MUST respond with an EAP-Request with * EAP-Type=EAP-TLS and no data. This serves as a fragment ACK. * * In order to prevent errors in the processing of fragments, the * EAP server MUST use increment the Identifier value for each * fragment ACK contained within an EAP-Request, and the peer * MUST include this Identifier value in the subsequent fragment * contained within an EAP- Reponse. * * EAP server sends an ACK when it determines there are More * fragments to receive to make the complete * TLS-record/TLS-Message */ static int eaptls_send_ack(eap_handler_t *handler, int peap_flag) { EAPTLS_PACKET reply; REQUEST *request = handler->request; RDEBUG2("ACKing Peer's TLS record fragment"); reply.code = FR_TLS_ACK; reply.length = TLS_HEADER_LEN + 1/*flags*/; reply.flags = peap_flag; reply.data = NULL; reply.dlen = 0; eaptls_compose(handler->eap_ds, &reply); return 1; }
/* The S flag is set only within the EAP-TLS start message sent from the EAP server to the peer. */ int eaptls_start(EAP_DS *eap_ds, int peap_flag) { EAPTLS_PACKET reply; reply.code = FR_TLS_START; reply.length = TLS_HEADER_LEN + 1/*flags*/; reply.flags = peap_flag; reply.flags = SET_START(reply.flags); reply.data = NULL; reply.dlen = 0; eaptls_compose(eap_ds, &reply); return 1; }
int eaptls_fail(eap_handler_t *handler, int peap_flag) { EAPTLS_PACKET reply; tls_session_t *tls_session = handler->opaque; handler->finished = true; reply.code = FR_TLS_FAIL; reply.length = TLS_HEADER_LEN; reply.flags = peap_flag; reply.data = NULL; reply.dlen = 0; tls_fail(tls_session); eaptls_compose(handler->eap_ds, &reply); return 1; }
int eaptls_fail(EAP_HANDLER *handler, int peap_flag) { EAPTLS_PACKET reply; tls_session_t *tls_session = handler->opaque; reply.code = EAPTLS_FAIL; reply.length = TLS_HEADER_LEN; reply.flags = peap_flag; reply.data = NULL; reply.dlen = 0; /* * Force the session to NOT be cached. */ SSL_CTX_remove_session(tls_session->ctx, tls_session->ssl->session); eaptls_compose(handler->eap_ds, &reply); return 1; }
/* * Frame the Dirty data that needs to be send to the client in an * EAP-Request. We always embed the TLS-length in all EAP-TLS * packets that we send, for easy reference purpose. Handle * fragmentation and sending the next fragment etc. */ int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) { EAPTLS_PACKET reply; unsigned int size; unsigned int nlen; unsigned int lbit = 0; /* This value determines whether we set (L)ength flag for EVERY packet we send and add corresponding "TLS Message Length" field. length_flag = true; This means we include L flag and "TLS Msg Len" in EVERY packet we send out. length_flag = false; This means we include L flag and "TLS Msg Len" **ONLY** in First packet of a fragment series. We do not use it anywhere else. Having L flag in every packet is prefered. */ if (ssn->length_flag) { lbit = 4; } if (ssn->fragment == 0) { ssn->tls_msg_len = ssn->dirty_out.used; } reply.code = FR_TLS_REQUEST; reply.flags = ssn->peap_flag; /* Send data, NOT more than the FRAGMENT size */ if (ssn->dirty_out.used > ssn->mtu) { size = ssn->mtu; reply.flags = SET_MORE_FRAGMENTS(reply.flags); /* Length MUST be included if it is the First Fragment */ if (ssn->fragment == 0) { lbit = 4; } ssn->fragment = 1; } else { size = ssn->dirty_out.used; ssn->fragment = 0; } reply.dlen = lbit + size; reply.length = TLS_HEADER_LEN + 1/*flags*/ + reply.dlen; reply.data = talloc_array(eap_ds, uint8_t, reply.length); if (!reply.data) return 0; if (lbit) { nlen = htonl(ssn->tls_msg_len); memcpy(reply.data, &nlen, lbit); reply.flags = SET_LENGTH_INCLUDED(reply.flags); } (ssn->record_minus)(&ssn->dirty_out, reply.data + lbit, size); eaptls_compose(eap_ds, &reply); talloc_free(reply.data); reply.data = NULL; return 1; }
int eaptls_success(EAP_HANDLER *handler, int peap_flag) { EAPTLS_PACKET reply; VALUE_PAIR *vp, *vps = NULL; REQUEST *request = handler->request; tls_session_t *tls_session = handler->opaque; reply.code = EAPTLS_SUCCESS; reply.length = TLS_HEADER_LEN; reply.flags = peap_flag; reply.data = NULL; reply.dlen = 0; /* * If there's no session resumption, delete the entry * from the cache. This means either it's disabled * globally for this SSL context, OR we were told to * disable it for this user. * * This also means you can't turn it on just for one * user. */ if ((!tls_session->allow_session_resumption) || (((vp = pairfind(request->config_items, 1127)) != NULL) && (vp->vp_integer == 0))) { SSL_CTX_remove_session(tls_session->ctx, tls_session->ssl->session); tls_session->allow_session_resumption = 0; /* * If we're in a resumed session and it's * not allowed, */ if (SSL_session_reused(tls_session->ssl)) { RDEBUG("FAIL: Forcibly stopping session resumption as it is not allowed."); return eaptls_fail(handler, peap_flag); } /* * Else resumption IS allowed, so we store the * user data in the cache. */ } else if (!SSL_session_reused(tls_session->ssl)) { RDEBUG2("Saving response in the cache"); vp = paircopy2(request->reply->vps, PW_USER_NAME); pairadd(&vps, vp); vp = paircopy2(request->packet->vps, PW_STRIPPED_USER_NAME); pairadd(&vps, vp); if (vps) { SSL_SESSION_set_ex_data(tls_session->ssl->session, eaptls_session_idx, vps); } else { RDEBUG2("WARNING: No information to cache: session caching will be disabled for this session."); SSL_CTX_remove_session(tls_session->ctx, tls_session->ssl->session); } /* * Else the session WAS allowed. Copy the cached * reply. */ } else { vp = SSL_SESSION_get_ex_data(tls_session->ssl->session, eaptls_session_idx); if (!vp) { RDEBUG("WARNING: No information in cached session!"); return eaptls_fail(handler, peap_flag); } else { RDEBUG("Adding cached attributes to the reply:"); debug_pair_list(vp); pairadd(&request->reply->vps, paircopy(vp)); /* * Mark the request as resumed. */ vp = pairmake("EAP-Session-Resumed", "1", T_OP_SET); if (vp) pairadd(&request->packet->vps, vp); } } /* * Call compose AFTER checking for cached data. */ eaptls_compose(handler->eap_ds, &reply); /* * Automatically generate MPPE keying material. */ if (tls_session->prf_label) { eaptls_gen_mppe_keys(&handler->request->reply->vps, tls_session->ssl, tls_session->prf_label); } else { RDEBUG("WARNING: Not adding MPPE keys because there is no PRF label"); } return 1; }