merge conflicts.
This commit is contained in:
parent
3c260e6046
commit
3c5783d32c
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.5 2014/01/03 02:15:43 christos Exp $
|
||||
# $NetBSD: Makefile,v 1.6 2014/10/16 19:29:29 christos Exp $
|
||||
|
||||
.include "${.CURDIR}/../Makefile.inc"
|
||||
|
||||
|
@ -65,7 +65,6 @@ SRCS+= \
|
|||
main.c \
|
||||
config_file.c \
|
||||
ctrl_iface.c \
|
||||
dump_state.c \
|
||||
eap_register.c
|
||||
|
||||
# l2_packet
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.3 2014/01/03 02:07:31 christos Exp $
|
||||
# $NetBSD: Makefile,v 1.4 2014/10/16 19:29:29 christos Exp $
|
||||
|
||||
.include "${.CURDIR}/../Makefile.inc"
|
||||
|
||||
|
@ -22,6 +22,7 @@ eap_register.c \
|
|||
eapol_supp_sm.c \
|
||||
eloop.c \
|
||||
events.c \
|
||||
ieee802_11_common.c \
|
||||
l2_packet_freebsd.c \
|
||||
main.c \
|
||||
md5.c \
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
/*
|
||||
* hostapd / State dump
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include <time.h>
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "radius/radius_client.h"
|
||||
#include "radius/radius_server.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "eapol_auth/eapol_auth_sm_i.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "ap/sta_info.h"
|
||||
#include "dump_state.h"
|
||||
|
||||
|
||||
static void fprint_char(FILE *f, char c)
|
||||
{
|
||||
if (c >= 32 && c < 127)
|
||||
fprintf(f, "%c", c);
|
||||
else
|
||||
fprintf(f, "<%02x>", c);
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_1x_dump_state(FILE *f, const char *prefix,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
if (sm == NULL)
|
||||
return;
|
||||
|
||||
fprintf(f, "%sIEEE 802.1X:\n", prefix);
|
||||
|
||||
if (sm->identity) {
|
||||
size_t i;
|
||||
fprintf(f, "%sidentity=", prefix);
|
||||
for (i = 0; i < sm->identity_len; i++)
|
||||
fprint_char(f, sm->identity[i]);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
fprintf(f, "%slast EAP type: Authentication Server: %d (%s) "
|
||||
"Supplicant: %d (%s)\n", prefix,
|
||||
sm->eap_type_authsrv,
|
||||
eap_server_get_name(0, sm->eap_type_authsrv),
|
||||
sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp));
|
||||
|
||||
fprintf(f, "%scached_packets=%s\n", prefix,
|
||||
sm->last_recv_radius ? "[RX RADIUS]" : "");
|
||||
|
||||
eapol_auth_dump_state(f, prefix, sm);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file
|
||||
*/
|
||||
static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||
{
|
||||
FILE *f;
|
||||
time_t now;
|
||||
struct sta_info *sta;
|
||||
int i;
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
char *buf;
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
if (!hapd->conf->dump_log_name) {
|
||||
wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump "
|
||||
"request");
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'",
|
||||
hapd->conf->dump_log_name);
|
||||
f = fopen(hapd->conf->dump_log_name, "w");
|
||||
if (f == NULL) {
|
||||
wpa_printf(MSG_WARNING, "Could not open dump file '%s' for "
|
||||
"writing.", hapd->conf->dump_log_name);
|
||||
return;
|
||||
}
|
||||
|
||||
time(&now);
|
||||
fprintf(f, "hostapd state dump - %s", ctime(&now));
|
||||
fprintf(f, "num_sta=%d num_sta_non_erp=%d "
|
||||
"num_sta_no_short_slot_time=%d\n"
|
||||
"num_sta_no_short_preamble=%d\n",
|
||||
hapd->num_sta, hapd->iface->num_sta_non_erp,
|
||||
hapd->iface->num_sta_no_short_slot_time,
|
||||
hapd->iface->num_sta_no_short_preamble);
|
||||
|
||||
for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
|
||||
fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
|
||||
|
||||
fprintf(f,
|
||||
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
|
||||
"\n"
|
||||
" capability=0x%x listen_interval=%d\n",
|
||||
sta->aid,
|
||||
sta->flags,
|
||||
(sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
|
||||
(sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
|
||||
(sta->flags & WLAN_STA_PS ? "[PS]" : ""),
|
||||
(sta->flags & WLAN_STA_TIM ? "[TIM]" : ""),
|
||||
(sta->flags & WLAN_STA_PERM ? "[PERM]" : ""),
|
||||
(ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""),
|
||||
(sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
|
||||
""),
|
||||
(sta->flags & WLAN_STA_SHORT_PREAMBLE ?
|
||||
"[SHORT_PREAMBLE]" : ""),
|
||||
(sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
|
||||
(sta->flags & WLAN_STA_WMM ? "[WMM]" : ""),
|
||||
(sta->flags & WLAN_STA_MFP ? "[MFP]" : ""),
|
||||
(sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
|
||||
(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
|
||||
(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
|
||||
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
|
||||
(sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
|
||||
sta->capability,
|
||||
sta->listen_interval);
|
||||
|
||||
fprintf(f, " supported_rates=");
|
||||
for (i = 0; i < sta->supported_rates_len; i++)
|
||||
fprintf(f, "%02x ", sta->supported_rates[i]);
|
||||
fprintf(f, "\n");
|
||||
|
||||
fprintf(f,
|
||||
" timeout_next=%s\n",
|
||||
(sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" :
|
||||
(sta->timeout_next == STA_DISASSOC ? "DISASSOC" :
|
||||
"DEAUTH")));
|
||||
|
||||
ieee802_1x_dump_state(f, " ", sta);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
buf = os_malloc(4096);
|
||||
if (buf) {
|
||||
int count = radius_client_get_mib(hapd->radius, buf, 4096);
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
else if (count > 4095)
|
||||
count = 4095;
|
||||
buf[count] = '\0';
|
||||
fprintf(f, "%s", buf);
|
||||
|
||||
#ifdef RADIUS_SERVER
|
||||
count = radius_server_get_mib(hapd->radius_srv, buf, 4096);
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
else if (count > 4095)
|
||||
count = 4095;
|
||||
buf[count] = '\0';
|
||||
fprintf(f, "%s", buf);
|
||||
#endif /* RADIUS_SERVER */
|
||||
|
||||
os_free(buf);
|
||||
}
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++)
|
||||
hostapd_dump_state(iface->bss[i]);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* hostapd / State dump
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DUMP_STATE_H
|
||||
#define DUMP_STATE_H
|
||||
|
||||
int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx);
|
||||
|
||||
#endif /* DUMP_STATE_H */
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd - command line interface for hostapd daemon
|
||||
* Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -18,7 +18,7 @@
|
|||
|
||||
static const char *hostapd_cli_version =
|
||||
"hostapd_cli v" VERSION_STR "\n"
|
||||
"Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> and contributors";
|
||||
"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
|
||||
|
||||
|
||||
static const char *hostapd_cli_license =
|
||||
|
@ -79,6 +79,7 @@ static const char *commands_help =
|
|||
#endif /* CONFIG_WPS_NFC */
|
||||
" wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
|
||||
" wps_config <SSID> <auth> <encr> <key> configure AP\n"
|
||||
" wps_get_status show current WPS status\n"
|
||||
#endif /* CONFIG_WPS */
|
||||
" get_config show current configuration\n"
|
||||
" help show this usage help\n"
|
||||
|
@ -90,7 +91,12 @@ static const char *commands_help =
|
|||
static struct wpa_ctrl *ctrl_conn;
|
||||
static int hostapd_cli_quit = 0;
|
||||
static int hostapd_cli_attached = 0;
|
||||
static const char *ctrl_iface_dir = "/var/run/hostapd";
|
||||
|
||||
#ifndef CONFIG_CTRL_IFACE_DIR
|
||||
#define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
|
||||
#endif /* CONFIG_CTRL_IFACE_DIR */
|
||||
static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
|
||||
|
||||
static char *ctrl_ifname = NULL;
|
||||
static const char *pid_file = NULL;
|
||||
static const char *action_file = NULL;
|
||||
|
@ -210,8 +216,21 @@ static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
|
||||
return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
|
||||
return wpa_ctrl_command(ctrl, "STATUS");
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
if (argc > 0) {
|
||||
char buf[100];
|
||||
os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, "MIB");
|
||||
}
|
||||
|
||||
|
@ -219,28 +238,19 @@ static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
|||
static int hostapd_cli_exec(const char *program, const char *arg1,
|
||||
const char *arg2)
|
||||
{
|
||||
char *cmd;
|
||||
char *arg;
|
||||
size_t len;
|
||||
int res;
|
||||
int ret = 0;
|
||||
|
||||
len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
|
||||
cmd = os_malloc(len);
|
||||
if (cmd == NULL)
|
||||
len = os_strlen(arg1) + os_strlen(arg2) + 2;
|
||||
arg = os_malloc(len);
|
||||
if (arg == NULL)
|
||||
return -1;
|
||||
res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
|
||||
if (res < 0 || (size_t) res >= len) {
|
||||
os_free(cmd);
|
||||
return -1;
|
||||
}
|
||||
cmd[len - 1] = '\0';
|
||||
#ifndef _WIN32_WCE
|
||||
if (system(cmd) < 0)
|
||||
ret = -1;
|
||||
#endif /* _WIN32_WCE */
|
||||
os_free(cmd);
|
||||
os_snprintf(arg, len, "%s %s", arg1, arg2);
|
||||
res = os_exec(program, arg, 1);
|
||||
os_free(arg);
|
||||
|
||||
return ret;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
@ -264,11 +274,14 @@ static void hostapd_cli_action_process(char *msg, size_t len)
|
|||
static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
char buf[64];
|
||||
if (argc != 1) {
|
||||
printf("Invalid 'sta' command - exactly one argument, STA "
|
||||
if (argc < 1) {
|
||||
printf("Invalid 'sta' command - at least one argument, STA "
|
||||
"address, is required.\n");
|
||||
return -1;
|
||||
}
|
||||
if (argc > 1)
|
||||
snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "STA %s", argv[0]);
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
@ -470,6 +483,29 @@ static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
|
|||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char cmd[64];
|
||||
int res;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Invalid 'nfc_get_handover_sel' command - two arguments "
|
||||
"are required.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
|
||||
argv[0], argv[1]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long NFC_GET_HANDOVER_SEL command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
|
||||
|
||||
|
@ -494,6 +530,13 @@ static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
|
@ -565,14 +608,14 @@ static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
|
|||
char buf[300];
|
||||
int res;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Invalid 'ess_disassoc' command - two arguments (STA "
|
||||
"addr and URL) are needed\n");
|
||||
if (argc < 3) {
|
||||
printf("Invalid 'ess_disassoc' command - three arguments (STA "
|
||||
"addr, disassoc timer, and URL) are needed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
|
||||
argv[0], argv[1]);
|
||||
res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
|
||||
argv[0], argv[1], argv[2]);
|
||||
if (res < 0 || res >= (int) sizeof(buf))
|
||||
return -1;
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
|
@ -652,6 +695,90 @@ static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char buf[200];
|
||||
int res;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("Invalid 'set_qos_map_set' command - "
|
||||
"one argument (comma delimited QoS map set) "
|
||||
"is needed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
|
||||
if (res < 0 || res >= (int) sizeof(buf))
|
||||
return -1;
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char buf[50];
|
||||
int res;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("Invalid 'send_qos_map_conf' command - "
|
||||
"one argument (STA addr) is needed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
|
||||
if (res < 0 || res >= (int) sizeof(buf))
|
||||
return -1;
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[300];
|
||||
int res;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
|
||||
"addr and URL) are needed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
|
||||
argv[0], argv[1]);
|
||||
if (res < 0 || res >= (int) sizeof(buf))
|
||||
return -1;
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char buf[300];
|
||||
int res;
|
||||
|
||||
if (argc < 3) {
|
||||
printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc > 3)
|
||||
res = os_snprintf(buf, sizeof(buf),
|
||||
"HS20_DEAUTH_REQ %s %s %s %s",
|
||||
argv[0], argv[1], argv[2], argv[3]);
|
||||
else
|
||||
res = os_snprintf(buf, sizeof(buf),
|
||||
"HS20_DEAUTH_REQ %s %s %s",
|
||||
argv[0], argv[1], argv[2]);
|
||||
if (res < 0 || res >= (int) sizeof(buf))
|
||||
return -1;
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
hostapd_cli_quit = 1;
|
||||
|
@ -706,8 +833,10 @@ static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
|
|||
}
|
||||
|
||||
hostapd_cli_close_connection();
|
||||
free(ctrl_ifname);
|
||||
ctrl_ifname = strdup(argv[0]);
|
||||
os_free(ctrl_ifname);
|
||||
ctrl_ifname = os_strdup(argv[0]);
|
||||
if (ctrl_ifname == NULL)
|
||||
return -1;
|
||||
|
||||
if (hostapd_cli_open_connection(ctrl_ifname)) {
|
||||
printf("Connected to interface '%s.\n", ctrl_ifname);
|
||||
|
@ -765,6 +894,66 @@ static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
int res;
|
||||
int i;
|
||||
char *tmp;
|
||||
int total;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Invalid chan_switch command: needs at least two "
|
||||
"arguments (count and freq)\n"
|
||||
"usage: <cs_count> <freq> [sec_channel_offset=] "
|
||||
"[center_freq1=] [center_freq2=] [bandwidth=] "
|
||||
"[blocktx] [ht|vht]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
|
||||
argv[0], argv[1]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long CHAN_SWITCH command.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
total = res;
|
||||
for (i = 2; i < argc; i++) {
|
||||
tmp = cmd + total;
|
||||
res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - total - 1) {
|
||||
printf("Too long CHAN_SWITCH command.\n");
|
||||
return -1;
|
||||
}
|
||||
total += res;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
char cmd[256];
|
||||
int res;
|
||||
|
||||
if (argc < 2 || argc > 3) {
|
||||
printf("Invalid vendor command\n"
|
||||
"usage: <vendor id> <command id> [<hex formatted command argument>]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
|
||||
argc == 3 ? argv[2] : "");
|
||||
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||
printf("Too long VENDOR command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_cli_cmd {
|
||||
const char *cmd;
|
||||
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
|
||||
|
@ -774,6 +963,7 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
{ "ping", hostapd_cli_cmd_ping },
|
||||
{ "mib", hostapd_cli_cmd_mib },
|
||||
{ "relog", hostapd_cli_cmd_relog },
|
||||
{ "status", hostapd_cli_cmd_status },
|
||||
{ "sta", hostapd_cli_cmd_sta },
|
||||
{ "all_sta", hostapd_cli_cmd_all_sta },
|
||||
{ "new_sta", hostapd_cli_cmd_new_sta },
|
||||
|
@ -791,9 +981,11 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
|
||||
{ "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
|
||||
{ "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
|
||||
{ "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
|
||||
{ "wps_config", hostapd_cli_cmd_wps_config },
|
||||
{ "wps_get_status", hostapd_cli_cmd_wps_get_status },
|
||||
#endif /* CONFIG_WPS */
|
||||
{ "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
|
||||
{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
|
||||
|
@ -805,6 +997,12 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
{ "quit", hostapd_cli_cmd_quit },
|
||||
{ "set", hostapd_cli_cmd_set },
|
||||
{ "get", hostapd_cli_cmd_get },
|
||||
{ "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
|
||||
{ "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
|
||||
{ "chan_switch", hostapd_cli_cmd_chan_switch },
|
||||
{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
|
||||
{ "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
|
||||
{ "vendor", hostapd_cli_cmd_vendor },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -1,429 +0,0 @@
|
|||
This patch is adding support for TLS hello extensions and externally
|
||||
generated pre-shared key material to OpenSSL 0.9.8. This is
|
||||
based on the patch from Alexey Kobozev <akobozev@cisco.com>
|
||||
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
|
||||
|
||||
|
||||
|
||||
diff -uprN openssl-0.9.8.orig/include/openssl/ssl.h openssl-0.9.8/include/openssl/ssl.h
|
||||
--- openssl-0.9.8.orig/include/openssl/ssl.h 2005-06-10 12:51:16.000000000 -0700
|
||||
+++ openssl-0.9.8/include/openssl/ssl.h 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -340,6 +340,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_extension_st TLS_EXTENSION;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
|
||||
typedef struct ssl_st SSL;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -968,6 +971,15 @@ struct ssl_st
|
||||
int first_packet;
|
||||
int client_version; /* what was passed, used for
|
||||
* SSLv3/TLS rollback check */
|
||||
+
|
||||
+ /* TLS externsions */
|
||||
+ TLS_EXTENSION *tls_extension;
|
||||
+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
|
||||
+ void *tls_extension_cb_arg;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
|
||||
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
diff -uprN openssl-0.9.8.orig/include/openssl/tls1.h openssl-0.9.8/include/openssl/tls1.h
|
||||
--- openssl-0.9.8.orig/include/openssl/tls1.h 2003-07-22 05:34:21.000000000 -0700
|
||||
+++ openssl-0.9.8/include/openssl/tls1.h 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -282,6 +282,14 @@ extern "C" {
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_extension_st
|
||||
+{
|
||||
+ unsigned short type;
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+};
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -uprN openssl-0.9.8.orig/ssl/Makefile openssl-0.9.8/ssl/Makefile
|
||||
--- openssl-0.9.8.orig/ssl/Makefile 2005-05-30 16:20:30.000000000 -0700
|
||||
+++ openssl-0.9.8/ssl/Makefile 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -24,7 +24,7 @@ LIBSRC= \
|
||||
s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \
|
||||
s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \
|
||||
s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \
|
||||
- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \
|
||||
+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \
|
||||
d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \
|
||||
d1_both.c d1_enc.c \
|
||||
ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
|
||||
@@ -35,7 +35,7 @@ LIBOBJ= \
|
||||
s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \
|
||||
s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \
|
||||
s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \
|
||||
- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \
|
||||
+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \
|
||||
d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \
|
||||
d1_both.o d1_enc.o \
|
||||
ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
|
||||
@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h ..
|
||||
t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
|
||||
t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
|
||||
t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c
|
||||
+t1_ext.o: t1_ext.c ssl_locl.h
|
||||
diff -uprN openssl-0.9.8.orig/ssl/s3_clnt.c openssl-0.9.8/ssl/s3_clnt.c
|
||||
--- openssl-0.9.8.orig/ssl/s3_clnt.c 2005-05-16 03:11:03.000000000 -0700
|
||||
+++ openssl-0.9.8/ssl/s3_clnt.c 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -606,6 +606,20 @@ int ssl3_client_hello(SSL *s)
|
||||
}
|
||||
*(p++)=0; /* Add the NULL method */
|
||||
|
||||
+ /* send client hello extensions if any */
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_extension)
|
||||
+ {
|
||||
+ // set the total extensions length
|
||||
+ s2n(s->tls_extension->length + 4, p);
|
||||
+
|
||||
+ // put the extensions with type and length
|
||||
+ s2n(s->tls_extension->type, p);
|
||||
+ s2n(s->tls_extension->length, p);
|
||||
+
|
||||
+ memcpy(p, s->tls_extension->data, s->tls_extension->length);
|
||||
+ p+=s->tls_extension->length;
|
||||
+ }
|
||||
+
|
||||
l=(p-d);
|
||||
d=buf;
|
||||
*(d++)=SSL3_MT_CLIENT_HELLO;
|
||||
@@ -628,7 +642,7 @@ int ssl3_get_server_hello(SSL *s)
|
||||
STACK_OF(SSL_CIPHER) *sk;
|
||||
SSL_CIPHER *c;
|
||||
unsigned char *p,*d;
|
||||
- int i,al,ok;
|
||||
+ int i,al,ok,pre_shared;
|
||||
unsigned int j;
|
||||
long n;
|
||||
SSL_COMP *comp;
|
||||
@@ -693,7 +707,24 @@ int ssl3_get_server_hello(SSL *s)
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
- if (j != 0 && j == s->session->session_id_length
|
||||
+ /* check if we want to resume the session based on external pre-shared secret */
|
||||
+ pre_shared = 0;
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
|
||||
+ s->session->session_id_length = j;
|
||||
+ memcpy(s->session->session_id, p, j);
|
||||
+ pre_shared = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((pre_shared || j != 0) && j == s->session->session_id_length
|
||||
&& memcmp(p,s->session->session_id,j) == 0)
|
||||
{
|
||||
if(s->sid_ctx_length != s->session->sid_ctx_length
|
||||
diff -uprN openssl-0.9.8.orig/ssl/s3_srvr.c openssl-0.9.8/ssl/s3_srvr.c
|
||||
--- openssl-0.9.8.orig/ssl/s3_srvr.c 2005-05-22 17:32:55.000000000 -0700
|
||||
+++ openssl-0.9.8/ssl/s3_srvr.c 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -955,6 +955,75 @@ int ssl3_get_client_hello(SSL *s)
|
||||
}
|
||||
#endif
|
||||
|
||||
+ /* Check for TLS client hello extension here */
|
||||
+ if (p < (d+n) && s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if (s->tls_extension_cb)
|
||||
+ {
|
||||
+ TLS_EXTENSION tls_ext;
|
||||
+ unsigned short ext_total_len;
|
||||
+
|
||||
+ n2s(p, ext_total_len);
|
||||
+ n2s(p, tls_ext.type);
|
||||
+ n2s(p, tls_ext.length);
|
||||
+
|
||||
+ // sanity check in TLS extension len
|
||||
+ if (tls_ext.length > (d+n) - p)
|
||||
+ {
|
||||
+ // just cut the lenth to packet border
|
||||
+ tls_ext.length = (d+n) - p;
|
||||
+ }
|
||||
+
|
||||
+ tls_ext.data = p;
|
||||
+
|
||||
+ // returns an alert code or 0
|
||||
+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg);
|
||||
+ if (al != 0)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Check if we want to use external pre-shared secret for this handshake */
|
||||
+ /* for not reused session only */
|
||||
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->ciphers=ciphers;
|
||||
+ s->session->verify_result=X509_V_OK;
|
||||
+
|
||||
+ ciphers=NULL;
|
||||
+
|
||||
+ /* check if some cipher was preferred by call back */
|
||||
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
|
||||
+ if (pref_cipher == NULL)
|
||||
+ {
|
||||
+ al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+
|
||||
+ s->session->cipher=pref_cipher;
|
||||
+
|
||||
+ if (s->cipher_list)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list);
|
||||
+
|
||||
+ if (s->cipher_list_by_id)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||
+
|
||||
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Given s->session->ciphers and SSL_get_ciphers, we must
|
||||
* pick a cipher */
|
||||
|
||||
diff -uprN openssl-0.9.8.orig/ssl/ssl_err.c openssl-0.9.8/ssl/ssl_err.c
|
||||
--- openssl-0.9.8.orig/ssl/ssl_err.c 2005-06-10 12:51:16.000000000 -0700
|
||||
+++ openssl-0.9.8/ssl/ssl_err.c 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
||||
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
|
||||
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
|
||||
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
|
||||
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
diff -uprN openssl-0.9.8.orig/ssl/ssl.h openssl-0.9.8/ssl/ssl.h
|
||||
--- openssl-0.9.8.orig/ssl/ssl.h 2005-06-10 12:51:16.000000000 -0700
|
||||
+++ openssl-0.9.8/ssl/ssl.h 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -340,6 +340,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_extension_st TLS_EXTENSION;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
|
||||
typedef struct ssl_st SSL;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -968,6 +971,15 @@ struct ssl_st
|
||||
int first_packet;
|
||||
int client_version; /* what was passed, used for
|
||||
* SSLv3/TLS rollback check */
|
||||
+
|
||||
+ /* TLS externsions */
|
||||
+ TLS_EXTENSION *tls_extension;
|
||||
+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
|
||||
+ void *tls_extension_cb_arg;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
|
||||
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
diff -uprN openssl-0.9.8.orig/ssl/ssl_sess.c openssl-0.9.8/ssl/ssl_sess.c
|
||||
--- openssl-0.9.8.orig/ssl/ssl_sess.c 2005-04-29 13:10:06.000000000 -0700
|
||||
+++ openssl-0.9.8/ssl/ssl_sess.c 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX *
|
||||
return(s->session_timeout);
|
||||
}
|
||||
|
||||
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
|
||||
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
|
||||
+{
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_secret_cb = tls_session_secret_cb;
|
||||
+ s->tls_session_secret_cb_arg = arg;
|
||||
+ return(1);
|
||||
+}
|
||||
+
|
||||
typedef struct timeout_param_st
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
diff -uprN openssl-0.9.8.orig/ssl/t1_ext.c openssl-0.9.8/ssl/t1_ext.c
|
||||
--- openssl-0.9.8.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800
|
||||
+++ openssl-0.9.8/ssl/t1_ext.c 2005-07-19 20:03:29.000000000 -0700
|
||||
@@ -0,0 +1,48 @@
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include "ssl_locl.h"
|
||||
+
|
||||
+
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
|
||||
+{
|
||||
+ if(s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if(s->tls_extension)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tls_extension);
|
||||
+ s->tls_extension = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if(ext_data)
|
||||
+ {
|
||||
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
|
||||
+ if(!s->tls_extension)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ s->tls_extension->type = ext_type;
|
||||
+ s->tls_extension->length = ext_len;
|
||||
+ s->tls_extension->data = s->tls_extension + 1;
|
||||
+ memcpy(s->tls_extension->data, ext_data, ext_len);
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg)
|
||||
+{
|
||||
+ if(s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ s->tls_extension_cb = cb;
|
||||
+ s->tls_extension_cb_arg = arg;
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff -uprN openssl-0.9.8.orig/ssl/t1_lib.c openssl-0.9.8/ssl/t1_lib.c
|
||||
--- openssl-0.9.8.orig/ssl/t1_lib.c 2005-04-26 09:02:40.000000000 -0700
|
||||
+++ openssl-0.9.8/ssl/t1_lib.c 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -131,6 +131,10 @@ int tls1_new(SSL *s)
|
||||
|
||||
void tls1_free(SSL *s)
|
||||
{
|
||||
+ if(s->tls_extension)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tls_extension);
|
||||
+ }
|
||||
ssl3_free(s);
|
||||
}
|
||||
|
||||
diff -uprN openssl-0.9.8.orig/ssl/tls1.h openssl-0.9.8/ssl/tls1.h
|
||||
--- openssl-0.9.8.orig/ssl/tls1.h 2003-07-22 05:34:21.000000000 -0700
|
||||
+++ openssl-0.9.8/ssl/tls1.h 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -282,6 +282,14 @@ extern "C" {
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_extension_st
|
||||
+{
|
||||
+ unsigned short type;
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+};
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -uprN openssl-0.9.8.orig/util/ssleay.num openssl-0.9.8/util/ssleay.num
|
||||
--- openssl-0.9.8.orig/util/ssleay.num 2005-05-08 17:22:02.000000000 -0700
|
||||
+++ openssl-0.9.8/util/ssleay.num 2005-07-19 20:02:15.000000000 -0700
|
||||
@@ -226,3 +226,6 @@ DTLSv1_server_method
|
||||
SSL_COMP_get_compression_methods 276 EXIST:!VMS:FUNCTION:COMP
|
||||
SSL_COMP_get_compress_methods 276 EXIST:VMS:FUNCTION:COMP
|
||||
SSL_SESSION_get_id 277 EXIST::FUNCTION:
|
||||
+SSL_set_hello_extension 278 EXIST::FUNCTION:
|
||||
+SSL_set_hello_extension_cb 279 EXIST::FUNCTION:
|
||||
+SSL_set_session_secret_cb 280 EXIST::FUNCTION:
|
|
@ -1,429 +0,0 @@
|
|||
This patch is adding support for TLS hello extensions and externally
|
||||
generated pre-shared key material to OpenSSL 0.9.8d. This is
|
||||
based on the patch from Alexey Kobozev <akobozev@cisco.com>
|
||||
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
|
||||
|
||||
|
||||
|
||||
diff -uprN openssl-0.9.8d.orig/include/openssl/ssl.h openssl-0.9.8d/include/openssl/ssl.h
|
||||
--- openssl-0.9.8d.orig/include/openssl/ssl.h 2006-06-14 06:52:49.000000000 -0700
|
||||
+++ openssl-0.9.8d/include/openssl/ssl.h 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -345,6 +345,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_extension_st TLS_EXTENSION;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
|
||||
typedef struct ssl_st SSL;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -973,6 +976,15 @@ struct ssl_st
|
||||
int first_packet;
|
||||
int client_version; /* what was passed, used for
|
||||
* SSLv3/TLS rollback check */
|
||||
+
|
||||
+ /* TLS externsions */
|
||||
+ TLS_EXTENSION *tls_extension;
|
||||
+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
|
||||
+ void *tls_extension_cb_arg;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
|
||||
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
diff -uprN openssl-0.9.8d.orig/include/openssl/tls1.h openssl-0.9.8d/include/openssl/tls1.h
|
||||
--- openssl-0.9.8d.orig/include/openssl/tls1.h 2006-06-14 10:52:01.000000000 -0700
|
||||
+++ openssl-0.9.8d/include/openssl/tls1.h 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -296,6 +296,14 @@ extern "C" {
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_extension_st
|
||||
+{
|
||||
+ unsigned short type;
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+};
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -uprN openssl-0.9.8d.orig/ssl/Makefile openssl-0.9.8d/ssl/Makefile
|
||||
--- openssl-0.9.8d.orig/ssl/Makefile 2006-02-03 17:49:35.000000000 -0800
|
||||
+++ openssl-0.9.8d/ssl/Makefile 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -24,7 +24,7 @@ LIBSRC= \
|
||||
s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \
|
||||
s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \
|
||||
s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \
|
||||
- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \
|
||||
+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \
|
||||
d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \
|
||||
d1_both.c d1_enc.c \
|
||||
ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
|
||||
@@ -35,7 +35,7 @@ LIBOBJ= \
|
||||
s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \
|
||||
s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \
|
||||
s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \
|
||||
- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \
|
||||
+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \
|
||||
d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \
|
||||
d1_both.o d1_enc.o \
|
||||
ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
|
||||
@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h ..
|
||||
t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
|
||||
t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
|
||||
t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c
|
||||
+t1_ext.o: t1_ext.c ssl_locl.h
|
||||
diff -uprN openssl-0.9.8d.orig/ssl/s3_clnt.c openssl-0.9.8d/ssl/s3_clnt.c
|
||||
--- openssl-0.9.8d.orig/ssl/s3_clnt.c 2005-12-12 23:41:46.000000000 -0800
|
||||
+++ openssl-0.9.8d/ssl/s3_clnt.c 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s)
|
||||
#endif
|
||||
*(p++)=0; /* Add the NULL method */
|
||||
|
||||
+ /* send client hello extensions if any */
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_extension)
|
||||
+ {
|
||||
+ // set the total extensions length
|
||||
+ s2n(s->tls_extension->length + 4, p);
|
||||
+
|
||||
+ // put the extensions with type and length
|
||||
+ s2n(s->tls_extension->type, p);
|
||||
+ s2n(s->tls_extension->length, p);
|
||||
+
|
||||
+ memcpy(p, s->tls_extension->data, s->tls_extension->length);
|
||||
+ p+=s->tls_extension->length;
|
||||
+ }
|
||||
+
|
||||
l=(p-d);
|
||||
d=buf;
|
||||
*(d++)=SSL3_MT_CLIENT_HELLO;
|
||||
@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s)
|
||||
STACK_OF(SSL_CIPHER) *sk;
|
||||
SSL_CIPHER *c;
|
||||
unsigned char *p,*d;
|
||||
- int i,al,ok;
|
||||
+ int i,al,ok,pre_shared;
|
||||
unsigned int j;
|
||||
long n;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s)
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
- if (j != 0 && j == s->session->session_id_length
|
||||
+ /* check if we want to resume the session based on external pre-shared secret */
|
||||
+ pre_shared = 0;
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
|
||||
+ s->session->session_id_length = j;
|
||||
+ memcpy(s->session->session_id, p, j);
|
||||
+ pre_shared = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((pre_shared || j != 0) && j == s->session->session_id_length
|
||||
&& memcmp(p,s->session->session_id,j) == 0)
|
||||
{
|
||||
if(s->sid_ctx_length != s->session->sid_ctx_length
|
||||
diff -uprN openssl-0.9.8d.orig/ssl/s3_srvr.c openssl-0.9.8d/ssl/s3_srvr.c
|
||||
--- openssl-0.9.8d.orig/ssl/s3_srvr.c 2006-09-28 04:29:03.000000000 -0700
|
||||
+++ openssl-0.9.8d/ssl/s3_srvr.c 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -943,6 +943,75 @@ int ssl3_get_client_hello(SSL *s)
|
||||
}
|
||||
#endif
|
||||
|
||||
+ /* Check for TLS client hello extension here */
|
||||
+ if (p < (d+n) && s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if (s->tls_extension_cb)
|
||||
+ {
|
||||
+ TLS_EXTENSION tls_ext;
|
||||
+ unsigned short ext_total_len;
|
||||
+
|
||||
+ n2s(p, ext_total_len);
|
||||
+ n2s(p, tls_ext.type);
|
||||
+ n2s(p, tls_ext.length);
|
||||
+
|
||||
+ // sanity check in TLS extension len
|
||||
+ if (tls_ext.length > (d+n) - p)
|
||||
+ {
|
||||
+ // just cut the lenth to packet border
|
||||
+ tls_ext.length = (d+n) - p;
|
||||
+ }
|
||||
+
|
||||
+ tls_ext.data = p;
|
||||
+
|
||||
+ // returns an alert code or 0
|
||||
+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg);
|
||||
+ if (al != 0)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Check if we want to use external pre-shared secret for this handshake */
|
||||
+ /* for not reused session only */
|
||||
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->ciphers=ciphers;
|
||||
+ s->session->verify_result=X509_V_OK;
|
||||
+
|
||||
+ ciphers=NULL;
|
||||
+
|
||||
+ /* check if some cipher was preferred by call back */
|
||||
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
|
||||
+ if (pref_cipher == NULL)
|
||||
+ {
|
||||
+ al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+
|
||||
+ s->session->cipher=pref_cipher;
|
||||
+
|
||||
+ if (s->cipher_list)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list);
|
||||
+
|
||||
+ if (s->cipher_list_by_id)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||
+
|
||||
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Given s->session->ciphers and SSL_get_ciphers, we must
|
||||
* pick a cipher */
|
||||
|
||||
diff -uprN openssl-0.9.8d.orig/ssl/ssl.h openssl-0.9.8d/ssl/ssl.h
|
||||
--- openssl-0.9.8d.orig/ssl/ssl.h 2006-06-14 06:52:49.000000000 -0700
|
||||
+++ openssl-0.9.8d/ssl/ssl.h 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -345,6 +345,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_extension_st TLS_EXTENSION;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
|
||||
typedef struct ssl_st SSL;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -973,6 +976,15 @@ struct ssl_st
|
||||
int first_packet;
|
||||
int client_version; /* what was passed, used for
|
||||
* SSLv3/TLS rollback check */
|
||||
+
|
||||
+ /* TLS externsions */
|
||||
+ TLS_EXTENSION *tls_extension;
|
||||
+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
|
||||
+ void *tls_extension_cb_arg;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
|
||||
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
diff -uprN openssl-0.9.8d.orig/ssl/ssl_err.c openssl-0.9.8d/ssl/ssl_err.c
|
||||
--- openssl-0.9.8d.orig/ssl/ssl_err.c 2006-01-08 13:52:46.000000000 -0800
|
||||
+++ openssl-0.9.8d/ssl/ssl_err.c 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
||||
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
|
||||
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
|
||||
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
|
||||
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
diff -uprN openssl-0.9.8d.orig/ssl/ssl_sess.c openssl-0.9.8d/ssl/ssl_sess.c
|
||||
--- openssl-0.9.8d.orig/ssl/ssl_sess.c 2005-12-30 15:51:57.000000000 -0800
|
||||
+++ openssl-0.9.8d/ssl/ssl_sess.c 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX *
|
||||
return(s->session_timeout);
|
||||
}
|
||||
|
||||
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
|
||||
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
|
||||
+{
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_secret_cb = tls_session_secret_cb;
|
||||
+ s->tls_session_secret_cb_arg = arg;
|
||||
+ return(1);
|
||||
+}
|
||||
+
|
||||
typedef struct timeout_param_st
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
diff -uprN openssl-0.9.8d.orig/ssl/t1_ext.c openssl-0.9.8d/ssl/t1_ext.c
|
||||
--- openssl-0.9.8d.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800
|
||||
+++ openssl-0.9.8d/ssl/t1_ext.c 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -0,0 +1,48 @@
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include "ssl_locl.h"
|
||||
+
|
||||
+
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
|
||||
+{
|
||||
+ if(s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if(s->tls_extension)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tls_extension);
|
||||
+ s->tls_extension = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if(ext_data)
|
||||
+ {
|
||||
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
|
||||
+ if(!s->tls_extension)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ s->tls_extension->type = ext_type;
|
||||
+ s->tls_extension->length = ext_len;
|
||||
+ s->tls_extension->data = s->tls_extension + 1;
|
||||
+ memcpy(s->tls_extension->data, ext_data, ext_len);
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg)
|
||||
+{
|
||||
+ if(s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ s->tls_extension_cb = cb;
|
||||
+ s->tls_extension_cb_arg = arg;
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff -uprN openssl-0.9.8d.orig/ssl/t1_lib.c openssl-0.9.8d/ssl/t1_lib.c
|
||||
--- openssl-0.9.8d.orig/ssl/t1_lib.c 2005-08-05 16:52:07.000000000 -0700
|
||||
+++ openssl-0.9.8d/ssl/t1_lib.c 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -97,6 +97,10 @@ int tls1_new(SSL *s)
|
||||
|
||||
void tls1_free(SSL *s)
|
||||
{
|
||||
+ if(s->tls_extension)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tls_extension);
|
||||
+ }
|
||||
ssl3_free(s);
|
||||
}
|
||||
|
||||
diff -uprN openssl-0.9.8d.orig/ssl/tls1.h openssl-0.9.8d/ssl/tls1.h
|
||||
--- openssl-0.9.8d.orig/ssl/tls1.h 2006-06-14 10:52:01.000000000 -0700
|
||||
+++ openssl-0.9.8d/ssl/tls1.h 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -296,6 +296,14 @@ extern "C" {
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_extension_st
|
||||
+{
|
||||
+ unsigned short type;
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+};
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -uprN openssl-0.9.8d.orig/util/ssleay.num openssl-0.9.8d/util/ssleay.num
|
||||
--- openssl-0.9.8d.orig/util/ssleay.num 2005-05-08 17:22:02.000000000 -0700
|
||||
+++ openssl-0.9.8d/util/ssleay.num 2006-12-10 08:20:02.000000000 -0800
|
||||
@@ -226,3 +226,6 @@ DTLSv1_server_method
|
||||
SSL_COMP_get_compression_methods 276 EXIST:!VMS:FUNCTION:COMP
|
||||
SSL_COMP_get_compress_methods 276 EXIST:VMS:FUNCTION:COMP
|
||||
SSL_SESSION_get_id 277 EXIST::FUNCTION:
|
||||
+SSL_set_hello_extension 278 EXIST::FUNCTION:
|
||||
+SSL_set_hello_extension_cb 279 EXIST::FUNCTION:
|
||||
+SSL_set_session_secret_cb 280 EXIST::FUNCTION:
|
|
@ -1,353 +0,0 @@
|
|||
This patch is adding support for TLS hello extensions and externally
|
||||
generated pre-shared key material to OpenSSL 0.9.8e. This is
|
||||
based on the patch from Alexey Kobozev <akobozev@cisco.com>
|
||||
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
|
||||
|
||||
|
||||
|
||||
diff -uprN openssl-0.9.8e.orig/ssl/Makefile openssl-0.9.8e/ssl/Makefile
|
||||
--- openssl-0.9.8e.orig/ssl/Makefile 2006-02-03 17:49:35.000000000 -0800
|
||||
+++ openssl-0.9.8e/ssl/Makefile 2007-03-22 20:23:19.000000000 -0700
|
||||
@@ -24,7 +24,7 @@ LIBSRC= \
|
||||
s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \
|
||||
s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \
|
||||
s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \
|
||||
- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \
|
||||
+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \
|
||||
d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \
|
||||
d1_both.c d1_enc.c \
|
||||
ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
|
||||
@@ -35,7 +35,7 @@ LIBOBJ= \
|
||||
s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \
|
||||
s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \
|
||||
s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \
|
||||
- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \
|
||||
+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \
|
||||
d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \
|
||||
d1_both.o d1_enc.o \
|
||||
ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
|
||||
@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h ..
|
||||
t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
|
||||
t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
|
||||
t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c
|
||||
+t1_ext.o: t1_ext.c ssl_locl.h
|
||||
diff -uprN openssl-0.9.8e.orig/ssl/s3_clnt.c openssl-0.9.8e/ssl/s3_clnt.c
|
||||
--- openssl-0.9.8e.orig/ssl/s3_clnt.c 2006-09-28 05:23:15.000000000 -0700
|
||||
+++ openssl-0.9.8e/ssl/s3_clnt.c 2007-03-22 20:23:19.000000000 -0700
|
||||
@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s)
|
||||
#endif
|
||||
*(p++)=0; /* Add the NULL method */
|
||||
|
||||
+ /* send client hello extensions if any */
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_extension)
|
||||
+ {
|
||||
+ // set the total extensions length
|
||||
+ s2n(s->tls_extension->length + 4, p);
|
||||
+
|
||||
+ // put the extensions with type and length
|
||||
+ s2n(s->tls_extension->type, p);
|
||||
+ s2n(s->tls_extension->length, p);
|
||||
+
|
||||
+ memcpy(p, s->tls_extension->data, s->tls_extension->length);
|
||||
+ p+=s->tls_extension->length;
|
||||
+ }
|
||||
+
|
||||
l=(p-d);
|
||||
d=buf;
|
||||
*(d++)=SSL3_MT_CLIENT_HELLO;
|
||||
@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s)
|
||||
STACK_OF(SSL_CIPHER) *sk;
|
||||
SSL_CIPHER *c;
|
||||
unsigned char *p,*d;
|
||||
- int i,al,ok;
|
||||
+ int i,al,ok,pre_shared;
|
||||
unsigned int j;
|
||||
long n;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s)
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
- if (j != 0 && j == s->session->session_id_length
|
||||
+ /* check if we want to resume the session based on external pre-shared secret */
|
||||
+ pre_shared = 0;
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
|
||||
+ s->session->session_id_length = j;
|
||||
+ memcpy(s->session->session_id, p, j);
|
||||
+ pre_shared = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((pre_shared || j != 0) && j == s->session->session_id_length
|
||||
&& memcmp(p,s->session->session_id,j) == 0)
|
||||
{
|
||||
if(s->sid_ctx_length != s->session->sid_ctx_length
|
||||
diff -uprN openssl-0.9.8e.orig/ssl/s3_srvr.c openssl-0.9.8e/ssl/s3_srvr.c
|
||||
--- openssl-0.9.8e.orig/ssl/s3_srvr.c 2007-02-07 12:36:40.000000000 -0800
|
||||
+++ openssl-0.9.8e/ssl/s3_srvr.c 2007-03-22 20:23:19.000000000 -0700
|
||||
@@ -945,6 +945,75 @@ int ssl3_get_client_hello(SSL *s)
|
||||
}
|
||||
#endif
|
||||
|
||||
+ /* Check for TLS client hello extension here */
|
||||
+ if (p < (d+n) && s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if (s->tls_extension_cb)
|
||||
+ {
|
||||
+ TLS_EXTENSION tls_ext;
|
||||
+ unsigned short ext_total_len;
|
||||
+
|
||||
+ n2s(p, ext_total_len);
|
||||
+ n2s(p, tls_ext.type);
|
||||
+ n2s(p, tls_ext.length);
|
||||
+
|
||||
+ // sanity check in TLS extension len
|
||||
+ if (tls_ext.length > (d+n) - p)
|
||||
+ {
|
||||
+ // just cut the lenth to packet border
|
||||
+ tls_ext.length = (d+n) - p;
|
||||
+ }
|
||||
+
|
||||
+ tls_ext.data = p;
|
||||
+
|
||||
+ // returns an alert code or 0
|
||||
+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg);
|
||||
+ if (al != 0)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Check if we want to use external pre-shared secret for this handshake */
|
||||
+ /* for not reused session only */
|
||||
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->ciphers=ciphers;
|
||||
+ s->session->verify_result=X509_V_OK;
|
||||
+
|
||||
+ ciphers=NULL;
|
||||
+
|
||||
+ /* check if some cipher was preferred by call back */
|
||||
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
|
||||
+ if (pref_cipher == NULL)
|
||||
+ {
|
||||
+ al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+
|
||||
+ s->session->cipher=pref_cipher;
|
||||
+
|
||||
+ if (s->cipher_list)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list);
|
||||
+
|
||||
+ if (s->cipher_list_by_id)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||
+
|
||||
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Given s->session->ciphers and SSL_get_ciphers, we must
|
||||
* pick a cipher */
|
||||
|
||||
diff -uprN openssl-0.9.8e.orig/ssl/ssl.h openssl-0.9.8e/ssl/ssl.h
|
||||
--- openssl-0.9.8e.orig/ssl/ssl.h 2007-02-19 09:55:07.000000000 -0800
|
||||
+++ openssl-0.9.8e/ssl/ssl.h 2007-03-22 20:23:19.000000000 -0700
|
||||
@@ -345,6 +345,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_extension_st TLS_EXTENSION;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
|
||||
typedef struct ssl_st SSL;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -973,6 +976,15 @@ struct ssl_st
|
||||
int first_packet;
|
||||
int client_version; /* what was passed, used for
|
||||
* SSLv3/TLS rollback check */
|
||||
+
|
||||
+ /* TLS externsions */
|
||||
+ TLS_EXTENSION *tls_extension;
|
||||
+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
|
||||
+ void *tls_extension_cb_arg;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
|
||||
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
diff -uprN openssl-0.9.8e.orig/ssl/ssl_err.c openssl-0.9.8e/ssl/ssl_err.c
|
||||
--- openssl-0.9.8e.orig/ssl/ssl_err.c 2006-11-21 12:14:46.000000000 -0800
|
||||
+++ openssl-0.9.8e/ssl/ssl_err.c 2007-03-22 20:23:19.000000000 -0700
|
||||
@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
||||
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
|
||||
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
|
||||
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
|
||||
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
diff -uprN openssl-0.9.8e.orig/ssl/ssl_sess.c openssl-0.9.8e/ssl/ssl_sess.c
|
||||
--- openssl-0.9.8e.orig/ssl/ssl_sess.c 2007-02-10 02:40:24.000000000 -0800
|
||||
+++ openssl-0.9.8e/ssl/ssl_sess.c 2007-03-22 20:23:19.000000000 -0700
|
||||
@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX *
|
||||
return(s->session_timeout);
|
||||
}
|
||||
|
||||
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
|
||||
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
|
||||
+{
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_secret_cb = tls_session_secret_cb;
|
||||
+ s->tls_session_secret_cb_arg = arg;
|
||||
+ return(1);
|
||||
+}
|
||||
+
|
||||
typedef struct timeout_param_st
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
diff -uprN openssl-0.9.8e.orig/ssl/t1_ext.c openssl-0.9.8e/ssl/t1_ext.c
|
||||
--- openssl-0.9.8e.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800
|
||||
+++ openssl-0.9.8e/ssl/t1_ext.c 2007-03-22 20:23:19.000000000 -0700
|
||||
@@ -0,0 +1,48 @@
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include "ssl_locl.h"
|
||||
+
|
||||
+
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
|
||||
+{
|
||||
+ if(s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if(s->tls_extension)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tls_extension);
|
||||
+ s->tls_extension = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if(ext_data)
|
||||
+ {
|
||||
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
|
||||
+ if(!s->tls_extension)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ s->tls_extension->type = ext_type;
|
||||
+ s->tls_extension->length = ext_len;
|
||||
+ s->tls_extension->data = s->tls_extension + 1;
|
||||
+ memcpy(s->tls_extension->data, ext_data, ext_len);
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg)
|
||||
+{
|
||||
+ if(s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ s->tls_extension_cb = cb;
|
||||
+ s->tls_extension_cb_arg = arg;
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff -uprN openssl-0.9.8e.orig/ssl/t1_lib.c openssl-0.9.8e/ssl/t1_lib.c
|
||||
--- openssl-0.9.8e.orig/ssl/t1_lib.c 2007-01-21 08:07:25.000000000 -0800
|
||||
+++ openssl-0.9.8e/ssl/t1_lib.c 2007-03-22 20:23:19.000000000 -0700
|
||||
@@ -97,6 +97,10 @@ int tls1_new(SSL *s)
|
||||
|
||||
void tls1_free(SSL *s)
|
||||
{
|
||||
+ if(s->tls_extension)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tls_extension);
|
||||
+ }
|
||||
ssl3_free(s);
|
||||
}
|
||||
|
||||
diff -uprN openssl-0.9.8e.orig/ssl/tls1.h openssl-0.9.8e/ssl/tls1.h
|
||||
--- openssl-0.9.8e.orig/ssl/tls1.h 2006-06-14 10:52:01.000000000 -0700
|
||||
+++ openssl-0.9.8e/ssl/tls1.h 2007-03-22 20:23:19.000000000 -0700
|
||||
@@ -296,6 +296,14 @@ extern "C" {
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_extension_st
|
||||
+{
|
||||
+ unsigned short type;
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+};
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -uprN openssl-0.9.8e.orig/util/ssleay.num openssl-0.9.8e/util/ssleay.num
|
||||
--- openssl-0.9.8e.orig/util/ssleay.num 2006-11-30 05:04:43.000000000 -0800
|
||||
+++ openssl-0.9.8e/util/ssleay.num 2007-03-22 20:24:07.000000000 -0700
|
||||
@@ -238,3 +238,6 @@ SSL_CTX_set_info_callback
|
||||
SSL_CTX_sess_get_new_cb 287 EXIST::FUNCTION:
|
||||
SSL_CTX_get_client_cert_cb 288 EXIST::FUNCTION:
|
||||
SSL_CTX_sess_get_remove_cb 289 EXIST::FUNCTION:
|
||||
+SSL_set_hello_extension 290 EXIST::FUNCTION:
|
||||
+SSL_set_hello_extension_cb 291 EXIST::FUNCTION:
|
||||
+SSL_set_session_secret_cb 292 EXIST::FUNCTION:
|
|
@ -1,330 +0,0 @@
|
|||
This patch adds support for TLS SessionTicket extension (RFC 5077) for
|
||||
the parts used by EAP-FAST (RFC 4851).
|
||||
|
||||
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
|
||||
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
|
||||
|
||||
OpenSSL 0.9.8g does not enable TLS extension support by default, so it
|
||||
will need to be enabled by adding enable-tlsext to config script
|
||||
command line.
|
||||
|
||||
|
||||
diff -upr openssl-0.9.8g.orig/ssl/s3_clnt.c openssl-0.9.8g/ssl/s3_clnt.c
|
||||
--- openssl-0.9.8g.orig/ssl/s3_clnt.c 2007-08-31 03:28:51.000000000 +0300
|
||||
+++ openssl-0.9.8g/ssl/s3_clnt.c 2008-04-15 17:11:46.000000000 +0300
|
||||
@@ -727,6 +727,20 @@ int ssl3_get_server_hello(SSL *s)
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ /* check if we want to resume the session based on external pre-shared secret */
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
|
||||
+ }
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
if (j != 0 && j == s->session->session_id_length
|
||||
&& memcmp(p,s->session->session_id,j) == 0)
|
||||
{
|
||||
diff -upr openssl-0.9.8g.orig/ssl/s3_srvr.c openssl-0.9.8g/ssl/s3_srvr.c
|
||||
--- openssl-0.9.8g.orig/ssl/s3_srvr.c 2007-09-30 21:55:59.000000000 +0300
|
||||
+++ openssl-0.9.8g/ssl/s3_srvr.c 2008-04-15 17:10:37.000000000 +0300
|
||||
@@ -928,6 +928,59 @@ int ssl3_get_client_hello(SSL *s)
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
|
||||
goto err;
|
||||
}
|
||||
+
|
||||
+ /* Check if we want to use external pre-shared secret for this
|
||||
+ * handshake for not reused session only. We need to generate
|
||||
+ * server_random before calling tls_session_secret_cb in order to allow
|
||||
+ * SessionTicket processing to use it in key derivation. */
|
||||
+ {
|
||||
+ unsigned long Time;
|
||||
+ unsigned char *pos;
|
||||
+ Time=(unsigned long)time(NULL); /* Time */
|
||||
+ pos=s->s3->server_random;
|
||||
+ l2n(Time,pos);
|
||||
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
+ {
|
||||
+ al=SSL_AD_INTERNAL_ERROR;
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->ciphers=ciphers;
|
||||
+ s->session->verify_result=X509_V_OK;
|
||||
+
|
||||
+ ciphers=NULL;
|
||||
+
|
||||
+ /* check if some cipher was preferred by call back */
|
||||
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
|
||||
+ if (pref_cipher == NULL)
|
||||
+ {
|
||||
+ al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+
|
||||
+ s->session->cipher=pref_cipher;
|
||||
+
|
||||
+ if (s->cipher_list)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list);
|
||||
+
|
||||
+ if (s->cipher_list_by_id)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||
+
|
||||
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ }
|
||||
+ }
|
||||
#endif
|
||||
/* Worst case, we will use the NULL compression, but if we have other
|
||||
* options, we will now look for them. We have i-1 compression
|
||||
@@ -1066,16 +1119,22 @@ int ssl3_send_server_hello(SSL *s)
|
||||
unsigned char *buf;
|
||||
unsigned char *p,*d;
|
||||
int i,sl;
|
||||
- unsigned long l,Time;
|
||||
+ unsigned long l;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
+ unsigned long Time;
|
||||
+#endif
|
||||
|
||||
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
|
||||
{
|
||||
buf=(unsigned char *)s->init_buf->data;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
p=s->s3->server_random;
|
||||
+ /* Generate server_random if it was not needed previously */
|
||||
Time=(unsigned long)time(NULL); /* Time */
|
||||
l2n(Time,p);
|
||||
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
return -1;
|
||||
+#endif
|
||||
/* Do the message type and length last */
|
||||
d=p= &(buf[4]);
|
||||
|
||||
diff -upr openssl-0.9.8g.orig/ssl/ssl.h openssl-0.9.8g/ssl/ssl.h
|
||||
--- openssl-0.9.8g.orig/ssl/ssl.h 2007-10-19 10:42:38.000000000 +0300
|
||||
+++ openssl-0.9.8g/ssl/ssl.h 2008-04-15 17:10:37.000000000 +0300
|
||||
@@ -342,6 +342,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_extension_st TLS_EXTENSION;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -363,6 +364,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
|
||||
typedef struct ssl_st SSL;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -1004,6 +1007,14 @@ struct ssl_st
|
||||
*/
|
||||
/* RFC4507 session ticket expected to be received or sent */
|
||||
int tlsext_ticket_expected;
|
||||
+
|
||||
+ /* TLS extensions */
|
||||
+ TLS_EXTENSION *tls_extension;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
+
|
||||
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
|
||||
#define session_ctx initial_ctx
|
||||
#else
|
||||
@@ -1589,6 +1600,12 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1778,6 +1795,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
diff -upr openssl-0.9.8g.orig/ssl/ssl_err.c openssl-0.9.8g/ssl/ssl_err.c
|
||||
--- openssl-0.9.8g.orig/ssl/ssl_err.c 2007-10-11 17:36:59.000000000 +0300
|
||||
+++ openssl-0.9.8g/ssl/ssl_err.c 2008-04-15 17:10:37.000000000 +0300
|
||||
@@ -250,6 +250,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
||||
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
|
||||
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
|
||||
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
|
||||
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
diff -upr openssl-0.9.8g.orig/ssl/ssl_sess.c openssl-0.9.8g/ssl/ssl_sess.c
|
||||
--- openssl-0.9.8g.orig/ssl/ssl_sess.c 2007-10-19 10:36:34.000000000 +0300
|
||||
+++ openssl-0.9.8g/ssl/ssl_sess.c 2008-04-15 17:10:37.000000000 +0300
|
||||
@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX *
|
||||
return(s->session_timeout);
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
|
||||
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
|
||||
+{
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_secret_cb = tls_session_secret_cb;
|
||||
+ s->tls_session_secret_cb_arg = arg;
|
||||
+ return(1);
|
||||
+}
|
||||
+
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
|
||||
+{
|
||||
+ if(s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if(s->tls_extension)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tls_extension);
|
||||
+ s->tls_extension = NULL;
|
||||
+ }
|
||||
+
|
||||
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
|
||||
+ if(!s->tls_extension)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ s->tls_extension->type = ext_type;
|
||||
+
|
||||
+ if(ext_data)
|
||||
+ {
|
||||
+ s->tls_extension->length = ext_len;
|
||||
+ s->tls_extension->data = s->tls_extension + 1;
|
||||
+ memcpy(s->tls_extension->data, ext_data, ext_len);
|
||||
+ } else {
|
||||
+ s->tls_extension->length = 0;
|
||||
+ s->tls_extension->data = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
typedef struct timeout_param_st
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
diff -upr openssl-0.9.8g.orig/ssl/t1_lib.c openssl-0.9.8g/ssl/t1_lib.c
|
||||
--- openssl-0.9.8g.orig/ssl/t1_lib.c 2007-10-19 10:44:10.000000000 +0300
|
||||
+++ openssl-0.9.8g/ssl/t1_lib.c 2008-04-15 17:10:37.000000000 +0300
|
||||
@@ -105,6 +105,12 @@ int tls1_new(SSL *s)
|
||||
|
||||
void tls1_free(SSL *s)
|
||||
{
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ if(s->tls_extension)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tls_extension);
|
||||
+ }
|
||||
+#endif
|
||||
ssl3_free(s);
|
||||
}
|
||||
|
||||
@@ -174,8 +180,24 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
int ticklen;
|
||||
if (s->session && s->session->tlsext_tick)
|
||||
ticklen = s->session->tlsext_ticklen;
|
||||
+ else if (s->session && s->tls_extension &&
|
||||
+ s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
|
||||
+ s->tls_extension->data)
|
||||
+ {
|
||||
+ ticklen = s->tls_extension->length;
|
||||
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
|
||||
+ if (!s->session->tlsext_tick)
|
||||
+ return NULL;
|
||||
+ memcpy(s->session->tlsext_tick, s->tls_extension->data,
|
||||
+ ticklen);
|
||||
+ s->session->tlsext_ticklen = ticklen;
|
||||
+ }
|
||||
else
|
||||
ticklen = 0;
|
||||
+ if (ticklen == 0 && s->tls_extension &&
|
||||
+ s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
|
||||
+ s->tls_extension->data == NULL)
|
||||
+ goto skip_ext;
|
||||
/* Check for enough room 2 for extension type, 2 for len
|
||||
* rest for ticket
|
||||
*/
|
||||
@@ -189,6 +211,7 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
ret += ticklen;
|
||||
}
|
||||
}
|
||||
+ skip_ext:
|
||||
|
||||
if ((extdatalen = ret-p-2)== 0)
|
||||
return p;
|
||||
@@ -543,6 +566,8 @@ int tls1_process_ticket(SSL *s, unsigned
|
||||
s->tlsext_ticket_expected = 1;
|
||||
return 0; /* Cache miss */
|
||||
}
|
||||
+ if (s->tls_session_secret_cb)
|
||||
+ return 0;
|
||||
return tls_decrypt_ticket(s, p, size, session_id, len,
|
||||
ret);
|
||||
}
|
||||
diff -upr openssl-0.9.8g.orig/ssl/tls1.h openssl-0.9.8g/ssl/tls1.h
|
||||
--- openssl-0.9.8g.orig/ssl/tls1.h 2007-08-28 04:12:44.000000000 +0300
|
||||
+++ openssl-0.9.8g/ssl/tls1.h 2008-04-15 17:10:37.000000000 +0300
|
||||
@@ -365,6 +365,14 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SER
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_extension_st
|
||||
+{
|
||||
+ unsigned short type;
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+};
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -upr openssl-0.9.8g.orig/util/ssleay.num openssl-0.9.8g/util/ssleay.num
|
||||
--- openssl-0.9.8g.orig/util/ssleay.num 2007-08-13 01:31:16.000000000 +0300
|
||||
+++ openssl-0.9.8g/util/ssleay.num 2008-04-15 17:10:37.000000000 +0300
|
||||
@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb
|
||||
SSL_set_SSL_CTX 290 EXIST::FUNCTION:
|
||||
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
|
||||
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
|
||||
+SSL_set_hello_extension 305 EXIST::FUNCTION:TLSEXT
|
||||
+SSL_set_session_secret_cb 306 EXIST::FUNCTION:TLSEXT
|
|
@ -1,344 +0,0 @@
|
|||
This patch adds support for TLS SessionTicket extension (RFC 5077) for
|
||||
the parts used by EAP-FAST (RFC 4851).
|
||||
|
||||
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
|
||||
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
|
||||
|
||||
OpenSSL 0.9.8h does not enable TLS extension support by default, so it
|
||||
will need to be enabled by adding enable-tlsext to config script
|
||||
command line.
|
||||
|
||||
|
||||
diff -upr openssl-0.9.8h.orig/ssl/s3_clnt.c openssl-0.9.8h/ssl/s3_clnt.c
|
||||
--- openssl-0.9.8h.orig/ssl/s3_clnt.c 2008-05-28 10:29:27.000000000 +0300
|
||||
+++ openssl-0.9.8h/ssl/s3_clnt.c 2008-05-29 10:44:25.000000000 +0300
|
||||
@@ -752,6 +752,20 @@ int ssl3_get_server_hello(SSL *s)
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ /* check if we want to resume the session based on external pre-shared secret */
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
|
||||
+ }
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
if (j != 0 && j == s->session->session_id_length
|
||||
&& memcmp(p,s->session->session_id,j) == 0)
|
||||
{
|
||||
@@ -2693,11 +2707,8 @@ static int ssl3_check_finished(SSL *s)
|
||||
{
|
||||
int ok;
|
||||
long n;
|
||||
- /* If we have no ticket or session ID is non-zero length (a match of
|
||||
- * a non-zero session length would never reach here) it cannot be a
|
||||
- * resumed session.
|
||||
- */
|
||||
- if (!s->session->tlsext_tick || s->session->session_id_length)
|
||||
+ /* If we have no ticket it cannot be a resumed session. */
|
||||
+ if (!s->session->tlsext_tick)
|
||||
return 1;
|
||||
/* this function is called when we really expect a Certificate
|
||||
* message, so permit appropriate message length */
|
||||
diff -upr openssl-0.9.8h.orig/ssl/s3_srvr.c openssl-0.9.8h/ssl/s3_srvr.c
|
||||
--- openssl-0.9.8h.orig/ssl/s3_srvr.c 2008-04-30 19:11:32.000000000 +0300
|
||||
+++ openssl-0.9.8h/ssl/s3_srvr.c 2008-05-28 18:49:34.000000000 +0300
|
||||
@@ -959,6 +959,59 @@ int ssl3_get_client_hello(SSL *s)
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
|
||||
goto err;
|
||||
}
|
||||
+
|
||||
+ /* Check if we want to use external pre-shared secret for this
|
||||
+ * handshake for not reused session only. We need to generate
|
||||
+ * server_random before calling tls_session_secret_cb in order to allow
|
||||
+ * SessionTicket processing to use it in key derivation. */
|
||||
+ {
|
||||
+ unsigned long Time;
|
||||
+ unsigned char *pos;
|
||||
+ Time=(unsigned long)time(NULL); /* Time */
|
||||
+ pos=s->s3->server_random;
|
||||
+ l2n(Time,pos);
|
||||
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
+ {
|
||||
+ al=SSL_AD_INTERNAL_ERROR;
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->ciphers=ciphers;
|
||||
+ s->session->verify_result=X509_V_OK;
|
||||
+
|
||||
+ ciphers=NULL;
|
||||
+
|
||||
+ /* check if some cipher was preferred by call back */
|
||||
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
|
||||
+ if (pref_cipher == NULL)
|
||||
+ {
|
||||
+ al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+
|
||||
+ s->session->cipher=pref_cipher;
|
||||
+
|
||||
+ if (s->cipher_list)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list);
|
||||
+
|
||||
+ if (s->cipher_list_by_id)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||
+
|
||||
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ }
|
||||
+ }
|
||||
#endif
|
||||
/* Worst case, we will use the NULL compression, but if we have other
|
||||
* options, we will now look for them. We have i-1 compression
|
||||
@@ -1097,16 +1150,22 @@ int ssl3_send_server_hello(SSL *s)
|
||||
unsigned char *buf;
|
||||
unsigned char *p,*d;
|
||||
int i,sl;
|
||||
- unsigned long l,Time;
|
||||
+ unsigned long l;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
+ unsigned long Time;
|
||||
+#endif
|
||||
|
||||
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
|
||||
{
|
||||
buf=(unsigned char *)s->init_buf->data;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
p=s->s3->server_random;
|
||||
+ /* Generate server_random if it was not needed previously */
|
||||
Time=(unsigned long)time(NULL); /* Time */
|
||||
l2n(Time,p);
|
||||
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
return -1;
|
||||
+#endif
|
||||
/* Do the message type and length last */
|
||||
d=p= &(buf[4]);
|
||||
|
||||
diff -upr openssl-0.9.8h.orig/ssl/ssl.h openssl-0.9.8h/ssl/ssl.h
|
||||
--- openssl-0.9.8h.orig/ssl/ssl.h 2008-04-30 19:11:32.000000000 +0300
|
||||
+++ openssl-0.9.8h/ssl/ssl.h 2008-05-28 18:49:34.000000000 +0300
|
||||
@@ -343,6 +343,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_extension_st TLS_EXTENSION;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -364,6 +365,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
|
||||
typedef struct ssl_st SSL;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -1027,6 +1030,14 @@ struct ssl_st
|
||||
|
||||
/* RFC4507 session ticket expected to be received or sent */
|
||||
int tlsext_ticket_expected;
|
||||
+
|
||||
+ /* TLS extensions */
|
||||
+ TLS_EXTENSION *tls_extension;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
+
|
||||
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
|
||||
#define session_ctx initial_ctx
|
||||
#else
|
||||
@@ -1625,6 +1636,12 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1815,6 +1832,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
diff -upr openssl-0.9.8h.orig/ssl/ssl_err.c openssl-0.9.8h/ssl/ssl_err.c
|
||||
--- openssl-0.9.8h.orig/ssl/ssl_err.c 2007-10-12 03:00:30.000000000 +0300
|
||||
+++ openssl-0.9.8h/ssl/ssl_err.c 2008-05-28 18:49:34.000000000 +0300
|
||||
@@ -251,6 +251,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
||||
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
|
||||
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
|
||||
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
|
||||
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
diff -upr openssl-0.9.8h.orig/ssl/ssl_sess.c openssl-0.9.8h/ssl/ssl_sess.c
|
||||
--- openssl-0.9.8h.orig/ssl/ssl_sess.c 2007-10-17 20:30:15.000000000 +0300
|
||||
+++ openssl-0.9.8h/ssl/ssl_sess.c 2008-05-28 18:49:34.000000000 +0300
|
||||
@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX *
|
||||
return(s->session_timeout);
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
|
||||
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
|
||||
+{
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_secret_cb = tls_session_secret_cb;
|
||||
+ s->tls_session_secret_cb_arg = arg;
|
||||
+ return(1);
|
||||
+}
|
||||
+
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
|
||||
+{
|
||||
+ if(s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if(s->tls_extension)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tls_extension);
|
||||
+ s->tls_extension = NULL;
|
||||
+ }
|
||||
+
|
||||
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
|
||||
+ if(!s->tls_extension)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ s->tls_extension->type = ext_type;
|
||||
+
|
||||
+ if(ext_data)
|
||||
+ {
|
||||
+ s->tls_extension->length = ext_len;
|
||||
+ s->tls_extension->data = s->tls_extension + 1;
|
||||
+ memcpy(s->tls_extension->data, ext_data, ext_len);
|
||||
+ } else {
|
||||
+ s->tls_extension->length = 0;
|
||||
+ s->tls_extension->data = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
typedef struct timeout_param_st
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
diff -upr openssl-0.9.8h.orig/ssl/t1_lib.c openssl-0.9.8h/ssl/t1_lib.c
|
||||
--- openssl-0.9.8h.orig/ssl/t1_lib.c 2008-05-28 10:26:33.000000000 +0300
|
||||
+++ openssl-0.9.8h/ssl/t1_lib.c 2008-05-28 18:49:34.000000000 +0300
|
||||
@@ -106,6 +106,12 @@ int tls1_new(SSL *s)
|
||||
|
||||
void tls1_free(SSL *s)
|
||||
{
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ if(s->tls_extension)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tls_extension);
|
||||
+ }
|
||||
+#endif
|
||||
ssl3_free(s);
|
||||
}
|
||||
|
||||
@@ -175,8 +181,24 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
int ticklen;
|
||||
if (s->session && s->session->tlsext_tick)
|
||||
ticklen = s->session->tlsext_ticklen;
|
||||
+ else if (s->session && s->tls_extension &&
|
||||
+ s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
|
||||
+ s->tls_extension->data)
|
||||
+ {
|
||||
+ ticklen = s->tls_extension->length;
|
||||
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
|
||||
+ if (!s->session->tlsext_tick)
|
||||
+ return NULL;
|
||||
+ memcpy(s->session->tlsext_tick, s->tls_extension->data,
|
||||
+ ticklen);
|
||||
+ s->session->tlsext_ticklen = ticklen;
|
||||
+ }
|
||||
else
|
||||
ticklen = 0;
|
||||
+ if (ticklen == 0 && s->tls_extension &&
|
||||
+ s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
|
||||
+ s->tls_extension->data == NULL)
|
||||
+ goto skip_ext;
|
||||
/* Check for enough room 2 for extension type, 2 for len
|
||||
* rest for ticket
|
||||
*/
|
||||
@@ -190,6 +212,7 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
ret += ticklen;
|
||||
}
|
||||
}
|
||||
+ skip_ext:
|
||||
|
||||
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
|
||||
{
|
||||
@@ -774,6 +797,8 @@ int tls1_process_ticket(SSL *s, unsigned
|
||||
s->tlsext_ticket_expected = 1;
|
||||
return 0; /* Cache miss */
|
||||
}
|
||||
+ if (s->tls_session_secret_cb)
|
||||
+ return 0;
|
||||
return tls_decrypt_ticket(s, p, size, session_id, len,
|
||||
ret);
|
||||
}
|
||||
diff -upr openssl-0.9.8h.orig/ssl/tls1.h openssl-0.9.8h/ssl/tls1.h
|
||||
--- openssl-0.9.8h.orig/ssl/tls1.h 2008-04-30 19:11:33.000000000 +0300
|
||||
+++ openssl-0.9.8h/ssl/tls1.h 2008-05-28 18:49:34.000000000 +0300
|
||||
@@ -398,6 +398,14 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_extension_st
|
||||
+{
|
||||
+ unsigned short type;
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+};
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -upr openssl-0.9.8h.orig/util/ssleay.num openssl-0.9.8h/util/ssleay.num
|
||||
--- openssl-0.9.8h.orig/util/ssleay.num 2007-08-13 01:31:16.000000000 +0300
|
||||
+++ openssl-0.9.8h/util/ssleay.num 2008-05-28 18:49:34.000000000 +0300
|
||||
@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb
|
||||
SSL_set_SSL_CTX 290 EXIST::FUNCTION:
|
||||
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
|
||||
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
|
||||
+SSL_set_hello_extension 305 EXIST::FUNCTION:TLSEXT
|
||||
+SSL_set_session_secret_cb 306 EXIST::FUNCTION:TLSEXT
|
|
@ -1,404 +0,0 @@
|
|||
This patch adds support for TLS SessionTicket extension (RFC 5077) for
|
||||
the parts used by EAP-FAST (RFC 4851).
|
||||
|
||||
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
|
||||
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
|
||||
|
||||
OpenSSL 0.9.8i does not enable TLS extension support by default, so it
|
||||
will need to be enabled by adding enable-tlsext to config script
|
||||
command line.
|
||||
|
||||
|
||||
Index: openssl-0.9.8i/ssl/s3_clnt.c
|
||||
===================================================================
|
||||
--- openssl-0.9.8i.orig/ssl/s3_clnt.c 2008-06-16 19:56:41.000000000 +0300
|
||||
+++ openssl-0.9.8i/ssl/s3_clnt.c 2008-11-23 20:39:40.000000000 +0200
|
||||
@@ -759,6 +759,21 @@
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ /* check if we want to resume the session based on external pre-shared secret */
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->session->cipher=pref_cipher ?
|
||||
+ pref_cipher : ssl_get_cipher_by_char(s,p+j);
|
||||
+ }
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
if (j != 0 && j == s->session->session_id_length
|
||||
&& memcmp(p,s->session->session_id,j) == 0)
|
||||
{
|
||||
@@ -2701,11 +2716,8 @@
|
||||
{
|
||||
int ok;
|
||||
long n;
|
||||
- /* If we have no ticket or session ID is non-zero length (a match of
|
||||
- * a non-zero session length would never reach here) it cannot be a
|
||||
- * resumed session.
|
||||
- */
|
||||
- if (!s->session->tlsext_tick || s->session->session_id_length)
|
||||
+ /* If we have no ticket it cannot be a resumed session. */
|
||||
+ if (!s->session->tlsext_tick)
|
||||
return 1;
|
||||
/* this function is called when we really expect a Certificate
|
||||
* message, so permit appropriate message length */
|
||||
Index: openssl-0.9.8i/ssl/s3_srvr.c
|
||||
===================================================================
|
||||
--- openssl-0.9.8i.orig/ssl/s3_srvr.c 2008-09-14 21:16:09.000000000 +0300
|
||||
+++ openssl-0.9.8i/ssl/s3_srvr.c 2008-11-23 20:37:40.000000000 +0200
|
||||
@@ -959,6 +959,59 @@
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
|
||||
goto err;
|
||||
}
|
||||
+
|
||||
+ /* Check if we want to use external pre-shared secret for this
|
||||
+ * handshake for not reused session only. We need to generate
|
||||
+ * server_random before calling tls_session_secret_cb in order to allow
|
||||
+ * SessionTicket processing to use it in key derivation. */
|
||||
+ {
|
||||
+ unsigned long Time;
|
||||
+ unsigned char *pos;
|
||||
+ Time=(unsigned long)time(NULL); /* Time */
|
||||
+ pos=s->s3->server_random;
|
||||
+ l2n(Time,pos);
|
||||
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
+ {
|
||||
+ al=SSL_AD_INTERNAL_ERROR;
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->ciphers=ciphers;
|
||||
+ s->session->verify_result=X509_V_OK;
|
||||
+
|
||||
+ ciphers=NULL;
|
||||
+
|
||||
+ /* check if some cipher was preferred by call back */
|
||||
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
|
||||
+ if (pref_cipher == NULL)
|
||||
+ {
|
||||
+ al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+
|
||||
+ s->session->cipher=pref_cipher;
|
||||
+
|
||||
+ if (s->cipher_list)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list);
|
||||
+
|
||||
+ if (s->cipher_list_by_id)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||
+
|
||||
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ }
|
||||
+ }
|
||||
#endif
|
||||
/* Worst case, we will use the NULL compression, but if we have other
|
||||
* options, we will now look for them. We have i-1 compression
|
||||
@@ -1097,16 +1150,22 @@
|
||||
unsigned char *buf;
|
||||
unsigned char *p,*d;
|
||||
int i,sl;
|
||||
- unsigned long l,Time;
|
||||
+ unsigned long l;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
+ unsigned long Time;
|
||||
+#endif
|
||||
|
||||
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
|
||||
{
|
||||
buf=(unsigned char *)s->init_buf->data;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
p=s->s3->server_random;
|
||||
+ /* Generate server_random if it was not needed previously */
|
||||
Time=(unsigned long)time(NULL); /* Time */
|
||||
l2n(Time,p);
|
||||
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
return -1;
|
||||
+#endif
|
||||
/* Do the message type and length last */
|
||||
d=p= &(buf[4]);
|
||||
|
||||
Index: openssl-0.9.8i/ssl/ssl_err.c
|
||||
===================================================================
|
||||
--- openssl-0.9.8i.orig/ssl/ssl_err.c 2008-08-13 22:44:44.000000000 +0300
|
||||
+++ openssl-0.9.8i/ssl/ssl_err.c 2008-11-23 20:33:43.000000000 +0200
|
||||
@@ -253,6 +253,7 @@
|
||||
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
|
||||
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
|
||||
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
|
||||
+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
Index: openssl-0.9.8i/ssl/ssl.h
|
||||
===================================================================
|
||||
--- openssl-0.9.8i.orig/ssl/ssl.h 2008-08-13 22:44:44.000000000 +0300
|
||||
+++ openssl-0.9.8i/ssl/ssl.h 2008-11-23 20:35:41.000000000 +0200
|
||||
@@ -344,6 +344,7 @@
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -362,6 +363,9 @@
|
||||
|
||||
DECLARE_STACK_OF(SSL_CIPHER)
|
||||
|
||||
+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -1034,6 +1038,18 @@
|
||||
|
||||
/* RFC4507 session ticket expected to be received or sent */
|
||||
int tlsext_ticket_expected;
|
||||
+
|
||||
+ /* TLS Session Ticket extension override */
|
||||
+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
|
||||
+
|
||||
+ /* TLS Session Ticket extension callback */
|
||||
+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
|
||||
+ void *tls_session_ticket_ext_cb_arg;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
+
|
||||
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
|
||||
#define session_ctx initial_ctx
|
||||
#else
|
||||
@@ -1632,6 +1648,15 @@
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
|
||||
+
|
||||
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
|
||||
+ void *arg);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1824,6 +1849,7 @@
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
Index: openssl-0.9.8i/ssl/ssl_sess.c
|
||||
===================================================================
|
||||
--- openssl-0.9.8i.orig/ssl/ssl_sess.c 2008-06-04 21:35:27.000000000 +0300
|
||||
+++ openssl-0.9.8i/ssl/ssl_sess.c 2008-11-23 20:32:24.000000000 +0200
|
||||
@@ -707,6 +707,61 @@
|
||||
return(s->session_timeout);
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
|
||||
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
|
||||
+ {
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_secret_cb = tls_session_secret_cb;
|
||||
+ s->tls_session_secret_cb_arg = arg;
|
||||
+ return(1);
|
||||
+ }
|
||||
+
|
||||
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
|
||||
+ void *arg)
|
||||
+ {
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_ticket_ext_cb = cb;
|
||||
+ s->tls_session_ticket_ext_cb_arg = arg;
|
||||
+ return(1);
|
||||
+ }
|
||||
+
|
||||
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
|
||||
+ {
|
||||
+ if (s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if (s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tlsext_session_ticket);
|
||||
+ s->tlsext_session_ticket = NULL;
|
||||
+ }
|
||||
+
|
||||
+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
|
||||
+ if (!s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (ext_data)
|
||||
+ {
|
||||
+ s->tlsext_session_ticket->length = ext_len;
|
||||
+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
|
||||
+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ s->tlsext_session_ticket->length = 0;
|
||||
+ s->tlsext_session_ticket->data = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
typedef struct timeout_param_st
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
Index: openssl-0.9.8i/ssl/t1_lib.c
|
||||
===================================================================
|
||||
--- openssl-0.9.8i.orig/ssl/t1_lib.c 2008-09-04 01:13:04.000000000 +0300
|
||||
+++ openssl-0.9.8i/ssl/t1_lib.c 2008-11-23 20:31:20.000000000 +0200
|
||||
@@ -106,6 +106,12 @@
|
||||
|
||||
void tls1_free(SSL *s)
|
||||
{
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ if (s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tlsext_session_ticket);
|
||||
+ }
|
||||
+#endif
|
||||
ssl3_free(s);
|
||||
}
|
||||
|
||||
@@ -175,8 +181,23 @@
|
||||
int ticklen;
|
||||
if (s->session && s->session->tlsext_tick)
|
||||
ticklen = s->session->tlsext_ticklen;
|
||||
+ else if (s->session && s->tlsext_session_ticket &&
|
||||
+ s->tlsext_session_ticket->data)
|
||||
+ {
|
||||
+ ticklen = s->tlsext_session_ticket->length;
|
||||
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
|
||||
+ if (!s->session->tlsext_tick)
|
||||
+ return NULL;
|
||||
+ memcpy(s->session->tlsext_tick,
|
||||
+ s->tlsext_session_ticket->data,
|
||||
+ ticklen);
|
||||
+ s->session->tlsext_ticklen = ticklen;
|
||||
+ }
|
||||
else
|
||||
ticklen = 0;
|
||||
+ if (ticklen == 0 && s->tlsext_session_ticket &&
|
||||
+ s->tlsext_session_ticket->data == NULL)
|
||||
+ goto skip_ext;
|
||||
/* Check for enough room 2 for extension type, 2 for len
|
||||
* rest for ticket
|
||||
*/
|
||||
@@ -190,6 +211,7 @@
|
||||
ret += ticklen;
|
||||
}
|
||||
}
|
||||
+ skip_ext:
|
||||
|
||||
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
|
||||
{
|
||||
@@ -407,6 +429,15 @@
|
||||
}
|
||||
|
||||
}
|
||||
+ else if (type == TLSEXT_TYPE_session_ticket)
|
||||
+ {
|
||||
+ if (s->tls_session_ticket_ext_cb &&
|
||||
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
|
||||
+ {
|
||||
+ *al = TLS1_AD_INTERNAL_ERROR;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
else if (type == TLSEXT_TYPE_status_request
|
||||
&& s->ctx->tlsext_status_cb)
|
||||
{
|
||||
@@ -553,6 +584,12 @@
|
||||
}
|
||||
else if (type == TLSEXT_TYPE_session_ticket)
|
||||
{
|
||||
+ if (s->tls_session_ticket_ext_cb &&
|
||||
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
|
||||
+ {
|
||||
+ *al = TLS1_AD_INTERNAL_ERROR;
|
||||
+ return 0;
|
||||
+ }
|
||||
if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
|
||||
|| (size > 0))
|
||||
{
|
||||
@@ -776,6 +813,15 @@
|
||||
s->tlsext_ticket_expected = 1;
|
||||
return 0; /* Cache miss */
|
||||
}
|
||||
+ if (s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ /* Indicate cache miss here and instead of
|
||||
+ * generating the session from ticket now,
|
||||
+ * trigger abbreviated handshake based on
|
||||
+ * external mechanism to calculate the master
|
||||
+ * secret later. */
|
||||
+ return 0;
|
||||
+ }
|
||||
return tls_decrypt_ticket(s, p, size, session_id, len,
|
||||
ret);
|
||||
}
|
||||
Index: openssl-0.9.8i/ssl/tls1.h
|
||||
===================================================================
|
||||
--- openssl-0.9.8i.orig/ssl/tls1.h 2008-04-30 19:11:33.000000000 +0300
|
||||
+++ openssl-0.9.8i/ssl/tls1.h 2008-11-23 20:22:38.000000000 +0200
|
||||
@@ -398,6 +398,13 @@
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_session_ticket_ext_st
|
||||
+ {
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+ };
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Index: openssl-0.9.8i/util/ssleay.num
|
||||
===================================================================
|
||||
--- openssl-0.9.8i.orig/util/ssleay.num 2008-06-05 13:57:21.000000000 +0300
|
||||
+++ openssl-0.9.8i/util/ssleay.num 2008-11-23 20:22:05.000000000 +0200
|
||||
@@ -242,3 +242,5 @@
|
||||
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
|
||||
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
|
||||
SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE
|
||||
+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
|
||||
+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT
|
|
@ -1,396 +0,0 @@
|
|||
This patch adds support for TLS SessionTicket extension (RFC 5077) for
|
||||
the parts used by EAP-FAST (RFC 4851).
|
||||
|
||||
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
|
||||
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
|
||||
|
||||
OpenSSL 0.9.8x does not enable TLS extension support by default, so it
|
||||
will need to be enabled by adding enable-tlsext to config script
|
||||
command line.
|
||||
|
||||
|
||||
diff -upr openssl-0.9.8x.orig/ssl/s3_clnt.c openssl-0.9.8x/ssl/s3_clnt.c
|
||||
--- openssl-0.9.8x.orig/ssl/s3_clnt.c 2011-12-26 21:38:28.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/s3_clnt.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -757,6 +757,21 @@ int ssl3_get_server_hello(SSL *s)
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ /* check if we want to resume the session based on external pre-shared secret */
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->session->cipher=pref_cipher ?
|
||||
+ pref_cipher : ssl_get_cipher_by_char(s,p+j);
|
||||
+ }
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
if (j != 0 && j == s->session->session_id_length
|
||||
&& memcmp(p,s->session->session_id,j) == 0)
|
||||
{
|
||||
@@ -2725,11 +2740,8 @@ int ssl3_check_finished(SSL *s)
|
||||
{
|
||||
int ok;
|
||||
long n;
|
||||
- /* If we have no ticket or session ID is non-zero length (a match of
|
||||
- * a non-zero session length would never reach here) it cannot be a
|
||||
- * resumed session.
|
||||
- */
|
||||
- if (!s->session->tlsext_tick || s->session->session_id_length)
|
||||
+ /* If we have no ticket it cannot be a resumed session. */
|
||||
+ if (!s->session->tlsext_tick)
|
||||
return 1;
|
||||
/* this function is called when we really expect a Certificate
|
||||
* message, so permit appropriate message length */
|
||||
diff -upr openssl-0.9.8x.orig/ssl/s3_srvr.c openssl-0.9.8x/ssl/s3_srvr.c
|
||||
--- openssl-0.9.8x.orig/ssl/s3_srvr.c 2012-02-16 17:21:17.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/s3_srvr.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -1009,6 +1009,59 @@ int ssl3_get_client_hello(SSL *s)
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
|
||||
goto err;
|
||||
}
|
||||
+
|
||||
+ /* Check if we want to use external pre-shared secret for this
|
||||
+ * handshake for not reused session only. We need to generate
|
||||
+ * server_random before calling tls_session_secret_cb in order to allow
|
||||
+ * SessionTicket processing to use it in key derivation. */
|
||||
+ {
|
||||
+ unsigned long Time;
|
||||
+ unsigned char *pos;
|
||||
+ Time=(unsigned long)time(NULL); /* Time */
|
||||
+ pos=s->s3->server_random;
|
||||
+ l2n(Time,pos);
|
||||
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
+ {
|
||||
+ al=SSL_AD_INTERNAL_ERROR;
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->ciphers=ciphers;
|
||||
+ s->session->verify_result=X509_V_OK;
|
||||
+
|
||||
+ ciphers=NULL;
|
||||
+
|
||||
+ /* check if some cipher was preferred by call back */
|
||||
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
|
||||
+ if (pref_cipher == NULL)
|
||||
+ {
|
||||
+ al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+
|
||||
+ s->session->cipher=pref_cipher;
|
||||
+
|
||||
+ if (s->cipher_list)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list);
|
||||
+
|
||||
+ if (s->cipher_list_by_id)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||
+
|
||||
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ }
|
||||
+ }
|
||||
#endif
|
||||
/* Worst case, we will use the NULL compression, but if we have other
|
||||
* options, we will now look for them. We have i-1 compression
|
||||
@@ -1147,16 +1200,22 @@ int ssl3_send_server_hello(SSL *s)
|
||||
unsigned char *buf;
|
||||
unsigned char *p,*d;
|
||||
int i,sl;
|
||||
- unsigned long l,Time;
|
||||
+ unsigned long l;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
+ unsigned long Time;
|
||||
+#endif
|
||||
|
||||
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
|
||||
{
|
||||
buf=(unsigned char *)s->init_buf->data;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
p=s->s3->server_random;
|
||||
+ /* Generate server_random if it was not needed previously */
|
||||
Time=(unsigned long)time(NULL); /* Time */
|
||||
l2n(Time,p);
|
||||
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
return -1;
|
||||
+#endif
|
||||
/* Do the message type and length last */
|
||||
d=p= &(buf[4]);
|
||||
|
||||
diff -upr openssl-0.9.8x.orig/ssl/ssl_err.c openssl-0.9.8x/ssl/ssl_err.c
|
||||
--- openssl-0.9.8x.orig/ssl/ssl_err.c 2012-03-12 16:50:55.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/ssl_err.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -264,6 +264,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
||||
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
|
||||
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
|
||||
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
|
||||
+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
diff -upr openssl-0.9.8x.orig/ssl/ssl.h openssl-0.9.8x/ssl/ssl.h
|
||||
--- openssl-0.9.8x.orig/ssl/ssl.h 2012-03-12 16:50:55.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/ssl.h 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -344,6 +344,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -362,6 +363,9 @@ typedef struct ssl_cipher_st
|
||||
|
||||
DECLARE_STACK_OF(SSL_CIPHER)
|
||||
|
||||
+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -1050,6 +1054,18 @@ struct ssl_st
|
||||
|
||||
/* RFC4507 session ticket expected to be received or sent */
|
||||
int tlsext_ticket_expected;
|
||||
+
|
||||
+ /* TLS Session Ticket extension override */
|
||||
+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
|
||||
+
|
||||
+ /* TLS Session Ticket extension callback */
|
||||
+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
|
||||
+ void *tls_session_ticket_ext_cb_arg;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
+
|
||||
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
|
||||
#define session_ctx initial_ctx
|
||||
#else
|
||||
@@ -1663,6 +1679,15 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
|
||||
+
|
||||
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
|
||||
+ void *arg);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1866,6 +1891,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_ENC 210
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
diff -upr openssl-0.9.8x.orig/ssl/ssl_sess.c openssl-0.9.8x/ssl/ssl_sess.c
|
||||
--- openssl-0.9.8x.orig/ssl/ssl_sess.c 2010-02-01 18:48:40.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/ssl_sess.c 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -712,6 +712,61 @@ long SSL_CTX_get_timeout(const SSL_CTX *
|
||||
return(s->session_timeout);
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
|
||||
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
|
||||
+ {
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_secret_cb = tls_session_secret_cb;
|
||||
+ s->tls_session_secret_cb_arg = arg;
|
||||
+ return(1);
|
||||
+ }
|
||||
+
|
||||
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
|
||||
+ void *arg)
|
||||
+ {
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_ticket_ext_cb = cb;
|
||||
+ s->tls_session_ticket_ext_cb_arg = arg;
|
||||
+ return(1);
|
||||
+ }
|
||||
+
|
||||
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
|
||||
+ {
|
||||
+ if (s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if (s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tlsext_session_ticket);
|
||||
+ s->tlsext_session_ticket = NULL;
|
||||
+ }
|
||||
+
|
||||
+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
|
||||
+ if (!s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (ext_data)
|
||||
+ {
|
||||
+ s->tlsext_session_ticket->length = ext_len;
|
||||
+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
|
||||
+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ s->tlsext_session_ticket->length = 0;
|
||||
+ s->tlsext_session_ticket->data = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
typedef struct timeout_param_st
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
diff -upr openssl-0.9.8x.orig/ssl/t1_lib.c openssl-0.9.8x/ssl/t1_lib.c
|
||||
--- openssl-0.9.8x.orig/ssl/t1_lib.c 2012-01-04 16:25:10.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/t1_lib.c 2012-07-07 10:47:31.153140501 +0300
|
||||
@@ -106,6 +106,12 @@ int tls1_new(SSL *s)
|
||||
|
||||
void tls1_free(SSL *s)
|
||||
{
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ if (s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tlsext_session_ticket);
|
||||
+ }
|
||||
+#endif
|
||||
ssl3_free(s);
|
||||
}
|
||||
|
||||
@@ -206,8 +212,23 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
int ticklen;
|
||||
if (!s->new_session && s->session && s->session->tlsext_tick)
|
||||
ticklen = s->session->tlsext_ticklen;
|
||||
+ else if (s->session && s->tlsext_session_ticket &&
|
||||
+ s->tlsext_session_ticket->data)
|
||||
+ {
|
||||
+ ticklen = s->tlsext_session_ticket->length;
|
||||
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
|
||||
+ if (!s->session->tlsext_tick)
|
||||
+ return NULL;
|
||||
+ memcpy(s->session->tlsext_tick,
|
||||
+ s->tlsext_session_ticket->data,
|
||||
+ ticklen);
|
||||
+ s->session->tlsext_ticklen = ticklen;
|
||||
+ }
|
||||
else
|
||||
ticklen = 0;
|
||||
+ if (ticklen == 0 && s->tlsext_session_ticket &&
|
||||
+ s->tlsext_session_ticket->data == NULL)
|
||||
+ goto skip_ext;
|
||||
/* Check for enough room 2 for extension type, 2 for len
|
||||
* rest for ticket
|
||||
*/
|
||||
@@ -221,6 +242,7 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
ret += ticklen;
|
||||
}
|
||||
}
|
||||
+ skip_ext:
|
||||
|
||||
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
|
||||
s->version != DTLS1_VERSION)
|
||||
@@ -486,6 +508,15 @@ int ssl_parse_clienthello_tlsext(SSL *s,
|
||||
return 0;
|
||||
renegotiate_seen = 1;
|
||||
}
|
||||
+ else if (type == TLSEXT_TYPE_session_ticket)
|
||||
+ {
|
||||
+ if (s->tls_session_ticket_ext_cb &&
|
||||
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
|
||||
+ {
|
||||
+ *al = TLS1_AD_INTERNAL_ERROR;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
else if (type == TLSEXT_TYPE_status_request &&
|
||||
s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
|
||||
{
|
||||
@@ -663,6 +694,12 @@ int ssl_parse_serverhello_tlsext(SSL *s,
|
||||
}
|
||||
else if (type == TLSEXT_TYPE_session_ticket)
|
||||
{
|
||||
+ if (s->tls_session_ticket_ext_cb &&
|
||||
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
|
||||
+ {
|
||||
+ *al = TLS1_AD_INTERNAL_ERROR;
|
||||
+ return 0;
|
||||
+ }
|
||||
if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
|
||||
|| (size > 0))
|
||||
{
|
||||
@@ -920,6 +957,15 @@ int tls1_process_ticket(SSL *s, unsigned
|
||||
s->tlsext_ticket_expected = 1;
|
||||
return 0; /* Cache miss */
|
||||
}
|
||||
+ if (s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ /* Indicate cache miss here and instead of
|
||||
+ * generating the session from ticket now,
|
||||
+ * trigger abbreviated handshake based on
|
||||
+ * external mechanism to calculate the master
|
||||
+ * secret later. */
|
||||
+ return 0;
|
||||
+ }
|
||||
return tls_decrypt_ticket(s, p, size, session_id, len,
|
||||
ret);
|
||||
}
|
||||
diff -upr openssl-0.9.8x.orig/ssl/tls1.h openssl-0.9.8x/ssl/tls1.h
|
||||
--- openssl-0.9.8x.orig/ssl/tls1.h 2009-11-08 16:51:54.000000000 +0200
|
||||
+++ openssl-0.9.8x/ssl/tls1.h 2012-07-07 10:46:31.501140621 +0300
|
||||
@@ -401,6 +401,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS extension struct */
|
||||
+struct tls_session_ticket_ext_st
|
||||
+ {
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+ };
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -upr openssl-0.9.8x.orig/util/ssleay.num openssl-0.9.8x/util/ssleay.num
|
||||
--- openssl-0.9.8x.orig/util/ssleay.num 2008-06-05 13:57:21.000000000 +0300
|
||||
+++ openssl-0.9.8x/util/ssleay.num 2012-07-07 10:46:31.505140623 +0300
|
||||
@@ -242,3 +242,5 @@ SSL_set_SSL_CTX
|
||||
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
|
||||
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
|
||||
SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE
|
||||
+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
|
||||
+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT
|
|
@ -1,374 +0,0 @@
|
|||
This patch adds support for TLS SessionTicket extension (RFC 5077) for
|
||||
the parts used by EAP-FAST (RFC 4851).
|
||||
|
||||
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
|
||||
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
|
||||
|
||||
NOTE: This patch (without SSL_set_hello_extension() wrapper) was
|
||||
merged into the upstream OpenSSL 0.9.9 tree and as such, an external
|
||||
patch for EAP-FAST support is not needed anymore.
|
||||
|
||||
|
||||
|
||||
Index: openssl-SNAP-20081111/ssl/s3_clnt.c
|
||||
===================================================================
|
||||
--- openssl-SNAP-20081111.orig/ssl/s3_clnt.c
|
||||
+++ openssl-SNAP-20081111/ssl/s3_clnt.c
|
||||
@@ -788,6 +788,23 @@ int ssl3_get_server_hello(SSL *s)
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ /* check if we want to resume the session based on external pre-shared secret */
|
||||
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if (s->tls_session_secret_cb(s, s->session->master_key,
|
||||
+ &s->session->master_key_length,
|
||||
+ NULL, &pref_cipher,
|
||||
+ s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->session->cipher = pref_cipher ?
|
||||
+ pref_cipher : ssl_get_cipher_by_char(s, p+j);
|
||||
+ }
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
if (j != 0 && j == s->session->session_id_length
|
||||
&& memcmp(p,s->session->session_id,j) == 0)
|
||||
{
|
||||
@@ -2927,11 +2944,8 @@ static int ssl3_check_finished(SSL *s)
|
||||
{
|
||||
int ok;
|
||||
long n;
|
||||
- /* If we have no ticket or session ID is non-zero length (a match of
|
||||
- * a non-zero session length would never reach here) it cannot be a
|
||||
- * resumed session.
|
||||
- */
|
||||
- if (!s->session->tlsext_tick || s->session->session_id_length)
|
||||
+ /* If we have no ticket it cannot be a resumed session. */
|
||||
+ if (!s->session->tlsext_tick)
|
||||
return 1;
|
||||
/* this function is called when we really expect a Certificate
|
||||
* message, so permit appropriate message length */
|
||||
Index: openssl-SNAP-20081111/ssl/s3_srvr.c
|
||||
===================================================================
|
||||
--- openssl-SNAP-20081111.orig/ssl/s3_srvr.c
|
||||
+++ openssl-SNAP-20081111/ssl/s3_srvr.c
|
||||
@@ -1010,6 +1010,59 @@ int ssl3_get_client_hello(SSL *s)
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
|
||||
goto err;
|
||||
}
|
||||
+
|
||||
+ /* Check if we want to use external pre-shared secret for this
|
||||
+ * handshake for not reused session only. We need to generate
|
||||
+ * server_random before calling tls_session_secret_cb in order to allow
|
||||
+ * SessionTicket processing to use it in key derivation. */
|
||||
+ {
|
||||
+ unsigned long Time;
|
||||
+ unsigned char *pos;
|
||||
+ Time=(unsigned long)time(NULL); /* Time */
|
||||
+ pos=s->s3->server_random;
|
||||
+ l2n(Time,pos);
|
||||
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
+ {
|
||||
+ al=SSL_AD_INTERNAL_ERROR;
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ SSL_CIPHER *pref_cipher=NULL;
|
||||
+
|
||||
+ s->session->master_key_length=sizeof(s->session->master_key);
|
||||
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
|
||||
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
|
||||
+ {
|
||||
+ s->hit=1;
|
||||
+ s->session->ciphers=ciphers;
|
||||
+ s->session->verify_result=X509_V_OK;
|
||||
+
|
||||
+ ciphers=NULL;
|
||||
+
|
||||
+ /* check if some cipher was preferred by call back */
|
||||
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
|
||||
+ if (pref_cipher == NULL)
|
||||
+ {
|
||||
+ al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
||||
+ goto f_err;
|
||||
+ }
|
||||
+
|
||||
+ s->session->cipher=pref_cipher;
|
||||
+
|
||||
+ if (s->cipher_list)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list);
|
||||
+
|
||||
+ if (s->cipher_list_by_id)
|
||||
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||
+
|
||||
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
||||
+ }
|
||||
+ }
|
||||
#endif
|
||||
|
||||
/* Worst case, we will use the NULL compression, but if we have other
|
||||
@@ -1134,16 +1187,22 @@ int ssl3_send_server_hello(SSL *s)
|
||||
unsigned char *buf;
|
||||
unsigned char *p,*d;
|
||||
int i,sl;
|
||||
- unsigned long l,Time;
|
||||
+ unsigned long l;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
+ unsigned long Time;
|
||||
+#endif
|
||||
|
||||
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
|
||||
{
|
||||
buf=(unsigned char *)s->init_buf->data;
|
||||
+#ifdef OPENSSL_NO_TLSEXT
|
||||
p=s->s3->server_random;
|
||||
+ /* Generate server_random if it was not needed previously */
|
||||
Time=(unsigned long)time(NULL); /* Time */
|
||||
l2n(Time,p);
|
||||
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
|
||||
return -1;
|
||||
+#endif
|
||||
/* Do the message type and length last */
|
||||
d=p= &(buf[4]);
|
||||
|
||||
Index: openssl-SNAP-20081111/ssl/ssl_err.c
|
||||
===================================================================
|
||||
--- openssl-SNAP-20081111.orig/ssl/ssl_err.c
|
||||
+++ openssl-SNAP-20081111/ssl/ssl_err.c
|
||||
@@ -263,6 +263,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
||||
{ERR_FUNC(SSL_F_TLS1_PRF), "tls1_prf"},
|
||||
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
|
||||
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
|
||||
+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
Index: openssl-SNAP-20081111/ssl/ssl.h
|
||||
===================================================================
|
||||
--- openssl-SNAP-20081111.orig/ssl/ssl.h
|
||||
+++ openssl-SNAP-20081111/ssl/ssl.h
|
||||
@@ -355,6 +355,7 @@ extern "C" {
|
||||
* 'struct ssl_st *' function parameters used to prototype callbacks
|
||||
* in SSL_CTX. */
|
||||
typedef struct ssl_st *ssl_crock_st;
|
||||
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
|
||||
|
||||
/* used to hold info on the particular ciphers used */
|
||||
typedef struct ssl_cipher_st
|
||||
@@ -378,6 +379,8 @@ typedef struct ssl_cipher_st
|
||||
|
||||
DECLARE_STACK_OF(SSL_CIPHER)
|
||||
|
||||
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
|
||||
+
|
||||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
|
||||
typedef struct ssl_method_st
|
||||
{
|
||||
@@ -1145,6 +1148,13 @@ struct ssl_st
|
||||
void *tlsext_opaque_prf_input;
|
||||
size_t tlsext_opaque_prf_input_len;
|
||||
|
||||
+ /* TLS Session Ticket extension override */
|
||||
+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
|
||||
+
|
||||
+ /* TLS pre-shared secret session resumption */
|
||||
+ tls_session_secret_cb_fn tls_session_secret_cb;
|
||||
+ void *tls_session_secret_cb_arg;
|
||||
+
|
||||
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
|
||||
#define session_ctx initial_ctx
|
||||
#else
|
||||
@@ -1746,6 +1756,16 @@ void *SSL_COMP_get_compression_methods(v
|
||||
int SSL_COMP_add_compression_method(int id,void *cm);
|
||||
#endif
|
||||
|
||||
+/* NOTE: This function will be removed; it is only here for backwards
|
||||
+ * compatibility for the API during testing. */
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
|
||||
+
|
||||
+/* TLS extensions functions */
|
||||
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
|
||||
+
|
||||
+/* Pre-shared secret session resumption functions */
|
||||
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
|
||||
+
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
@@ -1948,6 +1968,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_PRF 284
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
Index: openssl-SNAP-20081111/ssl/ssl_sess.c
|
||||
===================================================================
|
||||
--- openssl-SNAP-20081111.orig/ssl/ssl_sess.c
|
||||
+++ openssl-SNAP-20081111/ssl/ssl_sess.c
|
||||
@@ -834,6 +834,62 @@ long SSL_CTX_get_timeout(const SSL_CTX *
|
||||
return(s->session_timeout);
|
||||
}
|
||||
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
|
||||
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
|
||||
+ {
|
||||
+ if (s == NULL) return(0);
|
||||
+ s->tls_session_secret_cb = tls_session_secret_cb;
|
||||
+ s->tls_session_secret_cb_arg = arg;
|
||||
+ return(1);
|
||||
+ }
|
||||
+
|
||||
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
|
||||
+ {
|
||||
+ if (s->version >= TLS1_VERSION)
|
||||
+ {
|
||||
+ if (s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tlsext_session_ticket);
|
||||
+ s->tlsext_session_ticket = NULL;
|
||||
+ }
|
||||
+
|
||||
+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
|
||||
+ if (!s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (ext_data)
|
||||
+ {
|
||||
+ s->tlsext_session_ticket->length = ext_len;
|
||||
+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
|
||||
+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ s->tlsext_session_ticket->length = 0;
|
||||
+ s->tlsext_session_ticket->data = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+/* NOTE: This function will be removed; it is only here for backwards
|
||||
+ * compatibility for the API during testing. */
|
||||
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
|
||||
+ {
|
||||
+ if (ext_type != TLSEXT_TYPE_session_ticket)
|
||||
+ return 0;
|
||||
+
|
||||
+ return SSL_set_session_ticket_ext(s, ext_data, ext_len);
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
+
|
||||
typedef struct timeout_param_st
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
Index: openssl-SNAP-20081111/ssl/t1_lib.c
|
||||
===================================================================
|
||||
--- openssl-SNAP-20081111.orig/ssl/t1_lib.c
|
||||
+++ openssl-SNAP-20081111/ssl/t1_lib.c
|
||||
@@ -154,6 +154,12 @@ int tls1_new(SSL *s)
|
||||
|
||||
void tls1_free(SSL *s)
|
||||
{
|
||||
+#ifndef OPENSSL_NO_TLSEXT
|
||||
+ if (s->tlsext_session_ticket)
|
||||
+ {
|
||||
+ OPENSSL_free(s->tlsext_session_ticket);
|
||||
+ }
|
||||
+#endif /* OPENSSL_NO_TLSEXT */
|
||||
ssl3_free(s);
|
||||
}
|
||||
|
||||
@@ -357,8 +363,23 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
int ticklen;
|
||||
if (s->session && s->session->tlsext_tick)
|
||||
ticklen = s->session->tlsext_ticklen;
|
||||
+ else if (s->session && s->tlsext_session_ticket &&
|
||||
+ s->tlsext_session_ticket->data)
|
||||
+ {
|
||||
+ ticklen = s->tlsext_session_ticket->length;
|
||||
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
|
||||
+ if (!s->session->tlsext_tick)
|
||||
+ return NULL;
|
||||
+ memcpy(s->session->tlsext_tick,
|
||||
+ s->tlsext_session_ticket->data,
|
||||
+ ticklen);
|
||||
+ s->session->tlsext_ticklen = ticklen;
|
||||
+ }
|
||||
else
|
||||
ticklen = 0;
|
||||
+ if (ticklen == 0 && s->tlsext_session_ticket &&
|
||||
+ s->tlsext_session_ticket->data == NULL)
|
||||
+ goto skip_ext;
|
||||
/* Check for enough room 2 for extension type, 2 for len
|
||||
* rest for ticket
|
||||
*/
|
||||
@@ -371,6 +392,7 @@ unsigned char *ssl_add_clienthello_tlsex
|
||||
ret += ticklen;
|
||||
}
|
||||
}
|
||||
+ skip_ext:
|
||||
|
||||
#ifdef TLSEXT_TYPE_opaque_prf_input
|
||||
if (s->s3->client_opaque_prf_input != NULL)
|
||||
@@ -1435,6 +1457,15 @@ int tls1_process_ticket(SSL *s, unsigned
|
||||
s->tlsext_ticket_expected = 1;
|
||||
return 0; /* Cache miss */
|
||||
}
|
||||
+ if (s->tls_session_secret_cb)
|
||||
+ {
|
||||
+ /* Indicate cache miss here and instead of
|
||||
+ * generating the session from ticket now,
|
||||
+ * trigger abbreviated handshake based on
|
||||
+ * external mechanism to calculate the master
|
||||
+ * secret later. */
|
||||
+ return 0;
|
||||
+ }
|
||||
return tls_decrypt_ticket(s, p, size, session_id, len,
|
||||
ret);
|
||||
}
|
||||
Index: openssl-SNAP-20081111/ssl/tls1.h
|
||||
===================================================================
|
||||
--- openssl-SNAP-20081111.orig/ssl/tls1.h
|
||||
+++ openssl-SNAP-20081111/ssl/tls1.h
|
||||
@@ -512,6 +512,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
|
||||
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
|
||||
#endif
|
||||
|
||||
+/* TLS Session Ticket extension struct */
|
||||
+struct tls_session_ticket_ext_st
|
||||
+ {
|
||||
+ unsigned short length;
|
||||
+ void *data;
|
||||
+ };
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Index: openssl-SNAP-20081111/util/ssleay.num
|
||||
===================================================================
|
||||
--- openssl-SNAP-20081111.orig/util/ssleay.num
|
||||
+++ openssl-SNAP-20081111/util/ssleay.num
|
||||
@@ -254,3 +254,5 @@ PEM_read_bio_SSL_SESSION
|
||||
SSL_CTX_set_psk_server_callback 303 EXIST::FUNCTION:PSK
|
||||
SSL_get_psk_identity 304 EXIST::FUNCTION:PSK
|
||||
PEM_write_SSL_SESSION 305 EXIST:!WIN16:FUNCTION:
|
||||
+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
|
||||
+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* IEEE 802.11 RSN / WPA Authenticator
|
||||
* Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -11,6 +11,7 @@
|
|||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "utils/state_machine.h"
|
||||
#include "utils/bitfield.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
@ -82,11 +83,14 @@ static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
|
|||
|
||||
|
||||
static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
|
||||
const u8 *addr, const u8 *prev_psk)
|
||||
const u8 *addr,
|
||||
const u8 *p2p_dev_addr,
|
||||
const u8 *prev_psk)
|
||||
{
|
||||
if (wpa_auth->cb.get_psk == NULL)
|
||||
return NULL;
|
||||
return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, prev_psk);
|
||||
return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, p2p_dev_addr,
|
||||
prev_psk);
|
||||
}
|
||||
|
||||
|
||||
|
@ -207,6 +211,8 @@ static int wpa_use_aes_cmac(struct wpa_state_machine *sm)
|
|||
if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt))
|
||||
ret = 1;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN)
|
||||
ret = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -282,8 +288,9 @@ static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
|
|||
static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_group *group)
|
||||
{
|
||||
u8 buf[ETH_ALEN + 8 + sizeof(group)];
|
||||
u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)];
|
||||
u8 rkey[32];
|
||||
unsigned long ptr;
|
||||
|
||||
if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0)
|
||||
return -1;
|
||||
|
@ -295,7 +302,8 @@ static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
|
|||
*/
|
||||
os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
|
||||
wpa_get_ntp_timestamp(buf + ETH_ALEN);
|
||||
os_memcpy(buf + ETH_ALEN + 8, &group, sizeof(group));
|
||||
ptr = (unsigned long) group;
|
||||
os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
|
||||
if (random_get_bytes(rkey, sizeof(rkey)) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -419,6 +427,17 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
|
|||
wpa_rekey_gtk, wpa_auth, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (WPA_GET_BE32(conf->ip_addr_start)) {
|
||||
int count = WPA_GET_BE32(conf->ip_addr_end) -
|
||||
WPA_GET_BE32(conf->ip_addr_start) + 1;
|
||||
if (count > 1000)
|
||||
count = 1000;
|
||||
if (count > 0)
|
||||
wpa_auth->ip_pool = bitfield_alloc(count);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
return wpa_auth;
|
||||
}
|
||||
|
||||
|
@ -432,6 +451,8 @@ int wpa_init_keys(struct wpa_authenticator *wpa_auth)
|
|||
wpa_group_sm_step(wpa_auth, group);
|
||||
group->GInit = FALSE;
|
||||
wpa_group_sm_step(wpa_auth, group);
|
||||
if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -459,6 +480,11 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
|
|||
wpa_auth->ft_pmk_cache = NULL;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
bitfield_free(wpa_auth->ip_pool);
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
|
||||
os_free(wpa_auth->wpa_ie);
|
||||
|
||||
group = wpa_auth->group;
|
||||
|
@ -506,14 +532,20 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth,
|
|||
|
||||
|
||||
struct wpa_state_machine *
|
||||
wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr)
|
||||
wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
||||
const u8 *p2p_dev_addr)
|
||||
{
|
||||
struct wpa_state_machine *sm;
|
||||
|
||||
if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
|
||||
return NULL;
|
||||
|
||||
sm = os_zalloc(sizeof(struct wpa_state_machine));
|
||||
if (sm == NULL)
|
||||
return NULL;
|
||||
os_memcpy(sm->addr, addr, ETH_ALEN);
|
||||
if (p2p_dev_addr)
|
||||
os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
|
||||
|
||||
sm->wpa_auth = wpa_auth;
|
||||
sm->group = wpa_auth->group;
|
||||
|
@ -533,6 +565,8 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
|
|||
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"FT authentication already completed - do not "
|
||||
"start 4-way handshake");
|
||||
/* Go to PTKINITDONE state to allow GTK rekeying */
|
||||
sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
@ -570,12 +604,26 @@ void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
|
|||
|
||||
static void wpa_free_sta_sm(struct wpa_state_machine *sm)
|
||||
{
|
||||
#ifdef CONFIG_P2P
|
||||
if (WPA_GET_BE32(sm->ip_addr)) {
|
||||
u32 start;
|
||||
wpa_printf(MSG_DEBUG, "P2P: Free assigned IP "
|
||||
"address %u.%u.%u.%u from " MACSTR,
|
||||
sm->ip_addr[0], sm->ip_addr[1],
|
||||
sm->ip_addr[2], sm->ip_addr[3],
|
||||
MAC2STR(sm->addr));
|
||||
start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start);
|
||||
bitfield_clear(sm->wpa_auth->ip_pool,
|
||||
WPA_GET_BE32(sm->ip_addr) - start);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
if (sm->GUpdateStationKeys) {
|
||||
sm->group->GKeyDoneStations--;
|
||||
sm->GUpdateStationKeys = FALSE;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
os_free(sm->assoc_resp_ftie);
|
||||
wpabuf_free(sm->ft_pending_req_ies);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
os_free(sm->last_rx_eapol_key);
|
||||
os_free(sm->wpa_ie);
|
||||
|
@ -835,6 +883,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
|||
if (sm->pairwise == WPA_CIPHER_CCMP ||
|
||||
sm->pairwise == WPA_CIPHER_GCMP) {
|
||||
if (wpa_use_aes_cmac(sm) &&
|
||||
sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN &&
|
||||
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
||||
wpa_auth_logger(wpa_auth, sm->addr,
|
||||
LOGGER_WARNING,
|
||||
|
@ -958,6 +1007,9 @@ continue_processing:
|
|||
if (kde.rsn_ie) {
|
||||
eapol_key_ie = kde.rsn_ie;
|
||||
eapol_key_ie_len = kde.rsn_ie_len;
|
||||
} else if (kde.osen) {
|
||||
eapol_key_ie = kde.osen;
|
||||
eapol_key_ie_len = kde.osen_len;
|
||||
} else {
|
||||
eapol_key_ie = kde.wpa_ie;
|
||||
eapol_key_ie_len = kde.wpa_ie_len;
|
||||
|
@ -987,6 +1039,26 @@ continue_processing:
|
|||
return;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_P2P
|
||||
if (kde.ip_addr_req && kde.ip_addr_req[0] &&
|
||||
wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
|
||||
int idx;
|
||||
wpa_printf(MSG_DEBUG, "P2P: IP address requested in "
|
||||
"EAPOL-Key exchange");
|
||||
idx = bitfield_get_first_zero(wpa_auth->ip_pool);
|
||||
if (idx >= 0) {
|
||||
u32 start = WPA_GET_BE32(wpa_auth->conf.
|
||||
ip_addr_start);
|
||||
bitfield_set(wpa_auth->ip_pool, idx);
|
||||
WPA_PUT_BE32(sm->ip_addr, start + idx);
|
||||
wpa_printf(MSG_DEBUG, "P2P: Assigned IP "
|
||||
"address %u.%u.%u.%u to " MACSTR,
|
||||
sm->ip_addr[0], sm->ip_addr[1],
|
||||
sm->ip_addr[2], sm->ip_addr[3],
|
||||
MAC2STR(sm->addr));
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
break;
|
||||
case PAIRWISE_4:
|
||||
if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
|
||||
|
@ -1223,6 +1295,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
|||
|
||||
if (force_version)
|
||||
version = force_version;
|
||||
else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN)
|
||||
version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
|
||||
else if (wpa_use_aes_cmac(sm))
|
||||
version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
|
||||
else if (sm->pairwise != WPA_CIPHER_TKIP)
|
||||
|
@ -1230,7 +1304,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
|||
else
|
||||
version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
|
||||
|
||||
pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
|
||||
pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d "
|
||||
"ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d "
|
||||
|
@ -1245,6 +1319,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
|||
key_data_len = kde_len;
|
||||
|
||||
if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
||||
sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
|
||||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
|
||||
pad_len = key_data_len % 8;
|
||||
if (pad_len)
|
||||
|
@ -1313,8 +1388,10 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
|||
wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
|
||||
buf, key_data_len);
|
||||
if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
||||
sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
|
||||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
||||
if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf,
|
||||
if (aes_wrap(sm->PTK.kek, 16,
|
||||
(key_data_len - 8) / 8, buf,
|
||||
(u8 *) (key + 1))) {
|
||||
os_free(hdr);
|
||||
os_free(buf);
|
||||
|
@ -1345,6 +1422,16 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
|||
}
|
||||
wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len,
|
||||
key->key_mic);
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (!pairwise &&
|
||||
wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 &&
|
||||
drand48() <
|
||||
wpa_auth->conf.corrupt_gtk_rekey_mic_probability) {
|
||||
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
|
||||
"Corrupting group EAPOL-Key Key MIC");
|
||||
key->key_mic[0]++;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
}
|
||||
|
||||
wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx,
|
||||
|
@ -1404,7 +1491,7 @@ static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len)
|
|||
os_memset(key->key_mic, 0, 16);
|
||||
if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK,
|
||||
data, data_len, key->key_mic) ||
|
||||
os_memcmp(mic, key->key_mic, 16) != 0)
|
||||
os_memcmp_const(mic, key->key_mic, 16) != 0)
|
||||
ret = -1;
|
||||
os_memcpy(key->key_mic, mic, 16);
|
||||
return ret;
|
||||
|
@ -1596,6 +1683,7 @@ SM_STATE(WPA_PTK, AUTHENTICATION2)
|
|||
SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
|
||||
|
||||
wpa_group_ensure_init(sm->wpa_auth, sm->group);
|
||||
sm->ReAuthenticationRequest = FALSE;
|
||||
|
||||
/*
|
||||
* Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
|
||||
|
@ -1609,12 +1697,11 @@ SM_STATE(WPA_PTK, AUTHENTICATION2)
|
|||
if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
|
||||
wpa_printf(MSG_ERROR, "WPA: Failed to get random data for "
|
||||
"ANonce.");
|
||||
wpa_sta_disconnect(sm->wpa_auth, sm->addr);
|
||||
sm->Disconnect = TRUE;
|
||||
return;
|
||||
}
|
||||
wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
|
||||
WPA_NONCE_LEN);
|
||||
sm->ReAuthenticationRequest = FALSE;
|
||||
/* IEEE 802.11i does not clear TimeoutCtr here, but this is more
|
||||
* logical place than INITIALIZE since AUTHENTICATION2 can be
|
||||
* re-entered on ReAuthenticationRequest without going through
|
||||
|
@ -1666,7 +1753,7 @@ SM_STATE(WPA_PTK, INITPSK)
|
|||
{
|
||||
const u8 *psk;
|
||||
SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
|
||||
psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL);
|
||||
psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL);
|
||||
if (psk) {
|
||||
os_memcpy(sm->PMK, psk, PMK_LEN);
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
|
@ -1701,7 +1788,8 @@ SM_STATE(WPA_PTK, PTKSTART)
|
|||
* one possible PSK for this STA.
|
||||
*/
|
||||
if (sm->wpa == WPA_VERSION_WPA2 &&
|
||||
wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt)) {
|
||||
wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
|
||||
sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
|
||||
pmkid = buf;
|
||||
pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
|
||||
pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
|
||||
|
@ -1729,7 +1817,7 @@ SM_STATE(WPA_PTK, PTKSTART)
|
|||
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk,
|
||||
struct wpa_ptk *ptk)
|
||||
{
|
||||
size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64;
|
||||
size_t ptk_len = wpa_cipher_key_len(sm->pairwise) + 32;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
|
||||
return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len);
|
||||
|
@ -1759,7 +1847,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
|
|||
* the packet */
|
||||
for (;;) {
|
||||
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
|
||||
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk);
|
||||
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
|
||||
sm->p2p_dev_addr, pmk);
|
||||
if (pmk == NULL)
|
||||
break;
|
||||
} else
|
||||
|
@ -1789,7 +1878,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
|
|||
* Verify that PMKR1Name from EAPOL-Key message 2/4 matches
|
||||
* with the value we derived.
|
||||
*/
|
||||
if (os_memcmp(sm->sup_pmk_r1_name, sm->pmk_r1_name,
|
||||
if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
|
||||
WPA_PMK_NAME_LEN) != 0) {
|
||||
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"PMKR1Name mismatch in FT 4-way "
|
||||
|
@ -1833,7 +1922,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
|
|||
static int ieee80211w_kde_len(struct wpa_state_machine *sm)
|
||||
{
|
||||
if (sm->mgmt_frame_prot) {
|
||||
return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde);
|
||||
size_t len;
|
||||
len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
|
||||
return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1844,6 +1935,8 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
|
|||
{
|
||||
struct wpa_igtk_kde igtk;
|
||||
struct wpa_group *gsm = sm->group;
|
||||
u8 rsc[WPA_KEY_RSC_LEN];
|
||||
size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
|
||||
|
||||
if (!sm->mgmt_frame_prot)
|
||||
return pos;
|
||||
|
@ -1851,19 +1944,22 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
|
|||
igtk.keyid[0] = gsm->GN_igtk;
|
||||
igtk.keyid[1] = 0;
|
||||
if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
|
||||
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) < 0)
|
||||
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
|
||||
os_memset(igtk.pn, 0, sizeof(igtk.pn));
|
||||
os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
|
||||
else
|
||||
os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
|
||||
os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
|
||||
if (sm->wpa_auth->conf.disable_gtk) {
|
||||
/*
|
||||
* Provide unique random IGTK to each STA to prevent use of
|
||||
* IGTK in the BSS.
|
||||
*/
|
||||
if (random_get_bytes(igtk.igtk, WPA_IGTK_LEN) < 0)
|
||||
if (random_get_bytes(igtk.igtk, len) < 0)
|
||||
return pos;
|
||||
}
|
||||
pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
|
||||
(const u8 *) &igtk, sizeof(igtk), NULL, 0);
|
||||
(const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
|
||||
NULL, 0);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
@ -1968,6 +2064,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
|||
kde_len += 300; /* FTIE + 2 * TIE */
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_P2P
|
||||
if (WPA_GET_BE32(sm->ip_addr) > 0)
|
||||
kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
|
||||
#endif /* CONFIG_P2P */
|
||||
kde = os_malloc(kde_len);
|
||||
if (kde == NULL)
|
||||
return;
|
||||
|
@ -2029,6 +2129,16 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
|||
pos += 4;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_P2P
|
||||
if (WPA_GET_BE32(sm->ip_addr) > 0) {
|
||||
u8 addr[3 * 4];
|
||||
os_memcpy(addr, sm->ip_addr, 4);
|
||||
os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4);
|
||||
os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4);
|
||||
pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
|
||||
addr, sizeof(addr), NULL, 0);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
wpa_send_eapol(sm->wpa_auth, sm,
|
||||
(secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC |
|
||||
|
@ -2146,7 +2256,8 @@ SM_STEP(WPA_PTK)
|
|||
}
|
||||
break;
|
||||
case WPA_PTK_INITPSK:
|
||||
if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL))
|
||||
if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr,
|
||||
NULL))
|
||||
SM_ENTER(WPA_PTK, PTKSTART);
|
||||
else {
|
||||
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
|
||||
|
@ -2354,15 +2465,16 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
|
|||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
size_t len;
|
||||
len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
|
||||
os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
|
||||
inc_byte_array(group->Counter, WPA_NONCE_LEN);
|
||||
if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
|
||||
wpa_auth->addr, group->GNonce,
|
||||
group->IGTK[group->GN_igtk - 4],
|
||||
WPA_IGTK_LEN) < 0)
|
||||
group->IGTK[group->GN_igtk - 4], len) < 0)
|
||||
ret = -1;
|
||||
wpa_hexdump_key(MSG_DEBUG, "IGTK",
|
||||
group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN);
|
||||
group->IGTK[group->GN_igtk - 4], len);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
@ -2429,7 +2541,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
|
|||
/* update GTK when exiting WNM-Sleep Mode */
|
||||
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
|
||||
{
|
||||
if (sm->is_wnmsleep)
|
||||
if (sm == NULL || sm->is_wnmsleep)
|
||||
return;
|
||||
|
||||
wpa_group_update_sta(sm, NULL);
|
||||
|
@ -2438,6 +2550,7 @@ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
|
|||
|
||||
void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
|
||||
{
|
||||
if (sm)
|
||||
sm->is_wnmsleep = !!flag;
|
||||
}
|
||||
|
||||
|
@ -2478,26 +2591,27 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
|
|||
{
|
||||
struct wpa_group *gsm = sm->group;
|
||||
u8 *start = pos;
|
||||
size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
|
||||
|
||||
/*
|
||||
* IGTK subelement:
|
||||
* Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
|
||||
*/
|
||||
*pos++ = WNM_SLEEP_SUBELEM_IGTK;
|
||||
*pos++ = 2 + 6 + WPA_IGTK_LEN;
|
||||
*pos++ = 2 + 6 + len;
|
||||
WPA_PUT_LE16(pos, gsm->GN_igtk);
|
||||
pos += 2;
|
||||
if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
|
||||
return 0;
|
||||
pos += 6;
|
||||
|
||||
os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
|
||||
pos += WPA_IGTK_LEN;
|
||||
os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
|
||||
pos += len;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
|
||||
gsm->GN_igtk);
|
||||
wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
|
||||
gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
|
||||
gsm->IGTK[gsm->GN_igtk - 4], len);
|
||||
|
||||
return pos - start;
|
||||
}
|
||||
|
@ -2552,18 +2666,48 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
|
|||
ret = -1;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION &&
|
||||
wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK,
|
||||
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
enum wpa_alg alg;
|
||||
size_t len;
|
||||
|
||||
alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher);
|
||||
len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
|
||||
|
||||
if (ret == 0 &&
|
||||
wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
|
||||
broadcast_ether_addr, group->GN_igtk,
|
||||
group->IGTK[group->GN_igtk - 4],
|
||||
WPA_IGTK_LEN) < 0)
|
||||
group->IGTK[group->GN_igtk - 4], len) < 0)
|
||||
ret = -1;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
|
||||
{
|
||||
if (sm->group == ctx) {
|
||||
wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
|
||||
" for discconnection due to fatal failure",
|
||||
MAC2STR(sm->addr));
|
||||
sm->Disconnect = TRUE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_group *group)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE");
|
||||
group->changed = TRUE;
|
||||
group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
|
||||
wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
|
||||
}
|
||||
|
||||
|
||||
static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_group *group)
|
||||
{
|
||||
|
@ -2572,8 +2716,10 @@ static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
|
|||
group->changed = TRUE;
|
||||
group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
|
||||
|
||||
if (wpa_group_config_group_keys(wpa_auth, group) < 0)
|
||||
if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
|
||||
wpa_group_fatal_failure(wpa_auth, group);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2584,6 +2730,8 @@ static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
|
|||
{
|
||||
if (group->GInit) {
|
||||
wpa_group_gtk_init(wpa_auth, group);
|
||||
} else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
|
||||
/* Do not allow group operations */
|
||||
} else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
|
||||
group->GTKAuthenticator) {
|
||||
wpa_group_setkeysdone(wpa_auth, group);
|
||||
|
@ -2932,6 +3080,22 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
|
|||
}
|
||||
|
||||
|
||||
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
|
||||
const u8 *sta_addr)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
|
||||
if (wpa_auth == NULL || wpa_auth->pmksa == NULL)
|
||||
return;
|
||||
pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
|
||||
if (pmksa) {
|
||||
wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
|
||||
MACSTR " based on request", MAC2STR(sta_addr));
|
||||
pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct wpa_group *
|
||||
wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
|
||||
{
|
||||
|
@ -2976,6 +3140,9 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
|
|||
if (sm->group == group)
|
||||
return 0;
|
||||
|
||||
if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
|
||||
return -1;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state "
|
||||
"machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id);
|
||||
|
||||
|
@ -3020,3 +3187,22 @@ int wpa_auth_uses_sae(struct wpa_state_machine *sm)
|
|||
return 0;
|
||||
return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
|
||||
}
|
||||
|
||||
|
||||
int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
|
||||
{
|
||||
if (sm == NULL)
|
||||
return 0;
|
||||
return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
|
||||
{
|
||||
if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0)
|
||||
return -1;
|
||||
os_memcpy(addr, sm->ip_addr, 4);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* FIPS 186-2 PRF for Microsoft CryptoAPI
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
|
||||
{
|
||||
/* FIX: how to do this with CryptoAPI? */
|
||||
return -1;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* FIPS 186-2 PRF for libgcrypt
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
|
||||
{
|
||||
/* FIX: how to do this with libgcrypt? */
|
||||
return -1;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* FIPS 186-2 PRF for NSS
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
|
@ -62,6 +62,9 @@ struct bsd_driver_data {
|
|||
int prev_roaming; /* roaming state to restore on deinit */
|
||||
int prev_privacy; /* privacy state to restore on deinit */
|
||||
int prev_wpa; /* wpa state to restore on deinit */
|
||||
enum ieee80211_opmode opmode; /* operation mode */
|
||||
char *event_buf;
|
||||
size_t event_buf_len;
|
||||
};
|
||||
|
||||
/* Generic functions for hostapd and wpa_supplicant */
|
||||
|
@ -266,10 +269,15 @@ bsd_ctrl_iface(void *priv, int enable)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
if (enable) {
|
||||
if (ifr.ifr_flags & IFF_UP)
|
||||
return 0;
|
||||
ifr.ifr_flags |= IFF_UP;
|
||||
else
|
||||
} else {
|
||||
if (!(ifr.ifr_flags & IFF_UP))
|
||||
return 0;
|
||||
ifr.ifr_flags &= ~IFF_UP;
|
||||
}
|
||||
|
||||
if (ioctl(drv->sock, SIOCSIFFLAGS, &ifr) < 0) {
|
||||
perror("ioctl[SIOCSIFFLAGS]");
|
||||
|
@ -285,6 +293,9 @@ bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
|
|||
size_t seq_len, const u8 *key, size_t key_len)
|
||||
{
|
||||
struct ieee80211req_key wk;
|
||||
#ifdef IEEE80211_KEY_NOREPLAY
|
||||
struct bsd_driver_data *drv = priv;
|
||||
#endif /* IEEE80211_KEY_NOREPLAY */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d "
|
||||
"seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx,
|
||||
|
@ -339,6 +350,16 @@ bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
|
|||
}
|
||||
if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
|
||||
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
|
||||
#ifndef HOSTAPD
|
||||
#ifdef IEEE80211_KEY_NOREPLAY
|
||||
/*
|
||||
* Ignore replay failures in IBSS and AHDEMO mode.
|
||||
*/
|
||||
if (drv->opmode == IEEE80211_M_IBSS ||
|
||||
drv->opmode == IEEE80211_M_AHDEMO)
|
||||
wk.ik_flags |= IEEE80211_KEY_NOREPLAY;
|
||||
#endif /* IEEE80211_KEY_NOREPLAY */
|
||||
#endif /* HOSTAPD */
|
||||
wk.ik_keylen = key_len;
|
||||
if (seq) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
|
@ -474,26 +495,6 @@ bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params)
|
|||
return bsd_ctrl_iface(priv, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
bsd_set_sta_authorized(void *priv, const u8 *addr,
|
||||
int total_flags, int flags_or, int flags_and)
|
||||
{
|
||||
int authorized = -1;
|
||||
|
||||
/* For now, only support setting Authorized flag */
|
||||
if (flags_or & WPA_STA_AUTHORIZED)
|
||||
authorized = 1;
|
||||
if (!(flags_and & WPA_STA_AUTHORIZED))
|
||||
authorized = 0;
|
||||
|
||||
if (authorized < 0)
|
||||
return 0;
|
||||
|
||||
return bsd_send_mlme_param(priv, authorized ?
|
||||
IEEE80211_MLME_AUTHORIZE :
|
||||
IEEE80211_MLME_UNAUTHORIZE, 0, addr);
|
||||
}
|
||||
|
||||
static void
|
||||
bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
|
@ -586,7 +587,7 @@ bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static size_t
|
||||
rtbuf_len(void)
|
||||
{
|
||||
size_t len;
|
||||
|
@ -726,37 +727,26 @@ static void
|
|||
bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
{
|
||||
struct bsd_driver_data *drv = ctx;
|
||||
char *buf;
|
||||
struct if_announcemsghdr *ifan;
|
||||
struct rt_msghdr *rtm;
|
||||
struct ieee80211_michael_event *mic;
|
||||
struct ieee80211_join_event *join;
|
||||
struct ieee80211_leave_event *leave;
|
||||
int n, len;
|
||||
int n;
|
||||
union wpa_event_data data;
|
||||
|
||||
len = rtbuf_len();
|
||||
|
||||
buf = os_malloc(len);
|
||||
if (buf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
n = read(sock, buf, len);
|
||||
n = read(sock, drv->event_buf, drv->event_buf_len);
|
||||
if (n < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
wpa_printf(MSG_ERROR, "%s read() failed: %s\n",
|
||||
__func__, strerror(errno));
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
rtm = (struct rt_msghdr *) buf;
|
||||
rtm = (struct rt_msghdr *) drv->event_buf;
|
||||
if (rtm->rtm_version != RTM_VERSION) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
|
||||
rtm->rtm_version);
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
ifan = (struct if_announcemsghdr *) rtm;
|
||||
|
@ -797,7 +787,6 @@ bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
|
|||
}
|
||||
break;
|
||||
}
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -814,7 +803,15 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
|
|||
|
||||
drv = os_zalloc(sizeof(struct bsd_driver_data));
|
||||
if (drv == NULL) {
|
||||
printf("Could not allocate memory for bsd driver data\n");
|
||||
wpa_printf(MSG_ERROR, "Could not allocate memory for bsd driver data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
drv->event_buf_len = rtbuf_len();
|
||||
|
||||
drv->event_buf = os_malloc(drv->event_buf_len);
|
||||
if (drv->event_buf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@ -858,6 +855,7 @@ bad:
|
|||
l2_packet_deinit(drv->sock_xmit);
|
||||
if (drv->sock >= 0)
|
||||
close(drv->sock);
|
||||
os_free(drv->event_buf);
|
||||
os_free(drv);
|
||||
}
|
||||
return NULL;
|
||||
|
@ -878,9 +876,37 @@ bsd_deinit(void *priv)
|
|||
close(drv->sock);
|
||||
if (drv->sock_xmit != NULL)
|
||||
l2_packet_deinit(drv->sock_xmit);
|
||||
os_free(drv->event_buf);
|
||||
os_free(drv);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
bsd_commit(void *priv)
|
||||
{
|
||||
return bsd_ctrl_iface(priv, 1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
bsd_set_sta_authorized(void *priv, const u8 *addr,
|
||||
int total_flags, int flags_or, int flags_and)
|
||||
{
|
||||
int authorized = -1;
|
||||
|
||||
/* For now, only support setting Authorized flag */
|
||||
if (flags_or & WPA_STA_AUTHORIZED)
|
||||
authorized = 1;
|
||||
if (!(flags_and & WPA_STA_AUTHORIZED))
|
||||
authorized = 0;
|
||||
|
||||
if (authorized < 0)
|
||||
return 0;
|
||||
|
||||
return bsd_send_mlme_param(priv, authorized ?
|
||||
IEEE80211_MLME_AUTHORIZE :
|
||||
IEEE80211_MLME_UNAUTHORIZE, 0, addr);
|
||||
}
|
||||
#else /* HOSTAPD */
|
||||
|
||||
static int
|
||||
|
@ -1058,9 +1084,9 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
|
|||
if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
|
||||
return -1;
|
||||
|
||||
privacy = !(params->pairwise_suite == CIPHER_NONE &&
|
||||
params->group_suite == CIPHER_NONE &&
|
||||
params->key_mgmt_suite == KEY_MGMT_NONE &&
|
||||
privacy = !(params->pairwise_suite == WPA_CIPHER_NONE &&
|
||||
params->group_suite == WPA_CIPHER_NONE &&
|
||||
params->key_mgmt_suite == WPA_KEY_MGMT_NONE &&
|
||||
params->wpa_ie_len == 0);
|
||||
wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
|
||||
|
||||
|
@ -1156,7 +1182,6 @@ static void
|
|||
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
{
|
||||
struct bsd_driver_data *drv = sock_ctx;
|
||||
char *buf;
|
||||
struct if_announcemsghdr *ifan;
|
||||
struct if_msghdr *ifm;
|
||||
struct rt_msghdr *rtm;
|
||||
|
@ -1164,30 +1189,20 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
|||
struct ieee80211_michael_event *mic;
|
||||
struct ieee80211_leave_event *leave;
|
||||
struct ieee80211_join_event *join;
|
||||
int n, len;
|
||||
int n;
|
||||
|
||||
len = rtbuf_len();
|
||||
|
||||
buf = os_malloc(len);
|
||||
if (buf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
n = read(sock, buf, len);
|
||||
n = read(sock, drv->event_buf, drv->event_buf_len);
|
||||
if (n < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
wpa_printf(MSG_ERROR, "%s read() failed: %s\n",
|
||||
__func__, strerror(errno));
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
rtm = (struct rt_msghdr *) buf;
|
||||
rtm = (struct rt_msghdr *) drv->event_buf;
|
||||
if (rtm->rtm_version != RTM_VERSION) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
|
||||
rtm->rtm_version);
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
os_memset(&event, 0, sizeof(event));
|
||||
|
@ -1206,7 +1221,6 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
|||
event.interface_status.ievent = EVENT_INTERFACE_ADDED;
|
||||
break;
|
||||
#else
|
||||
os_free(buf);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
@ -1331,7 +1345,6 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
|||
wpa_printf(MSG_DEBUG, "RTM_???: %d", rtm->rtm_type);
|
||||
break;
|
||||
}
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1356,6 +1369,11 @@ wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res,
|
|||
result->caps = sr->isr_capinfo;
|
||||
result->level = sr->isr_rssi;
|
||||
result->noise = sr->isr_noise;
|
||||
/*
|
||||
* the rssi value reported by the kernel is in 0.5dB steps relative to
|
||||
* the reported noise floor. see ieee80211_node.h for details.
|
||||
*/
|
||||
result->level = sr->isr_rssi / 2 + sr->isr_noise;
|
||||
|
||||
pos = (u8 *)(result + 1);
|
||||
|
||||
|
@ -1497,6 +1515,33 @@ static int wpa_driver_bsd_capa(struct bsd_driver_data *drv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static enum ieee80211_opmode
|
||||
get80211opmode(struct bsd_driver_data *drv)
|
||||
{
|
||||
struct ifmediareq ifmr;
|
||||
|
||||
(void) memset(&ifmr, 0, sizeof(ifmr));
|
||||
(void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name));
|
||||
|
||||
if (ioctl(drv->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
|
||||
if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
|
||||
if (ifmr.ifm_current & IFM_FLAG0)
|
||||
return IEEE80211_M_AHDEMO;
|
||||
else
|
||||
return IEEE80211_M_IBSS;
|
||||
}
|
||||
if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
|
||||
return IEEE80211_M_HOSTAP;
|
||||
if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
|
||||
return IEEE80211_M_MONITOR;
|
||||
#ifdef IEEE80211_M_MBSS
|
||||
if (ifmr.ifm_current & IFM_IEEE80211_MBSS)
|
||||
return IEEE80211_M_MBSS;
|
||||
#endif /* IEEE80211_M_MBSS */
|
||||
}
|
||||
return IEEE80211_M_STA;
|
||||
}
|
||||
|
||||
static void *
|
||||
wpa_driver_bsd_init(void *ctx, const char *ifname)
|
||||
{
|
||||
|
@ -1507,6 +1552,15 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
|
|||
drv = os_zalloc(sizeof(*drv));
|
||||
if (drv == NULL)
|
||||
return NULL;
|
||||
|
||||
drv->event_buf_len = rtbuf_len();
|
||||
|
||||
drv->event_buf = os_malloc(drv->event_buf_len);
|
||||
if (drv->event_buf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: We require the interface name be mappable to an index.
|
||||
* This implies we do not support having wpa_supplicant
|
||||
|
@ -1522,6 +1576,12 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
|
|||
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (drv->sock < 0)
|
||||
goto fail1;
|
||||
|
||||
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
|
||||
/* Down interface during setup. */
|
||||
if (bsd_ctrl_iface(drv, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (drv->route < 0)
|
||||
goto fail;
|
||||
|
@ -1529,11 +1589,6 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
|
|||
wpa_driver_bsd_event_receive, ctx, drv);
|
||||
|
||||
drv->ctx = ctx;
|
||||
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
|
||||
|
||||
/* Down interface during setup. */
|
||||
if (bsd_ctrl_iface(drv, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
|
||||
wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
|
||||
|
@ -1554,10 +1609,13 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
|
|||
if (wpa_driver_bsd_capa(drv))
|
||||
goto fail;
|
||||
|
||||
drv->opmode = get80211opmode(drv);
|
||||
|
||||
return drv;
|
||||
fail:
|
||||
close(drv->sock);
|
||||
fail1:
|
||||
os_free(drv->event_buf);
|
||||
os_free(drv);
|
||||
return NULL;
|
||||
#undef GETPARAM
|
||||
|
@ -1583,6 +1641,7 @@ wpa_driver_bsd_deinit(void *priv)
|
|||
l2_packet_deinit(drv->sock_xmit);
|
||||
(void) close(drv->route); /* ioctl socket */
|
||||
(void) close(drv->sock); /* event socket */
|
||||
os_free(drv->event_buf);
|
||||
os_free(drv);
|
||||
}
|
||||
|
||||
|
@ -1609,6 +1668,8 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
|
|||
.read_sta_data = bsd_read_sta_driver_data,
|
||||
.sta_disassoc = bsd_sta_disassoc,
|
||||
.sta_deauth = bsd_sta_deauth,
|
||||
.sta_set_flags = bsd_set_sta_authorized,
|
||||
.commit = bsd_commit,
|
||||
#else /* HOSTAPD */
|
||||
.init = wpa_driver_bsd_init,
|
||||
.deinit = wpa_driver_bsd_deinit,
|
||||
|
@ -1627,6 +1688,5 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
|
|||
.hapd_set_ssid = bsd_set_ssid,
|
||||
.hapd_get_ssid = bsd_get_ssid,
|
||||
.hapd_send_eapol = bsd_send_eapol,
|
||||
.sta_set_flags = bsd_set_sta_authorized,
|
||||
.set_generic_elem = bsd_set_opt_ie,
|
||||
};
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "common/ieee802_11_defs.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "l2_packet/l2_packet.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "wps/wps.h"
|
||||
#include "driver.h"
|
||||
|
||||
|
@ -102,20 +101,6 @@ struct wpa_driver_test_data {
|
|||
unsigned int remain_on_channel_duration;
|
||||
|
||||
int current_freq;
|
||||
|
||||
struct p2p_data *p2p;
|
||||
unsigned int off_channel_freq;
|
||||
struct wpabuf *pending_action_tx;
|
||||
u8 pending_action_src[ETH_ALEN];
|
||||
u8 pending_action_dst[ETH_ALEN];
|
||||
u8 pending_action_bssid[ETH_ALEN];
|
||||
unsigned int pending_action_freq;
|
||||
unsigned int pending_action_no_cck;
|
||||
unsigned int pending_listen_freq;
|
||||
unsigned int pending_listen_duration;
|
||||
int pending_p2p_scan;
|
||||
struct sockaddr *probe_from;
|
||||
socklen_t probe_from_len;
|
||||
};
|
||||
|
||||
|
||||
|
@ -125,7 +110,6 @@ static int wpa_driver_test_attach(struct wpa_driver_test_data *drv,
|
|||
static void wpa_driver_test_close_test_socket(
|
||||
struct wpa_driver_test_data *drv);
|
||||
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv);
|
||||
|
||||
|
||||
static void test_driver_free_bss(struct test_driver_bss *bss)
|
||||
|
@ -479,34 +463,6 @@ static int wpa_driver_test_send_mlme(void *priv, const u8 *data,
|
|||
event.tx_status.ack = ret >= 0;
|
||||
wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (drv->p2p &&
|
||||
WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
||||
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
|
||||
if (drv->pending_action_tx == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - "
|
||||
"no pending operation");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (os_memcmp(hdr->addr1, drv->pending_action_dst, ETH_ALEN) !=
|
||||
0) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - "
|
||||
"unknown destination address");
|
||||
return ret;
|
||||
}
|
||||
|
||||
wpabuf_free(drv->pending_action_tx);
|
||||
drv->pending_action_tx = NULL;
|
||||
|
||||
p2p_send_action_cb(drv->p2p, drv->pending_action_freq,
|
||||
drv->pending_action_dst,
|
||||
drv->pending_action_src,
|
||||
drv->pending_action_bssid,
|
||||
ret >= 0);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -553,10 +509,6 @@ static void test_driver_scan(struct wpa_driver_test_data *drv,
|
|||
event.rx_probe_req.ie = ie;
|
||||
event.rx_probe_req.ie_len = ielen;
|
||||
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event);
|
||||
#ifdef CONFIG_P2P
|
||||
if (drv->p2p)
|
||||
p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen);
|
||||
#endif /* CONFIG_P2P */
|
||||
}
|
||||
|
||||
dl_list_for_each(bss, &drv->bss, struct test_driver_bss, list) {
|
||||
|
@ -1059,7 +1011,7 @@ static int test_driver_if_add(void *priv, enum wpa_driver_if_type type,
|
|||
const char *ifname, const u8 *addr,
|
||||
void *bss_ctx, void **drv_priv,
|
||||
char *force_ifname, u8 *if_addr,
|
||||
const char *bridge)
|
||||
const char *bridge, int use_existing)
|
||||
{
|
||||
struct test_driver_bss *dbss = priv;
|
||||
struct wpa_driver_test_data *drv = dbss->drv;
|
||||
|
@ -1313,24 +1265,7 @@ static void wpa_driver_test_poll(void *eloop_ctx, void *timeout_ctx)
|
|||
|
||||
static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct wpa_driver_test_data *drv = eloop_ctx;
|
||||
wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
|
||||
if (drv->pending_p2p_scan && drv->p2p) {
|
||||
#ifdef CONFIG_P2P
|
||||
size_t i;
|
||||
for (i = 0; i < drv->num_scanres; i++) {
|
||||
struct wpa_scan_res *bss = drv->scanres[i];
|
||||
if (p2p_scan_res_handler(drv->p2p, bss->bssid,
|
||||
bss->freq, bss->age,
|
||||
bss->level,
|
||||
(const u8 *) (bss + 1),
|
||||
bss->ie_len) > 0)
|
||||
return;
|
||||
}
|
||||
p2p_scan_res_handled(drv->p2p);
|
||||
#endif /* CONFIG_P2P */
|
||||
return;
|
||||
}
|
||||
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
||||
}
|
||||
|
||||
|
@ -1543,7 +1478,7 @@ static int wpa_driver_test_associate(
|
|||
struct wpa_driver_test_data *drv = dbss->drv;
|
||||
wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
|
||||
"group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
|
||||
__func__, priv, params->freq, params->pairwise_suite,
|
||||
__func__, priv, params->freq.freq, params->pairwise_suite,
|
||||
params->group_suite, params->key_mgmt_suite,
|
||||
params->auth_alg, params->mode);
|
||||
wpa_driver_update_mode(drv, params->mode == IEEE80211_MODE_AP);
|
||||
|
@ -1594,6 +1529,7 @@ static int wpa_driver_test_associate(
|
|||
#endif /* DRIVER_TEST_UNIX */
|
||||
|
||||
if (params->mode == IEEE80211_MODE_AP) {
|
||||
if (params->ssid)
|
||||
os_memcpy(dbss->ssid, params->ssid, params->ssid_len);
|
||||
dbss->ssid_len = params->ssid_len;
|
||||
os_memcpy(dbss->bssid, drv->own_addr, ETH_ALEN);
|
||||
|
@ -1615,6 +1551,7 @@ static int wpa_driver_test_associate(
|
|||
MAC2STR(drv->own_addr));
|
||||
if (ret >= 0 && ret < end - pos)
|
||||
pos += ret;
|
||||
if (params->ssid)
|
||||
pos += wpa_snprintf_hex(pos, end - pos, params->ssid,
|
||||
params->ssid_len);
|
||||
ret = os_snprintf(pos, end - pos, " ");
|
||||
|
@ -1640,12 +1577,15 @@ static int wpa_driver_test_associate(
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (params->ssid)
|
||||
os_memcpy(dbss->ssid, params->ssid, params->ssid_len);
|
||||
dbss->ssid_len = params->ssid_len;
|
||||
} else {
|
||||
drv->associated = 1;
|
||||
if (params->mode == IEEE80211_MODE_IBSS) {
|
||||
os_memcpy(dbss->ssid, params->ssid, params->ssid_len);
|
||||
if (params->ssid)
|
||||
os_memcpy(dbss->ssid, params->ssid,
|
||||
params->ssid_len);
|
||||
dbss->ssid_len = params->ssid_len;
|
||||
if (params->bssid)
|
||||
os_memcpy(dbss->bssid, params->bssid,
|
||||
|
@ -1948,30 +1888,8 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
|
|||
data_len - (mgmt->u.probe_req.variable - data);
|
||||
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ,
|
||||
&event);
|
||||
#ifdef CONFIG_P2P
|
||||
if (drv->p2p)
|
||||
p2p_probe_req_rx(drv->p2p, mgmt->sa,
|
||||
mgmt->da, mgmt->bssid,
|
||||
event.rx_probe_req.ie,
|
||||
event.rx_probe_req.ie_len);
|
||||
#endif /* CONFIG_P2P */
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (drv->p2p &&
|
||||
WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
||||
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
|
||||
size_t hdr_len;
|
||||
hdr_len = (const u8 *)
|
||||
&mgmt->u.action.u.vs_public_action.action - data;
|
||||
p2p_rx_action(drv->p2p, mgmt->da, mgmt->sa, mgmt->bssid,
|
||||
mgmt->u.action.category,
|
||||
&mgmt->u.action.u.vs_public_action.action,
|
||||
data_len - hdr_len, freq);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1987,31 +1905,8 @@ static void wpa_driver_test_scan_cmd(struct wpa_driver_test_data *drv,
|
|||
bss = dl_list_first(&drv->bss, struct test_driver_bss, list);
|
||||
|
||||
/* data: optional [ STA-addr | ' ' | IEs(hex) ] */
|
||||
#ifdef CONFIG_P2P
|
||||
if (drv->probe_req_report && drv->p2p && data_len) {
|
||||
const char *d = (const char *) data;
|
||||
u8 sa[ETH_ALEN];
|
||||
u8 ie[512];
|
||||
size_t ielen;
|
||||
|
||||
if (hwaddr_aton(d, sa))
|
||||
return;
|
||||
d += 18;
|
||||
while (*d == ' ')
|
||||
d++;
|
||||
ielen = os_strlen(d) / 2;
|
||||
if (ielen > sizeof(ie))
|
||||
ielen = sizeof(ie);
|
||||
if (hexstr2bin(d, ie, ielen) < 0)
|
||||
ielen = 0;
|
||||
drv->probe_from = from;
|
||||
drv->probe_from_len = fromlen;
|
||||
p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen);
|
||||
drv->probe_from = NULL;
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (!drv->ibss)
|
||||
if (bss == NULL || !drv->ibss)
|
||||
return;
|
||||
|
||||
pos = buf;
|
||||
|
@ -2166,12 +2061,6 @@ static void wpa_driver_test_deinit(void *priv)
|
|||
struct test_client_socket *cli, *prev;
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (drv->p2p)
|
||||
p2p_deinit(drv->p2p);
|
||||
wpabuf_free(drv->pending_action_tx);
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
cli = drv->cli;
|
||||
while (cli) {
|
||||
prev = cli;
|
||||
|
@ -2368,13 +2257,6 @@ static int wpa_driver_test_set_param(void *priv, const char *param)
|
|||
drv->use_associnfo = 1;
|
||||
}
|
||||
|
||||
if (os_strstr(param, "p2p_mgmt=1")) {
|
||||
wpa_printf(MSG_DEBUG, "test_driver: Use internal P2P "
|
||||
"management");
|
||||
if (wpa_driver_test_init_p2p(drv) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2464,8 +2346,6 @@ static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto,
|
|||
|
||||
static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa)
|
||||
{
|
||||
struct test_driver_bss *dbss = priv;
|
||||
struct wpa_driver_test_data *drv = dbss->drv;
|
||||
os_memset(capa, 0, sizeof(*capa));
|
||||
capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
|
||||
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
|
||||
|
@ -2481,8 +2361,6 @@ static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa)
|
|||
capa->auth = WPA_DRIVER_AUTH_OPEN |
|
||||
WPA_DRIVER_AUTH_SHARED |
|
||||
WPA_DRIVER_AUTH_LEAP;
|
||||
if (drv->p2p)
|
||||
capa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT;
|
||||
capa->flags |= WPA_DRIVER_FLAGS_AP;
|
||||
capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
|
||||
capa->flags |= WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE;
|
||||
|
@ -2690,33 +2568,6 @@ static int wpa_driver_test_send_action(void *priv, unsigned int freq,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
static void test_send_action_cb(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct wpa_driver_test_data *drv = eloop_ctx;
|
||||
|
||||
if (drv->pending_action_tx == NULL)
|
||||
return;
|
||||
|
||||
if (drv->off_channel_freq != drv->pending_action_freq) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Pending Action frame TX "
|
||||
"waiting for another freq=%u",
|
||||
drv->pending_action_freq);
|
||||
return;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "P2P: Sending pending Action frame to "
|
||||
MACSTR, MAC2STR(drv->pending_action_dst));
|
||||
wpa_driver_test_send_action(drv, drv->pending_action_freq, 0,
|
||||
drv->pending_action_dst,
|
||||
drv->pending_action_src,
|
||||
drv->pending_action_bssid,
|
||||
wpabuf_head(drv->pending_action_tx),
|
||||
wpabuf_len(drv->pending_action_tx),
|
||||
drv->pending_action_no_cck);
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
|
||||
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct wpa_driver_test_data *drv = eloop_ctx;
|
||||
|
@ -2728,9 +2579,6 @@ static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx)
|
|||
data.remain_on_channel.freq = drv->remain_on_channel_freq;
|
||||
data.remain_on_channel.duration = drv->remain_on_channel_duration;
|
||||
|
||||
if (drv->p2p)
|
||||
drv->off_channel_freq = 0;
|
||||
|
||||
drv->remain_on_channel_freq = 0;
|
||||
|
||||
wpa_supplicant_event(drv->ctx, EVENT_CANCEL_REMAIN_ON_CHANNEL, &data);
|
||||
|
@ -2764,18 +2612,6 @@ static int wpa_driver_test_remain_on_channel(void *priv, unsigned int freq,
|
|||
data.remain_on_channel.duration = duration;
|
||||
wpa_supplicant_event(drv->ctx, EVENT_REMAIN_ON_CHANNEL, &data);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (drv->p2p) {
|
||||
drv->off_channel_freq = drv->remain_on_channel_freq;
|
||||
test_send_action_cb(drv, NULL);
|
||||
if (drv->off_channel_freq == drv->pending_listen_freq) {
|
||||
p2p_listen_cb(drv->p2p, drv->pending_listen_freq,
|
||||
drv->pending_listen_duration);
|
||||
drv->pending_listen_freq = 0;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2803,464 +2639,6 @@ static int wpa_driver_test_probe_req_report(void *priv, int report)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
|
||||
static int wpa_driver_test_p2p_find(void *priv, unsigned int timeout, int type)
|
||||
{
|
||||
struct test_driver_bss *dbss = priv;
|
||||
struct wpa_driver_test_data *drv = dbss->drv;
|
||||
wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout);
|
||||
if (!drv->p2p)
|
||||
return -1;
|
||||
return p2p_find(drv->p2p, timeout, type, 0, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
static int wpa_driver_test_p2p_stop_find(void *priv)
|
||||
{
|
||||
struct test_driver_bss *dbss = priv;
|
||||
struct wpa_driver_test_data *drv = dbss->drv;
|
||||
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||
if (!drv->p2p)
|
||||
return -1;
|
||||
p2p_stop_find(drv->p2p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_driver_test_p2p_listen(void *priv, unsigned int timeout)
|
||||
{
|
||||
struct test_driver_bss *dbss = priv;
|
||||
struct wpa_driver_test_data *drv = dbss->drv;
|
||||
wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout);
|
||||
if (!drv->p2p)
|
||||
return -1;
|
||||
return p2p_listen(drv->p2p, timeout);
|
||||
}
|
||||
|
||||
|
||||
static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr,
|
||||
int wps_method, int go_intent,
|
||||
const u8 *own_interface_addr,
|
||||
unsigned int force_freq,
|
||||
int persistent_group)
|
||||
{
|
||||
struct test_driver_bss *dbss = priv;
|
||||
struct wpa_driver_test_data *drv = dbss->drv;
|
||||
wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR " wps_method=%d "
|
||||
"go_intent=%d "
|
||||
"own_interface_addr=" MACSTR " force_freq=%u "
|
||||
"persistent_group=%d)",
|
||||
__func__, MAC2STR(peer_addr), wps_method, go_intent,
|
||||
MAC2STR(own_interface_addr), force_freq, persistent_group);
|
||||
if (!drv->p2p)
|
||||
return -1;
|
||||
return p2p_connect(drv->p2p, peer_addr, wps_method, go_intent,
|
||||
own_interface_addr, force_freq, persistent_group,
|
||||
NULL, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
static int wpa_driver_test_wps_success_cb(void *priv, const u8 *peer_addr)
|
||||
{
|
||||
struct test_driver_bss *dbss = priv;
|
||||
struct wpa_driver_test_data *drv = dbss->drv;
|
||||
wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR ")",
|
||||
__func__, MAC2STR(peer_addr));
|
||||
if (!drv->p2p)
|
||||
return -1;
|
||||
p2p_wps_success_cb(drv->p2p, peer_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_driver_test_p2p_group_formation_failed(void *priv)
|
||||
{
|
||||
struct test_driver_bss *dbss = priv;
|
||||
struct wpa_driver_test_data *drv = dbss->drv;
|
||||
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||
if (!drv->p2p)
|
||||
return -1;
|
||||
p2p_group_formation_failed(drv->p2p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_driver_test_p2p_set_params(void *priv,
|
||||
const struct p2p_params *params)
|
||||
{
|
||||
struct test_driver_bss *dbss = priv;
|
||||
struct wpa_driver_test_data *drv = dbss->drv;
|
||||
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||
if (!drv->p2p)
|
||||
return -1;
|
||||
if (p2p_set_dev_name(drv->p2p, params->dev_name) < 0 ||
|
||||
p2p_set_pri_dev_type(drv->p2p, params->pri_dev_type) < 0 ||
|
||||
p2p_set_sec_dev_types(drv->p2p, params->sec_dev_type,
|
||||
params->num_sec_dev_types) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
|
||||
unsigned int num_req_dev_types,
|
||||
const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
|
||||
{
|
||||
struct wpa_driver_test_data *drv = ctx;
|
||||
struct wpa_driver_scan_params params;
|
||||
int ret;
|
||||
struct wpabuf *wps_ie, *ies;
|
||||
int social_channels[] = { 2412, 2437, 2462, 0, 0 };
|
||||
size_t ielen;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s(type=%d freq=%d)",
|
||||
__func__, type, freq);
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
|
||||
/* P2P Wildcard SSID */
|
||||
params.num_ssids = 1;
|
||||
params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
|
||||
params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
|
||||
|
||||
#if 0 /* TODO: WPS IE */
|
||||
wpa_s->wps->dev.p2p = 1;
|
||||
wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
|
||||
wpa_s->wps->uuid, WPS_REQ_ENROLLEE);
|
||||
#else
|
||||
wps_ie = wpabuf_alloc(1);
|
||||
#endif
|
||||
if (wps_ie == NULL)
|
||||
return -1;
|
||||
|
||||
ielen = p2p_scan_ie_buf_len(drv->p2p);
|
||||
ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
|
||||
if (ies == NULL) {
|
||||
wpabuf_free(wps_ie);
|
||||
return -1;
|
||||
}
|
||||
wpabuf_put_buf(ies, wps_ie);
|
||||
wpabuf_free(wps_ie);
|
||||
|
||||
p2p_scan_ie(drv->p2p, ies, dev_id);
|
||||
|
||||
params.extra_ies = wpabuf_head(ies);
|
||||
params.extra_ies_len = wpabuf_len(ies);
|
||||
|
||||
switch (type) {
|
||||
case P2P_SCAN_SOCIAL:
|
||||
params.freqs = social_channels;
|
||||
break;
|
||||
case P2P_SCAN_FULL:
|
||||
break;
|
||||
case P2P_SCAN_SOCIAL_PLUS_ONE:
|
||||
social_channels[3] = freq;
|
||||
params.freqs = social_channels;
|
||||
break;
|
||||
}
|
||||
|
||||
drv->pending_p2p_scan = 1;
|
||||
ret = wpa_driver_test_scan(drv, ¶ms);
|
||||
|
||||
wpabuf_free(ies);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int test_send_action(void *ctx, unsigned int freq, const u8 *dst,
|
||||
const u8 *src, const u8 *bssid, const u8 *buf,
|
||||
size_t len, unsigned int wait_time)
|
||||
{
|
||||
struct wpa_driver_test_data *drv = ctx;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s(freq=%u dst=" MACSTR " src=" MACSTR
|
||||
" bssid=" MACSTR " len=%d",
|
||||
__func__, freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
|
||||
(int) len);
|
||||
if (freq <= 0) {
|
||||
wpa_printf(MSG_WARNING, "P2P: No frequency specified for "
|
||||
"action frame TX");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (drv->pending_action_tx) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Dropped pending Action frame TX "
|
||||
"to " MACSTR, MAC2STR(drv->pending_action_dst));
|
||||
wpabuf_free(drv->pending_action_tx);
|
||||
}
|
||||
drv->pending_action_tx = wpabuf_alloc(len);
|
||||
if (drv->pending_action_tx == NULL)
|
||||
return -1;
|
||||
wpabuf_put_data(drv->pending_action_tx, buf, len);
|
||||
os_memcpy(drv->pending_action_src, src, ETH_ALEN);
|
||||
os_memcpy(drv->pending_action_dst, dst, ETH_ALEN);
|
||||
os_memcpy(drv->pending_action_bssid, bssid, ETH_ALEN);
|
||||
drv->pending_action_freq = freq;
|
||||
drv->pending_action_no_cck = 1;
|
||||
|
||||
if (drv->off_channel_freq == freq) {
|
||||
/* Already on requested channel; send immediately */
|
||||
/* TODO: Would there ever be need to extend the current
|
||||
* duration on the channel? */
|
||||
eloop_cancel_timeout(test_send_action_cb, drv, NULL);
|
||||
eloop_register_timeout(0, 0, test_send_action_cb, drv, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "P2P: Schedule Action frame to be transmitted "
|
||||
"once the driver gets to the requested channel");
|
||||
if (wpa_driver_test_remain_on_channel(drv, freq, wait_time) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Failed to request driver "
|
||||
"to remain on channel (%u MHz) for Action "
|
||||
"Frame TX", freq);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void test_send_action_done(void *ctx)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
|
||||
static void test_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
|
||||
{
|
||||
struct wpa_driver_test_data *drv = ctx;
|
||||
union wpa_event_data event;
|
||||
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||
os_memset(&event, 0, sizeof(event));
|
||||
event.p2p_go_neg_completed.res = res;
|
||||
wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_COMPLETED, &event);
|
||||
}
|
||||
|
||||
|
||||
static void test_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id)
|
||||
{
|
||||
struct wpa_driver_test_data *drv = ctx;
|
||||
union wpa_event_data event;
|
||||
wpa_printf(MSG_DEBUG, "%s(src=" MACSTR ")", __func__, MAC2STR(src));
|
||||
os_memset(&event, 0, sizeof(event));
|
||||
event.p2p_go_neg_req_rx.src = src;
|
||||
event.p2p_go_neg_req_rx.dev_passwd_id = dev_passwd_id;
|
||||
wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_REQ_RX, &event);
|
||||
}
|
||||
|
||||
|
||||
static void test_dev_found(void *ctx, const u8 *addr,
|
||||
const struct p2p_peer_info *info, int new_device)
|
||||
{
|
||||
struct wpa_driver_test_data *drv = ctx;
|
||||
union wpa_event_data event;
|
||||
char devtype[WPS_DEV_TYPE_BUFSIZE];
|
||||
wpa_printf(MSG_DEBUG, "%s(" MACSTR " p2p_dev_addr=" MACSTR
|
||||
" pri_dev_type=%s name='%s' config_methods=0x%x "
|
||||
"dev_capab=0x%x group_capab=0x%x)",
|
||||
__func__, MAC2STR(addr), MAC2STR(info->p2p_device_addr),
|
||||
wps_dev_type_bin2str(info->pri_dev_type, devtype,
|
||||
sizeof(devtype)),
|
||||
info->device_name, info->config_methods, info->dev_capab,
|
||||
info->group_capab);
|
||||
|
||||
os_memset(&event, 0, sizeof(event));
|
||||
event.p2p_dev_found.addr = addr;
|
||||
event.p2p_dev_found.dev_addr = info->p2p_device_addr;
|
||||
event.p2p_dev_found.pri_dev_type = info->pri_dev_type;
|
||||
event.p2p_dev_found.dev_name = info->device_name;
|
||||
event.p2p_dev_found.config_methods = info->config_methods;
|
||||
event.p2p_dev_found.dev_capab = info->dev_capab;
|
||||
event.p2p_dev_found.group_capab = info->group_capab;
|
||||
wpa_supplicant_event(drv->ctx, EVENT_P2P_DEV_FOUND, &event);
|
||||
}
|
||||
|
||||
|
||||
static int test_start_listen(void *ctx, unsigned int freq,
|
||||
unsigned int duration,
|
||||
const struct wpabuf *probe_resp_ie)
|
||||
{
|
||||
struct wpa_driver_test_data *drv = ctx;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s(freq=%u duration=%u)",
|
||||
__func__, freq, duration);
|
||||
|
||||
if (wpa_driver_test_probe_req_report(drv, 1) < 0)
|
||||
return -1;
|
||||
|
||||
drv->pending_listen_freq = freq;
|
||||
drv->pending_listen_duration = duration;
|
||||
|
||||
if (wpa_driver_test_remain_on_channel(drv, freq, duration) < 0) {
|
||||
drv->pending_listen_freq = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void test_stop_listen(void *ctx)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
|
||||
static int test_send_probe_resp(void *ctx, const struct wpabuf *buf)
|
||||
{
|
||||
struct wpa_driver_test_data *drv = ctx;
|
||||
char resp[512], *pos, *end;
|
||||
int ret;
|
||||
const struct ieee80211_mgmt *mgmt;
|
||||
const u8 *ie, *ie_end;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||
wpa_hexdump_buf(MSG_MSGDUMP, "Probe Response", buf);
|
||||
if (wpabuf_len(buf) < 24)
|
||||
return -1;
|
||||
if (!drv->probe_from) {
|
||||
wpa_printf(MSG_DEBUG, "%s: probe_from not set", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = resp;
|
||||
end = resp + sizeof(resp);
|
||||
|
||||
mgmt = wpabuf_head(buf);
|
||||
|
||||
/* reply: SCANRESP BSSID SSID IEs */
|
||||
ret = os_snprintf(pos, end - pos, "SCANRESP " MACSTR " ",
|
||||
MAC2STR(mgmt->bssid));
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return -1;
|
||||
pos += ret;
|
||||
|
||||
ie = mgmt->u.probe_resp.variable;
|
||||
ie_end = wpabuf_head_u8(buf) + wpabuf_len(buf);
|
||||
if (ie_end - ie < 2 || ie[0] != WLAN_EID_SSID ||
|
||||
ie + 2 + ie[1] > ie_end)
|
||||
return -1;
|
||||
pos += wpa_snprintf_hex(pos, end - pos, ie + 2, ie[1]);
|
||||
|
||||
ret = os_snprintf(pos, end - pos, " ");
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return -1;
|
||||
pos += ret;
|
||||
pos += wpa_snprintf_hex(pos, end - pos, ie, ie_end - ie);
|
||||
|
||||
sendto(drv->test_socket, resp, pos - resp, 0,
|
||||
drv->probe_from, drv->probe_from_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void test_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
|
||||
u16 update_indic, const u8 *tlvs, size_t tlvs_len)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
|
||||
static void test_sd_response(void *ctx, const u8 *sa, u16 update_indic,
|
||||
const u8 *tlvs, size_t tlvs_len)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
|
||||
static void test_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
|
||||
const u8 *dev_addr, const u8 *pri_dev_type,
|
||||
const char *dev_name, u16 supp_config_methods,
|
||||
u8 dev_capab, u8 group_capab,
|
||||
const u8 *group_id, size_t group_id_len)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)",
|
||||
__func__, MAC2STR(peer), config_methods);
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
|
||||
static void test_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)",
|
||||
__func__, MAC2STR(peer), config_methods);
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
|
||||
static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv)
|
||||
{
|
||||
#ifdef CONFIG_P2P
|
||||
struct p2p_config p2p;
|
||||
unsigned int r;
|
||||
int i;
|
||||
|
||||
os_memset(&p2p, 0, sizeof(p2p));
|
||||
p2p.msg_ctx = drv->ctx;
|
||||
p2p.cb_ctx = drv;
|
||||
p2p.p2p_scan = test_p2p_scan;
|
||||
p2p.send_action = test_send_action;
|
||||
p2p.send_action_done = test_send_action_done;
|
||||
p2p.go_neg_completed = test_go_neg_completed;
|
||||
p2p.go_neg_req_rx = test_go_neg_req_rx;
|
||||
p2p.dev_found = test_dev_found;
|
||||
p2p.start_listen = test_start_listen;
|
||||
p2p.stop_listen = test_stop_listen;
|
||||
p2p.send_probe_resp = test_send_probe_resp;
|
||||
p2p.sd_request = test_sd_request;
|
||||
p2p.sd_response = test_sd_response;
|
||||
p2p.prov_disc_req = test_prov_disc_req;
|
||||
p2p.prov_disc_resp = test_prov_disc_resp;
|
||||
|
||||
os_memcpy(p2p.dev_addr, drv->own_addr, ETH_ALEN);
|
||||
|
||||
p2p.reg_class = 12; /* TODO: change depending on location */
|
||||
/*
|
||||
* Pick one of the social channels randomly as the listen
|
||||
* channel.
|
||||
*/
|
||||
os_get_random((u8 *) &r, sizeof(r));
|
||||
p2p.channel = 1 + (r % 3) * 5;
|
||||
|
||||
/* TODO: change depending on location */
|
||||
p2p.op_reg_class = 12;
|
||||
/*
|
||||
* For initial tests, pick the operation channel randomly.
|
||||
* TODO: Use scan results (etc.) to select the best channel.
|
||||
*/
|
||||
p2p.op_channel = 1 + r % 11;
|
||||
|
||||
os_memcpy(p2p.country, "US ", 3);
|
||||
|
||||
/* FIX: fetch available channels from the driver */
|
||||
p2p.channels.reg_classes = 1;
|
||||
p2p.channels.reg_class[0].reg_class = 12; /* US/12 = 2.4 GHz band */
|
||||
p2p.channels.reg_class[0].channels = 11;
|
||||
for (i = 0; i < 11; i++)
|
||||
p2p.channels.reg_class[0].channel[i] = i + 1;
|
||||
|
||||
p2p.max_peers = 100;
|
||||
|
||||
drv->p2p = p2p_init(&p2p);
|
||||
if (drv->p2p == NULL)
|
||||
return -1;
|
||||
return 0;
|
||||
#else /* CONFIG_P2P */
|
||||
wpa_printf(MSG_INFO, "driver_test: P2P support not included");
|
||||
return -1;
|
||||
#endif /* CONFIG_P2P */
|
||||
}
|
||||
|
||||
|
||||
const struct wpa_driver_ops wpa_driver_test_ops = {
|
||||
"test",
|
||||
"wpa_supplicant test driver",
|
||||
|
@ -3302,14 +2680,4 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
|
|||
.remain_on_channel = wpa_driver_test_remain_on_channel,
|
||||
.cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel,
|
||||
.probe_req_report = wpa_driver_test_probe_req_report,
|
||||
#ifdef CONFIG_P2P
|
||||
.p2p_find = wpa_driver_test_p2p_find,
|
||||
.p2p_stop_find = wpa_driver_test_p2p_stop_find,
|
||||
.p2p_listen = wpa_driver_test_p2p_listen,
|
||||
.p2p_connect = wpa_driver_test_p2p_connect,
|
||||
.wps_success_cb = wpa_driver_test_wps_success_cb,
|
||||
.p2p_group_formation_failed =
|
||||
wpa_driver_test_p2p_group_formation_failed,
|
||||
.p2p_set_params = wpa_driver_test_p2p_set_params,
|
||||
#endif /* CONFIG_P2P */
|
||||
};
|
||||
|
|
|
@ -25,14 +25,32 @@ struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
|
|||
return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS,
|
||||
EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len,
|
||||
code, identifier);
|
||||
else if (type == EAP_WFA_UNAUTH_TLS_TYPE)
|
||||
return eap_msg_alloc(EAP_VENDOR_WFA_NEW,
|
||||
EAP_VENDOR_WFA_UNAUTH_TLS, payload_len,
|
||||
code, identifier);
|
||||
return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code,
|
||||
identifier);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_TLS_INTERNAL
|
||||
static void eap_server_tls_log_cb(void *ctx, const char *msg)
|
||||
{
|
||||
struct eap_sm *sm = ctx;
|
||||
eap_log_msg(sm, "TLS: %s", msg);
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL */
|
||||
|
||||
|
||||
int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||
int verify_peer)
|
||||
{
|
||||
if (sm->ssl_ctx == NULL) {
|
||||
wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method");
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->eap = sm;
|
||||
data->phase2 = sm->init_phase2;
|
||||
|
||||
|
@ -43,6 +61,13 @@ int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TLS_INTERNAL
|
||||
tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm);
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
tls_connection_set_test_flags(data->conn, sm->tls_test_flags);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#endif /* CONFIG_TLS_INTERNAL */
|
||||
|
||||
if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) {
|
||||
wpa_printf(MSG_INFO, "SSL: Failed to configure verification "
|
||||
"of TLS peer certificate");
|
||||
|
@ -394,6 +419,10 @@ int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
|
|||
pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
|
||||
EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
|
||||
&left);
|
||||
else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
|
||||
pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
|
||||
EAP_VENDOR_WFA_UNAUTH_TLS, respData,
|
||||
&left);
|
||||
else
|
||||
pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData,
|
||||
&left);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RADIUS Dynamic Authorization Server (DAS) (RFC 5176)
|
||||
* Copyright (c) 2012, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -16,9 +16,6 @@
|
|||
#include "radius_das.h"
|
||||
|
||||
|
||||
extern int wpa_debug_level;
|
||||
|
||||
|
||||
struct radius_das_data {
|
||||
int sock;
|
||||
u8 *shared_secret;
|
||||
|
@ -41,11 +38,16 @@ static struct radius_msg * radius_das_disconnect(struct radius_das_data *das,
|
|||
struct radius_msg *reply;
|
||||
u8 allowed[] = {
|
||||
RADIUS_ATTR_USER_NAME,
|
||||
RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
RADIUS_ATTR_CALLING_STATION_ID,
|
||||
RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
RADIUS_ATTR_ACCT_SESSION_ID,
|
||||
RADIUS_ATTR_EVENT_TIMESTAMP,
|
||||
RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
|
||||
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
#ifdef CONFIG_IPV6
|
||||
RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
#endif /* CONFIG_IPV6 */
|
||||
0
|
||||
};
|
||||
int error = 405;
|
||||
|
@ -70,6 +72,36 @@ static struct radius_msg * radius_das_disconnect(struct radius_das_data *das,
|
|||
|
||||
os_memset(&attrs, 0, sizeof(attrs));
|
||||
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
&buf, &len, NULL) == 0) {
|
||||
if (len != 4) {
|
||||
wpa_printf(MSG_INFO, "DAS: Invalid NAS-IP-Address from %s:%d",
|
||||
abuf, from_port);
|
||||
error = 407;
|
||||
goto fail;
|
||||
}
|
||||
attrs.nas_ip_addr = buf;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
&buf, &len, NULL) == 0) {
|
||||
if (len != 16) {
|
||||
wpa_printf(MSG_INFO, "DAS: Invalid NAS-IPv6-Address from %s:%d",
|
||||
abuf, from_port);
|
||||
error = 407;
|
||||
goto fail;
|
||||
}
|
||||
attrs.nas_ipv6_addr = buf;
|
||||
}
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
&buf, &len, NULL) == 0) {
|
||||
attrs.nas_identifier = buf;
|
||||
attrs.nas_identifier_len = len;
|
||||
}
|
||||
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CALLING_STATION_ID,
|
||||
&buf, &len, NULL) == 0) {
|
||||
if (len >= sizeof(tmp))
|
||||
|
@ -284,7 +316,7 @@ static int radius_das_open_socket(int port)
|
|||
|
||||
s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
perror("socket");
|
||||
wpa_printf(MSG_INFO, "RADIUS DAS: socket: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -292,7 +324,7 @@ static int radius_das_open_socket(int port)
|
|||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
wpa_printf(MSG_INFO, "RADIUS DAS: bind: %s", strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -7,17 +7,28 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "trace.h"
|
||||
#include "list.h"
|
||||
#include "eloop.h"
|
||||
|
||||
#if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_EPOLL)
|
||||
#error Do not define both of poll and epoll
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL)
|
||||
#define CONFIG_ELOOP_SELECT
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ELOOP_POLL
|
||||
#include <assert.h>
|
||||
#include <poll.h>
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
#include <sys/epoll.h>
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
|
||||
struct eloop_sock {
|
||||
int sock;
|
||||
|
@ -31,7 +42,7 @@ struct eloop_sock {
|
|||
|
||||
struct eloop_timeout {
|
||||
struct dl_list list;
|
||||
struct os_time time;
|
||||
struct os_reltime time;
|
||||
void *eloop_data;
|
||||
void *user_data;
|
||||
eloop_timeout_handler handler;
|
||||
|
@ -50,7 +61,11 @@ struct eloop_signal {
|
|||
struct eloop_sock_table {
|
||||
int count;
|
||||
struct eloop_sock *table;
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
eloop_event_type type;
|
||||
#else /* CONFIG_ELOOP_EPOLL */
|
||||
int changed;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
};
|
||||
|
||||
struct eloop_data {
|
||||
|
@ -63,6 +78,13 @@ struct eloop_data {
|
|||
struct pollfd *pollfds;
|
||||
struct pollfd **pollfds_map;
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
int epollfd;
|
||||
int epoll_max_event_num;
|
||||
int epoll_max_fd;
|
||||
struct eloop_sock *epoll_table;
|
||||
struct epoll_event *epoll_events;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
struct eloop_sock_table readers;
|
||||
struct eloop_sock_table writers;
|
||||
struct eloop_sock_table exceptions;
|
||||
|
@ -75,7 +97,6 @@ struct eloop_data {
|
|||
int pending_terminate;
|
||||
|
||||
int terminate;
|
||||
int reader_table_changed;
|
||||
};
|
||||
|
||||
static struct eloop_data eloop;
|
||||
|
@ -128,6 +149,17 @@ int eloop_init(void)
|
|||
{
|
||||
os_memset(&eloop, 0, sizeof(eloop));
|
||||
dl_list_init(&eloop.timeout);
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
eloop.epollfd = epoll_create1(0);
|
||||
if (eloop.epollfd < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n",
|
||||
__func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
eloop.readers.type = EVENT_TYPE_READ;
|
||||
eloop.writers.type = EVENT_TYPE_WRITE;
|
||||
eloop.exceptions.type = EVENT_TYPE_EXCEPTION;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef WPA_TRACE
|
||||
signal(SIGSEGV, eloop_sigsegv_handler);
|
||||
#endif /* WPA_TRACE */
|
||||
|
@ -139,6 +171,11 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
|
|||
int sock, eloop_sock_handler handler,
|
||||
void *eloop_data, void *user_data)
|
||||
{
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
struct eloop_sock *temp_table;
|
||||
struct epoll_event ev, *temp_events;
|
||||
int next;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
struct eloop_sock *tmp;
|
||||
int new_max_sock;
|
||||
|
||||
|
@ -174,6 +211,33 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
|
|||
eloop.pollfds = n;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
if (new_max_sock >= eloop.epoll_max_fd) {
|
||||
next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2;
|
||||
temp_table = os_realloc_array(eloop.epoll_table, next,
|
||||
sizeof(struct eloop_sock));
|
||||
if (temp_table == NULL)
|
||||
return -1;
|
||||
|
||||
eloop.epoll_max_fd = next;
|
||||
eloop.epoll_table = temp_table;
|
||||
}
|
||||
|
||||
if (eloop.count + 1 > eloop.epoll_max_event_num) {
|
||||
next = eloop.epoll_max_event_num == 0 ? 8 :
|
||||
eloop.epoll_max_event_num * 2;
|
||||
temp_events = os_realloc_array(eloop.epoll_events, next,
|
||||
sizeof(struct epoll_event));
|
||||
if (temp_events == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: malloc for epoll failed. "
|
||||
"%s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
eloop.epoll_max_event_num = next;
|
||||
eloop.epoll_events = temp_events;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
|
||||
eloop_trace_sock_remove_ref(table);
|
||||
tmp = os_realloc_array(table->table, table->count + 1,
|
||||
|
@ -190,9 +254,38 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
|
|||
table->table = tmp;
|
||||
eloop.max_sock = new_max_sock;
|
||||
eloop.count++;
|
||||
#ifndef CONFIG_ELOOP_EPOLL
|
||||
table->changed = 1;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
eloop_trace_sock_add_ref(table);
|
||||
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
os_memset(&ev, 0, sizeof(ev));
|
||||
switch (table->type) {
|
||||
case EVENT_TYPE_READ:
|
||||
ev.events = EPOLLIN;
|
||||
break;
|
||||
case EVENT_TYPE_WRITE:
|
||||
ev.events = EPOLLOUT;
|
||||
break;
|
||||
/*
|
||||
* Exceptions are always checked when using epoll, but I suppose it's
|
||||
* possible that someone registered a socket *only* for exception
|
||||
* handling.
|
||||
*/
|
||||
case EVENT_TYPE_EXCEPTION:
|
||||
ev.events = EPOLLERR | EPOLLHUP;
|
||||
break;
|
||||
}
|
||||
ev.data.fd = sock;
|
||||
if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d "
|
||||
"failed. %s\n", __func__, sock, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1],
|
||||
sizeof(struct eloop_sock));
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -219,8 +312,18 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
|
|||
}
|
||||
table->count--;
|
||||
eloop.count--;
|
||||
#ifndef CONFIG_ELOOP_EPOLL
|
||||
table->changed = 1;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
eloop_trace_sock_add_ref(table);
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d "
|
||||
"failed. %s\n", __func__, sock, strerror(errno));
|
||||
return;
|
||||
}
|
||||
os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock));
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
}
|
||||
|
||||
|
||||
|
@ -362,7 +465,9 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *readers,
|
|||
max_pollfd_map, POLLERR | POLLHUP);
|
||||
}
|
||||
|
||||
#else /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
|
||||
#ifdef CONFIG_ELOOP_SELECT
|
||||
|
||||
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
|
||||
fd_set *fds)
|
||||
|
@ -374,9 +479,11 @@ static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
|
|||
if (table->table == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < table->count; i++)
|
||||
for (i = 0; i < table->count; i++) {
|
||||
assert(table->table[i].sock >= 0);
|
||||
FD_SET(table->table[i].sock, fds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
|
||||
|
@ -399,7 +506,24 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
|
|||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_SELECT */
|
||||
|
||||
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
|
||||
{
|
||||
struct eloop_sock *table;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
table = &eloop.epoll_table[events[i].data.fd];
|
||||
if (table->handler == NULL)
|
||||
continue;
|
||||
table->handler(table->sock, table->eloop_data,
|
||||
table->user_data);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
|
||||
|
||||
static void eloop_sock_table_destroy(struct eloop_sock_table *table)
|
||||
|
@ -459,6 +583,7 @@ int eloop_register_sock(int sock, eloop_event_type type,
|
|||
{
|
||||
struct eloop_sock_table *table;
|
||||
|
||||
assert(sock >= 0);
|
||||
table = eloop_get_sock_table(type);
|
||||
return eloop_sock_table_add_sock(table, sock, handler,
|
||||
eloop_data, user_data);
|
||||
|
@ -484,7 +609,7 @@ int eloop_register_timeout(unsigned int secs, unsigned int usecs,
|
|||
timeout = os_zalloc(sizeof(*timeout));
|
||||
if (timeout == NULL)
|
||||
return -1;
|
||||
if (os_get_time(&timeout->time) < 0) {
|
||||
if (os_get_reltime(&timeout->time) < 0) {
|
||||
os_free(timeout);
|
||||
return -1;
|
||||
}
|
||||
|
@ -514,7 +639,7 @@ int eloop_register_timeout(unsigned int secs, unsigned int usecs,
|
|||
|
||||
/* Maintain timeouts in order of increasing time */
|
||||
dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
|
||||
if (os_time_before(&timeout->time, &tmp->time)) {
|
||||
if (os_reltime_before(&timeout->time, &tmp->time)) {
|
||||
dl_list_add(tmp->list.prev, &timeout->list);
|
||||
return 0;
|
||||
}
|
||||
|
@ -556,6 +681,33 @@ int eloop_cancel_timeout(eloop_timeout_handler handler,
|
|||
}
|
||||
|
||||
|
||||
int eloop_cancel_timeout_one(eloop_timeout_handler handler,
|
||||
void *eloop_data, void *user_data,
|
||||
struct os_reltime *remaining)
|
||||
{
|
||||
struct eloop_timeout *timeout, *prev;
|
||||
int removed = 0;
|
||||
struct os_reltime now;
|
||||
|
||||
os_get_reltime(&now);
|
||||
remaining->sec = remaining->usec = 0;
|
||||
|
||||
dl_list_for_each_safe(timeout, prev, &eloop.timeout,
|
||||
struct eloop_timeout, list) {
|
||||
if (timeout->handler == handler &&
|
||||
(timeout->eloop_data == eloop_data) &&
|
||||
(timeout->user_data == user_data)) {
|
||||
removed = 1;
|
||||
if (os_reltime_before(&now, &timeout->time))
|
||||
os_reltime_sub(&timeout->time, &now, remaining);
|
||||
eloop_remove_timeout(timeout);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
|
||||
int eloop_is_timeout_registered(eloop_timeout_handler handler,
|
||||
void *eloop_data, void *user_data)
|
||||
{
|
||||
|
@ -572,6 +724,70 @@ int eloop_is_timeout_registered(eloop_timeout_handler handler,
|
|||
}
|
||||
|
||||
|
||||
int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
|
||||
eloop_timeout_handler handler, void *eloop_data,
|
||||
void *user_data)
|
||||
{
|
||||
struct os_reltime now, requested, remaining;
|
||||
struct eloop_timeout *tmp;
|
||||
|
||||
dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
|
||||
if (tmp->handler == handler &&
|
||||
tmp->eloop_data == eloop_data &&
|
||||
tmp->user_data == user_data) {
|
||||
requested.sec = req_secs;
|
||||
requested.usec = req_usecs;
|
||||
os_get_reltime(&now);
|
||||
os_reltime_sub(&tmp->time, &now, &remaining);
|
||||
if (os_reltime_before(&requested, &remaining)) {
|
||||
eloop_cancel_timeout(handler, eloop_data,
|
||||
user_data);
|
||||
eloop_register_timeout(requested.sec,
|
||||
requested.usec,
|
||||
handler, eloop_data,
|
||||
user_data);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
|
||||
eloop_timeout_handler handler, void *eloop_data,
|
||||
void *user_data)
|
||||
{
|
||||
struct os_reltime now, requested, remaining;
|
||||
struct eloop_timeout *tmp;
|
||||
|
||||
dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
|
||||
if (tmp->handler == handler &&
|
||||
tmp->eloop_data == eloop_data &&
|
||||
tmp->user_data == user_data) {
|
||||
requested.sec = req_secs;
|
||||
requested.usec = req_usecs;
|
||||
os_get_reltime(&now);
|
||||
os_reltime_sub(&tmp->time, &now, &remaining);
|
||||
if (os_reltime_before(&remaining, &requested)) {
|
||||
eloop_cancel_timeout(handler, eloop_data,
|
||||
user_data);
|
||||
eloop_register_timeout(requested.sec,
|
||||
requested.usec,
|
||||
handler, eloop_data,
|
||||
user_data);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
static void eloop_handle_alarm(int sig)
|
||||
{
|
||||
|
@ -682,20 +898,24 @@ void eloop_run(void)
|
|||
#ifdef CONFIG_ELOOP_POLL
|
||||
int num_poll_fds;
|
||||
int timeout_ms = 0;
|
||||
#else /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#ifdef CONFIG_ELOOP_SELECT
|
||||
fd_set *rfds, *wfds, *efds;
|
||||
struct timeval _tv;
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_SELECT */
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
int timeout_ms = -1;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
int res;
|
||||
struct os_time tv, now;
|
||||
struct os_reltime tv, now;
|
||||
|
||||
#ifndef CONFIG_ELOOP_POLL
|
||||
#ifdef CONFIG_ELOOP_SELECT
|
||||
rfds = os_malloc(sizeof(*rfds));
|
||||
wfds = os_malloc(sizeof(*wfds));
|
||||
efds = os_malloc(sizeof(*efds));
|
||||
if (rfds == NULL || wfds == NULL || efds == NULL)
|
||||
goto out;
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_SELECT */
|
||||
|
||||
while (!eloop.terminate &&
|
||||
(!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
|
||||
|
@ -704,17 +924,18 @@ void eloop_run(void)
|
|||
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
|
||||
list);
|
||||
if (timeout) {
|
||||
os_get_time(&now);
|
||||
if (os_time_before(&now, &timeout->time))
|
||||
os_time_sub(&timeout->time, &now, &tv);
|
||||
os_get_reltime(&now);
|
||||
if (os_reltime_before(&now, &timeout->time))
|
||||
os_reltime_sub(&timeout->time, &now, &tv);
|
||||
else
|
||||
tv.sec = tv.usec = 0;
|
||||
#ifdef CONFIG_ELOOP_POLL
|
||||
#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
|
||||
timeout_ms = tv.sec * 1000 + tv.usec / 1000;
|
||||
#else /* CONFIG_ELOOP_POLL */
|
||||
#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
|
||||
#ifdef CONFIG_ELOOP_SELECT
|
||||
_tv.tv_sec = tv.sec;
|
||||
_tv.tv_usec = tv.usec;
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_SELECT */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ELOOP_POLL
|
||||
|
@ -724,30 +945,44 @@ void eloop_run(void)
|
|||
eloop.max_pollfd_map);
|
||||
res = poll(eloop.pollfds, num_poll_fds,
|
||||
timeout ? timeout_ms : -1);
|
||||
|
||||
if (res < 0 && errno != EINTR && errno != 0) {
|
||||
perror("poll");
|
||||
goto out;
|
||||
}
|
||||
#else /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#ifdef CONFIG_ELOOP_SELECT
|
||||
eloop_sock_table_set_fds(&eloop.readers, rfds);
|
||||
eloop_sock_table_set_fds(&eloop.writers, wfds);
|
||||
eloop_sock_table_set_fds(&eloop.exceptions, efds);
|
||||
res = select(eloop.max_sock + 1, rfds, wfds, efds,
|
||||
timeout ? &_tv : NULL);
|
||||
#endif /* CONFIG_ELOOP_SELECT */
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
if (eloop.count == 0) {
|
||||
res = 0;
|
||||
} else {
|
||||
res = epoll_wait(eloop.epollfd, eloop.epoll_events,
|
||||
eloop.count, timeout_ms);
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
if (res < 0 && errno != EINTR && errno != 0) {
|
||||
perror("select");
|
||||
wpa_printf(MSG_ERROR, "eloop: %s: %s",
|
||||
#ifdef CONFIG_ELOOP_POLL
|
||||
"poll"
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#ifdef CONFIG_ELOOP_SELECT
|
||||
"select"
|
||||
#endif /* CONFIG_ELOOP_SELECT */
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
"epoll"
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
eloop_process_pending_signals();
|
||||
|
||||
/* check if some registered timeouts have occurred */
|
||||
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
|
||||
list);
|
||||
if (timeout) {
|
||||
os_get_time(&now);
|
||||
if (!os_time_before(&now, &timeout->time)) {
|
||||
os_get_reltime(&now);
|
||||
if (!os_reltime_before(&now, &timeout->time)) {
|
||||
void *eloop_data = timeout->eloop_data;
|
||||
void *user_data = timeout->user_data;
|
||||
eloop_timeout_handler handler =
|
||||
|
@ -765,19 +1000,24 @@ void eloop_run(void)
|
|||
eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
|
||||
&eloop.exceptions, eloop.pollfds_map,
|
||||
eloop.max_pollfd_map);
|
||||
#else /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#ifdef CONFIG_ELOOP_SELECT
|
||||
eloop_sock_table_dispatch(&eloop.readers, rfds);
|
||||
eloop_sock_table_dispatch(&eloop.writers, wfds);
|
||||
eloop_sock_table_dispatch(&eloop.exceptions, efds);
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_SELECT */
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
eloop_sock_table_dispatch(eloop.epoll_events, res);
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
}
|
||||
|
||||
eloop.terminate = 0;
|
||||
out:
|
||||
#ifndef CONFIG_ELOOP_POLL
|
||||
#ifdef CONFIG_ELOOP_SELECT
|
||||
os_free(rfds);
|
||||
os_free(wfds);
|
||||
os_free(efds);
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_SELECT */
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -791,9 +1031,9 @@ void eloop_terminate(void)
|
|||
void eloop_destroy(void)
|
||||
{
|
||||
struct eloop_timeout *timeout, *prev;
|
||||
struct os_time now;
|
||||
struct os_reltime now;
|
||||
|
||||
os_get_time(&now);
|
||||
os_get_reltime(&now);
|
||||
dl_list_for_each_safe(timeout, prev, &eloop.timeout,
|
||||
struct eloop_timeout, list) {
|
||||
int sec, usec;
|
||||
|
@ -821,6 +1061,11 @@ void eloop_destroy(void)
|
|||
os_free(eloop.pollfds);
|
||||
os_free(eloop.pollfds_map);
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
os_free(eloop.epoll_table);
|
||||
os_free(eloop.epoll_events);
|
||||
close(eloop.epollfd);
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
}
|
||||
|
||||
|
||||
|
@ -843,7 +1088,13 @@ void eloop_wait_for_read_sock(int sock)
|
|||
pfd.events = POLLIN;
|
||||
|
||||
poll(&pfd, 1, -1);
|
||||
#else /* CONFIG_ELOOP_POLL */
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#if defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL)
|
||||
/*
|
||||
* We can use epoll() here. But epoll() requres 4 system calls.
|
||||
* epoll_create1(), epoll_ctl() for ADD, epoll_wait, and close() for
|
||||
* epoll fd. So select() is better for performance here.
|
||||
*/
|
||||
fd_set rfds;
|
||||
|
||||
if (sock < 0)
|
||||
|
@ -852,5 +1103,9 @@ void eloop_wait_for_read_sock(int sock)
|
|||
FD_ZERO(&rfds);
|
||||
FD_SET(sock, &rfds);
|
||||
select(sock + 1, &rfds, NULL, NULL, NULL);
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ELOOP_SELECT
|
||||
#undef CONFIG_ELOOP_SELECT
|
||||
#endif /* CONFIG_ELOOP_SELECT */
|
||||
|
|
|
@ -1,395 +0,0 @@
|
|||
/*
|
||||
* Event loop - empty template (basic structure, but no OS specific operations)
|
||||
* Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eloop.h"
|
||||
|
||||
|
||||
struct eloop_sock {
|
||||
int sock;
|
||||
void *eloop_data;
|
||||
void *user_data;
|
||||
void (*handler)(int sock, void *eloop_ctx, void *sock_ctx);
|
||||
};
|
||||
|
||||
struct eloop_timeout {
|
||||
struct os_time time;
|
||||
void *eloop_data;
|
||||
void *user_data;
|
||||
void (*handler)(void *eloop_ctx, void *sock_ctx);
|
||||
struct eloop_timeout *next;
|
||||
};
|
||||
|
||||
struct eloop_signal {
|
||||
int sig;
|
||||
void *user_data;
|
||||
void (*handler)(int sig, void *eloop_ctx, void *signal_ctx);
|
||||
int signaled;
|
||||
};
|
||||
|
||||
struct eloop_data {
|
||||
int max_sock, reader_count;
|
||||
struct eloop_sock *readers;
|
||||
|
||||
struct eloop_timeout *timeout;
|
||||
|
||||
int signal_count;
|
||||
struct eloop_signal *signals;
|
||||
int signaled;
|
||||
int pending_terminate;
|
||||
|
||||
int terminate;
|
||||
int reader_table_changed;
|
||||
};
|
||||
|
||||
static struct eloop_data eloop;
|
||||
|
||||
|
||||
int eloop_init(void)
|
||||
{
|
||||
memset(&eloop, 0, sizeof(eloop));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int eloop_register_read_sock(int sock,
|
||||
void (*handler)(int sock, void *eloop_ctx,
|
||||
void *sock_ctx),
|
||||
void *eloop_data, void *user_data)
|
||||
{
|
||||
struct eloop_sock *tmp;
|
||||
|
||||
tmp = (struct eloop_sock *)
|
||||
realloc(eloop.readers,
|
||||
(eloop.reader_count + 1) * sizeof(struct eloop_sock));
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
|
||||
tmp[eloop.reader_count].sock = sock;
|
||||
tmp[eloop.reader_count].eloop_data = eloop_data;
|
||||
tmp[eloop.reader_count].user_data = user_data;
|
||||
tmp[eloop.reader_count].handler = handler;
|
||||
eloop.reader_count++;
|
||||
eloop.readers = tmp;
|
||||
if (sock > eloop.max_sock)
|
||||
eloop.max_sock = sock;
|
||||
eloop.reader_table_changed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void eloop_unregister_read_sock(int sock)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (eloop.readers == NULL || eloop.reader_count == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < eloop.reader_count; i++) {
|
||||
if (eloop.readers[i].sock == sock)
|
||||
break;
|
||||
}
|
||||
if (i == eloop.reader_count)
|
||||
return;
|
||||
if (i != eloop.reader_count - 1) {
|
||||
memmove(&eloop.readers[i], &eloop.readers[i + 1],
|
||||
(eloop.reader_count - i - 1) *
|
||||
sizeof(struct eloop_sock));
|
||||
}
|
||||
eloop.reader_count--;
|
||||
eloop.reader_table_changed = 1;
|
||||
}
|
||||
|
||||
|
||||
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
|
||||
void (*handler)(void *eloop_ctx, void *timeout_ctx),
|
||||
void *eloop_data, void *user_data)
|
||||
{
|
||||
struct eloop_timeout *timeout, *tmp, *prev;
|
||||
|
||||
timeout = (struct eloop_timeout *) malloc(sizeof(*timeout));
|
||||
if (timeout == NULL)
|
||||
return -1;
|
||||
os_get_time(&timeout->time);
|
||||
timeout->time.sec += secs;
|
||||
timeout->time.usec += usecs;
|
||||
while (timeout->time.usec >= 1000000) {
|
||||
timeout->time.sec++;
|
||||
timeout->time.usec -= 1000000;
|
||||
}
|
||||
timeout->eloop_data = eloop_data;
|
||||
timeout->user_data = user_data;
|
||||
timeout->handler = handler;
|
||||
timeout->next = NULL;
|
||||
|
||||
if (eloop.timeout == NULL) {
|
||||
eloop.timeout = timeout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
prev = NULL;
|
||||
tmp = eloop.timeout;
|
||||
while (tmp != NULL) {
|
||||
if (os_time_before(&timeout->time, &tmp->time))
|
||||
break;
|
||||
prev = tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
if (prev == NULL) {
|
||||
timeout->next = eloop.timeout;
|
||||
eloop.timeout = timeout;
|
||||
} else {
|
||||
timeout->next = prev->next;
|
||||
prev->next = timeout;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
|
||||
void *eloop_data, void *user_data)
|
||||
{
|
||||
struct eloop_timeout *timeout, *prev, *next;
|
||||
int removed = 0;
|
||||
|
||||
prev = NULL;
|
||||
timeout = eloop.timeout;
|
||||
while (timeout != NULL) {
|
||||
next = timeout->next;
|
||||
|
||||
if (timeout->handler == handler &&
|
||||
(timeout->eloop_data == eloop_data ||
|
||||
eloop_data == ELOOP_ALL_CTX) &&
|
||||
(timeout->user_data == user_data ||
|
||||
user_data == ELOOP_ALL_CTX)) {
|
||||
if (prev == NULL)
|
||||
eloop.timeout = next;
|
||||
else
|
||||
prev->next = next;
|
||||
free(timeout);
|
||||
removed++;
|
||||
} else
|
||||
prev = timeout;
|
||||
|
||||
timeout = next;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
|
||||
int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx,
|
||||
void *timeout_ctx),
|
||||
void *eloop_data, void *user_data)
|
||||
{
|
||||
struct eloop_timeout *tmp;
|
||||
|
||||
tmp = eloop.timeout;
|
||||
while (tmp != NULL) {
|
||||
if (tmp->handler == handler &&
|
||||
tmp->eloop_data == eloop_data &&
|
||||
tmp->user_data == user_data)
|
||||
return 1;
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* TODO: replace with suitable signal handler */
|
||||
#if 0
|
||||
static void eloop_handle_signal(int sig)
|
||||
{
|
||||
int i;
|
||||
|
||||
eloop.signaled++;
|
||||
for (i = 0; i < eloop.signal_count; i++) {
|
||||
if (eloop.signals[i].sig == sig) {
|
||||
eloop.signals[i].signaled++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void eloop_process_pending_signals(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (eloop.signaled == 0)
|
||||
return;
|
||||
eloop.signaled = 0;
|
||||
|
||||
if (eloop.pending_terminate) {
|
||||
eloop.pending_terminate = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < eloop.signal_count; i++) {
|
||||
if (eloop.signals[i].signaled) {
|
||||
eloop.signals[i].signaled = 0;
|
||||
eloop.signals[i].handler(eloop.signals[i].sig,
|
||||
eloop.user_data,
|
||||
eloop.signals[i].user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int eloop_register_signal(int sig,
|
||||
void (*handler)(int sig, void *eloop_ctx,
|
||||
void *signal_ctx),
|
||||
void *user_data)
|
||||
{
|
||||
struct eloop_signal *tmp;
|
||||
|
||||
tmp = (struct eloop_signal *)
|
||||
realloc(eloop.signals,
|
||||
(eloop.signal_count + 1) *
|
||||
sizeof(struct eloop_signal));
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
|
||||
tmp[eloop.signal_count].sig = sig;
|
||||
tmp[eloop.signal_count].user_data = user_data;
|
||||
tmp[eloop.signal_count].handler = handler;
|
||||
tmp[eloop.signal_count].signaled = 0;
|
||||
eloop.signal_count++;
|
||||
eloop.signals = tmp;
|
||||
|
||||
/* TODO: register signal handler */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int eloop_register_signal_terminate(void (*handler)(int sig, void *eloop_ctx,
|
||||
void *signal_ctx),
|
||||
void *user_data)
|
||||
{
|
||||
#if 0
|
||||
/* TODO: for example */
|
||||
int ret = eloop_register_signal(SIGINT, handler, user_data);
|
||||
if (ret == 0)
|
||||
ret = eloop_register_signal(SIGTERM, handler, user_data);
|
||||
return ret;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int eloop_register_signal_reconfig(void (*handler)(int sig, void *eloop_ctx,
|
||||
void *signal_ctx),
|
||||
void *user_data)
|
||||
{
|
||||
#if 0
|
||||
/* TODO: for example */
|
||||
return eloop_register_signal(SIGHUP, handler, user_data);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void eloop_run(void)
|
||||
{
|
||||
int i;
|
||||
struct os_time tv, now;
|
||||
|
||||
while (!eloop.terminate &&
|
||||
(eloop.timeout || eloop.reader_count > 0)) {
|
||||
if (eloop.timeout) {
|
||||
os_get_time(&now);
|
||||
if (os_time_before(&now, &eloop.timeout->time))
|
||||
os_time_sub(&eloop.timeout->time, &now, &tv);
|
||||
else
|
||||
tv.sec = tv.usec = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: wait for any event (read socket ready, timeout (tv),
|
||||
* signal
|
||||
*/
|
||||
os_sleep(1, 0); /* just a dummy wait for testing */
|
||||
|
||||
eloop_process_pending_signals();
|
||||
|
||||
/* check if some registered timeouts have occurred */
|
||||
if (eloop.timeout) {
|
||||
struct eloop_timeout *tmp;
|
||||
|
||||
os_get_time(&now);
|
||||
if (!os_time_before(&now, &eloop.timeout->time)) {
|
||||
tmp = eloop.timeout;
|
||||
eloop.timeout = eloop.timeout->next;
|
||||
tmp->handler(tmp->eloop_data,
|
||||
tmp->user_data);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
eloop.reader_table_changed = 0;
|
||||
for (i = 0; i < eloop.reader_count; i++) {
|
||||
/*
|
||||
* TODO: call each handler that has pending data to
|
||||
* read
|
||||
*/
|
||||
if (0 /* TODO: eloop.readers[i].sock ready */) {
|
||||
eloop.readers[i].handler(
|
||||
eloop.readers[i].sock,
|
||||
eloop.readers[i].eloop_data,
|
||||
eloop.readers[i].user_data);
|
||||
if (eloop.reader_table_changed)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void eloop_terminate(void)
|
||||
{
|
||||
eloop.terminate = 1;
|
||||
}
|
||||
|
||||
|
||||
void eloop_destroy(void)
|
||||
{
|
||||
struct eloop_timeout *timeout, *prev;
|
||||
|
||||
timeout = eloop.timeout;
|
||||
while (timeout != NULL) {
|
||||
prev = timeout;
|
||||
timeout = timeout->next;
|
||||
free(prev);
|
||||
}
|
||||
free(eloop.readers);
|
||||
free(eloop.signals);
|
||||
}
|
||||
|
||||
|
||||
int eloop_terminated(void)
|
||||
{
|
||||
return eloop.terminate;
|
||||
}
|
||||
|
||||
|
||||
void eloop_wait_for_read_sock(int sock)
|
||||
{
|
||||
/*
|
||||
* TODO: wait for the file descriptor to have something available for
|
||||
* reading
|
||||
*/
|
||||
}
|
|
@ -23,6 +23,11 @@ struct os_time {
|
|||
os_time_t usec;
|
||||
};
|
||||
|
||||
struct os_reltime {
|
||||
os_time_t sec;
|
||||
os_time_t usec;
|
||||
};
|
||||
|
||||
/**
|
||||
* os_get_time - Get current time (sec, usec)
|
||||
* @t: Pointer to buffer for the time
|
||||
|
@ -30,21 +35,84 @@ struct os_time {
|
|||
*/
|
||||
int os_get_time(struct os_time *t);
|
||||
|
||||
/**
|
||||
* os_get_reltime - Get relative time (sec, usec)
|
||||
* @t: Pointer to buffer for the time
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int os_get_reltime(struct os_reltime *t);
|
||||
|
||||
/* Helper macros for handling struct os_time */
|
||||
|
||||
#define os_time_before(a, b) \
|
||||
((a)->sec < (b)->sec || \
|
||||
((a)->sec == (b)->sec && (a)->usec < (b)->usec))
|
||||
/* Helpers for handling struct os_time */
|
||||
|
||||
static inline int os_time_before(struct os_time *a, struct os_time *b)
|
||||
{
|
||||
return (a->sec < b->sec) ||
|
||||
(a->sec == b->sec && a->usec < b->usec);
|
||||
}
|
||||
|
||||
|
||||
static inline void os_time_sub(struct os_time *a, struct os_time *b,
|
||||
struct os_time *res)
|
||||
{
|
||||
res->sec = a->sec - b->sec;
|
||||
res->usec = a->usec - b->usec;
|
||||
if (res->usec < 0) {
|
||||
res->sec--;
|
||||
res->usec += 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Helpers for handling struct os_reltime */
|
||||
|
||||
static inline int os_reltime_before(struct os_reltime *a,
|
||||
struct os_reltime *b)
|
||||
{
|
||||
return (a->sec < b->sec) ||
|
||||
(a->sec == b->sec && a->usec < b->usec);
|
||||
}
|
||||
|
||||
|
||||
static inline void os_reltime_sub(struct os_reltime *a, struct os_reltime *b,
|
||||
struct os_reltime *res)
|
||||
{
|
||||
res->sec = a->sec - b->sec;
|
||||
res->usec = a->usec - b->usec;
|
||||
if (res->usec < 0) {
|
||||
res->sec--;
|
||||
res->usec += 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void os_reltime_age(struct os_reltime *start,
|
||||
struct os_reltime *age)
|
||||
{
|
||||
struct os_reltime now;
|
||||
|
||||
os_get_reltime(&now);
|
||||
os_reltime_sub(&now, start, age);
|
||||
}
|
||||
|
||||
|
||||
static inline int os_reltime_expired(struct os_reltime *now,
|
||||
struct os_reltime *ts,
|
||||
os_time_t timeout_secs)
|
||||
{
|
||||
struct os_reltime age;
|
||||
|
||||
os_reltime_sub(now, ts, &age);
|
||||
return (age.sec > timeout_secs) ||
|
||||
(age.sec == timeout_secs && age.usec > 0);
|
||||
}
|
||||
|
||||
|
||||
static inline int os_reltime_initialized(struct os_reltime *t)
|
||||
{
|
||||
return t->sec != 0 || t->usec != 0;
|
||||
}
|
||||
|
||||
#define os_time_sub(a, b, res) do { \
|
||||
(res)->sec = (a)->sec - (b)->sec; \
|
||||
(res)->usec = (a)->usec - (b)->usec; \
|
||||
if ((res)->usec < 0) { \
|
||||
(res)->sec--; \
|
||||
(res)->usec += 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* os_mktime - Convert broken-down time into seconds since 1970-01-01
|
||||
|
@ -171,6 +239,13 @@ int os_unsetenv(const char *name);
|
|||
*/
|
||||
char * os_readfile(const char *name, size_t *len);
|
||||
|
||||
/**
|
||||
* os_file_exists - Check whether the specified file exists
|
||||
* @fname: Path and name of the file
|
||||
* Returns: 1 if the file exists or 0 if not
|
||||
*/
|
||||
int os_file_exists(const char *fname);
|
||||
|
||||
/**
|
||||
* os_zalloc - Allocate and zero memory
|
||||
* @size: Number of bytes to allocate
|
||||
|
@ -360,15 +435,6 @@ int os_strcmp(const char *s1, const char *s2);
|
|||
*/
|
||||
int os_strncmp(const char *s1, const char *s2, size_t n);
|
||||
|
||||
/**
|
||||
* os_strncpy - Copy a string
|
||||
* @dest: Destination
|
||||
* @src: Source
|
||||
* @n: Maximum number of characters to copy
|
||||
* Returns: dest
|
||||
*/
|
||||
char * os_strncpy(char *dest, const char *src, size_t n);
|
||||
|
||||
/**
|
||||
* os_strstr - Locate a substring
|
||||
* @haystack: String (haystack) to search from
|
||||
|
@ -465,9 +531,6 @@ char * os_strdup(const char *s);
|
|||
#ifndef os_strncmp
|
||||
#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n))
|
||||
#endif
|
||||
#ifndef os_strncpy
|
||||
#define os_strncpy(d, s, n) strncpy((d), (s), (n))
|
||||
#endif
|
||||
#ifndef os_strrchr
|
||||
#define os_strrchr(s, c) strrchr((s), (c))
|
||||
#endif
|
||||
|
@ -493,6 +556,21 @@ static inline void * os_realloc_array(void *ptr, size_t nmemb, size_t size)
|
|||
return os_realloc(ptr, nmemb * size);
|
||||
}
|
||||
|
||||
/**
|
||||
* os_remove_in_array - Remove a member from an array by index
|
||||
* @ptr: Pointer to the array
|
||||
* @nmemb: Current member count of the array
|
||||
* @size: The size per member of the array
|
||||
* @idx: Index of the member to be removed
|
||||
*/
|
||||
static inline void os_remove_in_array(void *ptr, size_t nmemb, size_t size,
|
||||
size_t idx)
|
||||
{
|
||||
if (idx < nmemb - 1)
|
||||
os_memmove(((unsigned char *) ptr) + idx * size,
|
||||
((unsigned char *) ptr) + (idx + 1) * size,
|
||||
(nmemb - idx - 1) * size);
|
||||
}
|
||||
|
||||
/**
|
||||
* os_strlcpy - Copy a string with size bound and NUL-termination
|
||||
|
@ -506,6 +584,32 @@ static inline void * os_realloc_array(void *ptr, size_t nmemb, size_t size)
|
|||
*/
|
||||
size_t os_strlcpy(char *dest, const char *src, size_t siz);
|
||||
|
||||
/**
|
||||
* os_memcmp_const - Constant time memory comparison
|
||||
* @a: First buffer to compare
|
||||
* @b: Second buffer to compare
|
||||
* @len: Number of octets to compare
|
||||
* Returns: 0 if buffers are equal, non-zero if not
|
||||
*
|
||||
* This function is meant for comparing passwords or hash values where
|
||||
* difference in execution time could provide external observer information
|
||||
* about the location of the difference in the memory buffers. The return value
|
||||
* does not behave like os_memcmp(), i.e., os_memcmp_const() cannot be used to
|
||||
* sort items into a defined order. Unlike os_memcmp(), execution time of
|
||||
* os_memcmp_const() does not depend on the contents of the compared memory
|
||||
* buffers, but only on the total compared length.
|
||||
*/
|
||||
int os_memcmp_const(const void *a, const void *b, size_t len);
|
||||
|
||||
/**
|
||||
* os_exec - Execute an external program
|
||||
* @program: Path to the program
|
||||
* @arg: Command line argument string
|
||||
* @wait_completion: Whether to wait until the program execution completes
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int os_exec(const char *program, const char *arg, int wait_completion);
|
||||
|
||||
|
||||
#ifdef OS_REJECT_C_LIB_FUNCTIONS
|
||||
#define malloc OS_DO_NOT_USE_malloc
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
|
||||
/* $NetBSD: radiotap.h,v 1.3 2014/01/03 02:08:17 christos Exp $ */
|
||||
/* $NetBSD: radiotap.h,v 1.4 2014/10/16 19:29:30 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 David Young. All rights reserved.
|
||||
|
@ -175,6 +175,14 @@ struct ieee80211_radiotap_header {
|
|||
*
|
||||
* Number of unicast retries a transmitted frame used.
|
||||
*
|
||||
* IEEE80211_RADIOTAP_MCS u8, u8, u8 unitless
|
||||
*
|
||||
* Contains a bitmap of known fields/flags, the flags, and
|
||||
* the MCS index.
|
||||
*
|
||||
* IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitlesss
|
||||
*
|
||||
* Contains the AMPDU information for the subframe.
|
||||
*/
|
||||
enum ieee80211_radiotap_type {
|
||||
IEEE80211_RADIOTAP_TSFT = 0,
|
||||
|
@ -195,6 +203,13 @@ enum ieee80211_radiotap_type {
|
|||
IEEE80211_RADIOTAP_TX_FLAGS = 15,
|
||||
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
|
||||
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
|
||||
|
||||
IEEE80211_RADIOTAP_MCS = 19,
|
||||
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
|
||||
|
||||
/* valid in every it_present bitmap, even vendor namespaces */
|
||||
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
|
||||
IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
|
||||
IEEE80211_RADIOTAP_EXT = 31
|
||||
};
|
||||
|
||||
|
@ -227,8 +242,10 @@ enum ieee80211_radiotap_type {
|
|||
* 802.11 header and payload
|
||||
* (to 32-bit boundary)
|
||||
*/
|
||||
#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* frame failed FCS check */
|
||||
|
||||
/* For IEEE80211_RADIOTAP_RX_FLAGS */
|
||||
#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
|
||||
#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* bad PLCP */
|
||||
|
||||
/* For IEEE80211_RADIOTAP_TX_FLAGS */
|
||||
#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
|
||||
|
@ -237,4 +254,38 @@ enum ieee80211_radiotap_type {
|
|||
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
|
||||
#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ACK */
|
||||
|
||||
/* For IEEE80211_RADIOTAP_AMPDU_STATUS */
|
||||
#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
|
||||
#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
|
||||
#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
|
||||
#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
|
||||
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
|
||||
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
|
||||
|
||||
/* For IEEE80211_RADIOTAP_MCS */
|
||||
#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
|
||||
#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02
|
||||
#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
|
||||
#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
|
||||
#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10
|
||||
#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20
|
||||
#define IEEE80211_RADIOTAP_MCS_HAVE_NESS 0x40
|
||||
#define IEEE80211_RADIOTAP_MCS_NESS_BIT1 0x80
|
||||
|
||||
|
||||
#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
|
||||
#define IEEE80211_RADIOTAP_MCS_BW_20 0
|
||||
#define IEEE80211_RADIOTAP_MCS_BW_40 1
|
||||
#define IEEE80211_RADIOTAP_MCS_BW_20L 2
|
||||
#define IEEE80211_RADIOTAP_MCS_BW_20U 3
|
||||
#define IEEE80211_RADIOTAP_MCS_SGI 0x04
|
||||
#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
|
||||
#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
|
||||
#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
|
||||
#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
|
||||
#define IEEE80211_RADIOTAP_MCS_STBC_1 1
|
||||
#define IEEE80211_RADIOTAP_MCS_STBC_2 2
|
||||
#define IEEE80211_RADIOTAP_MCS_STBC_3 3
|
||||
#define IEEE80211_RADIOTAP_MCS_NESS_BIT0 0x80
|
||||
|
||||
#endif /* IEEE80211_RADIOTAP_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue