diff --git a/CMakeLists.txt b/CMakeLists.txt index b08b87f2..5cf55e3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -294,6 +294,13 @@ ELSEIF(${UNIX} AND NOT FTE_USE_SDL) #linux(ish) IF(NOT GNUTLS_FOUND) MESSAGE(WARNING "gnutls library NOT available. HTTPS/DTLS will not be available.") 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() #linux-only packages @@ -1207,7 +1214,7 @@ IF(FTE_PLUG_MPQ) ENDIF() #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) ADD_LIBRARY(plug_hl2 MODULE plugins/plugin.c diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index f19c2796..f1fe93a4 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1200,7 +1200,7 @@ void CL_CheckForResend (void) if (!connectinfo.clogged) 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)) { Cvar_Set(&cl_disconnectreason, va("Illegal server address")); @@ -1225,7 +1225,7 @@ void CL_CheckForResend (void) 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)) { Cvar_Set(&cl_disconnectreason, va("Unable to establish connection to %s\n", cls.servername)); @@ -1235,8 +1235,10 @@ void CL_CheckForResend (void) return; } + if (to->prot == NP_DGRAM) + connectinfo.nextadr++; //cycle hosts with each ping (if we got multiple). + contype |= 1; /*always try qw type connections*/ -// if ((connect_tries&3)==3) || (connect_defaultport==26000)) #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. #endif @@ -1304,10 +1306,15 @@ void CL_CheckForResend (void) if (!keeptrying) { - 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(); + if (to->prot != NP_DGRAM && connectinfo.nextadr+1 < connectinfo.numadr) + connectinfo.nextadr++; //cycle hosts with each ping (if we got multiple). + else + { + 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) port = cl_defaultport.value; #ifdef HAVE_DTLS - if (connectinfo.numadr) - NET_DTLS_Disconnect(cls.sockets, &connectinfo.adr[0]); + while (connectinfo.numadr) + NET_DTLS_Disconnect(cls.sockets, &connectinfo.adr[--connectinfo.numadr]); #endif memset(&connectinfo, 0, sizeof(connectinfo)); if (*cl_disconnectreason.string) @@ -1358,6 +1365,7 @@ void CL_BeginServerReconnect(void) connectinfo.istransfer = false; connectinfo.time = 0; connectinfo.tries = 0; //re-ensure routes. + connectinfo.nextadr = 0; //should at least be consistent, other than packetloss. yay. :\ NET_InitClient(false); } diff --git a/engine/common/net_ssl_gnutls.c b/engine/common/net_ssl_gnutls.c index aa768343..3275d302 100644 --- a/engine/common/net_ssl_gnutls.c +++ b/engine/common/net_ssl_gnutls.c @@ -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 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 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); @@ -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 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 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 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 #define GNUTLS_VERIFYFUNCS \ 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 #define GNUTLS_VERIFYFUNCS \ 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_prestate_set) \ GNUTLS_FUNC(gnutls_dtls_set_mtu) +// GNUTLS_FUNC(gnutls_psk_allocate_client_credentials) +// GNUTLS_FUNC(gnutls_psk_set_client_credentials) #else #define GNUTLS_DTLS_STUFF #endif @@ -303,7 +311,8 @@ static qboolean Init_GNUTLS(void) GNUTLS_FUNC(gnutls_certificate_set_x509_key_file) \ GNUTLS_VERIFYFUNCS \ 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_DTLS_STUFF \ GNUTLS_X509_STUFF @@ -318,6 +327,8 @@ static qboolean Init_GNUTLS(void) //#undef GNUTLS_FUNC {(void**)&qgnutls_bye, "gnutls_bye"}, {(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_transport_set_ptr, "gnutls_transport_set_ptr"}, {(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_prestate_set, "gnutls_dtls_prestate_set"}, {(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 {(void**)&qgnutls_sec_param_to_pk_bits, "gnutls_sec_param_to_pk_bits"}, @@ -413,8 +426,10 @@ static qboolean Init_GNUTLS(void) return false; #else #define GNUTLS_FUNC(name) q##name = name; + #define GNUTLS_FUNCPTR(name) q##name = &name; GNUTLS_FUNCS #undef GNUTLS_FUNC + #undef GNUTLS_FUNCPTR #endif return true; } @@ -673,7 +688,10 @@ static int SSL_DoHandshake(gnutlsfile_t *file) if (developer.ival) { 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 //we didn't like the peer. qgnutls_perror (err); @@ -683,6 +701,7 @@ static int SSL_DoHandshake(gnutlsfile_t *file) switch(err) { + case GNUTLS_E_INSUFFICIENT_CREDENTIALS: case GNUTLS_E_CERTIFICATE_ERROR: err = VFS_ERROR_UNTRUSTED; break; case GNUTLS_E_PREMATURE_TERMINATION: err = VFS_ERROR_EOF; 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); + if (!file->session) + return ne?-1:size; + switch(ne) { case NETERR_CLOGGED: @@ -1180,6 +1202,15 @@ qboolean SSL_InitGlobal(qboolean isserver) return false; 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) { // Initialize TLS session @@ -1187,28 +1218,42 @@ static qboolean SSL_InitConnection(gnutlsfile_t *newf, qboolean isserver, qboole if (!isserver) 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); #ifdef USE_ANON //qgnutls_kx_set_priority (newf->session, kx_prio); qgnutls_credentials_set (newf->session, GNUTLS_CRD_ANON, anoncred[isserver]); #else -//#if GNUTLS_VERSION_MAJOR >= 3 - //gnutls_priority_set_direct(); -//#else - //qgnutls_certificate_type_set_priority (newf->session, cert_type_priority); -//#endif - qgnutls_credentials_set (newf->session, GNUTLS_CRD_CERTIFICATE, xcred[isserver]); +#if 0//def HAVE_DTLS + if (datagram) + { //use some arbitrary PSK for dtls clients. + if (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 // Use default priorities 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); #endif -// if (isserver) //don't bother to auth any client certs -// qgnutls_certificate_server_set_request(newf->session, GNUTLS_CERT_IGNORE); - newf->handshaking = true; return true; @@ -1406,8 +1448,6 @@ static neterr_t GNUDTLS_Transmit(void *ctx, const qbyte *data, size_t datasize) { int ret; gnutlsfile_t *f = (gnutlsfile_t *)ctx; -// Sys_Printf("DTLS_Transmit: %u\n", datasize); -// Sys_Printf("%su\n", data); if (f->challenging) 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) return NETERR_MTU; -//Sys_Error("qgnutls_record_send returned %i\n", ret); if (qgnutls_error_is_fatal(ret)) 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) { - int cli_addr = 0xdeadbeef; int ret; gnutlsfile_t *f = (gnutlsfile_t *)ctx; -//Sys_Printf("DTLS_Received: %u\n", datasize); - if (f->challenging) { + int cli_addr = 0xdeadbeef; //FIXME: replace with client's IP:port. memset(&f->prestate, 0, sizeof(f->prestate)); ret = qgnutls_dtls_cookie_verify(&cookie_key, &cli_addr, sizeof(cli_addr), @@ -1452,21 +1489,17 @@ static neterr_t GNUDTLS_Received(void *ctx, sizebuf_t *message) if (ret < 0) { -//Sys_Printf("Sending cookie\n"); qgnutls_dtls_cookie_send(&cookie_key, &cli_addr, sizeof(cli_addr), &f->prestate, (gnutls_transport_ptr_t)f, DTLS_Push); return NETERR_CLOGGED; } -//Sys_Printf("Got correct cookie\n"); f->challenging = false; qgnutls_dtls_prestate_set(f->session, &f->prestate); 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; } @@ -1508,6 +1541,59 @@ static neterr_t GNUDTLS_Received(void *ctx, sizebuf_t *message) 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) { gnutlsfile_t *f = (gnutlsfile_t *)ctx; @@ -1532,6 +1618,7 @@ static neterr_t GNUDTLS_Timeouts(void *ctx) static const dtlsfuncs_t dtlsfuncs_gnutls = { GNUDTLS_CreateContext, + GNUDTLS_CheckConnection, GNUDTLS_DestroyContext, GNUDTLS_Transmit, GNUDTLS_Received, diff --git a/engine/common/net_ssl_winsspi.c b/engine/common/net_ssl_winsspi.c index 79a9c87d..e1d0715c 100644 --- a/engine/common/net_ssl_winsspi.c +++ b/engine/common/net_ssl_winsspi.c @@ -1231,6 +1231,7 @@ static neterr_t SSPI_DTLS_Timeouts(void *ctx) static const dtlsfuncs_t dtlsfuncs_schannel = { SSPI_DTLS_CreateContext, + NULL, SSPI_DTLS_DestroyContext, SSPI_DTLS_Transmit, SSPI_DTLS_Received, diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 603e0019..9a9f755f 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -3025,10 +3025,10 @@ qboolean NET_DTLS_Create(ftenet_connections_t *col, netadr_t *to) peer->timeout = realtime+timeout.value; if (peer->dtlsstate) { - if (peer->next) - peer->next->link = &peer->next; peer->link = &col->dtls; peer->next = col->dtls; + if (peer->next) + peer->next->link = &peer->next; col->dtls = peer; } else @@ -3039,10 +3039,54 @@ qboolean NET_DTLS_Create(ftenet_connections_t *col, netadr_t *to) } 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) { // Sys_Printf("Destroy %p\n", peer->dtlsstate); - if (peer->next) peer->next->link = peer->link; *peer->link = peer->next; @@ -3095,8 +3139,8 @@ qboolean NET_DTLS_Decode(ftenet_connections_t *col) switch(peer->funcs->Received(peer->dtlsstate, &net_message)) { case NETERR_DISCONNECTED: - Sys_Printf("disconnected %p\n", peer->dtlsstate); NET_DTLS_DisconnectPeer(col, peer); + net_message.cursize = 0; break; case NETERR_NOROUTE: return false; //not a valid dtls packet. @@ -7964,6 +8008,14 @@ qboolean NET_EnsureRoute(ftenet_connections_t *collection, char *routename, char return false; break; 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; case NP_WS: 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 scope = ASCOPE_LAN, desc = localtext("CGNAT"); else if (ip == BigLong(0x00000000)) //0.0.0.0/32 - scope = ASCOPE_LAN, desc = "any"; + scope = ASCOPE_HOST, desc = "any"; *outdesc = desc; 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 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) //:: - 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 { scope = NET_ClassifyAddressipv4(*(int*)(adr->address.ip6+12), &desc); @@ -8690,6 +8742,11 @@ qboolean NET_WasSpecialPacket(ftenet_connections_t *collection) return true; #endif +#if defined(HAVE_DTLS) && defined(HAVE_SERVER) + if (collection->islisten && NET_DTLS_CheckInbound(collection)) + return true; +#endif + return false; } diff --git a/engine/common/netinc.h b/engine/common/netinc.h index 077a1f75..32245bc3 100644 --- a/engine/common/netinc.h +++ b/engine/common/netinc.h @@ -349,6 +349,7 @@ 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. + 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); neterr_t (*Transmit)(void *ctx, const qbyte *data, size_t datasize); neterr_t (*Received)(void *ctx, sizebuf_t *message); //operates in-place... diff --git a/plugins/net_ssl_openssl.c b/plugins/net_ssl_openssl.c index efe34f4a..b343518e 100644 --- a/plugins/net_ssl_openssl.c +++ b/plugins/net_ssl_openssl.c @@ -125,7 +125,7 @@ static int QDECL OSSL_FRead (struct vfsfile_s *file, void *buffer, int bytestore case BIO_RR_ACCEPT: case BIO_RR_CONNECT: return -1; //should never happen - }; + } } if (BIO_should_retry(o->bio)) return 0; @@ -665,11 +665,16 @@ static neterr_t OSSL_Received(void *ctx, sizebuf_t *message) ossldtls_t *o = (ossldtls_t*)ctx; int r; - o->pending = message->data; - o->pendingsize = message->cursize; - r = BIO_read(o->bio, message->data, message->maxsize); - o->pending = NULL; - o->pendingsize = 0; + if (!message) + r = 0; + else + { + 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) { @@ -704,6 +709,7 @@ static neterr_t OSSL_Timeouts(void *ctx) static dtlsfuncs_t ossl_dtlsfuncs = { OSSL_CreateContext, + NULL, OSSL_DestroyContext, OSSL_Transmit, OSSL_Received,