mirror of
https://github.com/outbackdingo/nDPId.git
synced 2026-01-28 02:19:37 +00:00
Compare commits
2 Commits
main
...
add/tls-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f2bf9fdc3 | ||
|
|
ac4c7390a3 |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -51,6 +51,7 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install autoconf automake cmake libtool pkg-config gettext libjson-c-dev flex bison libpcap-dev zlib1g-dev
|
||||
sudo apt-get install ${{ matrix.compiler }} lcov iproute2
|
||||
sudo apt-get install rpm alien
|
||||
- name: Install Ubuntu Prerequisites (libgcrypt)
|
||||
if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=ON')
|
||||
run: |
|
||||
@@ -93,6 +94,9 @@ jobs:
|
||||
- name: CPack DEB
|
||||
run: |
|
||||
cd ./build && cpack -G DEB && sudo dpkg -i nDPId-*.deb && cd ..
|
||||
- name: CPack RPM
|
||||
run: |
|
||||
cd ./build && cpack -G RPM
|
||||
- name: systemd test
|
||||
if: startsWith(matrix.os, 'ubuntu-latest') && startsWith(matrix.compiler, 'default-cc')
|
||||
run: |
|
||||
|
||||
@@ -10,13 +10,20 @@ endif()
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
set(CMAKE_PROJECT_HOMEPAGE_URL "https://github.com/utoni/nDPId")
|
||||
set(CPACK_PACKAGE_NAME "nDPId")
|
||||
set(CPACK_PACKAGE_CONTACT "toni@impl.cc")
|
||||
set(CPACK_DEBIAN_PACKAGE_NAME "nDPId")
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Tiny nDPI based deep packet inspection daemons / toolkit.")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 1)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "GPL-3.0")
|
||||
|
||||
include(CPack)
|
||||
include(CheckFunctionExists)
|
||||
|
||||
@@ -46,6 +53,7 @@ option(ENABLE_SANITIZER_THREAD "Enable TSAN (does not work together with ASAN)."
|
||||
option(ENABLE_MEMORY_PROFILING "Enable dynamic memory tracking." OFF)
|
||||
option(ENABLE_ZLIB "Enable zlib support for nDPId (experimental)." OFF)
|
||||
option(ENABLE_SYSTEMD "Install systemd components." OFF)
|
||||
option(ENABLE_GNUTLS "Enable GnuTLS support for nDPIsrvd TCP connections." ON)
|
||||
option(BUILD_EXAMPLES "Build C examples." ON)
|
||||
option(BUILD_NDPI "Clone and build nDPI from github." OFF)
|
||||
if(BUILD_NDPI)
|
||||
@@ -134,9 +142,13 @@ if(ENABLE_SANITIZER_THREAD)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize=alignment -fsanitize=enum -fsanitize=thread")
|
||||
endif()
|
||||
if(ENABLE_ZLIB)
|
||||
set(ZLIB_DEFS "-DENABLE_ZLIB=1")
|
||||
set(NDPID_DEFS ${NDPID_DEFS} -DENABLE_ZLIB=1)
|
||||
pkg_check_modules(ZLIB REQUIRED zlib)
|
||||
endif()
|
||||
if(ENABLE_GNUTLS)
|
||||
set(NDPID_DEFS ${NDPID_DEFS} -DENABLE_GNUTLS=1)
|
||||
pkg_check_modules(GNUTLS REQUIRED gnutls)
|
||||
endif()
|
||||
if(NDPI_WITH_GCRYPT)
|
||||
message(STATUS "nDPI: Enable GCRYPT")
|
||||
set(NDPI_ADDITIONAL_ARGS "${NDPI_ADDITIONAL_ARGS} --with-local-libgcrypt")
|
||||
@@ -276,15 +288,17 @@ target_link_libraries(nDPId "${STATIC_LIBNDPI_LIB}" "${pkgcfg_lib_NDPI_ndpi}"
|
||||
|
||||
target_compile_definitions(nDPIsrvd PRIVATE -D_GNU_SOURCE=1 -DGIT_VERSION=\"${GIT_VERSION}\" ${NDPID_DEFS})
|
||||
target_include_directories(nDPIsrvd PRIVATE ${NDPID_DEPS_INC})
|
||||
target_link_libraries(nDPIsrvd "${pkgcfg_lib_GNUTLS_gnutls}")
|
||||
|
||||
target_include_directories(nDPId-test PRIVATE ${NDPID_DEPS_INC})
|
||||
target_compile_options(nDPId-test PRIVATE "-Wno-unused-function" "-pthread")
|
||||
target_compile_definitions(nDPId-test PRIVATE -D_GNU_SOURCE=1 -DNO_MAIN=1 -DGIT_VERSION=\"${GIT_VERSION}\"
|
||||
${NDPID_DEFS} ${ZLIB_DEFS} ${NDPID_TEST_MPROF_DEFS})
|
||||
${NDPID_DEFS} ${NDPID_TEST_MPROF_DEFS})
|
||||
target_include_directories(nDPId-test PRIVATE
|
||||
"${STATIC_LIBNDPI_INC}" "${DEFAULT_NDPI_INCLUDE}" ${NDPID_DEPS_INC})
|
||||
target_link_libraries(nDPId-test "${STATIC_LIBNDPI_LIB}" "${pkgcfg_lib_NDPI_ndpi}"
|
||||
"${pkgcfg_lib_PCRE_pcre}" "${pkgcfg_lib_MAXMINDDB_maxminddb}" "${pkgcfg_lib_ZLIB_z}"
|
||||
"${pkgcfg_lib_GNUTLS_gnutls}"
|
||||
"${GCRYPT_LIBRARY}" "${GCRYPT_ERROR_LIBRARY}" "${PCAP_LIBRARY}" "${LIBM_LIB}"
|
||||
"-pthread")
|
||||
|
||||
@@ -364,14 +378,19 @@ install(FILES schema/error_event_schema.json schema/daemon_event_schema.json
|
||||
message(STATUS "--------------------------")
|
||||
message(STATUS "nDPId GIT_VERSION........: ${GIT_VERSION}")
|
||||
message(STATUS "Cross Compilation........: ${CMAKE_CROSSCOMPILING}")
|
||||
message(STATUS "CMAKE_SYSTEM_NAME........: ${CMAKE_SYSTEM_NAME}")
|
||||
message(STATUS "CMAKE_SYSTEM_PROCESSOR...: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
message(STATUS "CMAKE_BUILD_TYPE.........: ${CMAKE_BUILD_TYPE}")
|
||||
message(STATUS "CMAKE_C_FLAGS............: ${CMAKE_C_FLAGS}")
|
||||
message(STATUS "NDPID_DEFS...............: ${NDPID_DEFS}")
|
||||
string(REPLACE ";" " " PRETTY_NDPID_DEFS "${NDPID_DEFS}")
|
||||
message(STATUS "NDPID_DEFS...............: ${PRETTY_NDPID_DEFS}")
|
||||
message(STATUS "ENABLE_COVERAGE..........: ${ENABLE_COVERAGE}")
|
||||
message(STATUS "ENABLE_SANITIZER.........: ${ENABLE_SANITIZER}")
|
||||
message(STATUS "ENABLE_SANITIZER_THREAD..: ${ENABLE_SANITIZER_THREAD}")
|
||||
message(STATUS "ENABLE_MEMORY_PROFILING..: ${ENABLE_MEMORY_PROFILING}")
|
||||
message(STATUS "ENABLE_ZLIB..............: ${ENABLE_ZLIB}")
|
||||
message(STATUS "ENABLE_SYSTEMD...........: ${ENABLE_SYSTEMD}")
|
||||
message(STATUS "ENABLE_GNUTLS............: ${ENABLE_GNUTLS}")
|
||||
if(STATIC_LIBNDPI_INSTALLDIR)
|
||||
message(STATUS "STATIC_LIBNDPI_INSTALLDIR: ${STATIC_LIBNDPI_INSTALLDIR}")
|
||||
endif()
|
||||
|
||||
@@ -1293,9 +1293,12 @@ int main(int argc, char ** argv)
|
||||
}
|
||||
|
||||
/* We do not have any sockets, any socket operation must fail! */
|
||||
collector_un_sockfd = -1;
|
||||
distributor_un_sockfd = -1;
|
||||
distributor_in_sockfd = -1;
|
||||
sockfds[COLLECTOR_UN] = -1;
|
||||
sockfds[DISTRIBUTOR_UN] = -1;
|
||||
sockfds[DISTRIBUTOR_IN] = -1;
|
||||
#ifdef ENABLE_GNUTLS
|
||||
sockfds[DISTRIBUTOR_IN_TLS] = -1;
|
||||
#endif
|
||||
|
||||
if (setup_remote_descriptors(MAX_REMOTE_DESCRIPTORS) != 0)
|
||||
{
|
||||
|
||||
617
nDPIsrvd.c
617
nDPIsrvd.c
@@ -1,6 +1,9 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef ENABLE_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <pwd.h>
|
||||
@@ -21,9 +24,12 @@
|
||||
|
||||
enum sock_type
|
||||
{
|
||||
COLLECTOR_UN,
|
||||
COLLECTOR_UN = 0,
|
||||
DISTRIBUTOR_UN,
|
||||
DISTRIBUTOR_IN,
|
||||
#ifdef ENABLE_GNUTLS
|
||||
DISTRIBUTOR_IN_TLS,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct nDPIsrvd_write_buffer
|
||||
@@ -64,6 +70,18 @@ struct remote_desc
|
||||
struct nDPIsrvd_write_buffer main_write_buffer;
|
||||
UT_array * additional_write_buffers;
|
||||
} event_distributor_in; /* TCP/IP socket */
|
||||
#ifdef ENABLE_GNUTLS
|
||||
struct
|
||||
{
|
||||
struct sockaddr_in peer;
|
||||
char peer_addr[INET_ADDRSTRLEN];
|
||||
|
||||
struct nDPIsrvd_write_buffer main_write_buffer;
|
||||
UT_array * additional_write_buffers;
|
||||
|
||||
gnutls_session_t session;
|
||||
} event_distributor_in_tls;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
@@ -75,12 +93,38 @@ static struct
|
||||
} remotes = {NULL, 0, 0};
|
||||
|
||||
static int nDPIsrvd_main_thread_shutdown = 0;
|
||||
static int collector_un_sockfd = -1;
|
||||
static int distributor_un_sockfd = -1;
|
||||
static int distributor_in_sockfd = -1;
|
||||
static struct nDPIsrvd_address distributor_in_address = {
|
||||
.raw.sa_family = 0xFFFF,
|
||||
static int sockfds[] = {[COLLECTOR_UN] = -1,
|
||||
[DISTRIBUTOR_UN] = -1,
|
||||
[DISTRIBUTOR_IN] = -1,
|
||||
#ifdef ENABLE_GNUTLS
|
||||
[DISTRIBUTOR_IN_TLS] = -1
|
||||
#endif
|
||||
};
|
||||
static struct nDPIsrvd_address addrs[] = {[COLLECTOR_UN] =
|
||||
{
|
||||
.raw.sa_family = 0xFFFF,
|
||||
},
|
||||
[DISTRIBUTOR_UN] =
|
||||
{
|
||||
.raw.sa_family = 0xFFFF,
|
||||
},
|
||||
[DISTRIBUTOR_IN] =
|
||||
{
|
||||
.raw.sa_family = 0xFFFF,
|
||||
},
|
||||
#ifdef ENABLE_GNUTLS
|
||||
[DISTRIBUTOR_IN_TLS] =
|
||||
{
|
||||
.raw.sa_family = 0xFFFF,
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef ENABLE_GNUTLS
|
||||
static int enable_tls;
|
||||
static gnutls_certificate_credentials_t x509_creds = NULL;
|
||||
static gnutls_priority_t prio_cache = NULL;
|
||||
#endif
|
||||
|
||||
static struct
|
||||
{
|
||||
@@ -93,6 +137,13 @@ static struct
|
||||
nDPIsrvd_ull max_remote_descriptors;
|
||||
nDPIsrvd_ull max_write_buffers;
|
||||
int bufferbloat_fallback_to_blocking;
|
||||
#ifdef ENABLE_GNUTLS
|
||||
char * distributor_in_tls_address;
|
||||
char * x509_certfile;
|
||||
char * x509_keyfile;
|
||||
char * x509_crlfile;
|
||||
char * x509_cafile;
|
||||
#endif
|
||||
} nDPIsrvd_options = {.pidfile = CMDARG(nDPIsrvd_PIDFILE),
|
||||
.collector_un_sockpath = CMDARG(COLLECTOR_UNIX_SOCKET),
|
||||
.distributor_un_sockpath = CMDARG(DISTRIBUTOR_UNIX_SOCKET),
|
||||
@@ -100,7 +151,6 @@ static struct
|
||||
.user = CMDARG(DEFAULT_CHUSER),
|
||||
.group = CMDARG(NULL),
|
||||
.max_remote_descriptors = nDPIsrvd_MAX_REMOTE_DESCRIPTORS,
|
||||
.max_write_buffers = nDPIsrvd_MAX_WRITE_BUFFERS,
|
||||
.bufferbloat_fallback_to_blocking = 1};
|
||||
|
||||
static void logger_nDPIsrvd(struct remote_desc const * const remote,
|
||||
@@ -169,15 +219,118 @@ void nDPIsrvd_memprof_log(char const * const format, ...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_GNUTLS
|
||||
static int gtls_global_init(char const * const certfile,
|
||||
char const * const keyfile,
|
||||
char const * const crlfile,
|
||||
char const * const cafile,
|
||||
gnutls_certificate_credentials_t * const x509_creds,
|
||||
gnutls_priority_t * prio_cache)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (gnutls_check_version("3.4.6") == NULL)
|
||||
{
|
||||
logger_early(1, "GnuTLS 3.4.6 or later is required.");
|
||||
return -1;
|
||||
}
|
||||
if ((error = gnutls_global_init()) < 0)
|
||||
{
|
||||
logger_early(1, "GnuTLS global init failed %s %s.", gnutls_strerror(error), gnutls_strerror_name(error));
|
||||
return -1;
|
||||
}
|
||||
if ((error = gnutls_certificate_allocate_credentials(x509_creds)) < 0)
|
||||
{
|
||||
logger_early(1,
|
||||
"GnuTLS certificate allocation failed %s %s.",
|
||||
gnutls_strerror(error),
|
||||
gnutls_strerror_name(error));
|
||||
return -1;
|
||||
}
|
||||
if ((error = gnutls_certificate_set_x509_crl_file(*x509_creds, crlfile, GNUTLS_X509_FMT_PEM)) < 0)
|
||||
{
|
||||
logger_early(1,
|
||||
"GnuTLS x509 crl file invalid. PEM format required %s %s.",
|
||||
gnutls_strerror(error),
|
||||
gnutls_strerror_name(error));
|
||||
return -1;
|
||||
}
|
||||
if ((error = gnutls_certificate_set_x509_key_file(*x509_creds, certfile, keyfile, GNUTLS_X509_FMT_PEM)) < 0)
|
||||
{
|
||||
logger_early(1,
|
||||
"GnuTLS x509 cert/key file invalid. PEM format required %s %s.",
|
||||
gnutls_strerror(error),
|
||||
gnutls_strerror_name(error));
|
||||
return -1;
|
||||
}
|
||||
if ((error = gnutls_certificate_set_x509_trust_file(*x509_creds, cafile, GNUTLS_X509_FMT_PEM)) < 0)
|
||||
{
|
||||
logger_early(1,
|
||||
"GnuTLS x509 ca file invalid. PEM format required: %s %s.",
|
||||
gnutls_strerror(error),
|
||||
gnutls_strerror_name(error));
|
||||
return -1;
|
||||
}
|
||||
if ((error = gnutls_priority_init(prio_cache, "SECURE256", NULL)) < 0)
|
||||
{
|
||||
logger_early(1,
|
||||
"GnuTLS priority cache init failed: %s %s.",
|
||||
gnutls_strerror(error),
|
||||
gnutls_strerror_name(error));
|
||||
return -1;
|
||||
}
|
||||
#if GNUTLS_VERSION_NUMBER >= 0x030506
|
||||
gnutls_certificate_set_known_dh_params(*x509_creds, GNUTLS_SEC_PARAM_HIGH);
|
||||
#else
|
||||
gnutls_certificate_set_dh_params(*x509_creds, GNUTLS_SEC_PARAM_HIGH);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gtls_init_session_server(struct remote_desc * const remote)
|
||||
{
|
||||
if (remote->sock_type != DISTRIBUTOR_IN_TLS)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (gnutls_init(&remote->event_distributor_in_tls.session, GNUTLS_SERVER) < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (gnutls_priority_set(remote->event_distributor_in_tls.session, prio_cache) < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (gnutls_credentials_set(remote->event_distributor_in_tls.session,
|
||||
GNUTLS_CRD_CERTIFICATE, x509_creds) < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
gnutls_session_set_verify_cert(remote->event_distributor_in_tls.session, NULL, 0);
|
||||
gnutls_certificate_server_set_request(remote->event_distributor_in_tls.session, GNUTLS_CERT_REQUIRE);
|
||||
gnutls_certificate_send_x509_rdn_sequence(remote->event_distributor_in_tls.session, 1);
|
||||
gnutls_handshake_set_timeout(remote->event_distributor_in_tls.session,
|
||||
GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
|
||||
|
||||
gnutls_transport_set_int(remote->event_distributor_in_tls.session, remote->fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct nDPIsrvd_json_buffer * get_read_buffer(struct remote_desc * const remote)
|
||||
{
|
||||
switch (remote->sock_type)
|
||||
{
|
||||
case COLLECTOR_UN:
|
||||
return &remote->event_collector_un.main_read_buffer;
|
||||
|
||||
case DISTRIBUTOR_UN:
|
||||
case DISTRIBUTOR_IN:
|
||||
#ifdef ENABLE_GNUTLS
|
||||
case DISTRIBUTOR_IN_TLS:
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -196,6 +349,11 @@ static struct nDPIsrvd_write_buffer * get_write_buffer(struct remote_desc * cons
|
||||
|
||||
case DISTRIBUTOR_IN:
|
||||
return &remote->event_distributor_in.main_write_buffer;
|
||||
|
||||
#ifdef ENABLE_GNUTLS
|
||||
case DISTRIBUTOR_IN_TLS:
|
||||
return &remote->event_distributor_in_tls.main_write_buffer;
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -213,6 +371,10 @@ static UT_array * get_additional_write_buffers(struct remote_desc * const remote
|
||||
|
||||
case DISTRIBUTOR_IN:
|
||||
return remote->event_distributor_in.additional_write_buffers;
|
||||
#ifdef ENABLE_GNUTLS
|
||||
case DISTRIBUTOR_IN_TLS:
|
||||
return remote->event_distributor_in_tls.additional_write_buffers;
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -291,6 +453,17 @@ static void logger_nDPIsrvd(struct remote_desc const * const remote,
|
||||
ntohs(remote->event_distributor_in.peer.sin_port),
|
||||
logbuf);
|
||||
break;
|
||||
#ifdef ENABLE_GNUTLS
|
||||
case DISTRIBUTOR_IN_TLS:
|
||||
logger(1,
|
||||
"%s %.*s:%u %s",
|
||||
prefix,
|
||||
(int)sizeof(remote->event_distributor_in_tls.peer_addr),
|
||||
remote->event_distributor_in_tls.peer_addr,
|
||||
ntohs(remote->event_distributor_in_tls.peer.sin_port),
|
||||
logbuf);
|
||||
break;
|
||||
#endif
|
||||
case COLLECTOR_UN:
|
||||
logger(1, "%s PID %d %s", prefix, remote->event_collector_un.pid, logbuf);
|
||||
break;
|
||||
@@ -454,24 +627,39 @@ static int fcntl_del_flags(int fd, int flags)
|
||||
|
||||
static int create_listen_sockets(void)
|
||||
{
|
||||
collector_un_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
distributor_un_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (collector_un_sockfd < 0 || distributor_un_sockfd < 0)
|
||||
sockfds[COLLECTOR_UN] = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
sockfds[DISTRIBUTOR_UN] = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sockfds[COLLECTOR_UN] < 0 || sockfds[DISTRIBUTOR_UN] < 0)
|
||||
{
|
||||
logger(1, "Error creating UNIX socket: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_GNUTLS
|
||||
if (enable_tls != 0)
|
||||
{
|
||||
if (nDPIsrvd_options.distributor_in_tls_address != NULL)
|
||||
{
|
||||
sockfds[DISTRIBUTOR_IN_TLS] = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfds[DISTRIBUTOR_IN_TLS] < 0)
|
||||
{
|
||||
logger(1, "Error creating distributor TLS proxy (server): %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is_cmdarg_set(&nDPIsrvd_options.distributor_in_address) != 0)
|
||||
{
|
||||
distributor_in_sockfd = socket(distributor_in_address.raw.sa_family, SOCK_STREAM, 0);
|
||||
if (distributor_in_sockfd < 0)
|
||||
sockfds[DISTRIBUTOR_IN] = socket(addrs[DISTRIBUTOR_IN].raw.sa_family, SOCK_STREAM, 0);
|
||||
if (sockfds[DISTRIBUTOR_IN] < 0)
|
||||
{
|
||||
logger(1, "Error creating TCP/IP socket: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
int opt = 1;
|
||||
if (setsockopt(distributor_in_sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
|
||||
if (setsockopt(sockfds[DISTRIBUTOR_IN], SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
|
||||
{
|
||||
logger(1, "Setting TCP/IP socket option SO_REUSEADDR failed: %s", strerror(errno));
|
||||
}
|
||||
@@ -479,8 +667,8 @@ static int create_listen_sockets(void)
|
||||
|
||||
{
|
||||
int opt = 1;
|
||||
if (setsockopt(collector_un_sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0 ||
|
||||
setsockopt(distributor_un_sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
|
||||
if (setsockopt(sockfds[COLLECTOR_UN], SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0 ||
|
||||
setsockopt(sockfds[DISTRIBUTOR_UN], SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
|
||||
{
|
||||
logger(1, "Setting UNIX socket option SO_REUSEADDR failed: %s", strerror(errno));
|
||||
}
|
||||
@@ -507,7 +695,7 @@ static int create_listen_sockets(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bind(collector_un_sockfd, (struct sockaddr *)&collector_addr, sizeof(collector_addr)) < 0)
|
||||
if (bind(sockfds[COLLECTOR_UN], (struct sockaddr *)&collector_addr, sizeof(collector_addr)) < 0)
|
||||
{
|
||||
logger(1,
|
||||
"Error binding Collector UNIX socket to `%s': %s",
|
||||
@@ -538,7 +726,7 @@ static int create_listen_sockets(void)
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (bind(distributor_un_sockfd, (struct sockaddr *)&distributor_addr, sizeof(distributor_addr)) < 0)
|
||||
if (bind(sockfds[DISTRIBUTOR_UN], (struct sockaddr *)&distributor_addr, sizeof(distributor_addr)) < 0)
|
||||
{
|
||||
logger(1,
|
||||
"Error binding Distributor socket to `%s': %s",
|
||||
@@ -550,7 +738,7 @@ static int create_listen_sockets(void)
|
||||
|
||||
if (is_cmdarg_set(&nDPIsrvd_options.distributor_in_address) != 0)
|
||||
{
|
||||
if (bind(distributor_in_sockfd, &distributor_in_address.raw, distributor_in_address.size) < 0)
|
||||
if (bind(sockfds[DISTRIBUTOR_IN], &addrs[DISTRIBUTOR_IN].raw, addrs[DISTRIBUTOR_IN].size) < 0)
|
||||
{
|
||||
logger(1,
|
||||
"Error binding Distributor TCP/IP socket to %s: %s",
|
||||
@@ -558,7 +746,7 @@ static int create_listen_sockets(void)
|
||||
strerror(errno));
|
||||
return 3;
|
||||
}
|
||||
if (listen(distributor_in_sockfd, 16) < 0)
|
||||
if (listen(sockfds[DISTRIBUTOR_IN], 16) < 0)
|
||||
{
|
||||
logger(1,
|
||||
"Error listening Distributor TCP/IP socket to %s: %s",
|
||||
@@ -566,7 +754,7 @@ static int create_listen_sockets(void)
|
||||
strerror(errno));
|
||||
return 3;
|
||||
}
|
||||
if (fcntl_add_flags(distributor_in_sockfd, O_NONBLOCK) != 0)
|
||||
if (fcntl_add_flags(sockfds[DISTRIBUTOR_IN], O_NONBLOCK) != 0)
|
||||
{
|
||||
logger(1,
|
||||
"Error setting Distributor TCP/IP socket %s to non-blocking mode: %s",
|
||||
@@ -576,13 +764,13 @@ static int create_listen_sockets(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (listen(collector_un_sockfd, 16) < 0 || listen(distributor_un_sockfd, 16) < 0)
|
||||
if (listen(sockfds[COLLECTOR_UN], 16) < 0 || listen(sockfds[DISTRIBUTOR_UN], 16) < 0)
|
||||
{
|
||||
logger(1, "Error listening UNIX socket: %s", strerror(errno));
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (fcntl_add_flags(collector_un_sockfd, O_NONBLOCK) != 0)
|
||||
if (fcntl_add_flags(sockfds[COLLECTOR_UN], O_NONBLOCK) != 0)
|
||||
{
|
||||
logger(1,
|
||||
"Error setting Collector UNIX socket `%s' to non-blocking mode: %s",
|
||||
@@ -591,7 +779,7 @@ static int create_listen_sockets(void)
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (fcntl_add_flags(distributor_un_sockfd, O_NONBLOCK) != 0)
|
||||
if (fcntl_add_flags(sockfds[DISTRIBUTOR_UN], O_NONBLOCK) != 0)
|
||||
{
|
||||
logger(1,
|
||||
"Error setting Distributor UNIX socket `%s' to non-blocking mode: %s",
|
||||
@@ -638,6 +826,17 @@ static struct remote_desc * get_remote_descriptor(enum sock_type type, int remot
|
||||
write_buffer = &remotes.desc[i].event_distributor_in.main_write_buffer;
|
||||
additional_write_buffers = &remotes.desc[i].event_distributor_in.additional_write_buffers;
|
||||
break;
|
||||
#ifdef ENABLE_GNUTLS
|
||||
case DISTRIBUTOR_IN_TLS:
|
||||
if (gtls_init_session_server(&remotes.desc[i]) != 0)
|
||||
{
|
||||
logger(1, "GnuTLS init session (server) failed.");
|
||||
return NULL;
|
||||
}
|
||||
write_buffer = &remotes.desc[i].event_distributor_in_tls.main_write_buffer;
|
||||
additional_write_buffers = &remotes.desc[i].event_distributor_in_tls.additional_write_buffers;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (additional_write_buffers != NULL && *additional_write_buffers == NULL)
|
||||
@@ -710,6 +909,19 @@ static void free_remote(int epollfd, struct remote_desc * remote)
|
||||
}
|
||||
nDPIsrvd_buffer_free(&remote->event_distributor_in.main_write_buffer.buf);
|
||||
break;
|
||||
#ifdef ENABLE_GNUTLS
|
||||
case DISTRIBUTOR_IN_TLS:
|
||||
if (errno != 0)
|
||||
{
|
||||
logger_nDPIsrvd(remote, "Error closing distributor(TLS) connection", ": %s", strerror(errno));
|
||||
}
|
||||
if (remote->event_distributor_in_tls.additional_write_buffers != NULL)
|
||||
{
|
||||
utarray_free(remote->event_distributor_in_tls.additional_write_buffers);
|
||||
}
|
||||
nDPIsrvd_buffer_free(&remote->event_distributor_in_tls.main_write_buffer.buf);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
memset(remote, 0, sizeof(*remote));
|
||||
@@ -791,7 +1003,7 @@ static int nDPIsrvd_parse_options(int argc, char ** argv)
|
||||
{
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "lL:c:dp:s:S:m:u:g:C:Dvh")) != -1)
|
||||
while ((opt = getopt(argc, argv, "lL:c:dp:s:S:m:u:g:C:DvX:x:h")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
@@ -845,6 +1057,64 @@ static int nDPIsrvd_parse_options(int argc, char ** argv)
|
||||
case 'v':
|
||||
fprintf(stderr, "%s", get_nDPId_version());
|
||||
return 1;
|
||||
case 'X':
|
||||
#ifdef ENABLE_GNUTLS
|
||||
nDPIsrvd_options.distributor_in_tls_address = strdup(optarg);
|
||||
enable_tls = 1;
|
||||
break;
|
||||
#else
|
||||
logger_early(1, "To use TLS capabilities (`-X'), GnuTLS support required.");
|
||||
return 1;
|
||||
#endif
|
||||
case 'x':
|
||||
{
|
||||
#ifdef ENABLE_GNUTLS
|
||||
static char * const x509_subopt_token[] = {"cert", "key", "crl", "ca", NULL};
|
||||
int errfnd = 0;
|
||||
char * subopts = optarg;
|
||||
char * value;
|
||||
|
||||
while (*subopts != '\0' && !errfnd)
|
||||
{
|
||||
int subopt = getsubopt(&subopts, x509_subopt_token, &value);
|
||||
if (value == NULL && subopt != -1)
|
||||
{
|
||||
logger_early(1, "Missing value for `%s'", x509_subopt_token[subopt]);
|
||||
return 1;
|
||||
}
|
||||
if (subopt == -1)
|
||||
{
|
||||
logger_early(1, "Invalid subopt: %s", value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (subopt)
|
||||
{
|
||||
case 0: /* cert */
|
||||
nDPIsrvd_options.x509_certfile = strdup(value);
|
||||
break;
|
||||
case 1: /* key */
|
||||
nDPIsrvd_options.x509_keyfile = strdup(value);
|
||||
break;
|
||||
case 2: /* crl */
|
||||
nDPIsrvd_options.x509_crlfile = strdup(value);
|
||||
break;
|
||||
case 3: /* ca */
|
||||
nDPIsrvd_options.x509_cafile = strdup(value);
|
||||
break;
|
||||
default:
|
||||
logger_early(1, "Invalid subopt: %s", value);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
enable_tls = 1;
|
||||
#else
|
||||
logger_early(1, "To use TLS capabilities (`-x'), GnuTLS support required.");
|
||||
return 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case 'h':
|
||||
default:
|
||||
fprintf(stderr, "%s\n", get_nDPId_version());
|
||||
@@ -870,6 +1140,10 @@ static int nDPIsrvd_parse_options(int argc, char ** argv)
|
||||
"\t-s\tPath to a listening UNIX socket (nDPIsrvd Distributor).\n"
|
||||
"\t \tDefault: %s\n"
|
||||
"\t-S\tAddress:Port of the listening TCP/IP socket (nDPIsrvd Distributor).\n"
|
||||
#ifdef ENABLE_GNUTLS
|
||||
"\t[-X tls-distributor-host:port]\n"
|
||||
"\t[-x cert=PEM-file] [-x key=PEM-file] [-x crl=file] [-x ca=PEM-file]\n"
|
||||
#endif
|
||||
"\t-v\tversion\n"
|
||||
"\t-h\tthis\n\n",
|
||||
argv[0],
|
||||
@@ -898,7 +1172,7 @@ static int nDPIsrvd_parse_options(int argc, char ** argv)
|
||||
|
||||
if (is_cmdarg_set(&nDPIsrvd_options.distributor_in_address) != 0)
|
||||
{
|
||||
if (nDPIsrvd_setup_address(&distributor_in_address, get_cmdarg(&nDPIsrvd_options.distributor_in_address)) != 0)
|
||||
if (nDPIsrvd_setup_address(&addrs[DISTRIBUTOR_IN], get_cmdarg(&nDPIsrvd_options.distributor_in_address)) != 0)
|
||||
{
|
||||
logger_early(1,
|
||||
"%s: Could not parse address %s",
|
||||
@@ -906,7 +1180,7 @@ static int nDPIsrvd_parse_options(int argc, char ** argv)
|
||||
get_cmdarg(&nDPIsrvd_options.distributor_in_address));
|
||||
return 1;
|
||||
}
|
||||
if (distributor_in_address.raw.sa_family == AF_UNIX)
|
||||
if (addrs[DISTRIBUTOR_IN].raw.sa_family == AF_UNIX)
|
||||
{
|
||||
logger_early(1,
|
||||
"%s: You've requested to setup another UNIX socket `%s', but there is already one at `%s'",
|
||||
@@ -917,6 +1191,44 @@ static int nDPIsrvd_parse_options(int argc, char ** argv)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_GNUTLS
|
||||
if (enable_tls != 0)
|
||||
{
|
||||
if (nDPIsrvd_options.x509_certfile == NULL || nDPIsrvd_options.x509_keyfile == NULL ||
|
||||
nDPIsrvd_options.x509_cafile == NULL)
|
||||
{
|
||||
logger_early(1,
|
||||
"%s: To use nDPIsrvd TLS capabilities, `-x cert', `-x key' and `-x ca' need to be set.",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nDPIsrvd_options.distributor_in_tls_address == NULL)
|
||||
{
|
||||
logger_early(1, "%s: To use nDPIsrvd TLS capabilities, `-X' need to bet set.", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nDPIsrvd_setup_address(&addrs[DISTRIBUTOR_IN_TLS],
|
||||
nDPIsrvd_options.distributor_in_tls_address) != 0)
|
||||
{
|
||||
logger_early(1,
|
||||
"%s: Could not parse address %s",
|
||||
argv[0],
|
||||
nDPIsrvd_options.distributor_in_tls_address);
|
||||
return 1;
|
||||
}
|
||||
if (addrs[DISTRIBUTOR_IN_TLS].raw.sa_family == AF_UNIX)
|
||||
{
|
||||
logger_early(1,
|
||||
"%s: You've requested to setup another UNIX socket `%s' for TLS, which is not supported. Please use `-s'.",
|
||||
argv[0],
|
||||
nDPIsrvd_options.distributor_in_tls_address);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
logger_early(1, "%s: Unexpected argument after options", argv[0]);
|
||||
@@ -947,6 +1259,63 @@ static struct remote_desc * accept_remote(int server_fd,
|
||||
return current;
|
||||
}
|
||||
|
||||
static pid_t get_pid_from_unix_socket(int fd, uid_t * const uid)
|
||||
{
|
||||
struct ucred ucred = {};
|
||||
socklen_t ucred_len = sizeof(ucred);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &ucred_len) == -1)
|
||||
{
|
||||
logger(1, "Error getting credentials from UNIX socket: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (uid != NULL)
|
||||
{
|
||||
*uid = ucred.uid;
|
||||
}
|
||||
|
||||
return ucred.pid;
|
||||
}
|
||||
|
||||
static char * get_username_from_uid(uid_t const uid)
|
||||
{
|
||||
struct passwd pwnam = {};
|
||||
struct passwd * pwres = NULL;
|
||||
ssize_t pwsiz = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||
if (pwsiz == -1)
|
||||
{
|
||||
pwsiz = BUFSIZ;
|
||||
}
|
||||
char buf[pwsiz];
|
||||
if (getpwuid_r(uid, &pwnam, &buf[0], pwsiz, &pwres) != 0)
|
||||
{
|
||||
logger(1, "Could not get passwd entry for user id %u", uid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return strdup(pwres->pw_name);
|
||||
}
|
||||
|
||||
int set_snd_opts(int fd)
|
||||
{
|
||||
int sockopt = NETWORK_BUFFER_MAX_SIZE;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockopt, sizeof(sockopt)) < 0)
|
||||
{
|
||||
logger(1, "Error setting socket option SO_SNDBUF: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
struct timeval send_timeout = {1, 0};
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&send_timeout, sizeof(send_timeout)) != 0)
|
||||
{
|
||||
logger(1, "Error setting socket option send timeout: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int new_connection(int epollfd, int eventfd)
|
||||
{
|
||||
union
|
||||
@@ -954,29 +1323,40 @@ static int new_connection(int epollfd, int eventfd)
|
||||
struct sockaddr_un saddr_collector_un;
|
||||
struct sockaddr_un saddr_distributor_un;
|
||||
struct sockaddr_in saddr_distributor_in;
|
||||
#ifdef ENABLE_GNUTLS
|
||||
struct sockaddr_in saddr_distributor_in_tls;
|
||||
#endif
|
||||
} sockaddr;
|
||||
|
||||
socklen_t peer_addr_len;
|
||||
enum sock_type stype;
|
||||
int server_fd;
|
||||
if (eventfd == collector_un_sockfd)
|
||||
if (eventfd == sockfds[COLLECTOR_UN])
|
||||
{
|
||||
peer_addr_len = sizeof(sockaddr.saddr_collector_un);
|
||||
stype = COLLECTOR_UN;
|
||||
server_fd = collector_un_sockfd;
|
||||
server_fd = sockfds[COLLECTOR_UN];
|
||||
}
|
||||
else if (eventfd == distributor_un_sockfd)
|
||||
else if (eventfd == sockfds[DISTRIBUTOR_UN])
|
||||
{
|
||||
peer_addr_len = sizeof(sockaddr.saddr_distributor_un);
|
||||
stype = DISTRIBUTOR_UN;
|
||||
server_fd = distributor_un_sockfd;
|
||||
server_fd = sockfds[DISTRIBUTOR_UN];
|
||||
}
|
||||
else if (eventfd == distributor_in_sockfd)
|
||||
else if (eventfd == sockfds[DISTRIBUTOR_IN])
|
||||
{
|
||||
peer_addr_len = sizeof(sockaddr.saddr_distributor_in);
|
||||
stype = DISTRIBUTOR_IN;
|
||||
server_fd = distributor_in_sockfd;
|
||||
server_fd = sockfds[DISTRIBUTOR_IN];
|
||||
}
|
||||
#ifdef ENABLE_GNUTLS
|
||||
else if (eventfd == sockfds[DISTRIBUTOR_IN_TLS])
|
||||
{
|
||||
peer_addr_len = sizeof(sockaddr.saddr_distributor_in_tls);
|
||||
stype = DISTRIBUTOR_IN_TLS;
|
||||
server_fd = sockfds[DISTRIBUTOR_IN_TLS];
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
@@ -1002,83 +1382,60 @@ static int new_connection(int epollfd, int eventfd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct ucred ucred = {};
|
||||
socklen_t ucred_len = sizeof(ucred);
|
||||
if (getsockopt(current->fd, SOL_SOCKET, SO_PEERCRED, &ucred, &ucred_len) == -1)
|
||||
current->event_collector_un.pid = get_pid_from_unix_socket(current->fd, NULL);
|
||||
if (current->event_collector_un.pid == -1)
|
||||
{
|
||||
logger(1, "Error getting credentials from UNIX socket: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
current->event_collector_un.pid = ucred.pid;
|
||||
|
||||
logger_nDPIsrvd(current, "New collector connection from", "");
|
||||
break;
|
||||
case DISTRIBUTOR_UN:
|
||||
case DISTRIBUTOR_IN:
|
||||
if (current->sock_type == DISTRIBUTOR_UN)
|
||||
current->event_distributor_un.peer = sockaddr.saddr_distributor_un;
|
||||
|
||||
uid_t uid;
|
||||
current->event_distributor_un.pid = get_pid_from_unix_socket(current->fd, &uid);
|
||||
if (current->event_distributor_un.pid == -1)
|
||||
{
|
||||
current->event_distributor_un.peer = sockaddr.saddr_distributor_un;
|
||||
|
||||
struct ucred ucred = {};
|
||||
socklen_t ucred_len = sizeof(ucred);
|
||||
if (getsockopt(current->fd, SOL_SOCKET, SO_PEERCRED, &ucred, &ucred_len) == -1)
|
||||
{
|
||||
logger(1, "Error getting credentials from UNIX socket: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct passwd pwnam = {};
|
||||
struct passwd * pwres = NULL;
|
||||
ssize_t pwsiz = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||
if (pwsiz == -1)
|
||||
{
|
||||
pwsiz = BUFSIZ;
|
||||
}
|
||||
char buf[pwsiz];
|
||||
if (getpwuid_r(ucred.uid, &pwnam, &buf[0], pwsiz, &pwres) != 0)
|
||||
{
|
||||
logger(1, "Could not get passwd entry for user id %u", ucred.uid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
current->event_distributor_un.pid = ucred.pid;
|
||||
current->event_distributor_un.user_name = strdup(pwres->pw_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
current->event_distributor_in.peer = sockaddr.saddr_distributor_in;
|
||||
|
||||
sockopt = 1;
|
||||
if (setsockopt(current->fd, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt)) < 0)
|
||||
{
|
||||
logger(1, "Error setting socket option SO_RCVBUF: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (inet_ntop(current->event_distributor_in.peer.sin_family,
|
||||
¤t->event_distributor_in.peer.sin_addr,
|
||||
¤t->event_distributor_in.peer_addr[0],
|
||||
sizeof(current->event_distributor_in.peer_addr)) == NULL)
|
||||
{
|
||||
logger(1, "Error converting an internet address: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
sockopt = NETWORK_BUFFER_MAX_SIZE;
|
||||
if (setsockopt(current->fd, SOL_SOCKET, SO_SNDBUF, &sockopt, sizeof(sockopt)) < 0)
|
||||
{
|
||||
logger(1, "Error setting socket option SO_SNDBUF: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
current->event_distributor_un.user_name = get_username_from_uid(uid);
|
||||
if (current->event_distributor_un.user_name == NULL)
|
||||
{
|
||||
struct timeval send_timeout = {1, 0};
|
||||
if (setsockopt(current->fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&send_timeout, sizeof(send_timeout)) != 0)
|
||||
{
|
||||
logger(1, "Error setting socket option send timeout: %s", strerror(errno));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (set_snd_opts(current->fd) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case DISTRIBUTOR_IN:
|
||||
#ifdef ENABLE_GNUTLS
|
||||
case DISTRIBUTOR_IN_TLS:
|
||||
#endif
|
||||
current->event_distributor_in.peer = sockaddr.saddr_distributor_in;
|
||||
|
||||
sockopt = 1;
|
||||
if (setsockopt(current->fd, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt)) < 0)
|
||||
{
|
||||
logger(1, "Error setting socket option SO_RCVBUF: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (inet_ntop(current->event_distributor_in.peer.sin_family,
|
||||
¤t->event_distributor_in.peer.sin_addr,
|
||||
¤t->event_distributor_in.peer_addr[0],
|
||||
sizeof(current->event_distributor_in.peer_addr)) == NULL)
|
||||
{
|
||||
logger(1, "Error converting an internet address: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (set_snd_opts(current->fd) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
logger_nDPIsrvd(current, "New distributor connection from", "");
|
||||
@@ -1389,8 +1746,12 @@ static int mainloop(int epollfd)
|
||||
{
|
||||
if ((events[i].events & EPOLLERR) != 0 || (events[i].events & EPOLLHUP) != 0)
|
||||
{
|
||||
if (events[i].data.fd != collector_un_sockfd && events[i].data.fd != distributor_un_sockfd &&
|
||||
events[i].data.fd != distributor_in_sockfd)
|
||||
if (events[i].data.fd != sockfds[COLLECTOR_UN] &&
|
||||
events[i].data.fd != sockfds[DISTRIBUTOR_UN] && events[i].data.fd != sockfds[DISTRIBUTOR_IN]
|
||||
#ifdef ENABLE_GNUTLS
|
||||
&& events[i].data.fd != sockfds[DISTRIBUTOR_IN_TLS]
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct remote_desc * const current = (struct remote_desc *)events[i].data.ptr;
|
||||
switch (current->sock_type)
|
||||
@@ -1402,18 +1763,28 @@ static int mainloop(int epollfd)
|
||||
case DISTRIBUTOR_IN:
|
||||
logger_nDPIsrvd(current, "Distributor connection", "closed");
|
||||
break;
|
||||
#ifdef ENABLE_GNUTLS
|
||||
case DISTRIBUTOR_IN_TLS:
|
||||
logger_nDPIsrvd(current, "Distributor (TLS) connection", "closed");
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
disconnect_client(epollfd, current);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger(1, "Epoll event error: %s", (errno != 0 ? strerror(errno) : "unknown"));
|
||||
if (errno != 0)
|
||||
{
|
||||
logger(1, "Epoll event error: %s", strerror(errno));
|
||||
} else {
|
||||
logger(1, "Epoll event error (unknown) for fd %d", events[i].data.fd);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (events[i].data.fd == collector_un_sockfd || events[i].data.fd == distributor_un_sockfd ||
|
||||
events[i].data.fd == distributor_in_sockfd)
|
||||
if (events[i].data.fd == sockfds[COLLECTOR_UN] || events[i].data.fd == sockfds[DISTRIBUTOR_UN] ||
|
||||
events[i].data.fd == sockfds[DISTRIBUTOR_IN])
|
||||
{
|
||||
/* New connection to collector / distributor. */
|
||||
if (new_connection(epollfd, events[i].data.fd) != 0)
|
||||
@@ -1473,21 +1844,21 @@ static int setup_event_queue(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (add_in_event_fd(epollfd, collector_un_sockfd) != 0)
|
||||
if (add_in_event_fd(epollfd, sockfds[COLLECTOR_UN]) != 0)
|
||||
{
|
||||
logger(1, "Error adding collector UNIX socket fd to epoll: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (add_in_event_fd(epollfd, distributor_un_sockfd) != 0)
|
||||
if (add_in_event_fd(epollfd, sockfds[DISTRIBUTOR_UN]) != 0)
|
||||
{
|
||||
logger(1, "Error adding distributor UNIX socket fd to epoll: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (distributor_in_sockfd >= 0)
|
||||
if (sockfds[DISTRIBUTOR_IN] >= 0)
|
||||
{
|
||||
if (add_in_event_fd(epollfd, distributor_in_sockfd) != 0)
|
||||
if (add_in_event_fd(epollfd, sockfds[DISTRIBUTOR_IN]) != 0)
|
||||
{
|
||||
logger(1, "Error adding distributor TCP/IP socket fd to epoll: %s", strerror(errno));
|
||||
return -1;
|
||||
@@ -1597,20 +1968,28 @@ int main(int argc, char ** argv)
|
||||
|
||||
logger(0, "collector UNIX socket listen on `%s'", get_cmdarg(&nDPIsrvd_options.collector_un_sockpath));
|
||||
logger(0, "distributor UNIX listen on `%s'", get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath));
|
||||
switch (distributor_in_address.raw.sa_family)
|
||||
switch (addrs[DISTRIBUTOR_IN].raw.sa_family)
|
||||
{
|
||||
default:
|
||||
goto error_unlink_sockets;
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
logger(0, "distributor TCP listen on `%s'", get_cmdarg(&nDPIsrvd_options.distributor_in_address));
|
||||
logger(1,
|
||||
"Please keep in mind that using a TCP Socket may leak sensitive information to "
|
||||
"everyone with access to the device/network. You've been warned!");
|
||||
"Please keep in mind that using a TCP Socket (with `-S') may leak sensitive information to "
|
||||
"everyone with access to the device/network. You've been warned!"
|
||||
"Please use TLS (with `-x' and `-X' if possible.");
|
||||
break;
|
||||
case AF_UNIX:
|
||||
case 0xFFFF:
|
||||
break;
|
||||
}
|
||||
#ifdef ENABLE_GNUTLS
|
||||
if (enable_tls)
|
||||
{
|
||||
logger(0, "distributor (TLS) TCP listen on `%s'", nDPIsrvd_options.distributor_in_tls_address);
|
||||
}
|
||||
#endif
|
||||
|
||||
errno = 0;
|
||||
if (change_user_group(get_cmdarg(&nDPIsrvd_options.user),
|
||||
@@ -1638,6 +2017,18 @@ int main(int argc, char ** argv)
|
||||
goto error_unlink_sockets;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_GNUTLS
|
||||
if (enable_tls != 0 && gtls_global_init(nDPIsrvd_options.x509_certfile,
|
||||
nDPIsrvd_options.x509_keyfile,
|
||||
nDPIsrvd_options.x509_crlfile,
|
||||
nDPIsrvd_options.x509_cafile,
|
||||
&x509_creds,
|
||||
&prio_cache) != 0)
|
||||
{
|
||||
goto error_unlink_sockets;
|
||||
}
|
||||
#endif
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
@@ -1656,9 +2047,9 @@ error_unlink_sockets:
|
||||
unlink(get_cmdarg(&nDPIsrvd_options.collector_un_sockpath));
|
||||
unlink(get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath));
|
||||
error:
|
||||
close(collector_un_sockfd);
|
||||
close(distributor_un_sockfd);
|
||||
close(distributor_in_sockfd);
|
||||
close(sockfds[COLLECTOR_UN]);
|
||||
close(sockfds[DISTRIBUTOR_UN]);
|
||||
close(sockfds[DISTRIBUTOR_IN]);
|
||||
|
||||
daemonize_shutdown(get_cmdarg(&nDPIsrvd_options.pidfile));
|
||||
logger(0, "Bye.");
|
||||
|
||||
32
scripts/generate-tls-ca.sh
Executable file
32
scripts/generate-tls-ca.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -e
|
||||
|
||||
OUTDIR="$(dirname ${0})"
|
||||
|
||||
printf 'Output directory: %s\n' "${OUTDIR}"
|
||||
|
||||
printf 'ca\ncert_signing_key' > template
|
||||
certtool --generate-privkey > "${OUTDIR}/ca-key.pem"
|
||||
certtool --generate-self-signed \
|
||||
--template template \
|
||||
--load-privkey "${OUTDIR}/ca-key.pem" \
|
||||
--outfile "${OUTDIR}/ca-cert.pem"
|
||||
rm template
|
||||
|
||||
printf 'expiration_days = 365' > template
|
||||
certtool --generate-crl --load-ca-privkey "${OUTDIR}/ca-key.pem" \
|
||||
--template template \
|
||||
--load-ca-certificate "${OUTDIR}/ca-cert.pem" \
|
||||
--outfile "${OUTDIR}/crl.pem"
|
||||
rm template
|
||||
|
||||
printf 'encryption_key\nsigning_key' > template
|
||||
certtool --generate-privkey > "${OUTDIR}/server-key.pem"
|
||||
certtool --generate-certificate \
|
||||
--template template \
|
||||
--load-privkey "${OUTDIR}/server-key.pem" \
|
||||
--load-ca-certificate "${OUTDIR}/ca-cert.pem" \
|
||||
--load-ca-privkey "${OUTDIR}/ca-key.pem" \
|
||||
--outfile "${OUTDIR}/server-cert.pem"
|
||||
rm template
|
||||
17
scripts/generate-tls-cert.sh
Executable file
17
scripts/generate-tls-cert.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -e
|
||||
|
||||
OUTDIR="$(dirname ${0})"
|
||||
|
||||
printf 'Output directory: %s\n' "${OUTDIR}"
|
||||
|
||||
printf 'encryption_key\nsigning_key' > template
|
||||
certtool --generate-privkey > "${OUTDIR}/client-key.pem"
|
||||
certtool --generate-certificate \
|
||||
--template template \
|
||||
--load-privkey "${OUTDIR}/client-key.pem" \
|
||||
--load-ca-certificate "${OUTDIR}/ca-cert.pem" \
|
||||
--load-ca-privkey "${OUTDIR}/ca-key.pem" \
|
||||
--outfile "${OUTDIR}/client-cert.pem"
|
||||
rm template
|
||||
167
tls-cli.c
Normal file
167
tls-cli.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/* This example code is placed in the public domain. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/x509.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define CHECK(x) assert((x) >= 0)
|
||||
|
||||
#define MAX_BUF 1024
|
||||
#define MSG "Hello TLS"
|
||||
|
||||
static int tcp_connect(void)
|
||||
{
|
||||
const char * PORT = "5556";
|
||||
const char * SERVER = "127.0.0.1";
|
||||
int err, sd;
|
||||
struct sockaddr_in sa;
|
||||
|
||||
/* connects to server
|
||||
*/
|
||||
sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
memset(&sa, '\0', sizeof(sa));
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(atoi(PORT));
|
||||
inet_pton(AF_INET, SERVER, &sa.sin_addr);
|
||||
|
||||
err = connect(sd, (struct sockaddr *)&sa, sizeof(sa));
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr, "Connect error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
static void tcp_close(int sd)
|
||||
{
|
||||
shutdown(sd, SHUT_RDWR); /* no more receptions */
|
||||
close(sd);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int ret, sd, ii;
|
||||
gnutls_session_t session;
|
||||
char buffer[MAX_BUF + 1], *desc;
|
||||
gnutls_datum_t out;
|
||||
int type;
|
||||
unsigned status;
|
||||
gnutls_certificate_credentials_t xcred;
|
||||
|
||||
if (gnutls_check_version("3.4.6") == NULL)
|
||||
{
|
||||
fprintf(stderr, "GnuTLS 3.4.6 or later is required for this example\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* for backwards compatibility with gnutls < 3.3.0 */
|
||||
CHECK(gnutls_global_init());
|
||||
|
||||
/* X509 stuff */
|
||||
CHECK(gnutls_certificate_allocate_credentials(&xcred));
|
||||
|
||||
gnutls_certificate_set_x509_key_file(xcred, "client-cert.pem", "client-key.pem", GNUTLS_X509_FMT_PEM);
|
||||
|
||||
CHECK(gnutls_certificate_set_x509_trust_file(xcred, "ca-cert.pem", GNUTLS_X509_FMT_PEM));
|
||||
|
||||
/* Initialize TLS session */
|
||||
CHECK(gnutls_init(&session, GNUTLS_CLIENT));
|
||||
|
||||
/* It is recommended to use the default priorities */
|
||||
CHECK(gnutls_set_default_priority(session));
|
||||
|
||||
/* put the x509 credentials to the current session */
|
||||
CHECK(gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred));
|
||||
|
||||
sd = tcp_connect();
|
||||
|
||||
gnutls_transport_set_int(session, sd);
|
||||
gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
|
||||
|
||||
/* Perform the TLS handshake */
|
||||
do
|
||||
{
|
||||
ret = gnutls_handshake(session);
|
||||
} while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret == GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR)
|
||||
{
|
||||
/* check certificate verification status */
|
||||
type = gnutls_certificate_type_get(session);
|
||||
status = gnutls_session_get_verify_cert_status(session);
|
||||
CHECK(gnutls_certificate_verification_status_print(status, type, &out, 0));
|
||||
printf("cert verify output: %s\n", out.data);
|
||||
gnutls_free(out.data);
|
||||
}
|
||||
fprintf(stderr, "*** Handshake failed: %s\n", gnutls_strerror(ret));
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc = gnutls_session_get_desc(session);
|
||||
printf("- Session info: %s\n", desc);
|
||||
gnutls_free(desc);
|
||||
}
|
||||
|
||||
/* send data */
|
||||
CHECK(gnutls_record_send(session, MSG, strlen(MSG)));
|
||||
|
||||
ret = gnutls_record_recv(session, buffer, MAX_BUF);
|
||||
if (ret == 0)
|
||||
{
|
||||
printf("- Peer has closed the TLS connection\n");
|
||||
goto end;
|
||||
}
|
||||
else if (ret < 0 && gnutls_error_is_fatal(ret) == 0)
|
||||
{
|
||||
fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret));
|
||||
}
|
||||
else if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
printf("- Received %d bytes: ", ret);
|
||||
for (ii = 0; ii < ret; ii++)
|
||||
{
|
||||
fputc(buffer[ii], stdout);
|
||||
}
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
|
||||
CHECK(gnutls_bye(session, GNUTLS_SHUT_RDWR));
|
||||
|
||||
end:
|
||||
|
||||
tcp_close(sd);
|
||||
|
||||
gnutls_deinit(session);
|
||||
|
||||
gnutls_certificate_free_credentials(xcred);
|
||||
|
||||
gnutls_global_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
146
tls-srv.c
Normal file
146
tls-srv.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/* This example code is placed in the public domain. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define CAFILE "ca-cert.pem"
|
||||
#define KEYFILE "server-key.pem"
|
||||
#define CERTFILE "server-cert.pem"
|
||||
#define CRLFILE "crl.pem"
|
||||
|
||||
#define CHECK(x) assert((x) >= 0)
|
||||
#define LOOP_CHECK(rval, cmd) \
|
||||
do \
|
||||
{ \
|
||||
rval = cmd; \
|
||||
} while (rval == GNUTLS_E_AGAIN || rval == GNUTLS_E_INTERRUPTED)
|
||||
|
||||
#define MAX_BUF 16
|
||||
#define PORT 5556 /* listen to 5556 port */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int listen_sd;
|
||||
int sd, ret;
|
||||
gnutls_certificate_credentials_t x509_cred;
|
||||
gnutls_priority_t priority_cache;
|
||||
struct sockaddr_in sa_serv;
|
||||
struct sockaddr_in sa_cli;
|
||||
socklen_t client_len;
|
||||
char topbuf[512];
|
||||
gnutls_session_t session;
|
||||
char buffer[MAX_BUF + 1];
|
||||
int optval = 1;
|
||||
|
||||
/* for backwards compatibility with gnutls < 3.3.0 */
|
||||
CHECK(gnutls_global_init());
|
||||
|
||||
CHECK(gnutls_certificate_allocate_credentials(&x509_cred));
|
||||
CHECK(gnutls_certificate_set_x509_crl_file(x509_cred, CRLFILE, GNUTLS_X509_FMT_PEM));
|
||||
CHECK(gnutls_certificate_set_x509_key_file(x509_cred, CERTFILE, KEYFILE, GNUTLS_X509_FMT_PEM));
|
||||
CHECK(gnutls_certificate_set_x509_trust_file(x509_cred, CAFILE, GNUTLS_X509_FMT_PEM));
|
||||
CHECK(gnutls_priority_init(&priority_cache, NULL, NULL));
|
||||
|
||||
#if GNUTLS_VERSION_NUMBER >= 0x030506
|
||||
/* only available since GnuTLS 3.5.6, on previous versions see
|
||||
* gnutls_certificate_set_dh_params(). */
|
||||
gnutls_certificate_set_known_dh_params(x509_cred, GNUTLS_SEC_PARAM_HIGH);
|
||||
#endif
|
||||
|
||||
/* Socket operations */
|
||||
listen_sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
memset(&sa_serv, '\0', sizeof(sa_serv));
|
||||
sa_serv.sin_family = AF_INET;
|
||||
sa_serv.sin_addr.s_addr = INADDR_ANY;
|
||||
sa_serv.sin_port = htons(PORT); /* Server Port number */
|
||||
|
||||
setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, sizeof(int));
|
||||
bind(listen_sd, (struct sockaddr *)&sa_serv, sizeof(sa_serv));
|
||||
listen(listen_sd, 1024);
|
||||
|
||||
printf("Server ready. Listening to port '%d'.\n", PORT);
|
||||
|
||||
client_len = sizeof(sa_cli);
|
||||
for (;;)
|
||||
{
|
||||
CHECK(gnutls_init(&session, GNUTLS_SERVER));
|
||||
CHECK(gnutls_priority_set(session, priority_cache));
|
||||
CHECK(gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred));
|
||||
gnutls_session_set_verify_cert(session, NULL, 0);
|
||||
gnutls_certificate_server_set_request(session, GNUTLS_CERT_REQUIRE);
|
||||
gnutls_certificate_send_x509_rdn_sequence(session, 1);
|
||||
gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
|
||||
|
||||
sd = accept(listen_sd, (struct sockaddr *)&sa_cli, &client_len);
|
||||
|
||||
printf("- connection from %s, port %d\n",
|
||||
inet_ntop(AF_INET, &sa_cli.sin_addr, topbuf, sizeof(topbuf)),
|
||||
ntohs(sa_cli.sin_port));
|
||||
|
||||
gnutls_transport_set_int(session, sd);
|
||||
|
||||
LOOP_CHECK(ret, gnutls_handshake(session));
|
||||
if (ret < 0)
|
||||
{
|
||||
close(sd);
|
||||
gnutls_deinit(session);
|
||||
fprintf(stderr, "*** Handshake has failed (%s)\n", gnutls_strerror(ret));
|
||||
continue;
|
||||
}
|
||||
printf("- Handshake was completed\n");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
LOOP_CHECK(ret, gnutls_record_recv(session, buffer, MAX_BUF));
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
printf("- Peer has closed the GnuTLS connection\n");
|
||||
break;
|
||||
}
|
||||
else if (ret < 0 && gnutls_error_is_fatal(ret) == 0)
|
||||
{
|
||||
fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret));
|
||||
}
|
||||
else if (ret < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\n*** Received corrupted "
|
||||
"data(%d). Closing the connection.\n",
|
||||
ret);
|
||||
break;
|
||||
}
|
||||
else if (ret > 0 && ret < MAX_BUF - 1)
|
||||
{
|
||||
buffer[ret] = '$';
|
||||
CHECK(gnutls_record_send(session, buffer, ret + 1));
|
||||
}
|
||||
}
|
||||
LOOP_CHECK(ret, gnutls_bye(session, GNUTLS_SHUT_WR));
|
||||
|
||||
close(sd);
|
||||
gnutls_deinit(session);
|
||||
}
|
||||
close(listen_sd);
|
||||
|
||||
gnutls_certificate_free_credentials(x509_cred);
|
||||
gnutls_priority_deinit(priority_cache);
|
||||
|
||||
gnutls_global_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user