mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-13 18:12:03 +08:00
simplified ciphersuite selection method and select ciphers based on server's desire.
This commit is contained in:
+77
-63
@@ -184,9 +184,65 @@ int url_cb(http_parser * parser, const char *at, size_t length)
|
|||||||
#define CS_AES128_GCM "OC-DTLS1_2-AES128-GCM"
|
#define CS_AES128_GCM "OC-DTLS1_2-AES128-GCM"
|
||||||
#define CS_AES256_GCM "OC-DTLS1_2-AES256-GCM"
|
#define CS_AES256_GCM "OC-DTLS1_2-AES256-GCM"
|
||||||
|
|
||||||
|
/* Consider switching to gperf when this table grows significantly.
|
||||||
|
*/
|
||||||
|
static const dtls_ciphersuite_st ciphersuites[] =
|
||||||
|
{
|
||||||
|
#if GNUTLS_VERSION_NUMBER >= 0x030207
|
||||||
|
{
|
||||||
|
.oc_name = CS_ESALSA20,
|
||||||
|
.gnutls_name = "NONE:+VERS-DTLS1.2:+COMP-NULL:+ESTREAM-SALSA20-256:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION",
|
||||||
|
.gnutls_version = GNUTLS_DTLS1_2,
|
||||||
|
.gnutls_mac = GNUTLS_MAC_SHA1,
|
||||||
|
.gnutls_cipher = GNUTLS_CIPHER_ESTREAM_SALSA20_256,
|
||||||
|
.server_prio = 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.oc_name = CS_SALSA20,
|
||||||
|
.gnutls_name = "NONE:+VERS-DTLS1.2:+COMP-NULL:+SALSA20-256:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION",
|
||||||
|
.gnutls_version = GNUTLS_DTLS1_2,
|
||||||
|
.gnutls_mac = GNUTLS_MAC_SHA1,
|
||||||
|
.gnutls_cipher = GNUTLS_CIPHER_SALSA20_256,
|
||||||
|
.server_prio = 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.oc_name = CS_AES128_GCM,
|
||||||
|
.gnutls_name = "NONE:+VERS-DTLS1.2:+COMP-NULL:+AES-128-GCM:+AEAD:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION:+SIGN-ALL",
|
||||||
|
.gnutls_version = GNUTLS_DTLS1_2,
|
||||||
|
.gnutls_mac = GNUTLS_MAC_AEAD,
|
||||||
|
.gnutls_cipher = GNUTLS_CIPHER_AES_128_GCM,
|
||||||
|
.server_prio = 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.oc_name = CS_AES256_GCM,
|
||||||
|
.gnutls_name = "NONE:+VERS-DTLS1.2:+COMP-NULL:+AES-256-GCM:+AEAD:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION:+SIGN-ALL",
|
||||||
|
.gnutls_version = GNUTLS_DTLS1_2,
|
||||||
|
.gnutls_mac = GNUTLS_MAC_AEAD,
|
||||||
|
.gnutls_cipher = GNUTLS_CIPHER_AES_256_GCM,
|
||||||
|
.server_prio = 80,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
.oc_name = "AES128-SHA",
|
||||||
|
.gnutls_name = "NONE:+VERS-DTLS0.9:+COMP-NULL:+AES-128-CBC:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION",
|
||||||
|
.gnutls_version = GNUTLS_DTLS0_9,
|
||||||
|
.gnutls_mac = GNUTLS_MAC_SHA1,
|
||||||
|
.gnutls_cipher = GNUTLS_CIPHER_AES_128_CBC,
|
||||||
|
.server_prio = 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.oc_name = "DES-CBC3-SHA",
|
||||||
|
.gnutls_name = "NONE:+VERS-DTLS0.9:+COMP-NULL:+3DES-CBC:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION",
|
||||||
|
.gnutls_version = GNUTLS_DTLS0_9,
|
||||||
|
.gnutls_mac = GNUTLS_MAC_SHA1,
|
||||||
|
.gnutls_cipher = GNUTLS_CIPHER_3DES_CBC,
|
||||||
|
.server_prio = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static void value_check(struct worker_st *ws, struct http_req_st *req)
|
static void value_check(struct worker_st *ws, struct http_req_st *req)
|
||||||
{
|
{
|
||||||
unsigned length;
|
unsigned length, i;
|
||||||
int ret;
|
int ret;
|
||||||
size_t nlen;
|
size_t nlen;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
@@ -232,60 +288,18 @@ static void value_check(struct worker_st *ws, struct http_req_st *req)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case HEADER_DTLS_CIPHERSUITE:
|
case HEADER_DTLS_CIPHERSUITE:
|
||||||
|
req->selected_ciphersuite = NULL;
|
||||||
|
|
||||||
str = (char *)req->value.data;
|
str = (char *)req->value.data;
|
||||||
while ((token = strtok(str, ":")) != NULL) {
|
while ((token = strtok(str, ":")) != NULL) {
|
||||||
#if GNUTLS_VERSION_NUMBER >= 0x030207
|
for (i=0;i<sizeof(ciphersuites)/sizeof(ciphersuites[0]);i++) {
|
||||||
if (strcmp(token, CS_ESALSA20) == 0) {
|
if (strcmp(token, ciphersuites[i].oc_name) == 0) {
|
||||||
req->selected_ciphersuite = CS_ESALSA20;
|
if (req->selected_ciphersuite == NULL ||
|
||||||
req->gnutls_ciphersuite =
|
req->selected_ciphersuite->server_prio < ciphersuites[i].server_prio) {
|
||||||
"NONE:+VERS-DTLS1.2:+COMP-NULL:+ESTREAM-SALSA20-256:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION";
|
|
||||||
req->gnutls_cipher =
|
req->selected_ciphersuite = &ciphersuites[i];
|
||||||
GNUTLS_CIPHER_ESTREAM_SALSA20_256;
|
}
|
||||||
req->gnutls_mac = GNUTLS_MAC_SHA1;
|
}
|
||||||
req->gnutls_version = GNUTLS_DTLS1_2;
|
|
||||||
break;
|
|
||||||
} else if (strcmp(token, CS_SALSA20) == 0) {
|
|
||||||
req->selected_ciphersuite = CS_SALSA20;
|
|
||||||
req->gnutls_ciphersuite =
|
|
||||||
"NONE:+VERS-DTLS1.2:+COMP-NULL:+SALSA20-256:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION";
|
|
||||||
req->gnutls_cipher = GNUTLS_CIPHER_SALSA20_256;
|
|
||||||
req->gnutls_mac = GNUTLS_MAC_SHA1;
|
|
||||||
req->gnutls_version = GNUTLS_DTLS1_2;
|
|
||||||
break;
|
|
||||||
} else if (strcmp(token, CS_AES128_GCM) == 0) {
|
|
||||||
req->selected_ciphersuite = CS_AES128_GCM;
|
|
||||||
req->gnutls_ciphersuite =
|
|
||||||
"NONE:+VERS-DTLS1.2:+COMP-NULL:+AES-128-GCM:+AEAD:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION:+SIGN-ALL";
|
|
||||||
req->gnutls_cipher = GNUTLS_CIPHER_AES_128_GCM;
|
|
||||||
req->gnutls_mac = GNUTLS_MAC_AEAD;
|
|
||||||
req->gnutls_version = GNUTLS_DTLS1_2;
|
|
||||||
break;
|
|
||||||
} else if (strcmp(token, CS_AES256_GCM) == 0) {
|
|
||||||
req->selected_ciphersuite = CS_AES256_GCM;
|
|
||||||
req->gnutls_ciphersuite =
|
|
||||||
"NONE:+VERS-DTLS1.2:+COMP-NULL:+AES-256-GCM:+AEAD:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION:+SIGN-ALL";
|
|
||||||
req->gnutls_cipher = GNUTLS_CIPHER_AES_256_GCM;
|
|
||||||
req->gnutls_mac = GNUTLS_MAC_AEAD;
|
|
||||||
req->gnutls_version = GNUTLS_DTLS1_2;
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (strcmp(token, "AES128-SHA") == 0) {
|
|
||||||
req->gnutls_ciphersuite =
|
|
||||||
"NONE:+VERS-DTLS0.9:+COMP-NULL:+AES-128-CBC:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION";
|
|
||||||
req->selected_ciphersuite = "AES128-SHA";
|
|
||||||
req->gnutls_cipher = GNUTLS_CIPHER_AES_128_CBC;
|
|
||||||
req->gnutls_mac = GNUTLS_MAC_SHA1;
|
|
||||||
req->gnutls_version = GNUTLS_DTLS0_9;
|
|
||||||
break;
|
|
||||||
} else if (strcmp(token, "DES-CBC3-SHA") == 0) {
|
|
||||||
req->gnutls_ciphersuite =
|
|
||||||
"NONE:+VERS-DTLS0.9:+COMP-NULL:+3DES-CBC:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION";
|
|
||||||
req->selected_ciphersuite = "DES-CBC3-SHA";
|
|
||||||
req->gnutls_cipher = GNUTLS_CIPHER_3DES_CBC;
|
|
||||||
req->gnutls_mac = GNUTLS_MAC_SHA1;
|
|
||||||
req->gnutls_version = GNUTLS_DTLS0_9;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
str = NULL;
|
str = NULL;
|
||||||
}
|
}
|
||||||
@@ -476,7 +490,7 @@ static int setup_dtls_connection(struct worker_st *ws)
|
|||||||
{ ws->master_secret, sizeof(ws->master_secret) };
|
{ ws->master_secret, sizeof(ws->master_secret) };
|
||||||
gnutls_datum_t sid = { ws->session_id, sizeof(ws->session_id) };
|
gnutls_datum_t sid = { ws->session_id, sizeof(ws->session_id) };
|
||||||
|
|
||||||
if (ws->req.gnutls_ciphersuite == NULL) {
|
if (ws->req.selected_ciphersuite == NULL) {
|
||||||
oclog(ws, LOG_ERR, "no DTLS ciphersuite negotiated");
|
oclog(ws, LOG_ERR, "no DTLS ciphersuite negotiated");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -493,7 +507,7 @@ static int setup_dtls_connection(struct worker_st *ws)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
gnutls_priority_set_direct(session, ws->req.gnutls_ciphersuite,
|
gnutls_priority_set_direct(session, ws->req.selected_ciphersuite->gnutls_name,
|
||||||
NULL);
|
NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
oclog(ws, LOG_ERR, "could not set TLS priority: %s",
|
oclog(ws, LOG_ERR, "could not set TLS priority: %s",
|
||||||
@@ -502,9 +516,9 @@ static int setup_dtls_connection(struct worker_st *ws)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = gnutls_session_set_premaster(session, GNUTLS_SERVER,
|
ret = gnutls_session_set_premaster(session, GNUTLS_SERVER,
|
||||||
ws->req.gnutls_version,
|
ws->req.selected_ciphersuite->gnutls_version,
|
||||||
GNUTLS_KX_RSA, ws->req.gnutls_cipher,
|
GNUTLS_KX_RSA, ws->req.selected_ciphersuite->gnutls_cipher,
|
||||||
ws->req.gnutls_mac, GNUTLS_COMP_NULL,
|
ws->req.selected_ciphersuite->gnutls_mac, GNUTLS_COMP_NULL,
|
||||||
&master, &sid);
|
&master, &sid);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
oclog(ws, LOG_ERR, "could not set TLS premaster: %s",
|
oclog(ws, LOG_ERR, "could not set TLS premaster: %s",
|
||||||
@@ -776,7 +790,7 @@ void session_info_send(worker_st * ws)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ws->udp_state != UP_DISABLED) {
|
if (ws->udp_state != UP_DISABLED) {
|
||||||
msg.dtls_ciphersuite = ws->req.selected_ciphersuite;
|
msg.dtls_ciphersuite = (char*)ws->req.selected_ciphersuite->oc_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ws->req.user_agent[0] != 0) {
|
if (ws->req.user_agent[0] != 0) {
|
||||||
@@ -1264,10 +1278,10 @@ static int connect_handler(worker_st * ws)
|
|||||||
SEND_ERR(ret);
|
SEND_ERR(ret);
|
||||||
|
|
||||||
oclog(ws, LOG_INFO, "DTLS ciphersuite: %s",
|
oclog(ws, LOG_INFO, "DTLS ciphersuite: %s",
|
||||||
ws->req.selected_ciphersuite);
|
ws->req.selected_ciphersuite->oc_name);
|
||||||
ret =
|
ret =
|
||||||
tls_printf(ws->session, "X-DTLS-CipherSuite: %s\r\n",
|
tls_printf(ws->session, "X-DTLS-CipherSuite: %s\r\n",
|
||||||
ws->req.selected_ciphersuite);
|
ws->req.selected_ciphersuite->oc_name);
|
||||||
SEND_ERR(ret);
|
SEND_ERR(ret);
|
||||||
|
|
||||||
/* assume that if IPv6 is used over TCP then the same would be used over UDP */
|
/* assume that if IPv6 is used over TCP then the same would be used over UDP */
|
||||||
@@ -1287,8 +1301,8 @@ static int connect_handler(worker_st * ws)
|
|||||||
|
|
||||||
overhead =
|
overhead =
|
||||||
CSTP_DTLS_OVERHEAD +
|
CSTP_DTLS_OVERHEAD +
|
||||||
tls_get_overhead(ws->req.gnutls_version,
|
tls_get_overhead(ws->req.selected_ciphersuite->gnutls_version,
|
||||||
ws->req.gnutls_cipher, ws->req.gnutls_mac);
|
ws->req.selected_ciphersuite->gnutls_cipher, ws->req.selected_ciphersuite->gnutls_mac);
|
||||||
dtls_mtu = ws->conn_mtu - overhead;
|
dtls_mtu = ws->conn_mtu - overhead;
|
||||||
|
|
||||||
tls_printf(ws->session, "X-DTLS-MTU: %u\r\n", dtls_mtu);
|
tls_printf(ws->session, "X-DTLS-MTU: %u\r\n", dtls_mtu);
|
||||||
|
|||||||
+10
-5
@@ -67,6 +67,15 @@ enum {
|
|||||||
S_AUTH_COMPLETE
|
S_AUTH_COMPLETE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct dtls_ciphersuite_st {
|
||||||
|
const char* oc_name;
|
||||||
|
const char* gnutls_name; /* the gnutls priority string to set */
|
||||||
|
unsigned server_prio; /* the highest the more we want to negotiate that */
|
||||||
|
unsigned gnutls_cipher;
|
||||||
|
unsigned gnutls_mac;
|
||||||
|
unsigned gnutls_version;
|
||||||
|
} dtls_ciphersuite_st;
|
||||||
|
|
||||||
struct http_req_st {
|
struct http_req_st {
|
||||||
char url[256];
|
char url[256];
|
||||||
|
|
||||||
@@ -87,11 +96,7 @@ struct http_req_st {
|
|||||||
char *body;
|
char *body;
|
||||||
unsigned int body_length;
|
unsigned int body_length;
|
||||||
|
|
||||||
char *gnutls_ciphersuite; /* static string */
|
const dtls_ciphersuite_st *selected_ciphersuite;
|
||||||
char *selected_ciphersuite; /* static string */
|
|
||||||
int gnutls_cipher;
|
|
||||||
int gnutls_mac;
|
|
||||||
int gnutls_version;
|
|
||||||
|
|
||||||
unsigned int headers_complete;
|
unsigned int headers_complete;
|
||||||
unsigned int message_complete;
|
unsigned int message_complete;
|
||||||
|
|||||||
Reference in New Issue
Block a user