diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c index 55892108e23cb9876b7b576c1a6ae521bb328520..d47e56699c9f4418c7ecedf845c5530ae9fd2e37 100644 --- a/src/sbbs3/ftpsrvr.c +++ b/src/sbbs3/ftpsrvr.c @@ -1169,6 +1169,14 @@ static BOOL start_tls(SOCKET *sock, CRYPT_SESSION *sess, BOOL resp) sockprintf(*sock, *sess, "431 TLS not available"); return FALSE; } + if ((status = cryptSetAttribute(*sess, CRYPT_SESSINFO_TLS_OPTIONS, CRYPT_TLSOPTION_MINVER_TLS12)) != CRYPT_OK) { + GCES(status, *sock, *sess, estr, "setting TLS minver"); + cryptDestroySession(*sess); + *sess = -1; + if(resp) + sockprintf(*sock, *sess, "431 TLS not available"); + return FALSE; + } if ((status = cryptSetAttribute(*sess, CRYPT_SESSINFO_TLS_OPTIONS, CRYPT_TLSOPTION_DISABLE_CERTVERIFY)) != CRYPT_OK) { GCES(status, *sock, *sess, estr, "disabling certificate verification"); cryptDestroySession(*sess); diff --git a/src/sbbs3/js_socket.c b/src/sbbs3/js_socket.c index e6429e6250c11980af52911f2eeda7b06bd35470..a8f2eb1e77848c3a012306c01995ff7812039c7f 100644 --- a/src/sbbs3/js_socket.c +++ b/src/sbbs3/js_socket.c @@ -2250,6 +2250,7 @@ enum { ,SOCK_PROP_NETWORK_ORDER ,SOCK_PROP_SSL_SESSION ,SOCK_PROP_SSL_SERVER + ,SOCK_PROP_TLS_MINVER }; @@ -2275,6 +2276,7 @@ static const char* socket_prop_desc[] = { ,"<tt>true</tt> if binary data is to be sent in Network Byte Order (big end first), default is <tt>true</tt>" ,"Set to <tt>true</tt> to enable SSL as a client on the socket" ,"Set to <tt>true</tt> to enable SSL as a server on the socket" + ,"Set to 100 to support TLS 1.0, 101 to support TLS 1.1 and 102 (default) for TLS 1.2, must be set before enabling TLS" /* statically-defined properties: */ ,"Array of socket option names supported by the current platform" @@ -2355,6 +2357,12 @@ static JSBool js_socket_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict nb=1; setsockopt(p->sock,IPPROTO_TCP,TCP_NODELAY,(char*)&nb,sizeof(nb)); if((ret=do_cryptAttribute(p->session, CRYPT_SESSINFO_NETWORKSOCKET, p->sock))==CRYPT_OK) { + int minver = CRYPT_TLSOPTION_MINVER_TLS12; + if (p->tls_minver == 100) + minver = CRYPT_TLSOPTION_MINVER_TLS10; + else if (p->tls_minver == 101) + minver = CRYPT_TLSOPTION_MINVER_TLS11; + do_cryptAttribute(p->session, CRYPT_SESSINFO_TLS_OPTIONS, minver); // Reduced compliance checking... required for acme-staging-v02.api.letsencrypt.org do_cryptAttribute(p->session, CRYPT_OPTION_CERT_COMPLIANCELEVEL, CRYPT_COMPLIANCELEVEL_REDUCED); if (tiny == SOCK_PROP_SSL_SESSION) { @@ -2406,6 +2414,17 @@ static JSBool js_socket_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict } JS_RESUMEREQUEST(cx, rc); break; + case SOCK_PROP_TLS_MINVER: + if(JS_ValueToInt32(cx,*vp,&i)) { + switch(i) { + case 100: + case 101: + case 102: + p->tls_minver = i; + break; + } + } + break; } return(JS_TRUE); @@ -2568,6 +2587,9 @@ static JSBool js_socket_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp) case SOCK_PROP_SSL_SERVER: *vp = BOOLEAN_TO_JSVAL(p->session != -1 && p->tls_server); break; + case SOCK_PROP_TLS_MINVER: + *vp = INT_TO_JSVAL(p->tls_minver); + break; } JS_RESUMEREQUEST(cx, rc); @@ -2599,6 +2621,7 @@ static jsSyncPropertySpec js_socket_properties[] = { { "network_byte_order",SOCK_PROP_NETWORK_ORDER,JSPROP_ENUMERATE, 311 }, { "ssl_session" ,SOCK_PROP_SSL_SESSION ,JSPROP_ENUMERATE, 316 }, { "ssl_server" ,SOCK_PROP_SSL_SERVER ,JSPROP_ENUMERATE, 316 }, + { "tls_minver" ,SOCK_PROP_TLS_MINVER ,JSPROP_ENUMERATE, 320 }, {0} }; @@ -2834,6 +2857,7 @@ JSObject* js_CreateSocketObjectWithoutParent(JSContext* cx, SOCKET sock, CRYPT_C p->network_byte_order = TRUE; p->session=session; p->unflushed = 0; + p->tls_minver = 102; if (p->sock != INVALID_SOCKET) { len=sizeof(p->remote_addr); @@ -3192,6 +3216,7 @@ connected: p->session=-1; p->unflushed = 0; p->is_connected = TRUE; + p->tls_minver = 102; if(!JS_SetPrivate(cx, obj, p)) { JS_ReportError(cx,"JS_SetPrivate failed"); @@ -3384,6 +3409,7 @@ js_listening_socket_constructor(JSContext *cx, uintN argc, jsval *arglist) p->session=-1; p->unflushed = 0; p->local_port = port; + p->tls_minver = 102; if(!JS_SetPrivate(cx, obj, p)) { JS_ReportError(cx,"JS_SetPrivate failed"); @@ -3497,6 +3523,7 @@ js_socket_constructor(JSContext *cx, uintN argc, jsval *arglist) p->network_byte_order = TRUE; p->session=-1; p->unflushed = 0; + p->tls_minver = 102; if(!JS_SetPrivate(cx, obj, p)) { JS_ReportError(cx,"JS_SetPrivate failed"); @@ -3618,6 +3645,7 @@ JSObject* js_CreateSocketObjectFromSet(JSContext* cx, JSObject* parent, char *na p->network_byte_order = TRUE; p->session=-1; p->unflushed = 0; + p->tls_minver = 102; if(!JS_SetPrivate(cx, obj, p)) { dbprintf(TRUE, p, "JS_SetPrivate failed"); diff --git a/src/sbbs3/js_socket.h b/src/sbbs3/js_socket.h index 8e5acce615d6cc0bed466172d073a9c8f8cc4142..a42da28d75f23ed10081a1b45d98d1bd61f61baf 100644 --- a/src/sbbs3/js_socket.h +++ b/src/sbbs3/js_socket.h @@ -26,6 +26,7 @@ typedef struct BOOL peeked; uint16_t local_port; js_callback_t *js_cb; + int tls_minver; } js_socket_private_t; #ifdef __cplusplus diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c index 29cc542ae99b639ef25095153ac2c9b1f53bd68d..72e48d254e41bac430e07b3782534df1839c0212 100644 --- a/src/sbbs3/services.c +++ b/src/sbbs3/services.c @@ -1097,6 +1097,7 @@ static void js_service_thread(void* arg) js_service_failure_cleanup(service, socket); return; } + HANDLE_CRYPT_CALL(cryptSetAttribute(service_client.tls_sess, CRYPT_SESSINFO_TLS_OPTIONS, CRYPT_TLSOPTION_MINVER_TLS12), &service_client, "setting minimum TLS version"); /* Add all the user/password combinations */ #if 0 // TLS-PSK is currently broken in cryptlib last = lastuser(&scfg);