Iplemented clean DTLS cookie handling.

Also certificate check is available, still with a hard-coded pem file.

FossilOrigin-Name: 2fb98eb2bf9e07bd7f21223dea499a992a7c38c963cfbeabbba2f7aa8ccd82af
This commit is contained in:
7u83@mail.ru 2014-08-16 10:38:04 +00:00
parent 14e08f96b5
commit 396c3ea5e0
1 changed files with 48 additions and 176 deletions

View File

@ -25,8 +25,10 @@
#include "dtls_openssl.h"
#include "cw_log.h"
#include "conn.h"
#include "cw_util.h"
#include "conn.h"
#include "sock.h"
#ifdef WITH_CW_LOG_DEBUG
@ -199,6 +201,11 @@ int dtls_openssl_set_certs(struct conn * conn, struct dtls_openssl_data *d)
int generate_session_id(const SSL *ssl, unsigned char * id, unsigned int *id_len)
{
/* BIO * b = SSL_get_rbio(ssl);
struct conn * conn = b->ptr;
*/
// printf ("MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMaking session id\n");
const char * sessid = "123456789";
memcpy(id,sessid,strlen(sessid));
@ -244,12 +251,18 @@ struct dtls_openssl_data * dtls_openssl_data_create(struct conn * conn, const SS
}
// SSL_CTX_set_session_cache_mode(d->ctx, SSL_SESS_CACHE_BOTH);
SSL_CTX_set_options(d->ctx, SSL_OP_COOKIE_EXCHANGE|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TICKET);
SSL_CTX_set_options(d->ctx, SSL_OP_COOKIE_EXCHANGE); //|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TICKET);
rc = SSL_CTX_load_verify_locations(d->ctx,"/home/tube/v/actube/ssl/root-ca.pem",NULL);
printf("Locations RC = %d\n",rc);
// SSL_CTX_set_options(d->ctx, SSL_OP_ALL);
SSL_CTX_set_cookie_generate_cb(d->ctx, dtls_openssl_generate_cookie);
SSL_CTX_set_cookie_verify_cb(d->ctx, dtls_openssl_verify_cookie);
// SSL_CTX_set_generate_session_id(d->ctx,generate_session_id);
@ -257,7 +270,8 @@ struct dtls_openssl_data * dtls_openssl_data_create(struct conn * conn, const SS
// SSL_CTX_set_verify(d->ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback);
SSL_CTX_set_verify(d->ctx, SSL_VERIFY_PEER, dtls_verify_callback);
// SSL_CTX_set_verify(d->ctx, SSL_VERIFY_PEER, dtls_verify_callback);
SSL_CTX_set_verify(d->ctx, SSL_VERIFY_PEER, NULL);
// SSL_CTX_set_tmp_rsa_callback(d->ctx,tmp_rsa_callback);
@ -403,195 +417,48 @@ int dtls_openssl_shutdown(struct conn *conn)
int cookie_initialized=0;
#define COOKIE_SECRET_LENGTH 16
unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
//int cookie_initialized=0;
//#define COOKIE_SECRET_LENGTH 16
//unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
int dtls_openssl_generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)
{
BIO * b = SSL_get_rbio(ssl);
struct conn * conn = b->ptr;
//printf(" Gen cookie!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
cw_rand(conn->dtls_cookie,sizeof(conn->dtls_cookie));
const char * coo = "1234567890123456";
memcpy(cookie,coo,strlen(coo));
*cookie_len=strlen(coo);
/* we "missuse" sockaddr2str to convert our cookie to a hex str */
cw_dbg(DBG_DTLS,"DTLS session cookie for %s generated: %s",
sock_addr2str(&conn->addr), sock_hwaddr2idstr(conn->dtls_cookie,sizeof(conn->dtls_cookie)));
memcpy(cookie,conn->dtls_cookie,sizeof(conn->dtls_cookie));
*cookie_len=sizeof(conn->dtls_cookie);
return 1;
unsigned char *buffer, result[EVP_MAX_MD_SIZE];
unsigned int length = 0, resultlength;
union {
struct sockaddr_storage ss;
struct sockaddr_in6 s6;
struct sockaddr_in s4;
} peer;
/* Initialize a random secret */
if (!cookie_initialized)
{
if (!RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH))
{
printf("error setting random cookie secret\n");
return 0;
}
cookie_initialized = 1;
}
return 1;
/* Read peer information */
(void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
/* Create buffer with peer's address and port */
length = 0;
switch (peer.ss.ss_family) {
case AF_INET:
length += sizeof(struct in_addr);
break;
case AF_INET6:
length += sizeof(struct in6_addr);
break;
default:
OPENSSL_assert(0);
break;
}
length += sizeof(in_port_t);
buffer = (unsigned char*) OPENSSL_malloc(length);
if (buffer == NULL) {
printf("out of memory\n");
return 0;
}
switch (peer.ss.ss_family) {
case AF_INET:
memcpy(buffer,
&peer.s4.sin_port,
sizeof(in_port_t));
memcpy(buffer + sizeof(peer.s4.sin_port),
&peer.s4.sin_addr,
sizeof(struct in_addr));
break;
case AF_INET6:
memcpy(buffer,
&peer.s6.sin6_port,
sizeof(in_port_t));
memcpy(buffer + sizeof(in_port_t),
&peer.s6.sin6_addr,
sizeof(struct in6_addr));
break;
default:
OPENSSL_assert(0);
break;
}
/* Calculate HMAC of buffer using the secret */
HMAC(EVP_sha1(), (const void*) cookie_secret, COOKIE_SECRET_LENGTH,
(const unsigned char*) buffer, length, result, &resultlength);
OPENSSL_free(buffer);
memcpy(cookie, result, resultlength);
*cookie_len = resultlength;
return 1;
}
int dtls_openssl_verify_cookie(SSL *ssl, unsigned char *cookie, unsigned int cookie_len)
int dtls_openssl_verify_cookie(SSL *ssl, unsigned char *cookie, unsigned int len)
{
BIO * b = SSL_get_rbio(ssl);
struct conn * conn = b->ptr;
//printf(" Verify cookie!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
char t[400];
strncpy(t,(char*)cookie,cookie_len);
t[cookie_len]=0;
// printf("TCoo: %s\n",t);
cw_dbg(DBG_DTLS,"Verifying DTLS cookie from %s: %s",
sock_addr2str(&conn->addr),sock_hwaddr2idstr(conn->dtls_cookie,len));
if (len != sizeof(conn->dtls_cookie)){
return 0;
}
if (memcmp(cookie,conn->dtls_cookie,len)!=0){
return 0;
}
return 1;
unsigned char *buffer, result[EVP_MAX_MD_SIZE];
unsigned int length = 0, resultlength;
union {
struct sockaddr_storage ss;
struct sockaddr_in6 s6;
struct sockaddr_in s4;
} peer;
/* If secret isn't initialized yet, the cookie can't be valid */
if (!cookie_initialized)
return 0;
/* Read peer information */
(void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
/* Create buffer with peer's address and port */
length = 0;
switch (peer.ss.ss_family) {
case AF_INET:
length += sizeof(struct in_addr);
break;
case AF_INET6:
length += sizeof(struct in6_addr);
break;
default:
OPENSSL_assert(0);
break;
}
length += sizeof(in_port_t);
buffer = (unsigned char*) OPENSSL_malloc(length);
if (buffer == NULL){
printf("out of memory\n");
return 0;
}
switch (peer.ss.ss_family) {
case AF_INET:
memcpy(buffer,
&peer.s4.sin_port,
sizeof(in_port_t));
memcpy(buffer + sizeof(in_port_t),
&peer.s4.sin_addr,
sizeof(struct in_addr));
break;
case AF_INET6:
memcpy(buffer,
&peer.s6.sin6_port,
sizeof(in_port_t));
memcpy(buffer + sizeof(in_port_t),
&peer.s6.sin6_addr,
sizeof(struct in6_addr));
break;
default:
OPENSSL_assert(0);
break;
}
/* Calculate HMAC of buffer using the secret */
HMAC(EVP_sha1(), (const void*) cookie_secret, COOKIE_SECRET_LENGTH,
(const unsigned char*) buffer, length, result, &resultlength);
OPENSSL_free(buffer);
if (cookie_len == resultlength && memcmp(result, cookie, resultlength) == 0)
return 1;
return 0;
}
/*
struct pass_info {
union {
struct sockaddr_storage ss;
struct sockaddr_in6 s6;
struct sockaddr_in s4;
} server_addr, client_addr;
SSL *ssl;
};
*/
}
int dtls_openssl_read(struct conn * conn, uint8_t *buffer, int len)
@ -608,6 +475,11 @@ int dtls_openssl_read(struct conn * conn, uint8_t *buffer, int len)
int dtls_openssl_write(struct conn * conn, const uint8_t *buffer, int len)
{
struct dtls_openssl_data * d = conn->dtls_data;
return SSL_write(d->ssl,buffer,len);
int rc = SSL_write(d->ssl,buffer,len);
if (dtls_openssl_log_error_queue("DTLS write error:")){
conn->dtls_error=1;
return -1;
}
return rc;
}