Add support for 'connect dtls://foo' without needing extra upgrading stuff first. This change allows for QEx to establish a dtls connection to our server, though the reverse still doesn't work.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6156 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
310bf64d83
commit
bf44769b4d
|
@ -294,6 +294,13 @@ ELSEIF(${UNIX} AND NOT FTE_USE_SDL) #linux(ish)
|
||||||
IF(NOT GNUTLS_FOUND)
|
IF(NOT GNUTLS_FOUND)
|
||||||
MESSAGE(WARNING "gnutls library NOT available. HTTPS/DTLS will not be available.")
|
MESSAGE(WARNING "gnutls library NOT available. HTTPS/DTLS will not be available.")
|
||||||
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_GNUTLS)
|
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_GNUTLS)
|
||||||
|
ELSE()
|
||||||
|
SET(GNUTLS_STATIC false CACHE BOOL "Link gnutls statically.") #usually as an .so though. :/
|
||||||
|
IF(GNUTLS_STATIC)
|
||||||
|
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};GNUTLS_STATIC)
|
||||||
|
SET(FTE_LIBS ${FTE_LIBS} ${GNUTLS_LIBRARY})
|
||||||
|
SET(FTESV_LIBS ${FTESV_LIBS} ${GNUTLS_LIBRARY})
|
||||||
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
#linux-only packages
|
#linux-only packages
|
||||||
|
@ -1207,7 +1214,7 @@ IF(FTE_PLUG_MPQ)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
#vpk package format plugin (halflife2)
|
#vpk package format plugin (halflife2)
|
||||||
SET(FTE_PLUG_HL2 false CACHE BOOL "Compile support for hl2 file formats.")
|
SET(FTE_PLUG_HL2 true CACHE BOOL "Compile support for hl2 file formats.")
|
||||||
IF(FTE_PLUG_HL2)
|
IF(FTE_PLUG_HL2)
|
||||||
ADD_LIBRARY(plug_hl2 MODULE
|
ADD_LIBRARY(plug_hl2 MODULE
|
||||||
plugins/plugin.c
|
plugins/plugin.c
|
||||||
|
|
|
@ -1200,7 +1200,7 @@ void CL_CheckForResend (void)
|
||||||
if (!connectinfo.clogged)
|
if (!connectinfo.clogged)
|
||||||
connectinfo.time = realtime+t2-t1; // for retransmit requests
|
connectinfo.time = realtime+t2-t1; // for retransmit requests
|
||||||
|
|
||||||
to = &connectinfo.adr[connectinfo.nextadr++%connectinfo.numadr];
|
to = &connectinfo.adr[connectinfo.nextadr%connectinfo.numadr];
|
||||||
if (!NET_IsClientLegal(to))
|
if (!NET_IsClientLegal(to))
|
||||||
{
|
{
|
||||||
Cvar_Set(&cl_disconnectreason, va("Illegal server address"));
|
Cvar_Set(&cl_disconnectreason, va("Illegal server address"));
|
||||||
|
@ -1225,7 +1225,7 @@ void CL_CheckForResend (void)
|
||||||
Con_TPrintf ("Connecting to %s...\n", cls.servername);
|
Con_TPrintf ("Connecting to %s...\n", cls.servername);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectinfo.tries == 0 && to == &connectinfo.adr[0])
|
if (connectinfo.tries == 0 && connectinfo.nextadr < connectinfo.numadr)
|
||||||
if (!NET_EnsureRoute(cls.sockets, "conn", cls.servername, to))
|
if (!NET_EnsureRoute(cls.sockets, "conn", cls.servername, to))
|
||||||
{
|
{
|
||||||
Cvar_Set(&cl_disconnectreason, va("Unable to establish connection to %s\n", cls.servername));
|
Cvar_Set(&cl_disconnectreason, va("Unable to establish connection to %s\n", cls.servername));
|
||||||
|
@ -1235,8 +1235,10 @@ void CL_CheckForResend (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (to->prot == NP_DGRAM)
|
||||||
|
connectinfo.nextadr++; //cycle hosts with each ping (if we got multiple).
|
||||||
|
|
||||||
contype |= 1; /*always try qw type connections*/
|
contype |= 1; /*always try qw type connections*/
|
||||||
// if ((connect_tries&3)==3) || (connect_defaultport==26000))
|
|
||||||
#ifdef VM_UI
|
#ifdef VM_UI
|
||||||
if (!UI_IsRunning()) //don't try to connect to nq servers when running a q3ui. I was getting annoying error messages from q3 servers due to this.
|
if (!UI_IsRunning()) //don't try to connect to nq servers when running a q3ui. I was getting annoying error messages from q3 servers due to this.
|
||||||
#endif
|
#endif
|
||||||
|
@ -1304,10 +1306,15 @@ void CL_CheckForResend (void)
|
||||||
|
|
||||||
if (!keeptrying)
|
if (!keeptrying)
|
||||||
{
|
{
|
||||||
Cvar_Set(&cl_disconnectreason, va("No route to \"%s\", giving up\n", cls.servername));
|
if (to->prot != NP_DGRAM && connectinfo.nextadr+1 < connectinfo.numadr)
|
||||||
Con_TPrintf ("No route to host, giving up\n");
|
connectinfo.nextadr++; //cycle hosts with each ping (if we got multiple).
|
||||||
connectinfo.trying = false;
|
else
|
||||||
SCR_EndLoadingPlaque();
|
{
|
||||||
|
Cvar_Set(&cl_disconnectreason, va("No route to \"%s\", giving up\n", cls.servername));
|
||||||
|
Con_TPrintf ("No route to host, giving up\n");
|
||||||
|
connectinfo.trying = false;
|
||||||
|
SCR_EndLoadingPlaque();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1324,8 +1331,8 @@ void CL_BeginServerConnect(const char *host, int port, qboolean noproxy)
|
||||||
if (!port)
|
if (!port)
|
||||||
port = cl_defaultport.value;
|
port = cl_defaultport.value;
|
||||||
#ifdef HAVE_DTLS
|
#ifdef HAVE_DTLS
|
||||||
if (connectinfo.numadr)
|
while (connectinfo.numadr)
|
||||||
NET_DTLS_Disconnect(cls.sockets, &connectinfo.adr[0]);
|
NET_DTLS_Disconnect(cls.sockets, &connectinfo.adr[--connectinfo.numadr]);
|
||||||
#endif
|
#endif
|
||||||
memset(&connectinfo, 0, sizeof(connectinfo));
|
memset(&connectinfo, 0, sizeof(connectinfo));
|
||||||
if (*cl_disconnectreason.string)
|
if (*cl_disconnectreason.string)
|
||||||
|
@ -1358,6 +1365,7 @@ void CL_BeginServerReconnect(void)
|
||||||
connectinfo.istransfer = false;
|
connectinfo.istransfer = false;
|
||||||
connectinfo.time = 0;
|
connectinfo.time = 0;
|
||||||
connectinfo.tries = 0; //re-ensure routes.
|
connectinfo.tries = 0; //re-ensure routes.
|
||||||
|
connectinfo.nextadr = 0; //should at least be consistent, other than packetloss. yay. :\
|
||||||
|
|
||||||
NET_InitClient(false);
|
NET_InitClient(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,8 @@ typedef int (VARGS gnutls_certificate_verify_function)(gnutls_session_t session)
|
||||||
|
|
||||||
static int (VARGS *qgnutls_bye)(gnutls_session_t session, gnutls_close_request_t how);
|
static int (VARGS *qgnutls_bye)(gnutls_session_t session, gnutls_close_request_t how);
|
||||||
static void (VARGS *qgnutls_perror)(int error);
|
static void (VARGS *qgnutls_perror)(int error);
|
||||||
|
static gnutls_alert_description_t (VARGS *qgnutls_alert_get)(gnutls_session_t session);
|
||||||
|
static const char *(VARGS *qgnutls_alert_get_name)(gnutls_alert_description_t alert);
|
||||||
static int (VARGS *qgnutls_handshake)(gnutls_session_t session);
|
static int (VARGS *qgnutls_handshake)(gnutls_session_t session);
|
||||||
static void (VARGS *qgnutls_transport_set_ptr)(gnutls_session_t session, gnutls_transport_ptr_t ptr);
|
static void (VARGS *qgnutls_transport_set_ptr)(gnutls_session_t session, gnutls_transport_ptr_t ptr);
|
||||||
static void (VARGS *qgnutls_transport_set_push_function)(gnutls_session_t session, gnutls_push_func push_func);
|
static void (VARGS *qgnutls_transport_set_push_function)(gnutls_session_t session, gnutls_push_func push_func);
|
||||||
|
@ -190,6 +192,9 @@ static int (VARGS *qgnutls_dtls_cookie_verify)(gnutls_datum_t * key, void *clien
|
||||||
static int (VARGS *qgnutls_dtls_cookie_send)(gnutls_datum_t * key, void *client_data, size_t client_data_size, gnutls_dtls_prestate_st * prestate, gnutls_transport_ptr_t ptr, gnutls_push_func push_func);
|
static int (VARGS *qgnutls_dtls_cookie_send)(gnutls_datum_t * key, void *client_data, size_t client_data_size, gnutls_dtls_prestate_st * prestate, gnutls_transport_ptr_t ptr, gnutls_push_func push_func);
|
||||||
static void (VARGS *qgnutls_dtls_prestate_set)(gnutls_session_t session, gnutls_dtls_prestate_st * prestate);
|
static void (VARGS *qgnutls_dtls_prestate_set)(gnutls_session_t session, gnutls_dtls_prestate_st * prestate);
|
||||||
static void (VARGS *qgnutls_dtls_set_mtu)(gnutls_session_t session, unsigned int mtu);
|
static void (VARGS *qgnutls_dtls_set_mtu)(gnutls_session_t session, unsigned int mtu);
|
||||||
|
|
||||||
|
//static int (VARGS *qgnutls_psk_allocate_client_credentials)(gnutls_psk_client_credentials_t *sc);
|
||||||
|
//static int (VARGS *qgnutls_psk_set_client_credentials)(gnutls_psk_client_credentials_t res, const char *username, const gnutls_datum_t * key, gnutls_psk_key_flags flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static unsigned int (VARGS *qgnutls_sec_param_to_pk_bits)(gnutls_pk_algorithm_t algo, gnutls_sec_param_t param);
|
static unsigned int (VARGS *qgnutls_sec_param_to_pk_bits)(gnutls_pk_algorithm_t algo, gnutls_sec_param_t param);
|
||||||
|
@ -231,7 +236,8 @@ static qboolean Init_GNUTLS(void)
|
||||||
#ifdef GNUTLS_HAVE_VERIFY3
|
#ifdef GNUTLS_HAVE_VERIFY3
|
||||||
#define GNUTLS_VERIFYFUNCS \
|
#define GNUTLS_VERIFYFUNCS \
|
||||||
GNUTLS_FUNC(gnutls_certificate_verify_peers3) \
|
GNUTLS_FUNC(gnutls_certificate_verify_peers3) \
|
||||||
GNUTLS_FUNC(gnutls_certificate_verification_status_print)
|
GNUTLS_FUNC(gnutls_certificate_verification_status_print) \
|
||||||
|
GNUTLS_FUNC(gnutls_certificate_get_peers)
|
||||||
#else
|
#else
|
||||||
#define GNUTLS_VERIFYFUNCS \
|
#define GNUTLS_VERIFYFUNCS \
|
||||||
GNUTLS_FUNC(gnutls_certificate_verify_peers2) \
|
GNUTLS_FUNC(gnutls_certificate_verify_peers2) \
|
||||||
|
@ -249,6 +255,8 @@ static qboolean Init_GNUTLS(void)
|
||||||
GNUTLS_FUNC(gnutls_dtls_cookie_send) \
|
GNUTLS_FUNC(gnutls_dtls_cookie_send) \
|
||||||
GNUTLS_FUNC(gnutls_dtls_prestate_set) \
|
GNUTLS_FUNC(gnutls_dtls_prestate_set) \
|
||||||
GNUTLS_FUNC(gnutls_dtls_set_mtu)
|
GNUTLS_FUNC(gnutls_dtls_set_mtu)
|
||||||
|
// GNUTLS_FUNC(gnutls_psk_allocate_client_credentials)
|
||||||
|
// GNUTLS_FUNC(gnutls_psk_set_client_credentials)
|
||||||
#else
|
#else
|
||||||
#define GNUTLS_DTLS_STUFF
|
#define GNUTLS_DTLS_STUFF
|
||||||
#endif
|
#endif
|
||||||
|
@ -303,7 +311,8 @@ static qboolean Init_GNUTLS(void)
|
||||||
GNUTLS_FUNC(gnutls_certificate_set_x509_key_file) \
|
GNUTLS_FUNC(gnutls_certificate_set_x509_key_file) \
|
||||||
GNUTLS_VERIFYFUNCS \
|
GNUTLS_VERIFYFUNCS \
|
||||||
GNUTLS_FUNC(gnutls_certificate_type_get) \
|
GNUTLS_FUNC(gnutls_certificate_type_get) \
|
||||||
GNUTLS_FUNC(gnutls_free) \
|
GNUTLS_FUNCPTR(gnutls_malloc) \
|
||||||
|
GNUTLS_FUNCPTR(gnutls_free) \
|
||||||
GNUTLS_FUNC(gnutls_server_name_set) \
|
GNUTLS_FUNC(gnutls_server_name_set) \
|
||||||
GNUTLS_DTLS_STUFF \
|
GNUTLS_DTLS_STUFF \
|
||||||
GNUTLS_X509_STUFF
|
GNUTLS_X509_STUFF
|
||||||
|
@ -318,6 +327,8 @@ static qboolean Init_GNUTLS(void)
|
||||||
//#undef GNUTLS_FUNC
|
//#undef GNUTLS_FUNC
|
||||||
{(void**)&qgnutls_bye, "gnutls_bye"},
|
{(void**)&qgnutls_bye, "gnutls_bye"},
|
||||||
{(void**)&qgnutls_perror, "gnutls_perror"},
|
{(void**)&qgnutls_perror, "gnutls_perror"},
|
||||||
|
{(void**)&qgnutls_alert_get, "gnutls_alert_get"},
|
||||||
|
{(void**)&qgnutls_alert_get_name, "gnutls_alert_get_name"},
|
||||||
{(void**)&qgnutls_handshake, "gnutls_handshake"},
|
{(void**)&qgnutls_handshake, "gnutls_handshake"},
|
||||||
{(void**)&qgnutls_transport_set_ptr, "gnutls_transport_set_ptr"},
|
{(void**)&qgnutls_transport_set_ptr, "gnutls_transport_set_ptr"},
|
||||||
{(void**)&qgnutls_transport_set_push_function, "gnutls_transport_set_push_function"},
|
{(void**)&qgnutls_transport_set_push_function, "gnutls_transport_set_push_function"},
|
||||||
|
@ -367,6 +378,8 @@ static qboolean Init_GNUTLS(void)
|
||||||
{(void**)&qgnutls_dtls_cookie_send, "gnutls_dtls_cookie_send"},
|
{(void**)&qgnutls_dtls_cookie_send, "gnutls_dtls_cookie_send"},
|
||||||
{(void**)&qgnutls_dtls_prestate_set, "gnutls_dtls_prestate_set"},
|
{(void**)&qgnutls_dtls_prestate_set, "gnutls_dtls_prestate_set"},
|
||||||
{(void**)&qgnutls_dtls_set_mtu, "gnutls_dtls_set_mtu"},
|
{(void**)&qgnutls_dtls_set_mtu, "gnutls_dtls_set_mtu"},
|
||||||
|
// {(void**)&qgnutls_psk_allocate_client_credentials, "gnutls_psk_allocate_client_credentials"},
|
||||||
|
// {(void**)&qgnutls_psk_set_client_credentials, "gnutls_psk_set_client_credentials"},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{(void**)&qgnutls_sec_param_to_pk_bits, "gnutls_sec_param_to_pk_bits"},
|
{(void**)&qgnutls_sec_param_to_pk_bits, "gnutls_sec_param_to_pk_bits"},
|
||||||
|
@ -413,8 +426,10 @@ static qboolean Init_GNUTLS(void)
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
#define GNUTLS_FUNC(name) q##name = name;
|
#define GNUTLS_FUNC(name) q##name = name;
|
||||||
|
#define GNUTLS_FUNCPTR(name) q##name = &name;
|
||||||
GNUTLS_FUNCS
|
GNUTLS_FUNCS
|
||||||
#undef GNUTLS_FUNC
|
#undef GNUTLS_FUNC
|
||||||
|
#undef GNUTLS_FUNCPTR
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -673,7 +688,10 @@ static int SSL_DoHandshake(gnutlsfile_t *file)
|
||||||
if (developer.ival)
|
if (developer.ival)
|
||||||
{
|
{
|
||||||
if (err == GNUTLS_E_FATAL_ALERT_RECEIVED)
|
if (err == GNUTLS_E_FATAL_ALERT_RECEIVED)
|
||||||
; //peer doesn't like us.
|
{ //peer doesn't like us.
|
||||||
|
gnutls_alert_description_t desc = qgnutls_alert_get(file->session);
|
||||||
|
Con_Printf(CON_ERROR"GNU%sTLS: %s: %s(%i)\n", file->datagram?"D":"", file->certname, qgnutls_alert_get_name(desc), desc);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
//we didn't like the peer.
|
//we didn't like the peer.
|
||||||
qgnutls_perror (err);
|
qgnutls_perror (err);
|
||||||
|
@ -683,6 +701,7 @@ static int SSL_DoHandshake(gnutlsfile_t *file)
|
||||||
|
|
||||||
switch(err)
|
switch(err)
|
||||||
{
|
{
|
||||||
|
case GNUTLS_E_INSUFFICIENT_CREDENTIALS:
|
||||||
case GNUTLS_E_CERTIFICATE_ERROR: err = VFS_ERROR_UNTRUSTED; break;
|
case GNUTLS_E_CERTIFICATE_ERROR: err = VFS_ERROR_UNTRUSTED; break;
|
||||||
case GNUTLS_E_PREMATURE_TERMINATION: err = VFS_ERROR_EOF; break;
|
case GNUTLS_E_PREMATURE_TERMINATION: err = VFS_ERROR_EOF; break;
|
||||||
case GNUTLS_E_PUSH_ERROR: err = file->pusherror; break;
|
case GNUTLS_E_PUSH_ERROR: err = file->pusherror; break;
|
||||||
|
@ -839,6 +858,9 @@ static ssize_t DTLS_Push(gnutls_transport_ptr_t p, const void *data, size_t size
|
||||||
|
|
||||||
// Sys_Printf("DTLS_Push: %u, err=%i\n", (unsigned)size, (int)ne);
|
// Sys_Printf("DTLS_Push: %u, err=%i\n", (unsigned)size, (int)ne);
|
||||||
|
|
||||||
|
if (!file->session)
|
||||||
|
return ne?-1:size;
|
||||||
|
|
||||||
switch(ne)
|
switch(ne)
|
||||||
{
|
{
|
||||||
case NETERR_CLOGGED:
|
case NETERR_CLOGGED:
|
||||||
|
@ -1180,6 +1202,15 @@ qboolean SSL_InitGlobal(qboolean isserver)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
static int GetPSKForUser(gnutls_session_t sess, const char *username, gnutls_datum_t * key)
|
||||||
|
{
|
||||||
|
Con_Printf("GetPSKForUser: %s\n", username);
|
||||||
|
key->size = 0;
|
||||||
|
key->data = key->size?gnutls_malloc(key->size):0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
static qboolean SSL_InitConnection(gnutlsfile_t *newf, qboolean isserver, qboolean datagram)
|
static qboolean SSL_InitConnection(gnutlsfile_t *newf, qboolean isserver, qboolean datagram)
|
||||||
{
|
{
|
||||||
// Initialize TLS session
|
// Initialize TLS session
|
||||||
|
@ -1187,28 +1218,42 @@ static qboolean SSL_InitConnection(gnutlsfile_t *newf, qboolean isserver, qboole
|
||||||
|
|
||||||
if (!isserver)
|
if (!isserver)
|
||||||
qgnutls_server_name_set(newf->session, GNUTLS_NAME_DNS, newf->certname, strlen(newf->certname));
|
qgnutls_server_name_set(newf->session, GNUTLS_NAME_DNS, newf->certname, strlen(newf->certname));
|
||||||
/*else
|
|
||||||
{
|
|
||||||
size_t size = sizeof(newf->certname);
|
|
||||||
unsigned int type = GNUTLS_NAME_DNS;
|
|
||||||
int err;
|
|
||||||
err=qgnutls_server_name_get(newf->session, newf->certname, &size, &type, 0);
|
|
||||||
if (err!=GNUTLS_E_SUCCESS)
|
|
||||||
*newf->certname = 0;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
qgnutls_session_set_ptr(newf->session, newf);
|
qgnutls_session_set_ptr(newf->session, newf);
|
||||||
|
|
||||||
#ifdef USE_ANON
|
#ifdef USE_ANON
|
||||||
//qgnutls_kx_set_priority (newf->session, kx_prio);
|
//qgnutls_kx_set_priority (newf->session, kx_prio);
|
||||||
qgnutls_credentials_set (newf->session, GNUTLS_CRD_ANON, anoncred[isserver]);
|
qgnutls_credentials_set (newf->session, GNUTLS_CRD_ANON, anoncred[isserver]);
|
||||||
#else
|
#else
|
||||||
//#if GNUTLS_VERSION_MAJOR >= 3
|
#if 0//def HAVE_DTLS
|
||||||
//gnutls_priority_set_direct();
|
if (datagram)
|
||||||
//#else
|
{ //use some arbitrary PSK for dtls clients.
|
||||||
//qgnutls_certificate_type_set_priority (newf->session, cert_type_priority);
|
if (isserver)
|
||||||
//#endif
|
{
|
||||||
qgnutls_credentials_set (newf->session, GNUTLS_CRD_CERTIFICATE, xcred[isserver]);
|
gnutls_psk_server_credentials_t pskcred;
|
||||||
|
qgnutls_psk_allocate_server_credentials(&pskcred);
|
||||||
|
qgnutls_psk_set_server_credentials_function(pskcred, GetPSKForUser);
|
||||||
|
qgnutls_psk_set_server_credentials_hint(pskcred, "id-quake-ex-dtls");
|
||||||
|
qgnutls_credentials_set(newf->session, GNUTLS_CRD_PSK, pskcred);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef HAVE_CLIENT
|
||||||
|
extern cvar_t name;
|
||||||
|
const char *namestr = name.string;
|
||||||
|
#else
|
||||||
|
const char *namestr = "Anonymous";
|
||||||
|
#endif
|
||||||
|
gnutls_psk_client_credentials_t pskcred;
|
||||||
|
const gnutls_datum_t key = { (void *) "deadbeef", 0 };
|
||||||
|
qgnutls_psk_allocate_client_credentials(&pskcred);
|
||||||
|
qgnutls_psk_set_client_credentials(pskcred, namestr, &key, GNUTLS_PSK_KEY_HEX);
|
||||||
|
|
||||||
|
qgnutls_credentials_set(newf->session, GNUTLS_CRD_PSK, pskcred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
qgnutls_credentials_set (newf->session, GNUTLS_CRD_CERTIFICATE, xcred[isserver]);
|
||||||
#endif
|
#endif
|
||||||
// Use default priorities
|
// Use default priorities
|
||||||
qgnutls_set_default_priority (newf->session);
|
qgnutls_set_default_priority (newf->session);
|
||||||
|
@ -1223,9 +1268,6 @@ static qboolean SSL_InitConnection(gnutlsfile_t *newf, qboolean isserver, qboole
|
||||||
qgnutls_transport_set_pull_timeout_function(newf->session, DTLS_Pull_Timeout);
|
qgnutls_transport_set_pull_timeout_function(newf->session, DTLS_Pull_Timeout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// if (isserver) //don't bother to auth any client certs
|
|
||||||
// qgnutls_certificate_server_set_request(newf->session, GNUTLS_CERT_IGNORE);
|
|
||||||
|
|
||||||
newf->handshaking = true;
|
newf->handshaking = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1406,8 +1448,6 @@ static neterr_t GNUDTLS_Transmit(void *ctx, const qbyte *data, size_t datasize)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
gnutlsfile_t *f = (gnutlsfile_t *)ctx;
|
gnutlsfile_t *f = (gnutlsfile_t *)ctx;
|
||||||
// Sys_Printf("DTLS_Transmit: %u\n", datasize);
|
|
||||||
// Sys_Printf("%su\n", data);
|
|
||||||
|
|
||||||
if (f->challenging)
|
if (f->challenging)
|
||||||
return NETERR_CLOGGED;
|
return NETERR_CLOGGED;
|
||||||
|
@ -1425,7 +1465,6 @@ static neterr_t GNUDTLS_Transmit(void *ctx, const qbyte *data, size_t datasize)
|
||||||
{
|
{
|
||||||
if (ret == GNUTLS_E_LARGE_PACKET)
|
if (ret == GNUTLS_E_LARGE_PACKET)
|
||||||
return NETERR_MTU;
|
return NETERR_MTU;
|
||||||
//Sys_Error("qgnutls_record_send returned %i\n", ret);
|
|
||||||
|
|
||||||
if (qgnutls_error_is_fatal(ret))
|
if (qgnutls_error_is_fatal(ret))
|
||||||
return NETERR_DISCONNECTED;
|
return NETERR_DISCONNECTED;
|
||||||
|
@ -1436,14 +1475,12 @@ static neterr_t GNUDTLS_Transmit(void *ctx, const qbyte *data, size_t datasize)
|
||||||
|
|
||||||
static neterr_t GNUDTLS_Received(void *ctx, sizebuf_t *message)
|
static neterr_t GNUDTLS_Received(void *ctx, sizebuf_t *message)
|
||||||
{
|
{
|
||||||
int cli_addr = 0xdeadbeef;
|
|
||||||
int ret;
|
int ret;
|
||||||
gnutlsfile_t *f = (gnutlsfile_t *)ctx;
|
gnutlsfile_t *f = (gnutlsfile_t *)ctx;
|
||||||
|
|
||||||
//Sys_Printf("DTLS_Received: %u\n", datasize);
|
|
||||||
|
|
||||||
if (f->challenging)
|
if (f->challenging)
|
||||||
{
|
{
|
||||||
|
int cli_addr = 0xdeadbeef; //FIXME: replace with client's IP:port.
|
||||||
memset(&f->prestate, 0, sizeof(f->prestate));
|
memset(&f->prestate, 0, sizeof(f->prestate));
|
||||||
ret = qgnutls_dtls_cookie_verify(&cookie_key,
|
ret = qgnutls_dtls_cookie_verify(&cookie_key,
|
||||||
&cli_addr, sizeof(cli_addr),
|
&cli_addr, sizeof(cli_addr),
|
||||||
|
@ -1452,21 +1489,17 @@ static neterr_t GNUDTLS_Received(void *ctx, sizebuf_t *message)
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
//Sys_Printf("Sending cookie\n");
|
|
||||||
qgnutls_dtls_cookie_send(&cookie_key,
|
qgnutls_dtls_cookie_send(&cookie_key,
|
||||||
&cli_addr, sizeof(cli_addr),
|
&cli_addr, sizeof(cli_addr),
|
||||||
&f->prestate,
|
&f->prestate,
|
||||||
(gnutls_transport_ptr_t)f, DTLS_Push);
|
(gnutls_transport_ptr_t)f, DTLS_Push);
|
||||||
return NETERR_CLOGGED;
|
return NETERR_CLOGGED;
|
||||||
}
|
}
|
||||||
//Sys_Printf("Got correct cookie\n");
|
|
||||||
f->challenging = false;
|
f->challenging = false;
|
||||||
|
|
||||||
qgnutls_dtls_prestate_set(f->session, &f->prestate);
|
qgnutls_dtls_prestate_set(f->session, &f->prestate);
|
||||||
qgnutls_dtls_set_mtu(f->session, 1440);
|
qgnutls_dtls_set_mtu(f->session, 1440);
|
||||||
|
|
||||||
// qgnutls_transport_set_push_function(f->session, DTLS_Push);
|
|
||||||
// qgnutls_transport_set_pull_function(f->session, DTLS_Pull);
|
|
||||||
f->handshaking = true;
|
f->handshaking = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1508,6 +1541,59 @@ static neterr_t GNUDTLS_Received(void *ctx, sizebuf_t *message)
|
||||||
return NETERR_SENT;
|
return NETERR_SENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static qboolean GNUDTLS_CheckConnection(void *cbctx, void *peeraddr, size_t peeraddrsize, void *indata, size_t insize, neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize), void (*EstablishTrueContext)(void **cbctx, void *state))
|
||||||
|
{ //called when we got a possibly-dtls packet out of the blue.
|
||||||
|
gnutlsfile_t *f;
|
||||||
|
int ret;
|
||||||
|
gnutls_dtls_prestate_st prestate;
|
||||||
|
|
||||||
|
memset(&prestate, 0, sizeof(prestate));
|
||||||
|
ret = qgnutls_dtls_cookie_verify(&cookie_key,
|
||||||
|
peeraddr, peeraddrsize,
|
||||||
|
indata, insize,
|
||||||
|
&prestate);
|
||||||
|
|
||||||
|
if (ret == GNUTLS_E_BAD_COOKIE)
|
||||||
|
{ //some sort of handshake with a bad/unknown cookie. send them a real one.
|
||||||
|
gnutlsfile_t f;
|
||||||
|
f.cbctx = cbctx;
|
||||||
|
f.cbpush = push;
|
||||||
|
f.session = NULL;
|
||||||
|
|
||||||
|
qgnutls_dtls_cookie_send(&cookie_key,
|
||||||
|
peeraddr, peeraddrsize,
|
||||||
|
&prestate,
|
||||||
|
(gnutls_transport_ptr_t)&f, DTLS_Push);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (ret < 0)
|
||||||
|
return false; //dunno... might still be dtls but doesn't seem to be needed... oh well...
|
||||||
|
|
||||||
|
//allocate our context
|
||||||
|
f = GNUDTLS_CreateContext(NULL, cbctx, push, true);
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
Con_Printf("GNUDTLS_CreateContext: failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//tell caller that this is an actual valid connection
|
||||||
|
EstablishTrueContext(&f->cbctx, f);
|
||||||
|
if (!f->cbctx)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//we're done with the challenge stuff
|
||||||
|
f->challenging = false;
|
||||||
|
|
||||||
|
//and this is the result...
|
||||||
|
qgnutls_dtls_prestate_set(f->session, &prestate);
|
||||||
|
qgnutls_dtls_set_mtu(f->session, 1440);
|
||||||
|
|
||||||
|
//still need to do the whole certificate thing though.
|
||||||
|
f->handshaking = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static neterr_t GNUDTLS_Timeouts(void *ctx)
|
static neterr_t GNUDTLS_Timeouts(void *ctx)
|
||||||
{
|
{
|
||||||
gnutlsfile_t *f = (gnutlsfile_t *)ctx;
|
gnutlsfile_t *f = (gnutlsfile_t *)ctx;
|
||||||
|
@ -1532,6 +1618,7 @@ static neterr_t GNUDTLS_Timeouts(void *ctx)
|
||||||
static const dtlsfuncs_t dtlsfuncs_gnutls =
|
static const dtlsfuncs_t dtlsfuncs_gnutls =
|
||||||
{
|
{
|
||||||
GNUDTLS_CreateContext,
|
GNUDTLS_CreateContext,
|
||||||
|
GNUDTLS_CheckConnection,
|
||||||
GNUDTLS_DestroyContext,
|
GNUDTLS_DestroyContext,
|
||||||
GNUDTLS_Transmit,
|
GNUDTLS_Transmit,
|
||||||
GNUDTLS_Received,
|
GNUDTLS_Received,
|
||||||
|
|
|
@ -1231,6 +1231,7 @@ static neterr_t SSPI_DTLS_Timeouts(void *ctx)
|
||||||
static const dtlsfuncs_t dtlsfuncs_schannel =
|
static const dtlsfuncs_t dtlsfuncs_schannel =
|
||||||
{
|
{
|
||||||
SSPI_DTLS_CreateContext,
|
SSPI_DTLS_CreateContext,
|
||||||
|
NULL,
|
||||||
SSPI_DTLS_DestroyContext,
|
SSPI_DTLS_DestroyContext,
|
||||||
SSPI_DTLS_Transmit,
|
SSPI_DTLS_Transmit,
|
||||||
SSPI_DTLS_Received,
|
SSPI_DTLS_Received,
|
||||||
|
|
|
@ -3025,10 +3025,10 @@ qboolean NET_DTLS_Create(ftenet_connections_t *col, netadr_t *to)
|
||||||
peer->timeout = realtime+timeout.value;
|
peer->timeout = realtime+timeout.value;
|
||||||
if (peer->dtlsstate)
|
if (peer->dtlsstate)
|
||||||
{
|
{
|
||||||
if (peer->next)
|
|
||||||
peer->next->link = &peer->next;
|
|
||||||
peer->link = &col->dtls;
|
peer->link = &col->dtls;
|
||||||
peer->next = col->dtls;
|
peer->next = col->dtls;
|
||||||
|
if (peer->next)
|
||||||
|
peer->next->link = &peer->next;
|
||||||
col->dtls = peer;
|
col->dtls = peer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3039,10 +3039,54 @@ qboolean NET_DTLS_Create(ftenet_connections_t *col, netadr_t *to)
|
||||||
}
|
}
|
||||||
return peer!=NULL;
|
return peer!=NULL;
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_SERVER
|
||||||
|
static void FTENET_DTLS_Established(void **ctx, void *state)
|
||||||
|
{
|
||||||
|
ftenet_connections_t *col;
|
||||||
|
struct dtlspeer_s *peer = Z_Malloc(sizeof(*peer));
|
||||||
|
memcpy(peer, *ctx, sizeof(*peer));
|
||||||
|
*ctx = peer;
|
||||||
|
col = peer->col;
|
||||||
|
|
||||||
|
peer->dtlsstate = state;
|
||||||
|
|
||||||
|
peer->timeout = realtime+timeout.value;
|
||||||
|
peer->link = &col->dtls;
|
||||||
|
peer->next = col->dtls;
|
||||||
|
if (peer->next)
|
||||||
|
peer->next->link = &peer->next;
|
||||||
|
col->dtls = peer;
|
||||||
|
}
|
||||||
|
qboolean NET_DTLS_CheckInbound(ftenet_connections_t *col)
|
||||||
|
{
|
||||||
|
extern cvar_t timeout, net_enable_dtls;
|
||||||
|
struct dtlspeer_s *peer;
|
||||||
|
netadr_t *from = &net_from;
|
||||||
|
if (from->prot != NP_DGRAM || !net_enable_dtls.ival || !col->dtlsfuncs)
|
||||||
|
return false;
|
||||||
|
for (peer = col->dtls; peer; peer = peer->next)
|
||||||
|
{
|
||||||
|
if (NET_CompareAdr(&peer->addr, from))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!peer)
|
||||||
|
{
|
||||||
|
if (col->dtlsfuncs->CheckConnection)
|
||||||
|
{
|
||||||
|
struct dtlspeer_s peer;
|
||||||
|
//fill it with preliminary info
|
||||||
|
peer.addr = *from;
|
||||||
|
peer.col = col;
|
||||||
|
peer.funcs = col->dtlsfuncs;
|
||||||
|
return col->dtlsfuncs->CheckConnection(&peer, from, sizeof(*from), net_message.data, net_message.cursize, FTENET_DTLS_DoSendPacket, FTENET_DTLS_Established);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
static void NET_DTLS_DisconnectPeer(ftenet_connections_t *col, struct dtlspeer_s *peer)
|
static void NET_DTLS_DisconnectPeer(ftenet_connections_t *col, struct dtlspeer_s *peer)
|
||||||
{
|
{
|
||||||
// Sys_Printf("Destroy %p\n", peer->dtlsstate);
|
// Sys_Printf("Destroy %p\n", peer->dtlsstate);
|
||||||
|
|
||||||
if (peer->next)
|
if (peer->next)
|
||||||
peer->next->link = peer->link;
|
peer->next->link = peer->link;
|
||||||
*peer->link = peer->next;
|
*peer->link = peer->next;
|
||||||
|
@ -3095,8 +3139,8 @@ qboolean NET_DTLS_Decode(ftenet_connections_t *col)
|
||||||
switch(peer->funcs->Received(peer->dtlsstate, &net_message))
|
switch(peer->funcs->Received(peer->dtlsstate, &net_message))
|
||||||
{
|
{
|
||||||
case NETERR_DISCONNECTED:
|
case NETERR_DISCONNECTED:
|
||||||
Sys_Printf("disconnected %p\n", peer->dtlsstate);
|
|
||||||
NET_DTLS_DisconnectPeer(col, peer);
|
NET_DTLS_DisconnectPeer(col, peer);
|
||||||
|
net_message.cursize = 0;
|
||||||
break;
|
break;
|
||||||
case NETERR_NOROUTE:
|
case NETERR_NOROUTE:
|
||||||
return false; //not a valid dtls packet.
|
return false; //not a valid dtls packet.
|
||||||
|
@ -7964,6 +8008,14 @@ qboolean NET_EnsureRoute(ftenet_connections_t *collection, char *routename, char
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case NP_DTLS:
|
case NP_DTLS:
|
||||||
|
adr->prot = NP_DGRAM;
|
||||||
|
NET_EnsureRoute(collection, routename, host, adr);
|
||||||
|
if (NET_DTLS_Create(collection, adr))
|
||||||
|
{
|
||||||
|
adr->prot = NP_DTLS;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
adr->prot = NP_DTLS;
|
||||||
break;
|
break;
|
||||||
case NP_WS:
|
case NP_WS:
|
||||||
case NP_WSS:
|
case NP_WSS:
|
||||||
|
@ -8038,7 +8090,7 @@ static enum addressscope_e NET_ClassifyAddressipv4(int ip, const char **outdesc)
|
||||||
else if ((ip&BigLong(0xffc00000)) == BigLong(0x64400000)) //100.64.x.x/10
|
else if ((ip&BigLong(0xffc00000)) == BigLong(0x64400000)) //100.64.x.x/10
|
||||||
scope = ASCOPE_LAN, desc = localtext("CGNAT");
|
scope = ASCOPE_LAN, desc = localtext("CGNAT");
|
||||||
else if (ip == BigLong(0x00000000)) //0.0.0.0/32
|
else if (ip == BigLong(0x00000000)) //0.0.0.0/32
|
||||||
scope = ASCOPE_LAN, desc = "any";
|
scope = ASCOPE_HOST, desc = "any";
|
||||||
|
|
||||||
*outdesc = desc;
|
*outdesc = desc;
|
||||||
return scope;
|
return scope;
|
||||||
|
@ -8066,7 +8118,7 @@ enum addressscope_e NET_ClassifyAddress(netadr_t *adr, const char **outdesc)
|
||||||
else if (memcmp(adr->address.ip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 16) == 0) //::1
|
else if (memcmp(adr->address.ip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 16) == 0) //::1
|
||||||
scope = ASCOPE_HOST, desc = "localhost";
|
scope = ASCOPE_HOST, desc = "localhost";
|
||||||
else if (memcmp(adr->address.ip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) //::
|
else if (memcmp(adr->address.ip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) //::
|
||||||
scope = ASCOPE_NET, desc = "any";
|
scope = ASCOPE_HOST, desc = "any";
|
||||||
else if (memcmp(adr->address.ip6, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12) == 0) //::ffff:x.y.z.w
|
else if (memcmp(adr->address.ip6, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12) == 0) //::ffff:x.y.z.w
|
||||||
{
|
{
|
||||||
scope = NET_ClassifyAddressipv4(*(int*)(adr->address.ip6+12), &desc);
|
scope = NET_ClassifyAddressipv4(*(int*)(adr->address.ip6+12), &desc);
|
||||||
|
@ -8690,6 +8742,11 @@ qboolean NET_WasSpecialPacket(ftenet_connections_t *collection)
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_DTLS) && defined(HAVE_SERVER)
|
||||||
|
if (collection->islisten && NET_DTLS_CheckInbound(collection))
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -349,6 +349,7 @@ struct dtlsfuncs_s;
|
||||||
typedef struct dtlsfuncs_s
|
typedef struct dtlsfuncs_s
|
||||||
{
|
{
|
||||||
void *(*CreateContext)(const char *remotehost, void *cbctx, neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize), qboolean isserver); //if remotehost is null then their certificate will not be validated.
|
void *(*CreateContext)(const char *remotehost, void *cbctx, neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize), qboolean isserver); //if remotehost is null then their certificate will not be validated.
|
||||||
|
qboolean (*CheckConnection)(void *cbctx, void *peeraddr, size_t peeraddrsize, void *indata, size_t insize, neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize), void (*EstablishTrueContext)(void **cbctx, void *state));
|
||||||
void (*DestroyContext)(void *ctx);
|
void (*DestroyContext)(void *ctx);
|
||||||
neterr_t (*Transmit)(void *ctx, const qbyte *data, size_t datasize);
|
neterr_t (*Transmit)(void *ctx, const qbyte *data, size_t datasize);
|
||||||
neterr_t (*Received)(void *ctx, sizebuf_t *message); //operates in-place...
|
neterr_t (*Received)(void *ctx, sizebuf_t *message); //operates in-place...
|
||||||
|
|
|
@ -125,7 +125,7 @@ static int QDECL OSSL_FRead (struct vfsfile_s *file, void *buffer, int bytestore
|
||||||
case BIO_RR_ACCEPT:
|
case BIO_RR_ACCEPT:
|
||||||
case BIO_RR_CONNECT:
|
case BIO_RR_CONNECT:
|
||||||
return -1; //should never happen
|
return -1; //should never happen
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
if (BIO_should_retry(o->bio))
|
if (BIO_should_retry(o->bio))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -665,11 +665,16 @@ static neterr_t OSSL_Received(void *ctx, sizebuf_t *message)
|
||||||
ossldtls_t *o = (ossldtls_t*)ctx;
|
ossldtls_t *o = (ossldtls_t*)ctx;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
o->pending = message->data;
|
if (!message)
|
||||||
o->pendingsize = message->cursize;
|
r = 0;
|
||||||
r = BIO_read(o->bio, message->data, message->maxsize);
|
else
|
||||||
o->pending = NULL;
|
{
|
||||||
o->pendingsize = 0;
|
o->pending = message->data;
|
||||||
|
o->pendingsize = message->cursize;
|
||||||
|
r = BIO_read(o->bio, message->data, message->maxsize);
|
||||||
|
o->pending = NULL;
|
||||||
|
o->pendingsize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
{
|
{
|
||||||
|
@ -704,6 +709,7 @@ static neterr_t OSSL_Timeouts(void *ctx)
|
||||||
static dtlsfuncs_t ossl_dtlsfuncs =
|
static dtlsfuncs_t ossl_dtlsfuncs =
|
||||||
{
|
{
|
||||||
OSSL_CreateContext,
|
OSSL_CreateContext,
|
||||||
|
NULL,
|
||||||
OSSL_DestroyContext,
|
OSSL_DestroyContext,
|
||||||
OSSL_Transmit,
|
OSSL_Transmit,
|
||||||
OSSL_Received,
|
OSSL_Received,
|
||||||
|
|
Loading…
Reference in New Issue