#ifndef _EAP_TLS_H
#define _EAP_TLS_H
#include <freeradius-devel/ident.h>
RCSIDH(eap_tls_h, "$Id$")
#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
#ifndef NO_OPENSSL
#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
#include "eap.h"
typedef enum {
EAPTLS_INVALID = 0,
EAPTLS_REQUEST,
EAPTLS_RESPONSE,
EAPTLS_SUCCESS,
EAPTLS_FAIL,
EAPTLS_NOOP,
EAPTLS_START,
EAPTLS_OK,
EAPTLS_ACK,
EAPTLS_FIRST_FRAGMENT,
EAPTLS_MORE_FRAGMENTS,
EAPTLS_LENGTH_INCLUDED,
EAPTLS_MORE_FRAGMENTS_WITH_LENGTH,
EAPTLS_HANDLED
} eaptls_status_t;
#define MAX_RECORD_SIZE 16384
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;
typedef struct _tls_session_t {
SSL_CTX *ctx;
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;
void (*record_init)(record_t *buf);
void (*record_close)(record_t *buf);
unsigned int (*record_plus)(record_t *buf, const void *ptr,
unsigned int size);
unsigned int (*record_minus)(record_t *buf, void *ptr,
unsigned int size);
unsigned int offset;
unsigned int tls_msg_len;
int fragment;
int length_flag;
int peap_flag;
void *opaque;
void (*free_opaque)(void *opaque);
const char *prf_label;
int allow_session_resumption;
} tls_session_t;
eaptls_status_t eaptls_process(EAP_HANDLER *handler);
int eaptls_success(EAP_HANDLER *handler, int peap_flag);
int eaptls_fail(EAP_HANDLER *handler, int peap_flag);
int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn);
void eaptls_gen_mppe_keys(VALUE_PAIR **reply_vps, SSL *s,
const char *prf_label);
void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size);
#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
#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))
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
};
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;
} EAPTLS_PACKET;
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);
int cbtls_password(char *buf, int num, int rwflag, void *userdata);
void cbtls_info(const SSL *s, int where, int ret);
void cbtls_msg(int write_p, int msg_version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg);
tls_session_t *eaptls_new_session(SSL_CTX *ssl_ctx, int client_cert);
int tls_handshake_recv(REQUEST *, tls_session_t *ssn);
int tls_handshake_send(REQUEST *,tls_session_t *ssn);
void tls_session_information(tls_session_t *tls_session);
void session_free(void *ssn);
void session_close(tls_session_t *ssn);
void session_init(tls_session_t *ssn);
extern int eaptls_handle_idx;
extern int eaptls_conf_idx;
extern int eaptls_session_idx;
#endif