diff --git a/configure.ac b/configure.ac index 8b58d18cb..1b961bb42 100644 --- a/configure.ac +++ b/configure.ac @@ -2503,11 +2503,44 @@ then fi +AC_ARG_ENABLE([wolfsentry], + [AS_HELP_STRING([--enable-wolfsentry],[Enable wolfSentry hooks and plugins (default: disabled)])], + [ ENABLED_WOLFSENTRY=$enableval ], + [ ENABLED_WOLFSENTRY=no ] + ) + +if test "$ENABLED_WOLFSENTRY" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WOLFSENTRY_HOOKS" + ENABLED_NETWORK_INTROSPECTION_DEFAULT=yes +else + ENABLED_NETWORK_INTROSPECTION_DEFAULT=no +fi + +AC_ARG_WITH([wolfsentry-lib], + [AS_HELP_STRING([--with-wolfsentry-lib=PATH],[PATH to directory with wolfSentry library])], + [WOLFSENTRY_LIB=-L$withval], + [WOLFSENTRY_LIB=""]) + +if test "$ENABLED_WOLFSENTRY" = "yes" +then + WOLFSENTRY_LIB="$WOLFSENTRY_LIB -lwolfsentry" +fi + +AC_ARG_WITH([wolfsentry-include], + [AS_HELP_STRING([--with-wolfsentry-include=PATH],[PATH to directory with wolfSentry header files])], + [WOLFSENTRY_INCLUDE=-I$withval], + [WOLFSENTRY_INCLUDE=""]) + +AC_SUBST([WOLFSENTRY_LIB]) +AC_SUBST([WOLFSENTRY_INCLUDE]) + + # API for tracking network connection attributes AC_ARG_ENABLE([network-introspection], [AS_HELP_STRING([--enable-network-introspection],[Enable network connection attribute tracking and callbacks (default: disabled)])], [ ENABLED_NETWORK_INTROSPECTION=$enableval ], - [ ENABLED_NETWORK_INTROSPECTION=no ] + [ ENABLED_NETWORK_INTROSPECTION=$ENABLED_NETWORK_INTROSPECTION_DEFAULT ] ) if test "$ENABLED_NETWORK_INTROSPECTION" = "yes" @@ -2516,6 +2549,12 @@ then fi +if test "$ENABLED_WOLFSENTRY" = "yes" && test "$ENABLED_NETWORK_INTROSPECTION" != "yes" +then + AC_MSG_ERROR([--enable-wolfsentry requires --enable-network-introspection]) +fi + + if test "$ENABLED_QT" = "yes" then # Requires opensslextra and opensslall @@ -6598,6 +6637,7 @@ echo " * CODING: $ENABLED_CODING" echo " * MEMORY: $ENABLED_MEMORY" echo " * I/O POOL: $ENABLED_IOPOOL" echo " * Connection tracking: $ENABLED_NETWORK_INTROSPECTION" +echo " * wolfSentry: $ENABLED_WOLFSENTRY" echo " * LIGHTY: $ENABLED_LIGHTY" echo " * HAPROXY: $ENABLED_HAPROXY" echo " * STUNNEL: $ENABLED_STUNNEL" diff --git a/examples/server/include.am b/examples/server/include.am index 8a3d75119..4de1e2837 100644 --- a/examples/server/include.am +++ b/examples/server/include.am @@ -7,8 +7,9 @@ if BUILD_EXAMPLE_SERVERS noinst_PROGRAMS += examples/server/server noinst_HEADERS += examples/server/server.h examples_server_server_SOURCES = examples/server/server.c -examples_server_server_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +examples_server_server_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) examples_server_server_DEPENDENCIES = src/libwolfssl.la +examples_server_server_CFLAGS = $(WOLFSENTRY_INCLUDE) endif EXTRA_DIST += examples/server/server.sln EXTRA_DIST += examples/server/server-ntru.vcproj diff --git a/examples/server/server.c b/examples/server/server.c index e8542fdb3..3264fc3f7 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -35,6 +35,11 @@ #include /* wc_ecc_fp_free */ #endif +#ifdef WOLFSSL_WOLFSENTRY_HOOKS +# include +# include +#endif + #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #include #include @@ -276,16 +281,20 @@ static int TestEmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) #endif /* WOLFSSL_DTLS */ -#ifdef WOLFSSL_NETWORK_INTROSPECTION +#ifdef WOLFSSL_WOLFSENTRY_HOOKS -static int test_NetworkFilterCallback(WOLFSSL *ssl, struct wolfSSL_network_connection *nc, void *ctx, wolfSSL_netfilter_decision_t *decision) { +static int wolfSentry_NetworkFilterCallback(WOLFSSL *ssl, struct wolfSSL_network_connection *nc, struct wolfsentry_context *wolfsentry, wolfSSL_netfilter_decision_t *decision) { const void *remote_addr2; const void *local_addr2; char inet_ntop_buf[INET6_ADDRSTRLEN], inet_ntop_buf2[INET6_ADDRSTRLEN]; int ret; + struct { + struct wolfsentry_sockaddr s; + byte buf[16]; + } remote, local; + wolfsentry_action_res_t action_results; (void)ssl; - (void)ctx; if ((ret = wolfSSL_get_endpoint_addrs(nc, &remote_addr2, &local_addr2)) != WOLFSSL_SUCCESS) { printf("wolfSSL_get_endpoints(): %s\n", wolfSSL_ERR_error_string(ret, NULL)); @@ -301,11 +310,36 @@ static int test_NetworkFilterCallback(WOLFSSL *ssl, struct wolfSSL_network_conne inet_ntop(nc->family, local_addr2, inet_ntop_buf2, sizeof inet_ntop_buf2), nc->interface); - *decision = WOLFSSL_NETFILTER_ACCEPT; - return 0; + remote.s.sa_family = nc->family; + remote.s.sa_proto = nc->proto; + remote.s.sa_port = nc->remote_port; + remote.s.addr_len = nc->remote_addr_len; + remote.s.interface = nc->interface; + memcpy(remote.s.addr, remote_addr2, nc->remote_addr_len); + + local.s.sa_family = nc->family; + local.s.sa_proto = nc->proto; + local.s.sa_port = nc->local_port; + local.s.addr_len = nc->local_addr_len; + local.s.interface = nc->interface; + memcpy(local.s.addr, local_addr2, nc->local_addr_len); + + ret = wolfsentry_route_event_dispatch(wolfsentry, &remote.s, &local.s, WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN, NULL /* event_label */, 0 /* event_label_len */, NULL /* caller_context */, NULL /* id */, NULL /* inexact_matches */, &action_results); + + if (ret == 0) { + if (WOLFSENTRY_CHECK_BITS(action_results, WOLFSENTRY_ACTION_RES_REJECT)) + *decision = WOLFSSL_NETFILTER_REJECT; + else if (WOLFSENTRY_CHECK_BITS(action_results, WOLFSENTRY_ACTION_RES_ACCEPT)) + *decision = WOLFSSL_NETFILTER_ACCEPT; + else + *decision = WOLFSSL_NETFILTER_PASS; + } else + *decision = WOLFSSL_NETFILTER_PASS; + + return WOLFSSL_SUCCESS; } -#endif /* WOLFSSL_NETWORK_INTROSPECTION */ +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ static int NonBlockingSSL_Accept(SSL* ssl) { @@ -1035,6 +1069,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) wolfSSL_method_func method = NULL; SSL_CTX* ctx = 0; SSL* ssl = 0; +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + struct wolfsentry_context *wolfsentry = NULL; +#endif int useWebServerMsg = 0; char input[SRV_READ_SZ]; @@ -1870,9 +1907,67 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (ctx == NULL) err_sys_ex(catastrophic, "unable to get ctx"); -#ifdef WOLFSSL_NETWORK_INTROSPECTION - if (wolfSSL_CTX_set_AcceptFilter(ctx, test_NetworkFilterCallback, NULL /* AcceptFilter_arg */) < 0) - err_sys_ex(catastrophic, "unable to install test_NetworkFilterCallback"); +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + ret = wolfsentry_init(NULL /* allocator */, NULL /* timecbs */, 0 /* route_private_data_size */, 0 /* route_private_data_alignment */, &wolfsentry); + if (ret != 0) { + fprintf(stderr, "wolfsentry_init() returned " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); + err_sys_ex(catastrophic, "unable to initialize wolfSentry"); + } + + { + struct wolfsentry_route_table *table; + + if ((ret = wolfsentry_route_get_table_static(wolfsentry, &table)) != 0) + fprintf(stderr, "wolfsentry_route_get_table_static() returned " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); + if (ret == 0) { + if ((ret = wolfsentry_route_table_default_policy_set(wolfsentry, table, WOLFSENTRY_ACTION_RES_REJECT|WOLFSENTRY_ACTION_RES_STOP)) != 0) + fprintf(stderr, "wolfsentry_route_table_default_policy_set(WOLFSENTRY_ACTION_RES_REJECT) returned " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); + } + + if (ret == 0) { + struct { + struct wolfsentry_sockaddr sa; + byte buf[16]; + } remote, local; + wolfsentry_ent_id_t id; + wolfsentry_action_res_t action_results; + + memset(&remote, 0, sizeof remote); + memset(&local, 0, sizeof local); +#ifdef TEST_IPV6 + remote.sa.sa_family = local.sa.sa_family = AF_INET6; + remote.sa.addr_len = 128; +#else + remote.sa.sa_family = local.sa.sa_family = AF_INET; + remote.sa.addr_len = 32; + memcpy(remote.sa.addr, "\177\000\000\001", 4); +#endif +// remote.sa.sa_proto = local.sa.sa_proto = IPPROTO_TCP; + + if ((ret = wolfsentry_route_insert_static + (wolfsentry, NULL /* caller_context */, &remote.sa, &local.sa, + WOLFSENTRY_ROUTE_FLAG_GREENLISTED | + WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN | + WOLFSENTRY_ROUTE_FLAG_TRIGGER_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_REMOTE_INTERFACE_WILDCARD| + WOLFSENTRY_ROUTE_FLAG_LOCAL_INTERFACE_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_LOCAL_ADDR_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_PROTO_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_PORT_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_LOCAL_PORT_WILDCARD, + 0 /* event_label_len */, 0 /* event_label */, &id, &action_results)) < 0) + fprintf(stderr, "wolfsentry_route_insert_static() returned " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); +// else +// fprintf(stderr, "wolfsentry static greenlist rule for localhost has ID %u.\n",id); + } + + if (ret != 0) + err_sys_ex(catastrophic, "unable to configure route table"); + } + + + if (wolfSSL_CTX_set_AcceptFilter(ctx, (NetworkFilterCallback_t)wolfSentry_NetworkFilterCallback, wolfsentry) < 0) + err_sys_ex(catastrophic, "unable to install wolfSentry_NetworkFilterCallback"); #endif if (simulateWantWrite) @@ -2566,7 +2661,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) err_sys_ex(catastrophic, "error in wolfSSL_get_endpoints()"); } - printf("stored: family=%d proto=%d rport=%d lport=%d raddr=%s laddr=%s interface=%d\n", + printf("stored connection attrs: family=%d proto=%d rport=%d lport=%d raddr=%s laddr=%s interface=%d\n", nc->family, nc->proto, nc->remote_port, @@ -3014,6 +3109,13 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) exit: +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + ret = wolfsentry_shutdown(&wolfsentry); + if (ret != 0) { + fprintf(stderr, "wolfsentry_shutdown() returned " WOLFSENTRY_ERROR_FMT, WOLFSENTRY_ERROR_FMT_ARGS(ret)); + } +#endif + #if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) \ && (defined(NO_MAIN_DRIVER) || defined(HAVE_STACK_SIZE)) wc_ecc_fp_free(); /* free per thread cache */ diff --git a/src/internal.c b/src/internal.c index a86ca0a61..4a43752cc 100644 --- a/src/internal.c +++ b/src/internal.c @@ -19449,7 +19449,10 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case TOO_MUCH_EARLY_DATA: return "Too much early data"; - + + case SOCKET_FILTERED_E: + return "Session stopped by network filter"; + default : return "unknown error number"; } diff --git a/src/ssl.c b/src/ssl.c index 8dd44bffc..f10827580 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1222,6 +1222,8 @@ WOLFSSL_API int wolfSSL_copy_endpoints_layer2( return wolfSSL_copy_endpoints_1(&ssl->buffers.network_connection_layer2, nc, nc_size, remote_addr, local_addr); } +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + WOLFSSL_API int wolfSSL_CTX_set_AcceptFilter(WOLFSSL_CTX *ctx, NetworkFilterCallback_t AcceptFilter, void *AcceptFilter_arg) { ctx->AcceptFilter = AcceptFilter; ctx->AcceptFilter_arg = AcceptFilter_arg; @@ -1234,6 +1236,8 @@ WOLFSSL_API int wolfSSL_set_AcceptFilter(WOLFSSL *ssl, NetworkFilterCallback_t A return WOLFSSL_SUCCESS; } +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ + #endif /* WOLFSSL_NETWORK_INTROSPECTION */ #ifndef WOLFSSL_LEANPSK @@ -13126,7 +13130,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, wolfSSL_netfilter_decision_t res; if ((ssl->AcceptFilter(ssl, &ssl->buffers.network_connection, ssl->AcceptFilter_arg, &res) == WOLFSSL_SUCCESS) && (res == WOLFSSL_NETFILTER_REJECT)) { - WOLFSSL_ERROR(ssl->error = SOCKET_ERROR_E); + WOLFSSL_ERROR(ssl->error = SOCKET_FILTERED_E); return WOLFSSL_FATAL_ERROR; } } @@ -13134,7 +13138,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, wolfSSL_netfilter_decision_t res; if ((ssl->AcceptFilter(ssl, &ssl->buffers.network_connection_layer2, ssl->AcceptFilter_arg, &res) == WOLFSSL_SUCCESS) && (res == WOLFSSL_NETFILTER_REJECT)) { - WOLFSSL_ERROR(ssl->error = SOCKET_ERROR_E); + WOLFSSL_ERROR(ssl->error = SOCKET_FILTERED_E); return WOLFSSL_FATAL_ERROR; } } diff --git a/src/tls13.c b/src/tls13.c index cbc891458..ec0c303c7 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -8356,12 +8356,12 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) return WOLFSSL_FATAL_ERROR; } -#ifdef WOLFSSL_NETWORK_INTROSPECTION +#ifdef WOLFSSL_WOLFSENTRY_HOOKS if (ssl->AcceptFilter && (ssl->buffers.network_connection.remote_addr_len > 0)) { wolfSSL_netfilter_decision_t res; if ((ssl->AcceptFilter(ssl, &ssl->buffers.network_connection, ssl->AcceptFilter_arg, &res) == WOLFSSL_SUCCESS) && (res == WOLFSSL_NETFILTER_REJECT)) { - WOLFSSL_ERROR(ssl->error = SOCKET_ERROR_E); + WOLFSSL_ERROR(ssl->error = SOCKET_FILTERED_E); return WOLFSSL_FATAL_ERROR; } } @@ -8369,11 +8369,11 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) wolfSSL_netfilter_decision_t res; if ((ssl->AcceptFilter(ssl, &ssl->buffers.network_connection_layer2, ssl->AcceptFilter_arg, &res) == WOLFSSL_SUCCESS) && (res == WOLFSSL_NETFILTER_REJECT)) { - WOLFSSL_ERROR(ssl->error = SOCKET_ERROR_E); + WOLFSSL_ERROR(ssl->error = SOCKET_FILTERED_E); return WOLFSSL_FATAL_ERROR; } } -#endif /* WOLFSSL_NETWORK_INTROSPECTION */ +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ #ifndef NO_CERTS /* allow no private key if using PK callbacks and CB is set */ diff --git a/tests/include.am b/tests/include.am index 0601a0a6e..6a49cac42 100644 --- a/tests/include.am +++ b/tests/include.am @@ -13,8 +13,8 @@ tests_unit_test_SOURCES = \ tests/srp.c \ examples/client/client.c \ examples/server/server.c -tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -tests_unit_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) $(WOLFSENTRY_INCLUDE) +tests_unit_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) tests_unit_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += tests/unit.h diff --git a/testsuite/include.am b/testsuite/include.am index ed2604427..a3eea3978 100644 --- a/testsuite/include.am +++ b/testsuite/include.am @@ -13,8 +13,8 @@ testsuite_testsuite_test_SOURCES = \ examples/echoserver/echoserver.c \ examples/server/server.c \ testsuite/testsuite.c -testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -testsuite_testsuite_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) $(WOLFSENTRY_INCLUDE) +testsuite_testsuite_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) testsuite_testsuite_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += testsuite/testsuite.sln diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 4e2ab6e38..0c3399d3e 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -171,7 +171,9 @@ enum wolfSSL_ErrorCodes { NO_CERT_ERROR = -440, /* TLS1.3 - no cert set error */ APP_DATA_READY = -441, /* DTLS1.2 application data ready for read */ TOO_MUCH_EARLY_DATA = -442, /* Too much Early data */ - + + SOCKET_FILTERED_E = -443, /* Session stopped by network filter */ + /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ /* begin negotiation parameter errors */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index c16fbc2ff..b36d7f9a4 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2860,10 +2860,10 @@ struct WOLFSSL_CTX { CallbackInfoState* CBIS; /* used to get info about SSL state */ WOLFSSL_X509_VERIFY_PARAM* param; /* verification parameters*/ #endif -#ifdef WOLFSSL_NETWORK_INTROSPECTION +#ifdef WOLFSSL_WOLFSENTRY_HOOKS NetworkFilterCallback_t AcceptFilter; void *AcceptFilter_arg; -#endif /* WOLFSSL_NETWORK_INTROSPECTION */ +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ CallbackIORecv CBIORecv; CallbackIOSend CBIOSend; #ifdef WOLFSSL_DTLS @@ -4084,10 +4084,10 @@ struct WOLFSSL { #ifdef OPENSSL_EXTRA byte cbioFlag; /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */ #endif -#ifdef WOLFSSL_NETWORK_INTROSPECTION +#ifdef WOLFSSL_WOLFSENTRY_HOOKS NetworkFilterCallback_t AcceptFilter; void *AcceptFilter_arg; -#endif /* WOLFSSL_NETWORK_INTROSPECTION */ +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ CallbackIORecv CBIORecv; CallbackIOSend CBIOSend; #ifdef WOLFSSL_STATIC_MEMORY diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 935a6b820..a754e6db9 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1221,9 +1221,11 @@ typedef enum { WOLFSSL_NETFILTER_REJECT = 2 } wolfSSL_netfilter_decision_t; +#ifdef WOLFSSL_WOLFSENTRY_HOOKS typedef int (*NetworkFilterCallback_t)(WOLFSSL *ssl, struct wolfSSL_network_connection *nc, void *ctx, wolfSSL_netfilter_decision_t *decision); WOLFSSL_API int wolfSSL_CTX_set_AcceptFilter(WOLFSSL_CTX *ctx, NetworkFilterCallback_t AcceptFilter, void *AcceptFilter_arg); WOLFSSL_API int wolfSSL_set_AcceptFilter(WOLFSSL *ssl, NetworkFilterCallback_t AcceptFilter, void *AcceptFilter_arg); +#endif #endif /* WOLFSSL_NETWORK_INTROSPECTION */