Pull from CVS head:
authornbk <nbk>
Mon, 6 Feb 2006 15:33:52 +0000 (15:33 +0000)
committernbk <nbk>
Mon, 6 Feb 2006 15:33:52 +0000 (15:33 +0000)
Move TLS code from rlm_eap_tls to libeap.

src/modules/rlm_eap/libeap/mppe_keys.c [moved from src/modules/rlm_eap/types/rlm_eap_tls/mppe_keys.c with 100% similarity]
src/modules/rlm_eap/types/rlm_eap_tls/cb.c [deleted file]
src/modules/rlm_eap/types/rlm_eap_tls/eap_tls.c [deleted file]
src/modules/rlm_eap/types/rlm_eap_tls/eap_tls.h [deleted file]
src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
src/modules/rlm_eap/types/rlm_eap_tls/tls.c [deleted file]

diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/cb.c b/src/modules/rlm_eap/types/rlm_eap_tls/cb.c
deleted file mode 100644 (file)
index 4eb173c..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * cb.c
- *
- * Version:     $Id$
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
- */
-#include "eap_tls.h"
-
-#ifndef NO_OPENSSL
-
-void cbtls_info(const SSL *s, int where, int ret)
-{
-       const char *str, *state;
-       int w;
-
-       w = where & ~SSL_ST_MASK;
-       if (w & SSL_ST_CONNECT) str="    TLS_connect";
-       else if (w & SSL_ST_ACCEPT) str="    TLS_accept";
-       else str="    (other)";
-
-       state = SSL_state_string_long(s);
-       state = state ? state : "NULL";
-
-       if (where & SSL_CB_LOOP) {
-               if (debug_flag) radlog(L_INFO, "%s: %s\n", str, state);
-       } else if (where & SSL_CB_HANDSHAKE_START) {
-               if (debug_flag) radlog(L_INFO, "%s: %s\n", str, state);
-       } else if (where & SSL_CB_HANDSHAKE_DONE) {
-               radlog(L_INFO, "%s: %s\n", str, state);
-       } else if (where & SSL_CB_ALERT) {
-               str=(where & SSL_CB_READ)?"read":"write";
-               radlog(L_ERR,"TLS Alert %s:%s:%s\n", str,
-                       SSL_alert_type_string_long(ret),
-                       SSL_alert_desc_string_long(ret));
-       } else if (where & SSL_CB_EXIT) {
-               if (ret == 0)
-                       radlog(L_ERR, "%s:failed in %s\n", str, state);
-               else if (ret < 0)
-                       radlog(L_ERR, "%s:error in %s\n", str, state);
-       }
-}
-
-/*
- *     Before trusting a certificate, you must make sure that the
- *     certificate is 'valid'. There are several steps that your
- *     application can take in determining if a certificate is
- *     valid. Commonly used steps are:
- *
- *     1.Verifying the certificate's signature, and verifying that
- *     the certificate has been issued by a trusted Certificate
- *     Authority.
- *
- *     2.Verifying that the certificate is valid for the present date
- *     (i.e. it is being presented within its validity dates).
- *
- *     3.Verifying that the certificate has not been revoked by its
- *     issuing Certificate Authority, by checking with respect to a
- *     Certificate Revocation List (CRL).
- *
- *     4.Verifying that the credentials presented by the certificate
- *     fulfill additional requirements specific to the application,
- *     such as with respect to access control lists or with respect
- *     to OCSP (Online Certificate Status Processing).
- *
- *     NOTE: This callback will be called multiple times based on the
- *     depth of the root certificate chain
- */
-int cbtls_verify(int ok, X509_STORE_CTX *ctx)
-{
-       char subject[256]; /* Used for the subject name */
-       char issuer[256]; /* Used for the issuer name */
-       char buf[256];
-       char cn_str[256];
-       EAP_HANDLER *handler = NULL;
-       X509 *client_cert;
-       SSL *ssl;
-       int err, depth;
-       EAP_TLS_CONF *conf;
-       int my_ok = ok;
-
-       client_cert = X509_STORE_CTX_get_current_cert(ctx);
-       err = X509_STORE_CTX_get_error(ctx);
-       depth = X509_STORE_CTX_get_error_depth(ctx);
-
-       if(!my_ok)
-               radlog(L_ERR,"--> verify error:num=%d:%s\n",err,
-                       X509_verify_cert_error_string(err));
-       /*
-        *      Catch too long Certificate chains
-        */
-
-       /*
-        * Retrieve the pointer to the SSL of the connection currently treated
-        * and the application specific data stored into the SSL object.
-        */
-       ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
-       handler = (EAP_HANDLER *)SSL_get_ex_data(ssl, 0);
-       conf = (EAP_TLS_CONF *)SSL_get_ex_data(ssl, 1);
-
-       /*
-        *      Get the Subject & Issuer
-        */
-       subject[0] = issuer[0] = '\0';
-       X509_NAME_oneline(X509_get_subject_name(client_cert), subject, 256);
-       X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), issuer, 256);
-
-       /*
-        *      Get the Common Name
-        */
-       X509_NAME_get_text_by_NID(X509_get_subject_name(client_cert),
-             NID_commonName, buf, 256);
-
-       switch (ctx->error) {
-
-       case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
-               radlog(L_ERR, "issuer= %s\n", issuer);
-               break;
-       case X509_V_ERR_CERT_NOT_YET_VALID:
-       case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
-               radlog(L_ERR, "notBefore=");
-#if 0
-               ASN1_TIME_print(bio_err, X509_get_notBefore(ctx->current_cert));
-#endif
-               break;
-       case X509_V_ERR_CERT_HAS_EXPIRED:
-       case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
-               radlog(L_ERR, "notAfter=");
-#if 0
-               ASN1_TIME_print(bio_err, X509_get_notAfter(ctx->current_cert));
-#endif
-               break;
-       }
-
-       /*
-        *      If we're at the actual client cert and the conf tells
-        *      us to, check the CN in the cert against the xlat'ed
-        *      value
-        */
-       if (depth == 0 && conf->check_cert_cn != NULL) {
-               if (!radius_xlat(cn_str, sizeof(cn_str), conf->check_cert_cn, handler->request, NULL)) {
-                       radlog(L_ERR, "rlm_eap_tls (%s): xlat failed.",
-                               conf->check_cert_cn);
-                       /* if this fails, fail the verification */
-                       my_ok = 0;
-               }
-               DEBUG2("    rlm_eap_tls: checking certificate CN (%s) with xlat'ed value (%s)", buf, cn_str);
-               if (strncmp(cn_str, buf, sizeof(buf)) != 0) {
-                       my_ok = 0;
-                       radlog(L_AUTH, "rlm_eap_tls: Certificate CN (%s) does not match specified value (%s)!", buf, cn_str);
-               }
-       }
-
-       if (debug_flag > 0) {
-               radlog(L_INFO, "chain-depth=%d, ", depth);
-               /*
-                 if (depth > 0) {
-                 return ok;
-                 }
-               */
-               radlog(L_INFO, "error=%d", err);
-
-               radlog(L_INFO, "--> User-Name = %s", handler->identity);
-               radlog(L_INFO, "--> BUF-Name = %s", buf);
-               radlog(L_INFO, "--> subject = %s", subject);
-               radlog(L_INFO, "--> issuer  = %s", issuer);
-               radlog(L_INFO, "--> verify return:%d", my_ok);
-       }
-       return my_ok;
-}
-
-
-/*
- *     Fill in our 'info' with TLS data.
- */
-void cbtls_msg(int write_p, int msg_version, int content_type,
-              const void *buf, size_t len,
-              SSL *ssl UNUSED, void *arg)
-{
-       tls_session_t *state = (tls_session_t *)arg;
-
-       state->info.origin = (unsigned char)write_p;
-       state->info.content_type = (unsigned char)content_type;
-       state->info.record_len = len;
-       state->info.version = msg_version;
-       state->info.initialized = 1;
-
-       if (content_type == SSL3_RT_ALERT) {
-               state->info.alert_level = ((const unsigned char*)buf)[0];
-               state->info.alert_description = ((const unsigned char*)buf)[1];
-               state->info.handshake_type = 0x00;
-
-       } else if (content_type == SSL3_RT_HANDSHAKE) {
-               state->info.handshake_type = ((const unsigned char*)buf)[0];
-               state->info.alert_level = 0x00;
-               state->info.alert_description = 0x00;
-       }
-       tls_session_information(state);
-}
-
-int cbtls_password(char *buf,
-                  int num UNUSED,
-                  int rwflag UNUSED,
-                  void *userdata)
-{
-       strcpy(buf, (char *)userdata);
-       return(strlen((char *)userdata));
-}
-
-RSA *cbtls_rsa(SSL *s UNUSED, int is_export UNUSED, int keylength)
-{
-       static RSA *rsa_tmp=NULL;
-
-       if (rsa_tmp == NULL) {
-               radlog(L_INFO, "Generating temp (%d bit) RSA key...", keylength);
-               rsa_tmp=RSA_generate_key(keylength, RSA_F4, NULL, NULL);
-       }
-       return(rsa_tmp);
-}
-
-#endif /* !defined(NO_OPENSSL) */
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/eap_tls.c b/src/modules/rlm_eap/types/rlm_eap_tls/eap_tls.c
deleted file mode 100644 (file)
index 94da912..0000000
+++ /dev/null
@@ -1,834 +0,0 @@
-/*
- * eap_tls.c
- *
- * Version:     $Id$
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
- * Copyright 2003  Alan DeKok <aland@freeradius.org>
- */
-
-/*
- *
- *  TLS Packet Format in EAP
- *  --- ------ ------ -- ---
- * 0                   1                   2                   3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |     Code      |   Identifier  |            Length             |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |     Type      |     Flags     |      TLS Message Length
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |     TLS Message Length        |       TLS Data...
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- */
-
-#include "eap_tls.h"
-
-/*
- *      Allocate a new TLS_PACKET
- */
-EAPTLS_PACKET *eaptls_alloc(void)
-{
-       EAPTLS_PACKET   *rp;
-
-       if ((rp = malloc(sizeof(EAPTLS_PACKET))) == NULL) {
-               radlog(L_ERR, "rlm_eap_tls: out of memory");
-               return NULL;
-       }
-       memset(rp, 0, sizeof(EAPTLS_PACKET));
-       return rp;
-}
-
-/*
- *      Free EAPTLS_PACKET
- */
-void eaptls_free(EAPTLS_PACKET **eaptls_packet_ptr)
-{
-       EAPTLS_PACKET *eaptls_packet;
-
-       if (!eaptls_packet_ptr) return;
-       eaptls_packet = *eaptls_packet_ptr;
-       if (eaptls_packet == NULL) return;
-
-       if (eaptls_packet->data) {
-               free(eaptls_packet->data);
-               eaptls_packet->data = NULL;
-       }
-
-       free(eaptls_packet);
-       *eaptls_packet_ptr = NULL;
-}
-
-/*
-   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 = EAPTLS_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_success(EAP_DS *eap_ds, int peap_flag)
-{
-       EAPTLS_PACKET   reply;
-
-       reply.code = EAPTLS_SUCCESS;
-       reply.length = TLS_HEADER_LEN;
-       reply.flags = peap_flag;
-       reply.data = NULL;
-       reply.dlen = 0;
-
-       eaptls_compose(eap_ds, &reply);
-
-       return 1;
-}
-
-int eaptls_fail(EAP_DS *eap_ds, int peap_flag)
-{
-       EAPTLS_PACKET   reply;
-
-       reply.code = EAPTLS_FAIL;
-       reply.length = TLS_HEADER_LEN;
-       reply.flags = peap_flag;
-       reply.data = NULL;
-       reply.dlen = 0;
-
-       eaptls_compose(eap_ds, &reply);
-
-       return 1;
-}
-
-/*
-   A single TLS record may be up to 16384 octets in length, but a TLS
-   message may span multiple TLS records, and a TLS certificate message
-   may in principle be as long as 16MB.
-*/
-
-/*
- *     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 = EAPTLS_REQUEST;
-       reply.flags = ssn->peap_flag;
-
-       /* Send data, NOT more than the FRAGMENT size */
-       if (ssn->dirty_out.used > ssn->offset) {
-               size = ssn->offset;
-               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 = malloc(reply.dlen);
-       if (lbit) {
-               nlen = htonl(ssn->tls_msg_len);
-               memcpy(reply.data, &nlen, lbit);
-               reply.flags = SET_LENGTH_INCLUDED(reply.flags);
-       }
-       record_minus(&ssn->dirty_out, reply.data + lbit, size);
-
-       eaptls_compose(eap_ds, &reply);
-       free(reply.data);
-       reply.data = NULL;
-
-       return 1;
-}
-
-/*
- * Acknowledge received is for one of the following messages sent earlier
- * 1. Handshake completed Message, so now send, EAP-Success
- * 2. Alert Message, now send, EAP-Failure
- * 3. Fragment Message, now send, next Fragment
- */
-static eaptls_status_t eaptls_ack_handler(EAP_HANDLER *handler)
-{
-       tls_session_t *tls_session;
-
-       tls_session = (tls_session_t *)handler->opaque;
-       if (tls_session == NULL){
-               radlog(L_ERR, "rlm_eap_tls: Unexpected ACK received");
-               return EAPTLS_FAIL;
-       }
-       if (tls_session->info.initialized == 0) {
-               DEBUG("  rlm_eap_tls: No SSL info available. Waiting for more SSL data.");
-               return EAPTLS_REQUEST;
-       }
-       if (tls_session->info.origin == 0) {
-               radlog(L_ERR, "rlm_eap_tls: Unexpected ACK received");
-               return EAPTLS_FAIL;
-       }
-
-       switch (tls_session->info.content_type) {
-       case alert:
-               DEBUG2("  rlm_eap_tls: ack alert");
-               eaptls_fail(handler->eap_ds, tls_session->peap_flag);
-               return EAPTLS_FAIL;
-
-       case handshake:
-               if (tls_session->info.handshake_type == finished) {
-                       DEBUG2("  rlm_eap_tls: ack handshake is finished");
-                       return EAPTLS_SUCCESS;
-               }
-
-               DEBUG2("  rlm_eap_tls: ack handshake fragment handler");
-               /* Fragmentation handler, send next fragment */
-               return EAPTLS_REQUEST;
-
-               /*
-                *      For the rest of the conditions, switch over
-                *      to the default section below.
-                */
-       default:
-               DEBUG2("  rlm_eap_tls: ack default");
-               radlog(L_ERR, "rlm_eap_tls: Invalid ACK received: %d",
-                      tls_session->info.content_type);
-               return EAPTLS_FAIL;
-       }
-}
-
-/*
- *     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 = EAPTLS_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;
-}
-
-/*
- *     The S flag is set only within the EAP-TLS start message sent
- *     from the EAP server to the peer.
- *
- *     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. The EAP peer MUST wait.
- */
-static eaptls_status_t eaptls_verify(EAP_HANDLER *handler)
-{
-       EAP_DS *eap_ds = handler->eap_ds;
-       EAP_DS *prev_eap_ds = handler->prev_eapds;
-       eaptls_packet_t *eaptls_packet, *eaptls_prev = NULL;
-
-       /*
-        *      We don't check ANY of the input parameters.  It's all
-        *      code which works together, so if something is wrong,
-        *      we SHOULD core dump.
-        *
-        *      e.g. if eap_ds is NULL, of if eap_ds->response is
-        *      NULL, of if it's NOT an EAP-Response, or if the packet
-        *      is too short.  See eap_validation()., in ../../eap.c
-        *
-        *      Also, eaptype_select() takes care of selecting the
-        *      appropriate type, so we don't need to check
-        *      eap_ds->response->type.type == PW_EAP_TLS, or anything
-        *      else.
-        */
-       eaptls_packet = (eaptls_packet_t *)eap_ds->response->type.data;
-       if (prev_eap_ds && prev_eap_ds->response)
-               eaptls_prev = (eaptls_packet_t *)prev_eap_ds->response->type.data;
-
-       /*
-        *      check for ACK
-        *
-        *      If there's no TLS data, or there's 1 byte of TLS data,
-        *      with the flags set to zero, then it's an ACK.
-        *
-        *      Find if this is a reply to the previous request sent
-        */
-       if ((eaptls_packet == NULL) ||
-           ((eap_ds->response->length == EAP_HEADER_LEN + 2) &&
-            ((eaptls_packet->flags & 0xc0) == 0x00))) {
-
-               if (prev_eap_ds->request->id == eap_ds->response->id) {
-                       /*
-                        *      Run the ACK handler directly from here.
-                        */
-                       radlog(L_INFO, "rlm_eap_tls: Received EAP-TLS ACK message");
-                       return eaptls_ack_handler(handler);
-               } else {
-                       radlog(L_ERR, "rlm_eap_tls: Received Invalid EAP-TLS ACK message");
-                       return EAPTLS_INVALID;
-               }
-       }
-
-       /*
-        *      We send TLS_START, but do not receive it.
-        */
-       if (TLS_START(eaptls_packet->flags)) {
-               radlog(L_ERR, "rlm_eap_tls:  Received unexpected EAP-TLS Start message");
-               return EAPTLS_INVALID;
-       }
-
-       /*
-        *      The L bit (length included) is set to indicate the
-        *      presence of the four octet TLS Message Length field,
-        *      and MUST be set for the first fragment of a fragmented
-        *      TLS message or set of messages.
-        *
-        *      The M bit (more fragments) is set on all but the last
-        *      fragment.
-        *
-        *      The S bit (EAP-TLS start) is set in an EAP-TLS Start
-        *      message. This differentiates the EAP-TLS Start message
-        *      from a fragment acknowledgement.
-        */
-       if (TLS_LENGTH_INCLUDED(eaptls_packet->flags)) {
-               if (TLS_MORE_FRAGMENTS(eaptls_packet->flags)) {
-                       /*
-                        * FIRST_FRAGMENT is identified
-                        * 1. If there is no previous EAP-response received.
-                        * 2. If EAP-response received, then its M bit not set.
-                        *      (It is because Last fragment will not have M bit set)
-                        */
-                       if ((prev_eap_ds->response == NULL) ||
-                           (eaptls_prev == NULL) ||
-                           !TLS_MORE_FRAGMENTS(eaptls_prev->flags)) {
-
-                               radlog(L_INFO, "rlm_eap_tls:  Received EAP-TLS First Fragment of the message");
-                               return EAPTLS_FIRST_FRAGMENT;
-                       } else {
-
-                               radlog(L_INFO, "rlm_eap_tls:  More Fragments with length included");
-                               return EAPTLS_MORE_FRAGMENTS_WITH_LENGTH;
-                       }
-               } else {
-
-                       radlog(L_INFO, "rlm_eap_tls:  Length Included");
-                       return EAPTLS_LENGTH_INCLUDED;
-               }
-       }
-
-       if (TLS_MORE_FRAGMENTS(eaptls_packet->flags)) {
-               radlog(L_INFO, "rlm_eap_tls:  More fragments to follow");
-               return EAPTLS_MORE_FRAGMENTS;
-       }
-
-       /*
-        *      None of the flags are set, but it's still a valid
-        *      EAPTLS packet.
-        */
-       return EAPTLS_OK;
-}
-
-/*
- * EAPTLS_PACKET
- * code   =  EAP-code
- * id     =  EAP-id
- * length = code + id + length + flags + tlsdata
- *        =  1   +  1 +   2    +  1    +  X
- * length = EAP-length - 1(EAP-Type = 1 octet)
- * flags  = EAP-typedata[0] (1 octet)
- * dlen   = EAP-typedata[1-4] (4 octets), if L flag set
- *        = length - 5(code+id+length+flags), otherwise
- * data   = EAP-typedata[5-n], if L flag set
- *        = EAP-typedata[1-n], otherwise
- * packet = EAP-typedata (complete typedata)
- *
- * Points to consider during EAP-TLS data extraction
- * 1. In the received packet, No data will be present incase of ACK-NAK
- * 2. Incase if more fragments need to be received then ACK after retreiving this fragment.
- *
- *  RFC 2716 Section 4.2.  PPP EAP TLS Request Packet
- *
- *  0                   1                   2                   3
- *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *  |     Code      |   Identifier  |            Length             |
- *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *  |     Type      |     Flags     |      TLS Message Length
- *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *  |     TLS Message Length        |       TLS Data...
- *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *  The Length field is two octets and indicates the length of the EAP
- *  packet including the Code, Identifir, Length, Type, and TLS data
- *  fields.
- */
-static EAPTLS_PACKET *eaptls_extract(EAP_DS *eap_ds, eaptls_status_t status)
-{
-       EAPTLS_PACKET   *tlspacket;
-       uint32_t        data_len = 0;
-       uint32_t        len = 0;
-       uint8_t         *data = NULL;
-
-       if (status  == EAPTLS_INVALID)
-               return NULL;
-
-       /*
-        *      The main EAP code & eaptls_verify() take care of
-        *      ensuring that the packet is OK, and that we can
-        *      extract the various fields we want.
-        *
-        *      e.g. a TLS packet with zero data is allowed as an ACK,
-        *      but we will never see it here, as we will simply
-        *      send another fragment, instead of trying to extract
-        *      the data.
-        *
-        *      MUST have TLS type octet, followed by flags, followed
-        *      by data.
-        */
-       rad_assert(eap_ds->response->length > 2);
-
-       tlspacket = eaptls_alloc();
-       if (tlspacket == NULL) return NULL;
-
-       /*
-        *      Code & id for EAPTLS & EAP are same
-        *      but eaptls_length = eap_length - 1(EAP-Type = 1 octet)
-        *
-        *      length = code + id + length + type + tlsdata
-        *             =  1   +  1 +   2    +  1    +  X
-        */
-       tlspacket->code = eap_ds->response->code;
-       tlspacket->id = eap_ds->response->id;
-       tlspacket->length = eap_ds->response->length - 1; /* EAP type */
-       tlspacket->flags = eap_ds->response->type.data[0];
-
-       /*
-        *      A quick sanity check of the flags.  If we've been told
-        *      that there's a length, and there isn't one, then stop.
-        */
-       if (TLS_LENGTH_INCLUDED(tlspacket->flags) &&
-           (tlspacket->length < 5)) { /* flags + TLS message length */
-               radlog(L_ERR, "rlm_eap_tls: Invalid EAP-TLS packet received.  (Length bit is set, but no length was found.)");
-               eaptls_free(&tlspacket);
-               return NULL;
-       }
-
-       /*
-        *      If the final TLS packet is larger than we can handle, die
-        *      now.
-        *
-        *      Likewise, if the EAP packet says N bytes, and the TLS
-        *      packet says there's fewer bytes, it's a problem.
-        *
-        *      FIXME: Try to ensure that the claimed length is
-        *      consistent across multiple TLS fragments.
-        */
-       if (TLS_LENGTH_INCLUDED(tlspacket->flags)) {
-               memcpy(&data_len, &eap_ds->response->type.data[1], 4);
-               data_len = ntohl(data_len);
-               if (data_len > MAX_RECORD_SIZE) {
-                       radlog(L_ERR, "rlm_eap_tls: The EAP-TLS packet will contain more data than we can process.");
-                       eaptls_free(&tlspacket);
-                       return NULL;
-               }
-
-#if 0
-               DEBUG2(" TLS: %d %d\n", data_len, tlspacket->length);
-
-               if (data_len < tlspacket->length) {
-                       radlog(L_ERR, "rlm_eap_tls: EAP-TLS packet claims to be smaller than the encapsulating EAP packet.");
-                       eaptls_free(&tlspacket);
-                       return NULL;
-               }
-#endif
-       }
-
-       switch (status) {
-       /*
-        *      The TLS Message Length field is four octets, and
-        *      provides the total length of the TLS message or set of
-        *      messages that is being fragmented; this simplifies
-        *      buffer allocation.
-        *
-        *      Dynamic allocation of buffers as & when we know the
-        *      length should solve the problem.
-        */
-       case EAPTLS_FIRST_FRAGMENT:
-       case EAPTLS_LENGTH_INCLUDED:
-       case EAPTLS_MORE_FRAGMENTS_WITH_LENGTH:
-               if (tlspacket->length < 5) { /* flags + TLS message length */
-                       radlog(L_ERR, "rlm_eap_tls: Invalid EAP-TLS packet received.  (Expected length, got none.)");
-                       eaptls_free(&tlspacket);
-                       return NULL;
-               }
-
-               /*
-                *      Extract all the TLS fragments from the
-                *      previous eap_ds Start appending this
-                *      fragment to the above ds
-                */
-               memcpy(&data_len, &eap_ds->response->type.data[1], sizeof(uint32_t));
-               data_len = ntohl(data_len);
-               data = (eap_ds->response->type.data + 5/*flags+TLS-Length*/);
-               len = eap_ds->response->type.length - 5/*flags+TLS-Length*/;
-
-               /*
-                *      Hmm... this should be an error, too.
-                */
-               if (data_len > len) {
-                       data_len = len;
-               }
-               break;
-
-               /*
-                *      Data length is implicit, from the EAP header.
-                */
-       case EAPTLS_MORE_FRAGMENTS:
-       case EAPTLS_OK:
-               data_len = eap_ds->response->type.length - 1/*flags*/;
-               data = eap_ds->response->type.data + 1/*flags*/;
-               break;
-
-       default:
-               radlog(L_ERR, "rlm_eap_tls: Invalid EAP-TLS packet received");
-               eaptls_free(&tlspacket);
-               return NULL;
-       }
-
-       tlspacket->dlen = data_len;
-       if (data_len) {
-               tlspacket->data = (unsigned char *)malloc(data_len);
-               if (tlspacket->data == NULL) {
-                       radlog(L_ERR, "rlm_eap_tls: out of memory");
-                       eaptls_free(&tlspacket);
-                       return NULL;
-               }
-               memcpy(tlspacket->data, data, data_len);
-       }
-
-       return tlspacket;
-}
-
-
-
-/*
- * To process the TLS,
- *  INCOMING DATA:
- *     1. EAP-TLS should get the compelete TLS data from the peer.
- *     2. Store that data in a data structure with any other required info
- *     3. Handle that data structure to the TLS module.
- *     4. TLS module will perform its operations on the data and
- *     handle back to EAP-TLS
- *
- *  OUTGOING DATA:
- *     1. EAP-TLS if necessary will fragment it and send it to the
- *     destination.
- *
- *     During EAP-TLS initialization, TLS Context object will be
- *     initialized and stored.  For every new authentication
- *     requests, TLS will open a new session object and that session
- *     object should be maintained even after the session is
- *     completed for session resumption. (Probably later as a feature
- *     as we donot know who maintains these session objects ie,
- *     SSL_CTX (internally) or TLS module(explicitly). If TLS module,
- *     then how to let SSL API know about these sessions.)
- */
-static void eaptls_operation(EAPTLS_PACKET *eaptls_packet UNUSED,
-                            eaptls_status_t status, EAP_HANDLER *handler)
-{
-       tls_session_t *tls_session;
-
-       tls_session = (tls_session_t *)handler->opaque;
-
-       if ((status == EAPTLS_MORE_FRAGMENTS) ||
-           (status == EAPTLS_MORE_FRAGMENTS_WITH_LENGTH) ||
-           (status == EAPTLS_FIRST_FRAGMENT)) {
-               /*
-                * Send the ACK.
-                */
-               eaptls_send_ack(handler->eap_ds, tls_session->peap_flag);
-       } else {
-               /*
-                *      We have the complete TLS-data or TLS-message.
-                *
-                *      Clean the dirty message.
-                *
-                *      Authenticate the user and send
-                *      Success/Failure.
-                *
-                *      If more info
-                *      is required then send another request.  */
-               if (tls_handshake_recv(tls_session)) {
-                       /*
-                        *      FIXME: return success/fail.
-                        *
-                        *      TLS proper can decide what to do, then.
-                        */
-                       eaptls_request(handler->eap_ds, tls_session);
-               } else {
-                       eaptls_fail(handler->eap_ds, tls_session->peap_flag);
-               }
-       }
-       return;
-}
-
-
-/*
- * In the actual authentication first verify the packet and then create the data structure
- */
-/*
- * To process the TLS,
- *  INCOMING DATA:
- *     1. EAP-TLS should get the compelete TLS data from the peer.
- *     2. Store that data in a data structure with any other required info
- *     3. Hand this data structure to the TLS module.
- *     4. TLS module will perform its operations on the data and hands back to EAP-TLS
- *  OUTGOING DATA:
- *     1. EAP-TLS if necessary will fragment it and send it to the destination.
- *
- *     During EAP-TLS initialization, TLS Context object will be
- *     initialized and stored.  For every new authentication
- *     requests, TLS will open a new session object and that
- *     session object SHOULD be maintained even after the session
- *     is completed, for session resumption. (Probably later as a
- *     feature, as we do not know who maintains these session
- *     objects ie, SSL_CTX (internally) or TLS module (explicitly). If
- *     TLS module, then how to let SSL API know about these
- *     sessions.)
- */
-
-/*
- *     Process an EAP request
- */
-eaptls_status_t eaptls_process(EAP_HANDLER *handler)
-{
-       tls_session_t *tls_session = (tls_session_t *) handler->opaque;
-       EAPTLS_PACKET   *tlspacket;
-       eaptls_status_t status;
-
-       DEBUG2("  rlm_eap_tls: processing TLS");
-
-       /* This case is when SSL generates Alert then we
-        * send that alert to the client and then send the EAP-Failure
-        */
-       status = eaptls_verify(handler);
-       DEBUG2("  eaptls_verify returned %d\n", status);
-
-       switch (status) {
-       default:
-       case EAPTLS_INVALID:
-       case EAPTLS_FAIL:
-
-               /*
-                *      Success means that we're done the initial
-                *      handshake.  For TTLS, this means send stuff
-                *      back to the client, and the client sends us
-                *      more tunneled data.
-                */
-       case EAPTLS_SUCCESS:
-               return status;
-               break;
-
-               /*
-                *      Normal TLS request, continue with the "get rest
-                *      of fragments" phase.
-                */
-       case EAPTLS_REQUEST:
-               eaptls_request(handler->eap_ds, tls_session);
-               return EAPTLS_HANDLED;
-               break;
-
-               /*
-                *      The handshake is done, and we're in the "tunnel
-                *      data" phase.
-                */
-       case EAPTLS_OK:
-               DEBUG2("  rlm_eap_tls: Done initial handshake");
-
-               /*
-                *      Get the rest of the fragments.
-                */
-       case EAPTLS_FIRST_FRAGMENT:
-       case EAPTLS_MORE_FRAGMENTS:
-       case EAPTLS_LENGTH_INCLUDED:
-       case EAPTLS_MORE_FRAGMENTS_WITH_LENGTH:
-               break;
-       }
-
-       /*
-        *      Extract the TLS packet from the buffer.
-        */
-       if ((tlspacket = eaptls_extract(handler->eap_ds, status)) == NULL)
-               return EAPTLS_FAIL;
-
-       /*
-        *      Get the session struct from the handler
-        *
-        *      update the dirty_in buffer
-        *
-        *      NOTE: This buffer will contain partial data when M bit is set.
-        *
-        *      CAUTION while reinitializing this buffer, it should be
-        *      reinitialized only when this M bit is NOT set.
-        */
-       if (tlspacket->dlen !=
-           record_plus(&tls_session->dirty_in, tlspacket->data, tlspacket->dlen)) {
-               eaptls_free(&tlspacket);
-               radlog(L_ERR, "rlm_eap_tls: Exceeded maximum record size");
-               return EAPTLS_FAIL;
-       }
-
-       /*
-        *      SSL initalization is done.  Return.
-        *
-        *      The TLS data will be in the tls_session structure.
-        */
-       if (SSL_is_init_finished(tls_session->ssl)) {
-               eaptls_free(&tlspacket);
-               return EAPTLS_OK;
-       }
-
-       /*
-        *      Continue the handshake.
-        */
-       eaptls_operation(tlspacket, status, handler);
-
-       eaptls_free(&tlspacket);
-       return EAPTLS_HANDLED;
-}
-
-
-/*
- *     compose the TLS reply packet in the EAP reply typedata
- */
-int eaptls_compose(EAP_DS *eap_ds, EAPTLS_PACKET *reply)
-{
-       uint8_t *ptr;
-
-       /*
-        *      Don't set eap_ds->request->type.type, as the main EAP
-        *      handler will do that for us.  This allows the TLS
-        *      module to be called from TTLS & PEAP.
-        */
-
-       /*
-        *      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. The EAP peer MUST wait until it receives
-        *      the EAP-Request before sending another fragment.
-        *
-        *      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_ds->request->type.data = malloc(reply->length - TLS_HEADER_LEN + 1);
-       if (eap_ds->request->type.data == NULL) {
-               radlog(L_ERR, "rlm_eap_tls: out of memory");
-               return 0;
-       }
-
-       /* EAPTLS Header length is excluded while computing EAP typelen */
-       eap_ds->request->type.length = reply->length - TLS_HEADER_LEN;
-
-       ptr = eap_ds->request->type.data;
-       *ptr++ = (uint8_t)(reply->flags & 0xFF);
-
-       if (reply->dlen) memcpy(ptr, reply->data, reply->dlen);
-
-       switch (reply->code) {
-       case EAPTLS_ACK:
-       case EAPTLS_START:
-       case EAPTLS_REQUEST:
-               eap_ds->request->code = PW_EAP_REQUEST;
-               break;
-       case EAPTLS_SUCCESS:
-               eap_ds->request->code = PW_EAP_SUCCESS;
-               break;
-       case EAPTLS_FAIL:
-               eap_ds->request->code = PW_EAP_FAILURE;
-               break;
-       default:
-               /* Should never enter here */
-               eap_ds->request->code = PW_EAP_FAILURE;
-               break;
-       }
-
-       return 1;
-}
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/eap_tls.h b/src/modules/rlm_eap/types/rlm_eap_tls/eap_tls.h
deleted file mode 100644 (file)
index d1ca5d0..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * eap_tls.h
- *
- * Version:     $Id$
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
- * Copyright 2003  Alan DeKok <aland@freeradius.org>
- */
-#ifndef _EAP_TLS_H
-#define _EAP_TLS_H
-
-#include "rlm_eap_tls.h"
-
-#define BUFFER_SIZE 1024
-
-#define EAP_TLS_START                  1
-#define EAP_TLS_ACK            2
-#define EAP_TLS_SUCCESS         3
-#define EAP_TLS_FAIL           4
-#define EAP_TLS_ALERT                  9
-
-#define TLS_HEADER_LEN          4
-
-/*
- *     RFC 2716, Section 4.2:
- *
- *        Flags
- *
- *      0 1 2 3 4 5 6 7 8
- *      +-+-+-+-+-+-+-+-+
- *      |L M S R R R R R|
- *      +-+-+-+-+-+-+-+-+
- *
- *      L = Length included
- *      M = More fragments
- *      S = EAP-TLS start
- *      R = Reserved
- */
-#define TLS_START(x)           (((x) & 0x20) != 0)
-#define TLS_MORE_FRAGMENTS(x)  (((x) & 0x40) != 0)
-#define TLS_LENGTH_INCLUDED(x)         (((x) & 0x80) != 0)
-
-#define TLS_CHANGE_CIPHER_SPEC(x)      (((x) & 0x0014) == 0x0014)
-#define TLS_ALERT(x)                   (((x) & 0x0015) == 0x0015)
-#define TLS_HANDSHAKE(x)               (((x) & 0x0016) == 0x0016)
-
-#define SET_START(x)           ((x) | (0x20))
-#define SET_MORE_FRAGMENTS(x)  ((x) | (0x40))
-#define SET_LENGTH_INCLUDED(x)         ((x) | (0x80))
-
-
-/*
- *     Following enums from rfc2246
- *
- *     Hmm... since we dpeend on OpenSSL, it would be smarter to
- *     use the OpenSSL names for these.
- */
-enum ContentType {
-       change_cipher_spec = 20,
-       alert = 21,
-       handshake = 22,
-       application_data = 23
-};
-
-enum AlertLevel {
-       warning = 1,
-       fatal = 2
-};
-
-enum AlertDescription {
-       close_notify = 0,
-       unexpected_message = 10,
-       bad_record_mac = 20,
-       decryption_failed = 21,
-       record_overflow = 22,
-       decompression_failure = 30,
-       handshake_failure = 40,
-       bad_certificate = 42,
-       unsupported_certificate = 43,
-       certificate_revoked = 44,
-       certificate_expired = 45,
-       certificate_unknown = 46,
-       illegal_parameter = 47,
-       unknown_ca = 48,
-       access_denied = 49,
-       decode_error = 50,
-       decrypt_error = 51,
-       export_restriction = 60,
-       protocol_version = 70,
-       insufficient_security = 71,
-       internal_error = 80,
-       user_canceled = 90,
-       no_renegotiation = 100
-};
-
-enum HandshakeType {
-       hello_request = 0,
-       client_hello = 1,
-       server_hello = 2,
-       certificate = 11,
-       server_key_exchange  = 12,
-       certificate_request = 13,
-       server_hello_done = 14,
-       certificate_verify = 15,
-       client_key_exchange = 16,
-       finished = 20
-};
-
-
-/*
- * From rfc
-   Flags
-
-      0 1 2 3 4 5 6 7 8
-      +-+-+-+-+-+-+-+-+
-      |L M S R R R R R|
-      +-+-+-+-+-+-+-+-+
-
-      L = Length included
-      M = More fragments
-      S = EAP-TLS start
-      R = Reserved
-
-      The L bit (length included) is set to indicate the presence of the
-      four octet TLS Message Length field, and MUST be set for the first
-      fragment of a fragmented TLS message or set of messages. The M bit
-      (more fragments) is set on all but the last fragment. The S bit
-      (EAP-TLS start) is set in an EAP-TLS Start message.  This
-      differentiates the EAP-TLS Start message from a fragment
-      acknowledgement.
-
-   TLS Message Length
-
-      The TLS Message Length field is four octets, and is present only
-      if the L bit is set. This field provides the total length of the
-      TLS message or set of messages that is being fragmented.
-
-   TLS data
-
-      The TLS data consists of the encapsulated TLS packet in TLS record
-      format.
- *
- * The data structures present here
- * maps only to the typedata in the EAP packet
- *
- * Based on the L bit flag, first 4 bytes of data indicate the length
- */
-typedef struct tls_packet_t {
-       uint8_t         flags;
-       uint8_t         data[1];
-} eaptls_packet_t;
-
-typedef struct tls_packet {
-       uint8_t         code;
-       uint8_t         id;
-       uint32_t        length;
-       uint8_t         flags;
-       uint8_t         *data;
-       uint32_t        dlen;
-
-       //uint8_t               *packet;  /* Wired EAP-TLS packet as found in typdedata of EAP_PACKET */
-} EAPTLS_PACKET;
-
-
-/* configured values goes right here */
-typedef struct eap_tls_conf {
-       char            *private_key_password;
-       char            *private_key_file;
-       char            *certificate_file;
-       char            *random_file;
-       char            *ca_path;
-       char            *ca_file;
-       char            *dh_file;
-       char            *rsa_file;
-       int             rsa_key;
-       int             dh_key;
-       int             rsa_key_length;
-       int             dh_key_length;
-       int             verify_depth;
-       int             file_type;
-       int             include_length;
-
-       /*
-        *      Always < 4096 (due to radius limit), 0 by default = 2048
-        */
-       int             fragment_size;
-       int             check_crl;
-       char            *check_cert_cn;
-} EAP_TLS_CONF;
-
-
-/* This structure gets stored in arg */
-typedef struct _eap_tls_t {
-       EAP_TLS_CONF    *conf;
-       SSL_CTX         *ctx;
-} eap_tls_t;
-
-
-/* EAP-TLS framework */
-EAPTLS_PACKET  *eaptls_alloc(void);
-void           eaptls_free(EAPTLS_PACKET **eaptls_packet_ptr);
-int            eaptls_start(EAP_DS *eap_ds, int peap);
-int            eaptls_compose(EAP_DS *eap_ds, EAPTLS_PACKET *reply);
-
-/* Callbacks */
-int            cbtls_password(char *buf, int num, int rwflag, void *userdata);
-void           cbtls_info(const SSL *s, int where, int ret);
-int            cbtls_verify(int ok, X509_STORE_CTX *ctx);
-void           cbtls_msg(int write_p, int msg_version, int content_type,
-                       const void *buf, size_t len, SSL *ssl, void *arg);
-RSA            *cbtls_rsa(SSL *s, int is_export, int keylength);
-
-/* TLS */
-tls_session_t  *eaptls_new_session(SSL_CTX *ssl_ctx, int client_cert);
-int            tls_handshake_recv(tls_session_t *ssn);
-int            tls_handshake_send(tls_session_t *ssn);
-void           tls_session_information(tls_session_t *tls_session);
-
-/* Session */
-void           session_free(void *ssn);
-void           session_close(tls_session_t *ssn);
-void           session_init(tls_session_t *ssn);
-
-/* record */
-void           record_init(record_t *buf);
-void           record_close(record_t *buf);
-unsigned int   record_plus(record_t *buf, const unsigned char *ptr,
-                           unsigned int size);
-unsigned int   record_minus(record_t *buf, unsigned char *ptr,
-                            unsigned int size);
-#endif /*_EAP_TLS_H*/
index 33a8709..1b30287 100644 (file)
 #ifndef _RLM_EAP_TLS_H
 #define _RLM_EAP_TLS_H
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netdb.h>
-#include <fcntl.h>
-#include <signal.h>
-
-#include <ctype.h>
-#include <sys/time.h>
-#include <arpa/inet.h>
-
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "config.h"
-
-#ifndef NO_OPENSSL
-/*
- *     For RH 9, which apparently needs this.
- */
-#ifndef OPENSSL_NO_KRB5
-#define OPENSSL_NO_KRB5
-#endif
-#include <openssl/err.h>
-#ifdef HAVE_OPENSSL_ENGINE_H
-#include <openssl/engine.h>
-#endif
-#include <openssl/ssl.h>
-#endif /* !defined(NO_OPENSSL) */
-
-#include "eap.h"
-
-typedef enum {
-        EAPTLS_INVALID = 0,            /* invalid, don't reply */
-        EAPTLS_REQUEST,                /* request, ok to send, invalid to receive */
-        EAPTLS_RESPONSE,                       /* response, ok to receive, invalid to send */
-        EAPTLS_SUCCESS,                /* success, send success */
-        EAPTLS_FAIL,                   /* fail, send fail */
-        EAPTLS_NOOP,                   /* noop, continue */
-
-        EAPTLS_START,                  /* start, ok to send, invalid to receive */
-        EAPTLS_OK,                     /* ok, continue */
-        EAPTLS_ACK,                    /* acknowledge, continue */
-        EAPTLS_FIRST_FRAGMENT,         /* first fragment */
-        EAPTLS_MORE_FRAGMENTS,         /* more fragments, to send/receive */
-        EAPTLS_LENGTH_INCLUDED,                /* length included */
-        EAPTLS_MORE_FRAGMENTS_WITH_LENGTH,   /* more fragments with length */
-        EAPTLS_HANDLED                 /* tls code has handled it */
-} eaptls_status_t;
-
-#define MAX_RECORD_SIZE 16384
-
-/*
- *     A single TLS record may be up to 16384 octets in length, but a
- *     TLS message may span multiple TLS records, and a TLS
- *     certificate message may in principle be as long as 16MB.
- *
- *     However, note that in order to protect against reassembly
- *     lockup and denial of service attacks, it may be desirable for
- *     an implementation to set a maximum size for one such group of
- *     TLS messages.
- *
- *     The TLS Message Length field is four octets, and provides the
- *     total length of the TLS message or set of messages that is
- *     being fragmented; this simplifies buffer allocation.
- */
-
-/*
- * FIXME: Dynamic allocation of buffer to overcome MAX_RECORD_SIZE overflows.
- *     or configure TLS not to exceed MAX_RECORD_SIZE.
- */
-typedef struct _record_t {
-       unsigned char data[MAX_RECORD_SIZE];
-       unsigned int  used;
-} record_t;
-
-typedef struct _tls_info_t {
-       unsigned char   origin;
-       unsigned char   content_type;
-       unsigned char   handshake_type;
-       unsigned char   alert_level;
-       unsigned char   alert_description;
-       char            info_description[256];
-       size_t          record_len;
-       int             version;
-       char            initialized;
-} tls_info_t;
-
-/*
- * tls_session_t Structure gets stored as opaque in EAP_HANDLER
- * This contains EAP-REQUEST specific data
- * (ie EAPTLS_DATA(fragment), EAPTLS-ALERT, EAPTLS-REQUEST ...)
- *
- * clean_in  - data that needs to be sent but only after it is soiled.
- * dirty_in  - data EAP server receives.
- * clean_out - data that is cleaned after receiving.
- * dirty_out - data EAP server sends.
- * offset    - current fragment size transmitted
- * fragment  - Flag, In fragment mode or not.
- * tls_msg_len - Actual/Total TLS message length.
- * length_flag - A flag to include length in every TLS Data/Alert packet
- *                                     if set to no then only the first fragment contains length
- */
-typedef struct _tls_session_t {
-       SSL             *ssl;
-       tls_info_t      info;
-
-       BIO             *into_ssl;
-       BIO             *from_ssl;
-       record_t        clean_in;
-       record_t        clean_out;
-       record_t        dirty_in;
-       record_t        dirty_out;
-
-       /*
-        * Framed-MTU attribute in RADIUS,
-        * if present, can also be used to set this
-        */
-       unsigned int    offset;
-       unsigned int    tls_msg_len;
-       int             fragment;
-       int             length_flag;
-       int             peap_flag;
-
-       /*
-        *      Used by TTLS & PEAP to keep track of other per-session
-        *      data.
-        */
-       void            *opaque;
-       void            (*free_opaque)(void *opaque);
-} tls_session_t;
-
-
-/*
- *     Externally exported TLS functions.
- */
-eaptls_status_t eaptls_process(EAP_HANDLER *handler);
-
-int            eaptls_success(EAP_DS *eap_ds, int peap_flag);
-int            eaptls_fail(EAP_DS *eap_ds, int peap_flag);
-int            eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn);
-
-
-/* MPPE key generation */
-void            eaptls_gen_mppe_keys(VALUE_PAIR **reply_vps, SSL *s,
-                                    const char *prf_label);
-void           eapttls_gen_challenge(SSL *s, char *buffer, int size);
+#include "eap_tls.h"
 
 #endif /* _RLM_EAP_TLS_H */
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/tls.c b/src/modules/rlm_eap/types/rlm_eap_tls/tls.c
deleted file mode 100644 (file)
index 125aed5..0000000
+++ /dev/null
@@ -1,538 +0,0 @@
-/*
- * tls.c
- *
- * Version:     $Id$
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
- * Copyright 2003  Alan DeKok <aland@freeradius.org>
- */
-#include "eap_tls.h"
-
-tls_session_t *eaptls_new_session(SSL_CTX *ssl_ctx, int client_cert)
-{
-       tls_session_t *state = NULL;
-       SSL *new_tls = NULL;
-       int verify_mode = SSL_VERIFY_NONE;
-
-       if ((new_tls = SSL_new(ssl_ctx)) == NULL) {
-               radlog(L_ERR, "rlm_eap_tls: Error creating new SSL");
-               ERR_print_errors_fp(stderr);
-               return NULL;
-       }
-
-       /* We use the SSL's "app_data" to indicate a call-back */
-       SSL_set_app_data(new_tls, NULL);
-
-       state = (tls_session_t *)malloc(sizeof(*state));
-       memset(state, 0, sizeof(*state));
-       session_init(state);
-       state->ssl = new_tls;
-
-       /*
-        *      Create & hook the BIOs to handle the dirty side of the
-        *      SSL.  This is *very important* as we want to handle
-        *      the transmission part.  Now the only IO interface
-        *      that SSL is aware of, is our defined BIO buffers.
-        *
-        *      This means that all SSL IO is done to/from memory,
-        *      and we can update those BIOs from the EAP packets we've
-        *      received.
-        */
-       state->into_ssl = BIO_new(BIO_s_mem());
-       state->from_ssl = BIO_new(BIO_s_mem());
-       SSL_set_bio(state->ssl, state->into_ssl, state->from_ssl);
-
-       /*
-        *      Add the message callback to identify what type of
-        *      message/handshake is passed
-        */
-       SSL_set_msg_callback(new_tls, cbtls_msg);
-       SSL_set_msg_callback_arg(new_tls, state);
-       SSL_set_info_callback(new_tls, cbtls_info);
-
-       /*
-        *      Verify the peer certificate, if asked.
-        */
-       if (client_cert) {
-               DEBUG2(" rlm_eap_tls: Requiring client certificate");
-               verify_mode = SSL_VERIFY_PEER;
-               verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
-               verify_mode |= SSL_VERIFY_CLIENT_ONCE;
-       }
-       SSL_set_verify(state->ssl, verify_mode, cbtls_verify);
-
-       /*
-        *      In Server mode we only accept.
-        */
-       SSL_set_accept_state(state->ssl);
-
-       return state;
-}
-
-/*
- *     Print out some text describing the error.
- */
-static void int_ssl_check(SSL *s, int ret, const char *text)
-{
-       int e;
-
-       ERR_print_errors_fp(stderr);
-       e = SSL_get_error(s, ret);
-
-       switch(e) {
-               /*
-                *      These seem to be harmless and already "dealt
-                *      with" by our non-blocking environment. NB:
-                *      "ZERO_RETURN" is the clean "error"
-                *      indicating a successfully closed SSL
-                *      tunnel. We let this happen because our IO
-                *      loop should not appear to have broken on
-                *      this condition - and outside the IO loop, the
-                *      "shutdown" state is checked.
-                *
-                *      Don't print anything if we ignore the error.
-                */
-       case SSL_ERROR_NONE:
-       case SSL_ERROR_WANT_READ:
-       case SSL_ERROR_WANT_WRITE:
-       case SSL_ERROR_WANT_X509_LOOKUP:
-       case SSL_ERROR_ZERO_RETURN:
-               return;
-
-               /*
-                *      These seem to be indications of a genuine
-                *      error that should result in the SSL tunnel
-                *      being regarded as "dead".
-                */
-       case SSL_ERROR_SYSCALL:
-               radlog(L_ERR, "rlm_eap_tls: %s failed in a system call (%d), TLS session fails.",
-                      text, ret);
-               SSL_set_app_data(s, (char *)1);
-               return;
-
-       case SSL_ERROR_SSL:
-               radlog(L_ERR, "rlm_eap_tls: %s failed inside of TLS (%d), TLS session fails.",
-                      text, ret);
-               SSL_set_app_data(s, (char *)1);
-               return;
-
-       default:
-               /*
-                *      For any other errors that (a) exist, and (b)
-                *      crop up - we need to interpret what to do with
-                *      them - so "politely inform" the caller that
-                *      the code needs updating here.
-                */
-               radlog(L_ERR, "rlm_eap_tls: FATAL SSL error ..... %d\n", e);
-               break;
-       }
-}
-
-/*
- * We are the server, we always get the dirty data
- * (Handshake data is also considered as dirty data)
- * During handshake, since SSL API handles itself,
- * After clean-up, dirty_out will be filled with
- * the data required for handshaking. So we check
- * if dirty_out is empty then we simply send it back.
- * As of now, if handshake is successful, then it is EAP-Success
- * or else EAP-failure should be sent
- *
- * Fill the Bio with the dirty data to clean it
- * Get the cleaned data from SSL, if it is not Handshake data
- */
-int tls_handshake_recv(tls_session_t *ssn)
-{
-       int err;
-
-       BIO_write(ssn->into_ssl, ssn->dirty_in.data, ssn->dirty_in.used);
-       err = SSL_read(ssn->ssl, ssn->clean_out.data,
-                      sizeof(ssn->clean_out.data));
-       if (err > 0) {
-               ssn->clean_out.used = err;
-       } else {
-               int_ssl_check(ssn->ssl, err, "SSL_read");
-       }
-
-       /* Some Extra STATE information for easy debugging */
-       if (SSL_is_init_finished(ssn->ssl)) {
-               DEBUG2("SSL Connection Established\n");
-       }
-       if (SSL_in_init(ssn->ssl)) {
-               DEBUG2("In SSL Handshake Phase\n");
-       }
-       if (SSL_in_before(ssn->ssl)) {
-               DEBUG2("Before SSL Handshake Phase\n");
-       }
-       if (SSL_in_accept_init(ssn->ssl)) {
-               DEBUG2("In SSL Accept mode \n");
-       }
-       if (SSL_in_connect_init(ssn->ssl)) {
-               DEBUG2("In SSL Connect mode \n");
-       }
-
-       if (ssn->info.content_type != application_data) {
-               err = BIO_read(ssn->from_ssl, ssn->dirty_out.data,
-                              sizeof(ssn->dirty_out.data));
-               if (err > 0) {
-                       ssn->dirty_out.used = err;
-               } else {
-                       int_ssl_check(ssn->ssl, err, "BIO_read");
-                       record_init(&ssn->dirty_in);
-                       return 0;
-               }
-       } else {
-               radlog(L_INFO, "rlm_eap_tls: Application Data");
-               /* Its clean application data, do whatever we want */
-               record_init(&ssn->clean_out);
-       }
-
-       /* We are done with dirty_in, reinitialize it */
-       record_init(&ssn->dirty_in);
-       return 1;
-}
-
-/*
- *     Take clear-text user data, and encrypt it into the output buffer,
- *     to send to the client at the other end of the SSL connection.
- */
-int tls_handshake_send(tls_session_t *ssn)
-{
-       int err;
-
-       /*
-        *      If there's un-encrypted data in 'clean_in', then write
-        *      that data to the SSL session, and then call the BIO function
-        *      to get that encrypted data from the SSL session, into
-        *      a buffer which we can then package into an EAP packet.
-        *
-        *      Based on Server's logic this clean_in is expected to
-        *      contain the data to send to the client.
-        */
-       if (ssn->clean_in.used > 0) {
-               SSL_write(ssn->ssl, ssn->clean_in.data, ssn->clean_in.used);
-
-               /* Get the dirty data from Bio to send it */
-               err = BIO_read(ssn->from_ssl, ssn->dirty_out.data,
-                              sizeof(ssn->dirty_out.data));
-               if (err > 0) {
-                       ssn->dirty_out.used = err;
-               } else {
-                       int_ssl_check(ssn->ssl, err, "handshake_send");
-               }
-       }
-
-       return 1;
-}
-
-void session_init(tls_session_t *ssn)
-{
-       ssn->ssl = NULL;
-       ssn->into_ssl = ssn->from_ssl = NULL;
-       record_init(&ssn->clean_in);
-       record_init(&ssn->clean_out);
-       record_init(&ssn->dirty_in);
-       record_init(&ssn->dirty_out);
-
-       memset(&ssn->info, 0, sizeof(ssn->info));
-
-       ssn->offset = 0;
-       ssn->fragment = 0;
-       ssn->tls_msg_len = 0;
-       ssn->length_flag = 0;
-       ssn->opaque = NULL;
-       ssn->free_opaque = NULL;
-}
-
-void session_close(tls_session_t *ssn)
-{
-       if(ssn->ssl)
-               SSL_free(ssn->ssl);
-#if 0
-/*
- * WARNING: SSL_free seems to decrement the reference counts already,
- *     so doing this might crash the application.
- */
-       if(ssn->into_ssl)
-               BIO_free(ssn->into_ssl);
-       if(ssn->from_ssl)
-               BIO_free(ssn->from_ssl);
-#endif
-       record_close(&ssn->clean_in);
-       record_close(&ssn->clean_out);
-       record_close(&ssn->dirty_in);
-       record_close(&ssn->dirty_out);
-       session_init(ssn);
-}
-
-void session_free(void *ssn)
-{
-       tls_session_t *sess = (tls_session_t *)ssn;
-
-       if (!ssn) return;
-
-       /*
-        *      Free any opaque TTLS or PEAP data.
-        */
-       if ((sess->opaque) && (sess->free_opaque)) {
-               sess->free_opaque(sess->opaque);
-               sess->opaque = NULL;
-       }
-
-       session_close(sess);
-
-       free(sess);
-}
-
-void record_init(record_t *rec)
-{
-       rec->used = 0;
-}
-
-void record_close(record_t *rec)
-{
-       rec->used = 0;
-}
-
-
-/*
- *     Copy data to the intermediate buffer, before we send
- *     it somewhere.
- */
-unsigned int record_plus(record_t *rec, const unsigned char *ptr,
-                        unsigned int size)
-{
-       unsigned int added = MAX_RECORD_SIZE - rec->used;
-
-       if(added > size)
-               added = size;
-       if(added == 0)
-               return 0;
-       memcpy(rec->data + rec->used, ptr, added);
-       rec->used += added;
-       return added;
-}
-
-/*
- *     Take data from the buffer, and give it to the caller.
- */
-unsigned int record_minus(record_t *rec, unsigned char *ptr,
-                         unsigned int size)
-{
-       unsigned int taken = rec->used;
-
-       if(taken > size)
-               taken = size;
-       if(taken == 0)
-               return 0;
-       if(ptr)
-               memcpy(ptr, rec->data, taken);
-       rec->used -= taken;
-
-       /*
-        *      This is pretty bad...
-        */
-       if(rec->used > 0)
-               memmove(rec->data, rec->data + taken, rec->used);
-       return taken;
-}
-
-void tls_session_information(tls_session_t *tls_session)
-{
-       const char *str_write_p, *str_version, *str_content_type = "";
-       const char *str_details1 = "", *str_details2= "";
-
-       /*
-        *      Don't print this out in the normal course of
-        *      operations.
-        */
-       if (debug_flag == 0) {
-               return;
-       }
-
-       str_write_p = tls_session->info.origin ? ">>>" : "<<<";
-
-       switch (tls_session->info.version)
-       {
-       case SSL2_VERSION:
-               str_version = "SSL 2.0";
-               break;
-       case SSL3_VERSION:
-               str_version = "SSL 3.0 ";
-               break;
-       case TLS1_VERSION:
-               str_version = "TLS 1.0 ";
-               break;
-       default:
-               str_version = "Unknown TLS version";
-               break;
-       }
-
-       if (tls_session->info.version == SSL3_VERSION ||
-           tls_session->info.version == TLS1_VERSION) {
-               switch (tls_session->info.content_type) {
-               case SSL3_RT_CHANGE_CIPHER_SPEC:
-                       str_content_type = "ChangeCipherSpec";
-                       break;
-               case SSL3_RT_ALERT:
-                       str_content_type = "Alert";
-                       break;
-               case SSL3_RT_HANDSHAKE:
-                       str_content_type = "Handshake";
-                       break;
-               case SSL3_RT_APPLICATION_DATA:
-                       str_content_type = "ApplicationData";
-                       break;
-               default:
-                       str_content_type = "UnknownContentType";
-                       break;
-               }
-
-               if (tls_session->info.content_type == SSL3_RT_ALERT) {
-                       str_details1 = ", ???";
-
-                       if (tls_session->info.record_len == 2) {
-
-                               switch (tls_session->info.alert_level) {
-                               case SSL3_AL_WARNING:
-                                       str_details1 = ", warning";
-                                       break;
-                               case SSL3_AL_FATAL:
-                                       str_details1 = ", fatal";
-                                       break;
-                               }
-
-                               str_details2 = " ???";
-                               switch (tls_session->info.alert_description) {
-                               case SSL3_AD_CLOSE_NOTIFY:
-                                       str_details2 = " close_notify";
-                                       break;
-                               case SSL3_AD_UNEXPECTED_MESSAGE:
-                                       str_details2 = " unexpected_message";
-                                       break;
-                               case SSL3_AD_BAD_RECORD_MAC:
-                                       str_details2 = " bad_record_mac";
-                                       break;
-                               case TLS1_AD_DECRYPTION_FAILED:
-                                       str_details2 = " decryption_failed";
-                                       break;
-                               case TLS1_AD_RECORD_OVERFLOW:
-                                       str_details2 = " record_overflow";
-                                       break;
-                               case SSL3_AD_DECOMPRESSION_FAILURE:
-                                       str_details2 = " decompression_failure";
-                                       break;
-                               case SSL3_AD_HANDSHAKE_FAILURE:
-                                       str_details2 = " handshake_failure";
-                                       break;
-                               case SSL3_AD_BAD_CERTIFICATE:
-                                       str_details2 = " bad_certificate";
-                                       break;
-                               case SSL3_AD_UNSUPPORTED_CERTIFICATE:
-                                       str_details2 = " unsupported_certificate";
-                                       break;
-                               case SSL3_AD_CERTIFICATE_REVOKED:
-                                       str_details2 = " certificate_revoked";
-                                       break;
-                               case SSL3_AD_CERTIFICATE_EXPIRED:
-                                       str_details2 = " certificate_expired";
-                                       break;
-                               case SSL3_AD_CERTIFICATE_UNKNOWN:
-                                       str_details2 = " certificate_unknown";
-                                       break;
-                               case SSL3_AD_ILLEGAL_PARAMETER:
-                                       str_details2 = " illegal_parameter";
-                                       break;
-                               case TLS1_AD_UNKNOWN_CA:
-                                       str_details2 = " unknown_ca";
-                                       break;
-                               case TLS1_AD_ACCESS_DENIED:
-                                       str_details2 = " access_denied";
-                                       break;
-                               case TLS1_AD_DECODE_ERROR:
-                                       str_details2 = " decode_error";
-                                       break;
-                               case TLS1_AD_DECRYPT_ERROR:
-                                       str_details2 = " decrypt_error";
-                                       break;
-                               case TLS1_AD_EXPORT_RESTRICTION:
-                                       str_details2 = " export_restriction";
-                                       break;
-                               case TLS1_AD_PROTOCOL_VERSION:
-                                       str_details2 = " protocol_version";
-                                       break;
-                               case TLS1_AD_INSUFFICIENT_SECURITY:
-                                       str_details2 = " insufficient_security";
-                                       break;
-                               case TLS1_AD_INTERNAL_ERROR:
-                                       str_details2 = " internal_error";
-                                       break;
-                               case TLS1_AD_USER_CANCELLED:
-                                       str_details2 = " user_canceled";
-                                       break;
-                               case TLS1_AD_NO_RENEGOTIATION:
-                                       str_details2 = " no_renegotiation";
-                                       break;
-                               }
-                       }
-               }
-
-               if (tls_session->info.content_type == SSL3_RT_HANDSHAKE) {
-                       str_details1 = "???";
-
-                       if (tls_session->info.record_len > 0)
-                       switch (tls_session->info.handshake_type)
-                       {
-                       case SSL3_MT_HELLO_REQUEST:
-                               str_details1 = ", HelloRequest";
-                               break;
-                       case SSL3_MT_CLIENT_HELLO:
-                               str_details1 = ", ClientHello";
-                               break;
-                       case SSL3_MT_SERVER_HELLO:
-                               str_details1 = ", ServerHello";
-                               break;
-                       case SSL3_MT_CERTIFICATE:
-                               str_details1 = ", Certificate";
-                               break;
-                       case SSL3_MT_SERVER_KEY_EXCHANGE:
-                               str_details1 = ", ServerKeyExchange";
-                               break;
-                       case SSL3_MT_CERTIFICATE_REQUEST:
-                               str_details1 = ", CertificateRequest";
-                               break;
-                       case SSL3_MT_SERVER_DONE:
-                               str_details1 = ", ServerHelloDone";
-                               break;
-                       case SSL3_MT_CERTIFICATE_VERIFY:
-                               str_details1 = ", CertificateVerify";
-                               break;
-                       case SSL3_MT_CLIENT_KEY_EXCHANGE:
-                               str_details1 = ", ClientKeyExchange";
-                               break;
-                       case SSL3_MT_FINISHED:
-                               str_details1 = ", Finished";
-                               break;
-                       }
-               }
-       }
-
-       sprintf(tls_session->info.info_description, "%s %s%s [length %04lx]%s%s\n",
-               str_write_p, str_version, str_content_type,
-               (unsigned long)tls_session->info.record_len, str_details1, str_details2);
-       DEBUG2("  rlm_eap_tls: %s\n", tls_session->info.info_description);
-}