mirror of
https://github.com/openssl/openssl.git
synced 2024-12-16 05:23:50 +08:00
Refactoring BIO: Adapt BIO_s_datagram and all that depends on it
The control commands that previously took a struct sockaddr * have been changed to take a BIO_ADDR * instead. Reviewed-by: Kurt Roeckx <kurt@openssl.org>
This commit is contained in:
parent
75d5bd4e7d
commit
d858c87653
60
apps/s_cb.c
60
apps/s_cb.c
@ -737,14 +737,9 @@ int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
|
||||
unsigned int *cookie_len)
|
||||
{
|
||||
unsigned char *buffer;
|
||||
unsigned int length;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in s4;
|
||||
#if OPENSSL_USE_IPV6
|
||||
struct sockaddr_in6 s6;
|
||||
#endif
|
||||
} peer;
|
||||
size_t length;
|
||||
unsigned short port;
|
||||
BIO_ADDR *peer = NULL;
|
||||
|
||||
/* Initialize a random secret */
|
||||
if (!cookie_initialized) {
|
||||
@ -755,50 +750,31 @@ int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
|
||||
cookie_initialized = 1;
|
||||
}
|
||||
|
||||
peer = BIO_ADDR_new();
|
||||
if (peer == NULL) {
|
||||
BIO_printf(bio_err, "memory full\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read peer information */
|
||||
(void)BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
|
||||
(void)BIO_dgram_get_peer(SSL_get_rbio(ssl), peer);
|
||||
|
||||
/* Create buffer with peer's address and port */
|
||||
length = 0;
|
||||
switch (peer.sa.sa_family) {
|
||||
case AF_INET:
|
||||
length += sizeof(struct in_addr);
|
||||
length += sizeof(peer.s4.sin_port);
|
||||
break;
|
||||
#if OPENSSL_USE_IPV6
|
||||
case AF_INET6:
|
||||
length += sizeof(struct in6_addr);
|
||||
length += sizeof(peer.s6.sin6_port);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
OPENSSL_assert(0);
|
||||
break;
|
||||
}
|
||||
BIO_ADDR_rawaddress(peer, NULL, &length);
|
||||
OPENSSL_assert(length != 0);
|
||||
port = BIO_ADDR_rawport(peer);
|
||||
length += sizeof(port);
|
||||
buffer = app_malloc(length, "cookie generate buffer");
|
||||
|
||||
switch (peer.sa.sa_family) {
|
||||
case AF_INET:
|
||||
memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port));
|
||||
memcpy(buffer + sizeof(peer.s4.sin_port),
|
||||
&peer.s4.sin_addr, sizeof(struct in_addr));
|
||||
break;
|
||||
#if OPENSSL_USE_IPV6
|
||||
case AF_INET6:
|
||||
memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port));
|
||||
memcpy(buffer + sizeof(peer.s6.sin6_port),
|
||||
&peer.s6.sin6_addr, sizeof(struct in6_addr));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
OPENSSL_assert(0);
|
||||
break;
|
||||
}
|
||||
memcpy(buffer, &port, sizeof(port));
|
||||
BIO_ADDR_rawaddress(peer, buffer + sizeof(port), NULL);
|
||||
|
||||
/* Calculate HMAC of buffer using the secret */
|
||||
HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH,
|
||||
buffer, length, cookie, cookie_len);
|
||||
|
||||
OPENSSL_free(buffer);
|
||||
BIO_ADDR_free(peer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -2432,12 +2432,15 @@ static int init_ssl_connection(SSL *con)
|
||||
unsigned next_proto_neg_len;
|
||||
#endif
|
||||
unsigned char *exportedkeymat;
|
||||
#ifndef OPENSSL_NO_DTLS
|
||||
struct sockaddr_storage client;
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_DTLS
|
||||
if(dtlslisten) {
|
||||
BIO_ADDR *client = NULL;
|
||||
|
||||
if ((client = BIO_ADDR_new()) == NULL) {
|
||||
BIO_printf(bio_err, "ERROR - memory\n");
|
||||
return 0;
|
||||
}
|
||||
i = DTLSv1_listen(con, &client);
|
||||
if (i > 0) {
|
||||
BIO *wbio;
|
||||
@ -2448,11 +2451,12 @@ static int init_ssl_connection(SSL *con)
|
||||
BIO_get_fd(wbio, &fd);
|
||||
}
|
||||
|
||||
if(!wbio || connect(fd, (struct sockaddr *)&client,
|
||||
sizeof(struct sockaddr_storage))) {
|
||||
if(!wbio || BIO_connect(fd, client, 0) == 0) {
|
||||
BIO_printf(bio_err, "ERROR - unable to connect\n");
|
||||
BIO_ADDR_free(client);
|
||||
return 0;
|
||||
}
|
||||
BIO_ADDR_free(client);
|
||||
dtlslisten = 0;
|
||||
i = SSL_accept(con);
|
||||
}
|
||||
|
@ -58,10 +58,8 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#define USE_SOCKETS
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include "bio_lcl.h"
|
||||
#ifndef OPENSSL_NO_DGRAM
|
||||
|
||||
# if !(defined(_WIN32) || defined(OPENSSL_SYS_VMS))
|
||||
@ -156,13 +154,7 @@ static BIO_METHOD methods_dgramp_sctp = {
|
||||
# endif
|
||||
|
||||
typedef struct bio_dgram_data_st {
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sa_in;
|
||||
# if OPENSSL_USE_IPV6
|
||||
struct sockaddr_in6 sa_in6;
|
||||
# endif
|
||||
} peer;
|
||||
BIO_ADDR peer;
|
||||
unsigned int connected;
|
||||
unsigned int _errno;
|
||||
unsigned int mtu;
|
||||
@ -179,13 +171,7 @@ typedef struct bio_dgram_sctp_save_message_st {
|
||||
} bio_dgram_sctp_save_message;
|
||||
|
||||
typedef struct bio_dgram_sctp_data_st {
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sa_in;
|
||||
# if OPENSSL_USE_IPV6
|
||||
struct sockaddr_in6 sa_in6;
|
||||
# endif
|
||||
} peer;
|
||||
BIO_ADDR peer;
|
||||
unsigned int connected;
|
||||
unsigned int _errno;
|
||||
unsigned int mtu;
|
||||
@ -369,40 +355,20 @@ static int dgram_read(BIO *b, char *out, int outl)
|
||||
bio_dgram_data *data = (bio_dgram_data *)b->ptr;
|
||||
int flags = 0;
|
||||
|
||||
struct {
|
||||
/*
|
||||
* See commentary in b_sock.c. <appro>
|
||||
*/
|
||||
union {
|
||||
size_t s;
|
||||
int i;
|
||||
} len;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sa_in;
|
||||
# if OPENSSL_USE_IPV6
|
||||
struct sockaddr_in6 sa_in6;
|
||||
# endif
|
||||
} peer;
|
||||
} sa;
|
||||
|
||||
sa.len.s = 0;
|
||||
sa.len.i = sizeof(sa.peer);
|
||||
BIO_ADDR peer;
|
||||
socklen_t len = sizeof(peer);
|
||||
|
||||
if (out != NULL) {
|
||||
clear_socket_error();
|
||||
memset(&sa.peer, 0, sizeof(sa.peer));
|
||||
memset(&peer, 0, sizeof(peer));
|
||||
dgram_adjust_rcv_timeout(b);
|
||||
if (data->peekmode)
|
||||
flags = MSG_PEEK;
|
||||
ret = recvfrom(b->num, out, outl, flags, &sa.peer.sa, (void *)&sa.len);
|
||||
if (sizeof(sa.len.i) != sizeof(sa.len.s) && sa.len.i == 0) {
|
||||
OPENSSL_assert(sa.len.s <= sizeof(sa.peer));
|
||||
sa.len.i = (int)sa.len.s;
|
||||
}
|
||||
ret = recvfrom(b->num, out, outl, flags,
|
||||
BIO_ADDR_sockaddr_noconst(&peer), &len);
|
||||
|
||||
if (!data->connected && ret >= 0)
|
||||
BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer);
|
||||
BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &peer);
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret < 0) {
|
||||
@ -426,18 +392,14 @@ static int dgram_write(BIO *b, const char *in, int inl)
|
||||
if (data->connected)
|
||||
ret = writesocket(b->num, in, inl);
|
||||
else {
|
||||
int peerlen = sizeof(data->peer);
|
||||
int peerlen = BIO_ADDR_sockaddr_size(&data->peer);
|
||||
|
||||
if (data->peer.sa.sa_family == AF_INET)
|
||||
peerlen = sizeof(data->peer.sa_in);
|
||||
# if OPENSSL_USE_IPV6
|
||||
else if (data->peer.sa.sa_family == AF_INET6)
|
||||
peerlen = sizeof(data->peer.sa_in6);
|
||||
# endif
|
||||
# if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
|
||||
ret = sendto(b->num, (char *)in, inl, 0, &data->peer.sa, peerlen);
|
||||
ret = sendto(b->num, (char *)in, inl, 0,
|
||||
BIO_ADDR_sockaddr(&data->peer), peerlen);
|
||||
# else
|
||||
ret = sendto(b->num, in, inl, 0, &data->peer.sa, peerlen);
|
||||
ret = sendto(b->num, in, inl, 0,
|
||||
BIO_ADDR_sockaddr(&data->peer), peerlen);
|
||||
# endif
|
||||
}
|
||||
|
||||
@ -455,27 +417,31 @@ static long dgram_get_mtu_overhead(bio_dgram_data *data)
|
||||
{
|
||||
long ret;
|
||||
|
||||
switch (data->peer.sa.sa_family) {
|
||||
switch (BIO_ADDR_family(&data->peer)) {
|
||||
case AF_INET:
|
||||
/*
|
||||
* Assume this is UDP - 20 bytes for IP, 8 bytes for UDP
|
||||
*/
|
||||
ret = 28;
|
||||
break;
|
||||
# if OPENSSL_USE_IPV6
|
||||
# ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
# ifdef IN6_IS_ADDR_V4MAPPED
|
||||
if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
|
||||
/*
|
||||
* Assume this is UDP - 20 bytes for IP, 8 bytes for UDP
|
||||
*/
|
||||
ret = 28;
|
||||
else
|
||||
struct in6_addr tmp_addr;
|
||||
if (BIO_ADDR_rawaddress(&data->peer, &tmp_addr, NULL)
|
||||
&& IN6_IS_ADDR_V4MAPPED(&tmp_addr))
|
||||
/*
|
||||
* Assume this is UDP - 20 bytes for IP, 8 bytes for UDP
|
||||
*/
|
||||
ret = 28;
|
||||
else
|
||||
# endif
|
||||
/*
|
||||
* Assume this is UDP - 40 bytes for IP, 8 bytes for UDP
|
||||
*/
|
||||
ret = 48;
|
||||
}
|
||||
break;
|
||||
# endif
|
||||
default:
|
||||
@ -490,20 +456,13 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
long ret = 1;
|
||||
int *ip;
|
||||
struct sockaddr *to = NULL;
|
||||
bio_dgram_data *data = NULL;
|
||||
int sockopt_val = 0;
|
||||
# if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
|
||||
socklen_t sockopt_len; /* assume that system supporting IP_MTU is
|
||||
* modern enough to define socklen_t */
|
||||
socklen_t addr_len;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in s4;
|
||||
# if OPENSSL_USE_IPV6
|
||||
struct sockaddr_in6 s6;
|
||||
# endif
|
||||
} addr;
|
||||
BIO_ADDR addr;
|
||||
# endif
|
||||
|
||||
data = (bio_dgram_data *)b->ptr;
|
||||
@ -546,20 +505,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
ret = 1;
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_CONNECT:
|
||||
to = (struct sockaddr *)ptr;
|
||||
switch (to->sa_family) {
|
||||
case AF_INET:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in));
|
||||
break;
|
||||
# if OPENSSL_USE_IPV6
|
||||
case AF_INET6:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
|
||||
break;
|
||||
# endif
|
||||
default:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa));
|
||||
break;
|
||||
}
|
||||
BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr));
|
||||
break;
|
||||
/* (Linux)kernel sets DF bit on outgoing IP packets */
|
||||
case BIO_CTRL_DGRAM_MTU_DISCOVER:
|
||||
@ -644,18 +590,22 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
|
||||
ret = -dgram_get_mtu_overhead(data);
|
||||
switch (data->peer.sa.sa_family) {
|
||||
switch (BIO_ADDR_family(&data->peer)) {
|
||||
case AF_INET:
|
||||
ret += 576;
|
||||
break;
|
||||
# if OPENSSL_USE_IPV6
|
||||
case AF_INET6:
|
||||
{
|
||||
# ifdef IN6_IS_ADDR_V4MAPPED
|
||||
if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
|
||||
ret += 576;
|
||||
else
|
||||
struct in6_addr tmp_addr;
|
||||
if (BIO_ADDR_rawaddress(&data->peer, &tmp_addr, NULL)
|
||||
&& IN6_IS_ADDR_V4MAPPED(&tmp_addr))
|
||||
ret += 576;
|
||||
else
|
||||
# endif
|
||||
ret += 1280;
|
||||
ret += 1280;
|
||||
}
|
||||
break;
|
||||
# endif
|
||||
default:
|
||||
@ -670,61 +620,24 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
ret = num;
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_SET_CONNECTED:
|
||||
to = (struct sockaddr *)ptr;
|
||||
|
||||
if (to != NULL) {
|
||||
if (ptr != NULL) {
|
||||
data->connected = 1;
|
||||
switch (to->sa_family) {
|
||||
case AF_INET:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in));
|
||||
break;
|
||||
# if OPENSSL_USE_IPV6
|
||||
case AF_INET6:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
|
||||
break;
|
||||
# endif
|
||||
default:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa));
|
||||
break;
|
||||
}
|
||||
BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr));
|
||||
} else {
|
||||
data->connected = 0;
|
||||
memset(&data->peer, 0, sizeof(data->peer));
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_GET_PEER:
|
||||
switch (data->peer.sa.sa_family) {
|
||||
case AF_INET:
|
||||
ret = sizeof(data->peer.sa_in);
|
||||
break;
|
||||
# if OPENSSL_USE_IPV6
|
||||
case AF_INET6:
|
||||
ret = sizeof(data->peer.sa_in6);
|
||||
break;
|
||||
# endif
|
||||
default:
|
||||
ret = sizeof(data->peer.sa);
|
||||
break;
|
||||
}
|
||||
ret = BIO_ADDR_sockaddr_size(&data->peer);
|
||||
/* FIXME: if num < ret, we will only return part of an address.
|
||||
That should bee an error, no? */
|
||||
if (num == 0 || num > ret)
|
||||
num = ret;
|
||||
memcpy(ptr, &data->peer, (ret = num));
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_SET_PEER:
|
||||
to = (struct sockaddr *)ptr;
|
||||
switch (to->sa_family) {
|
||||
case AF_INET:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in));
|
||||
break;
|
||||
# if OPENSSL_USE_IPV6
|
||||
case AF_INET6:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
|
||||
break;
|
||||
# endif
|
||||
default:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa));
|
||||
break;
|
||||
}
|
||||
BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr));
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
|
||||
memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
|
||||
|
14
ssl/d1_lib.c
14
ssl/d1_lib.c
@ -75,7 +75,7 @@
|
||||
static void get_current_time(struct timeval *t);
|
||||
static int dtls1_set_handshake_header(SSL *s, int type, unsigned long len);
|
||||
static int dtls1_handshake_write(SSL *s);
|
||||
int dtls1_listen(SSL *s, struct sockaddr *client);
|
||||
int dtls1_listen(SSL *s, BIO_ADDR *client);
|
||||
static unsigned int dtls1_link_min_mtu(void);
|
||||
|
||||
/* XDTLS: figure out the right values */
|
||||
@ -484,7 +484,7 @@ static void get_current_time(struct timeval *t)
|
||||
#define LISTEN_SEND_VERIFY_REQUEST 1
|
||||
|
||||
|
||||
int dtls1_listen(SSL *s, struct sockaddr *client)
|
||||
int dtls1_listen(SSL *s, BIO_ADDR *client)
|
||||
{
|
||||
int next, n, ret = 0, clearpkt = 0;
|
||||
unsigned char cookie[DTLS1_COOKIE_LENGTH];
|
||||
@ -495,7 +495,7 @@ int dtls1_listen(SSL *s, struct sockaddr *client)
|
||||
unsigned int rectype, versmajor, msgseq, msgtype, clientvers, cookielen;
|
||||
BIO *rbio, *wbio;
|
||||
BUF_MEM *bufm;
|
||||
struct sockaddr_storage tmpclient;
|
||||
BIO_ADDR *tmpclient = NULL;
|
||||
PACKET pkt, msgpkt, msgpayload, session, cookiepkt;
|
||||
|
||||
/* Ensure there is no state left over from a previous invocation */
|
||||
@ -805,11 +805,14 @@ int dtls1_listen(SSL *s, struct sockaddr *client)
|
||||
* This is unneccessary if rbio and wbio are one and the same - but
|
||||
* maybe they're not.
|
||||
*/
|
||||
if(BIO_dgram_get_peer(rbio, &tmpclient) <= 0
|
||||
|| BIO_dgram_set_peer(wbio, &tmpclient) <= 0) {
|
||||
if ((tmpclient = BIO_ADDR_new()) == NULL
|
||||
|| BIO_dgram_get_peer(rbio, tmpclient) <= 0
|
||||
|| BIO_dgram_set_peer(wbio, tmpclient) <= 0) {
|
||||
SSLerr(SSL_F_DTLS1_LISTEN, ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
BIO_ADDR_free(tmpclient);
|
||||
tmpclient = NULL;
|
||||
|
||||
if (BIO_write(wbio, buf, reclen) < (int)reclen) {
|
||||
if(BIO_should_retry(wbio)) {
|
||||
@ -863,6 +866,7 @@ int dtls1_listen(SSL *s, struct sockaddr *client)
|
||||
ret = 1;
|
||||
clearpkt = 0;
|
||||
end:
|
||||
BIO_ADDR_free(tmpclient);
|
||||
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL);
|
||||
if (clearpkt) {
|
||||
/* Dump this packet. Ignore return value */
|
||||
|
Loading…
Reference in New Issue
Block a user