diff --git a/.gitmodules b/.gitmodules index 28d6a265..26a1f354 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,5 +12,5 @@ branch = develop [submodule "src/ssl_dane"] path = src/ssl_dane - url = https://github.com/banburybill/ssl_dane - branch = feature/windows-native-build + url = https://github.com/getdnsapi/ssl_dane + branch = getdns diff --git a/.travis.yml b/.travis.yml index 7ea9244e..75d8f25d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,8 +19,9 @@ addons: - clang - wget - openssh-client + - libgnutls28-dev script: - mkdir tests - cd tests - ../src/test/tpkg/run-all.sh -# - ../src/test/tpkg/run-one.sh 275-server-capabilities.tpkg -V +# - ../src/test/tpkg/run-one.sh 290-transports.tpkg -V diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d22d3ca..413709da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ endif () set(PACKAGE "getdns") set(PACKAGE_NAME "getdns") -set(PACKAGE_VERSION "1.6.0") +set(PACKAGE_VERSION "1.7.0") set(PACKAGE_BUGREPORT "team@getdnsapi.net") set(PACKAGE_URL "https://getdnsapi.net") @@ -25,7 +25,7 @@ set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}${RELEASE_CANDIDATE}") set(PACKAGE_TARNAME "${PACKAGE}-${PACKAGE_VERSION}${RELEASE_CANDIDATE}") set(GETDNS_VERSION "${PACKAGE_VERSION}${RELEASE_CANDIDATE}") -set(GETDNS_NUMERIC_VERSION 0x01060000) +set(GETDNS_NUMERIC_VERSION 0x01070000) set(API_VERSION "December 2015") set(API_NUMERIC_VERSION 0x07df0c00) @@ -68,10 +68,11 @@ set(API_NUMERIC_VERSION 0x07df0c00) # getdns-1.5.0 had libversion 11:0:1 # getdns-1.5.1 had libversion 11:1:1 # getdns-1.5.2 had libversion 11:2:1 -# getdns-1.6.0 has libversion 11:3:1 -set(GETDNS_VERSION_CURRENT 11) -set(GETDNS_VERSION_REVISION 3) -set(GETDNS_VERSION_AGE 1) +# getdns-1.6.0 had libversion 11:3:1 +# getdns-1.7.0 has libversion 12:0:2 +set(GETDNS_VERSION_CURRENT 12) +set(GETDNS_VERSION_REVISION 0) +set(GETDNS_VERSION_AGE 2) project(getdns VERSION ${PACKAGE_VERSION} LANGUAGES C) @@ -102,7 +103,7 @@ elseif (APPLE) elseif (UNIX) set(HOSTOS "unix") - if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") + if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600") endif () if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") @@ -166,6 +167,8 @@ option(BUILD_LIBUV "Build libuv support library available." ON) option(USE_LIBIDN2 "Use libidn2 if available." ON) option(USE_GNUTLS "Use GnuTLS for TLS connections." OFF) +option(FORCE_COMPAT_STRPTIME "Force use of internal strptime when cross-compiling." OFF) + # Above names chosen for user consistency. Now define substituted names. set(REQ_DEBUG ${ENABLE_DEBUG_REQ}) set(SCHED_DEBUG ${ENABLE_DEBUG_SCHED}) @@ -334,8 +337,11 @@ check_include_file(openssl/err.h HAVE_OPENSSL_ERR_H) check_include_file(openssl/rand.h HAVE_OPENSSL_RAND_H) check_include_file(openssl/conf.h HAVE_OPENSSL_CONF_H) check_include_file(openssl/engine.h HAVE_OPENSSL_ENGINE_H) +check_include_file(openssl/bn.h HAVE_OPENSSL_BN_H) +check_include_file(openssl/dsa.h HAVE_OPENSSL_DSA_H) +check_include_file(openssl/rsa.h HAVE_OPENSSL_RSA_H) -set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES}) +set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES} ${getdns_system_libs}) check_function_exists(DSA_SIG_set0 HAVE_DSA_SIG_SET0) check_function_exists(DSA_set0_pqg HAVE_DSA_SET0_PQG) check_function_exists(DSA_set0_key HAVE_DSA_SET0_KEY) @@ -489,9 +495,19 @@ if (NOT ENABLE_STUB_ONLY) set(CMAKE_REQUIRED_INCLUDES ${LIBUNBOUND_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${LIBUNBOUND_LIBRARIES}) - check_include_file(unbound-event.h HAVE_UNBOUND_EVENT_H) - check_symbol_exists(ub_ctx_create_ub_event "unbound-event.h" HAVE_UNBOUND_EVENT_API) - check_symbol_exists(ub_ctx_set_stub "unbound-event.h" HAVE_UB_CTX_SET_STUB) + + check_symbol_exists(ub_ctx_set_stub "unbound.h" HAVE_UB_CTX_SET_STUB) + + if (ENABLE_UNBOUND_EVENT_API) + check_include_file(unbound-event.h HAVE_UNBOUND_EVENT_H) + check_symbol_exists(ub_ctx_create_ub_event "unbound-event.h" HAVE_UNBOUND_EVENT_API) + endif () +else () + # Ensure we're not using libunbound items. + set(HAVE_LIBUNBOUND 0) + set(HAVE_UNBOUND_EVENT_H 0) + set(HAVE_UNBOUND_EVENT_API 0) + set(HAVE_UB_CTX_SET_STUB 0) endif () # Event loop extension @@ -521,7 +537,14 @@ set(STRPTIME_TEST_SOURCE "\n if (!res) return 1; return 0; }") if (HAVE_STRPTIME) - check_c_source_runs("${STRPTIME_TEST_SOURCE}" STRPTIME_WORKS) + if (CMAKE_CROSSCOMPILING) + if (NOT FORCE_COMPAT_STRPTIME) + message(WARNING "Assuming strptime() is POSIX compliant with %t matching any white space. Specify FORCE_COMPAT_STRPTIME on non-compliant platforms e.g. BSD derived.") + set(STRPTIME_WORKS 1) + endif () + else () + check_c_source_runs("${STRPTIME_TEST_SOURCE}" STRPTIME_WORKS) + endif () endif () try_compile(HAVE___FUNC__ @@ -549,6 +572,8 @@ else () endif () endif () +check_symbol_exists(TCP_USER_TIMEOUT "sys/socket.h;netinet/tcp.h" HAVE_DECL_TCP_USER_TIMEOUT) + # Main library add_library(getdns_objects OBJECT src/anchor.c @@ -770,27 +795,27 @@ if (USE_LIBEV) set_property(TARGET ev_objects PROPERTY POSITION_INDEPENDENT_CODE 1) set_property(TARGET ev_objects PROPERTY C_STANDARD 11) if (ENABLE_STATIC) - add_library(getdns_ex_ev STATIC $) - target_include_directories(getdns_ex_ev PRIVATE Libev::Libev) - target_link_libraries(getdns_ex_ev PUBLIC getdns Libev::Libev) + add_library(getdns_ext_ev STATIC $) + target_include_directories(getdns_ext_ev PRIVATE Libev::Libev) + target_link_libraries(getdns_ext_ev PUBLIC getdns Libev::Libev) if (Libunbound_FOUND) - target_link_libraries(getdns_ex_ev PUBLIC Libunbound::Libunbound) + target_link_libraries(getdns_ext_ev PUBLIC Libunbound::Libunbound) endif () - set_target_properties(getdns_ex_ev PROPERTIES OUTPUT_NAME getdns_ex_ev${static_lib_suffix}) + set_target_properties(getdns_ext_ev PROPERTIES OUTPUT_NAME getdns_ext_ev${static_lib_suffix}) endif () if (ENABLE_SHARED) - add_library(getdns_ex_ev_shared SHARED $) - target_include_directories(getdns_ex_ev_shared PRIVATE Libev::Libev) - target_link_libraries(getdns_ex_ev_shared PUBLIC getdns_shared Libev::Libev) + add_library(getdns_ext_ev_shared SHARED $) + target_include_directories(getdns_ext_ev_shared PRIVATE Libev::Libev) + target_link_libraries(getdns_ext_ev_shared PUBLIC getdns_shared Libev::Libev) if (Libunbound_FOUND) - target_link_libraries(getdns_ex_ev_shared PUBLIC Libunbound::Libunbound) + target_link_libraries(getdns_ext_ev_shared PUBLIC Libunbound::Libunbound) endif () - set_target_properties(getdns_ex_ev_shared PROPERTIES OUTPUT_NAME getdns_ex_ev) - target_shared_library_version(getdns_ex_ev_shared ${GETDNS_VERSION_CURRENT} ${GETDNS_VERSION_REVISION} ${GETDNS_VERSION_AGE}) + set_target_properties(getdns_ext_ev_shared PROPERTIES OUTPUT_NAME getdns_ext_ev) + target_shared_library_version(getdns_ext_ev_shared ${GETDNS_VERSION_CURRENT} ${GETDNS_VERSION_REVISION} ${GETDNS_VERSION_AGE}) file(STRINGS src/extension/libev.symbols symbols) - target_shared_library_exports(getdns_ex_ev_shared getdns_ex_ev "${symbols}") + target_shared_library_exports(getdns_ext_ev_shared getdns_ext_ev "${symbols}") if (NOT ENABLE_STATIC) - add_library(getdns_ex_ev ALIAS getdns_ex_ev_shared) + add_library(getdns_ext_ev ALIAS getdns_ext_ev_shared) endif () endif () else () @@ -821,27 +846,27 @@ if (USE_LIBEVENT2) set_property(TARGET event2_objects PROPERTY POSITION_INDEPENDENT_CODE 1) set_property(TARGET event2_objects PROPERTY C_STANDARD 11) if (ENABLE_STATIC) - add_library(getdns_ex_event STATIC $) - target_include_directories(getdns_ex_event PRIVATE Libevent2::Libevent_code) - target_link_libraries(getdns_ex_event PUBLIC getdns Libevent2::Libevent_core) + add_library(getdns_ext_event STATIC $) + target_include_directories(getdns_ext_event PRIVATE Libevent2::Libevent_code) + target_link_libraries(getdns_ext_event PUBLIC getdns Libevent2::Libevent_core) if (Libunbound_FOUND) - target_link_libraries(getdns_ex_event PUBLIC Libunbound::Libunbound) + target_link_libraries(getdns_ext_event PUBLIC Libunbound::Libunbound) endif () - set_target_properties(getdns_ex_event PROPERTIES OUTPUT_NAME getdns_ex_event${static_lib_suffix}) + set_target_properties(getdns_ext_event PROPERTIES OUTPUT_NAME getdns_ext_event${static_lib_suffix}) endif () if (ENABLE_SHARED) - add_library(getdns_ex_event_shared SHARED $) - target_include_directories(getdns_ex_event_shared PRIVATE Libevent2::Libevent_code) - target_link_libraries(getdns_ex_event_shared PUBLIC getdns_shared Libevent2::Libevent_core) + add_library(getdns_ext_event_shared SHARED $) + target_include_directories(getdns_ext_event_shared PRIVATE Libevent2::Libevent_code) + target_link_libraries(getdns_ext_event_shared PUBLIC getdns_shared Libevent2::Libevent_core) if (Libunbound_FOUND) - target_link_libraries(getdns_ex_event_shared PUBLIC Libunbound::Libunbound) + target_link_libraries(getdns_ext_event_shared PUBLIC Libunbound::Libunbound) endif () - set_target_properties(getdns_ex_event_shared PROPERTIES OUTPUT_NAME getdns_ex_event) - target_shared_library_version(getdns_ex_event_shared ${GETDNS_VERSION_CURRENT} ${GETDNS_VERSION_REVISION} ${GETDNS_VERSION_AGE}) + set_target_properties(getdns_ext_event_shared PROPERTIES OUTPUT_NAME getdns_ext_event) + target_shared_library_version(getdns_ext_event_shared ${GETDNS_VERSION_CURRENT} ${GETDNS_VERSION_REVISION} ${GETDNS_VERSION_AGE}) file(STRINGS src/extension/libevent.symbols symbols) - target_shared_library_exports(getdns_ex_event_shared getdns_ex_event "${symbols}") + target_shared_library_exports(getdns_ext_event_shared getdns_ext_event "${symbols}") if (NOT ENABLE_STATIC) - add_library(getdns_ex_event ALIAS getdns_ex_event_shared) + add_library(getdns_ext_event ALIAS getdns_ext_event_shared) endif () endif () else () @@ -873,27 +898,27 @@ if (USE_LIBUV) set_property(TARGET uv_objects PROPERTY POSITION_INDEPENDENT_CODE 1) set_property(TARGET uv_objects PROPERTY C_STANDARD 11) if (ENABLE_STATIC) - add_library(getdns_ex_uv STATIC $) - target_include_directories(getdns_ex_uv PRIVATE Libuv::Libuv) - target_link_libraries(getdns_ex_uv PUBLIC getdns Libuv::Libuv) + add_library(getdns_ext_uv STATIC $) + target_include_directories(getdns_ext_uv PRIVATE Libuv::Libuv) + target_link_libraries(getdns_ext_uv PUBLIC getdns Libuv::Libuv) if (Libunbound_FOUND) - target_link_libraries(getdns_ex_uv PUBLIC Libunbound::Libunbound) + target_link_libraries(getdns_ext_uv PUBLIC Libunbound::Libunbound) endif () - set_target_properties(getdns_ex_uv PROPERTIES OUTPUT_NAME getdns_ex_uv${static_lib_suffix}) + set_target_properties(getdns_ext_uv PROPERTIES OUTPUT_NAME getdns_ext_uv${static_lib_suffix}) endif () if (ENABLE_SHARED) - add_library(getdns_ex_uv_shared SHARED $) - target_include_directories(getdns_ex_uv_shared PRIVATE Libuv::Libuv) - target_link_libraries(getdns_ex_uv_shared PUBLIC getdns_shared Libuv::Libuv) + add_library(getdns_ext_uv_shared SHARED $) + target_include_directories(getdns_ext_uv_shared PRIVATE Libuv::Libuv) + target_link_libraries(getdns_ext_uv_shared PUBLIC getdns_shared Libuv::Libuv) if (Libunbound_FOUND) - target_link_libraries(getdns_ex_uv_shared PUBLIC Libunbound::Libunbound) + target_link_libraries(getdns_ext_uv_shared PUBLIC Libunbound::Libunbound) endif () - set_target_properties(getdns_ex_uv_shared PROPERTIES OUTPUT_NAME getdns_ex_uv) - target_shared_library_version(getdns_ex_uv_shared ${GETDNS_VERSION_CURRENT} ${GETDNS_VERSION_REVISION} ${GETDNS_VERSION_AGE}) + set_target_properties(getdns_ext_uv_shared PROPERTIES OUTPUT_NAME getdns_ext_uv) + target_shared_library_version(getdns_ext_uv_shared ${GETDNS_VERSION_CURRENT} ${GETDNS_VERSION_REVISION} ${GETDNS_VERSION_AGE}) file(STRINGS src/extension/libuv.symbols symbols) - target_shared_library_exports(getdns_ex_uv_shared getdns_ex_uv "${symbols}") + target_shared_library_exports(getdns_ext_uv_shared getdns_ext_uv "${symbols}") if (NOT ENABLE_STATIC) - add_library(getdns_ex_uv ALIAS getdns_ex_uv_shared) + add_library(getdns_ext_uv ALIAS getdns_ext_uv_shared) endif () endif () else () @@ -955,7 +980,7 @@ if (BUILD_TESTING) if (USE_LIBEVENT2) add_executable(check_getdns_event ${GETDNS_TEST_SOURCE_FILES}) - target_link_libraries(check_getdns_event PRIVATE ${GETDNS_TEST_LINK_LIBS} getdns_ex_event) + target_link_libraries(check_getdns_event PRIVATE ${GETDNS_TEST_LINK_LIBS} getdns_ext_event) add_test(NAME test_libevent COMMAND check_getdns_event) set_property(TEST test_libevent PROPERTY ENVIRONMENT "GETDNS_TEST_PORT=44321;CK_TIMEOUT_MULTIPLIER=2;CK_LOG_FILE_NAME=check_getdns_event.log" @@ -964,7 +989,7 @@ if (BUILD_TESTING) if (USE_LIBEV) add_executable(check_getdns_ev ${GETDNS_TEST_SOURCE_FILES}) - target_link_libraries(check_getdns_ev PRIVATE ${GETDNS_TEST_LINK_LIBS} getdns_ex_ev) + target_link_libraries(check_getdns_ev PRIVATE ${GETDNS_TEST_LINK_LIBS} getdns_ext_ev) add_test(NAME test_libev COMMAND check_getdns_ev) set_property(TEST test_libev PROPERTY ENVIRONMENT "GETDNS_TEST_PORT=45321;CK_TIMEOUT_MULTIPLIER=2;CK_LOG_FILE_NAME=check_getdns_ev.log" @@ -973,7 +998,7 @@ if (BUILD_TESTING) if (USE_LIBUV) add_executable(check_getdns_uv ${GETDNS_TEST_SOURCE_FILES}) - target_link_libraries(check_getdns_uv PRIVATE ${GETDNS_TEST_LINK_LIBS} getdns_ex_uv) + target_link_libraries(check_getdns_uv PRIVATE ${GETDNS_TEST_LINK_LIBS} getdns_ext_uv) add_test(NAME test_libuv COMMAND check_getdns_uv) set_property(TEST test_libuv PROPERTY ENVIRONMENT "GETDNS_TEST_PORT=46321;CK_TIMEOUT_MULTIPLIER=2;CK_LOG_FILE_NAME=check_getdns_uv.log" @@ -1043,43 +1068,43 @@ configure_file(getdns.pc.in getdns.pc @ONLY) # Installing. if (ENABLE_STATIC) - install(TARGETS getdns LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) + install(TARGETS getdns LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) if (USE_LIBEV) - install(TARGETS getdns_ex_ev LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) + install(TARGETS getdns_ext_ev LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif () if (USE_LIBEVENT2) - install(TARGETS getdns_ex_event LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) + install(TARGETS getdns_ext_event LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif () if (USE_LIBUV) - install(TARGETS getdns_ex_uv LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) + install(TARGETS getdns_ext_uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif () endif () if (ENABLE_SHARED) - install(TARGETS getdns_shared LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) + install(TARGETS getdns_shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) if (USE_LIBEV) - install(TARGETS getdns_ex_ev_shared LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) + install(TARGETS getdns_ext_ev_shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif () if (USE_LIBEVENT2) - install(TARGETS getdns_ex_event_shared LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) + install(TARGETS getdns_ext_event_shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif () if (USE_LIBUV) - install(TARGETS getdns_ex_uv_shared LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) + install(TARGETS getdns_ext_uv_shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif () endif () if (BUILD_GETDNS_QUERY) - install(TARGETS getdns_query RUNTIME DESTINATION bin) + install(TARGETS getdns_query RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif () if (BUILD_GETDNS_SERVER_MON) - install(TARGETS getdns_server_mon RUNTIME DESTINATION bin) + install(TARGETS getdns_server_mon RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif () -install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/getdns DESTINATION include) +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/getdns DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man3 DESTINATION share/man) set(docdir share/doc/getdns) install(FILES AUTHORS ChangeLog COPYING LICENSE NEWS README.md DESTINATION ${docdir}) install(FILES spec/index.html DESTINATION ${docdir}/spec) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/getdns.pc DESTINATION lib/pkgconfig) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/getdns.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) install(CODE "message(\"\ ***\n\ @@ -1123,17 +1148,17 @@ if (BUILD_EXAMPLES) if (USE_LIBEVENT2) add_executable(example-simple-answers spec/example/example-simple-answers.c) target_include_directories(example-simple-answers PRIVATE spec/example) - target_link_libraries(example-simple-answers PRIVATE getdns getdns_ex_event) + target_link_libraries(example-simple-answers PRIVATE getdns getdns_ext_event) set_property(TARGET example-simple-answers PROPERTY C_STANDARD 11) add_executable(example-tree spec/example/example-tree.c) target_include_directories(example-tree PRIVATE spec/example) - target_link_libraries(example-tree PRIVATE getdns getdns_ex_event) + target_link_libraries(example-tree PRIVATE getdns getdns_ext_event) set_property(TARGET example-tree PROPERTY C_STANDARD 11) add_executable(example-reverse spec/example/example-reverse.c) target_include_directories(example-reverse PRIVATE spec/example) - target_link_libraries(example-reverse PRIVATE getdns getdns_ex_event) + target_link_libraries(example-reverse PRIVATE getdns getdns_ext_event) set_property(TARGET example-reverse PROPERTY C_STANDARD 11) else () message(WARNING "\ diff --git a/ChangeLog b/ChangeLog index a01dfc61..7bcb12e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +* 2021-06-04: Version 1.7.0 + * Make TLS Handshake timeout max 4/5th of timeout for the query, + just like connection setup timeout was, so fallback transport + have a chance too when TCP connection setup is less well + detectable (as with TCP_FASTOPEN on MacOS). + * Issue #466: Memory leak with retrying queries (for examples + with search paths). Thanks doublez13. + * Issue #480: Handling of strptime when Cross compiling with CMake. + A new option to FORCE_COMPAT_STRPTIME (default disabled) will + (when disabled) make cmake assume the target platform has a POSIX + compatible strptime when cross-compiling. + * Setting of the number of milliseconds send data may remain + unacknowledged by the peer in a TCP connection (when supported + by the OS) with getdns_context_set_tcp_send_timeout() + Thanks maciejsszmigiero. + * Issue #497: Fix typo in CMAKE included files, so Stubby can use + TLS v1.3 with chipersuites options ON. Thanks har-riz. + * Basic name compression on server replied messages. Thanks amialkow! + This alleviates (but might not completely resolve) issues #495 and + #320 . + * Eventloop extensions back to the old names libgetdns_ext_event, + libgetdns_ext_ev and libgetdns_ext_uv. + * Compilation warning fixes. Thanks Andreas! + * 2020-02-28: Version 1.6.0 * Issues #457, #458, #461: New symbols with libnettle >= 3.4. Thanks hanvinke & kometchtech for testing & reporting. diff --git a/cmake/include/cmakeconfig.h.in b/cmake/include/cmakeconfig.h.in index 834a23cf..6c44d3bf 100644 --- a/cmake/include/cmakeconfig.h.in +++ b/cmake/include/cmakeconfig.h.in @@ -58,6 +58,9 @@ #cmakedefine HAVE_OPENSSL_RAND_H 1 #cmakedefine HAVE_OPENSSL_CONF_H 1 #cmakedefine HAVE_OPENSSL_ENGINE_H 1 +#cmakedefine HAVE_OPENSSL_BN_H 1 +#cmakedefine HAVE_OPENSSL_DSA_H 1 +#cmakedefine HAVE_OPENSSL_RSA_H 1 #cmakedefine HAVE_DSA_SIG_SET0 1 #cmakedefine HAVE_DSA_SET0_PQG 1 @@ -88,8 +91,8 @@ #cmakedefine HAVE_OPENSSL_VERSION 1 #cmakedefine HAVE_SSL_CTX_DANE_ENABLE 1 -#cmakedefine HAVE_SSL_CTX_SET_CIPHERSUITS 1 -#cmakedefine HAVE_SSL_SET_CIPHERSUITS 1 +#cmakedefine HAVE_SSL_CTX_SET_CIPHERSUITES 1 +#cmakedefine HAVE_SSL_SET_CIPHERSUITES 1 #cmakedefine HAVE_OPENSSL_INIT_CRYPTO 1 @@ -211,6 +214,8 @@ #cmakedefine USE_OSX_TCP_FASTOPEN 1 +#cmakedefine HAVE_DECL_TCP_USER_TIMEOUT 1 + #cmakedefine HAVE_NEW_UV_TIMER_CB 1 #cmakedefine HAVE_TARGET_ENDIANNESS @@ -447,7 +452,7 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo # define ATTR_UNUSED(x) x #elif defined(__cplusplus) # define ATTR_UNUSED(x) -#elif defined(HAVE_ATTR_UNUSED) +#elif defined(__GNUC__) # define ATTR_UNUSED(x) x __attribute__((unused)) #else /* !HAVE_ATTR_UNUSED */ # define ATTR_UNUSED(x) x diff --git a/cmake/modules/TargetSharedLibraryExports.cmake b/cmake/modules/TargetSharedLibraryExports.cmake index ab3f960e..b9f3ac27 100644 --- a/cmake/modules/TargetSharedLibraryExports.cmake +++ b/cmake/modules/TargetSharedLibraryExports.cmake @@ -20,7 +20,7 @@ function(target_shared_library_exports lib libname symbols) file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/${libname}.ver" " ${symbol};\n") endforeach () file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/${libname}.ver" "local:\n *;\n};\n") - target_link_libraries(${lib} PRIVATE "-Wl,--version-script=getdns.ver") + target_link_libraries(${lib} PRIVATE "-Wl,--version-script=${libname}.ver") else () message(WARNING "Unknown platform, ${lib} exports not set.") endif () diff --git a/doc/getdns_general.3.in b/doc/getdns_general.3.in index 27b25574..be109560 100644 --- a/doc/getdns_general.3.in +++ b/doc/getdns_general.3.in @@ -76,7 +76,7 @@ getdns_dict **response) The getdns_general(3) and getdns_general_sync functions provide public entry points into the getdns API library to retrieve any valid responses to a query from the DNS (note that other namespaces in the context are not used). Most -typical use cases for applications are probably satisifed via calls to +typical use cases for applications are probably satisfied via calls to getdns_address(3) which would replace getaddrinfo(3). .HP 3 diff --git a/getdns.pc.in b/getdns.pc.in index 604f800f..a2a3ca92 100644 --- a/getdns.pc.in +++ b/getdns.pc.in @@ -1,9 +1,9 @@ prefix=@prefix@ exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include +libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ -Name: getdns +Name: getdns Version: @GETDNS_VERSION@ Description: A modern asynchronous DNS library diff --git a/getdns_ext_event.pc.in b/getdns_ext_event.pc.in index fec7946a..8c547aa1 100644 --- a/getdns_ext_event.pc.in +++ b/getdns_ext_event.pc.in @@ -1,9 +1,9 @@ prefix=@prefix@ exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include +libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ -Name: getdns_ext_event +Name: getdns_ext_event Version: @GETDNS_VERSION@ Description: A modern asynchronous DNS library diff --git a/src/compat/mkstemp.c b/src/compat/mkstemp.c index 4d5acc8f..49d3e919 100644 --- a/src/compat/mkstemp.c +++ b/src/compat/mkstemp.c @@ -39,5 +39,5 @@ int mkstemp(char *template) { if (_mktemp_s(template, strlen(template) + 1) != 0) return -1; - return open(template, _O_CREAT | _O_EXCL, _S_IWRITE); + return open(template, _O_CREAT | _O_EXCL | _O_RDWR, _S_IWRITE | _S_IREAD); } diff --git a/src/const-info.c b/src/const-info.c index 6265c523..3c1bc073 100644 --- a/src/const-info.c +++ b/src/const-info.c @@ -248,6 +248,7 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_OPCODE_STATUS", 2 }, { "GETDNS_OPCODE_UPDATE", 5 }, { "GETDNS_RCODE_BADALG", 21 }, + { "GETDNS_RCODE_BADCOOKIE", 23 }, { "GETDNS_RCODE_BADKEY", 17 }, { "GETDNS_RCODE_BADMODE", 19 }, { "GETDNS_RCODE_BADNAME", 20 }, @@ -255,7 +256,6 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RCODE_BADTIME", 18 }, { "GETDNS_RCODE_BADTRUNC", 22 }, { "GETDNS_RCODE_BADVERS", 16 }, - { "GETDNS_RCODE_COOKIE", 23 }, { "GETDNS_RCODE_FORMERR", 1 }, { "GETDNS_RCODE_NOERROR", 0 }, { "GETDNS_RCODE_NOTAUTH", 9 }, @@ -328,6 +328,7 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RRTYPE_GPOS", 27 }, { "GETDNS_RRTYPE_HINFO", 13 }, { "GETDNS_RRTYPE_HIP", 55 }, + { "GETDNS_RRTYPE_HTTPS", 65 }, { "GETDNS_RRTYPE_IPSECKEY", 45 }, { "GETDNS_RRTYPE_ISDN", 20 }, { "GETDNS_RRTYPE_IXFR", 251 }, @@ -373,6 +374,7 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RRTYPE_SPF", 99 }, { "GETDNS_RRTYPE_SRV", 33 }, { "GETDNS_RRTYPE_SSHFP", 44 }, + { "GETDNS_RRTYPE_SVCB", 64 }, { "GETDNS_RRTYPE_TA", 32768 }, { "GETDNS_RRTYPE_TALINK", 58 }, { "GETDNS_RRTYPE_TKEY", 249 }, diff --git a/src/context.c b/src/context.c index 6264ae99..7937a1f2 100644 --- a/src/context.c +++ b/src/context.c @@ -926,6 +926,7 @@ upstream_init(getdns_upstream *upstream, /* For sharing a socket to this upstream with TCP */ upstream->fd = -1; upstream->expires = 0; + upstream->tls_fallback_ok = 0; upstream->tls_obj = NULL; upstream->tls_session = NULL; upstream->tls_cipher_list = NULL; @@ -952,9 +953,12 @@ upstream_init(getdns_upstream *upstream, (void) getdns_eventloop_event_init( &upstream->finished_event, upstream, NULL, NULL, NULL); - upstream->has_client_cookie = 0; - upstream->has_prev_client_cookie = 0; - upstream->has_server_cookie = 0; + upstream->server_cookie_len = 0; + (void) memset(&upstream->server_cookie, 0, + sizeof(upstream->server_cookie)); + upstream->src_addr_checked = 0; + (void) memset(&upstream->src_addr, 0, sizeof(upstream->src_addr)); + upstream->src_addr_len = 0; upstream->tsig_alg = GETDNS_NO_TSIG; upstream->tsig_dname_len = 0; @@ -1289,7 +1293,7 @@ transaction_id_cmp(const void *id1, const void *id2) static void NULL_update_callback( getdns_context *context, getdns_context_code_t code, void *userarg) -{ (void)context; (void)code; (void)userarg; } +{ (void)context; (void)code; (void)userarg; /* unused parameters */ } static int netreq_expiry_cmp(const void *id1, const void *id2) @@ -1431,6 +1435,7 @@ getdns_context_create_with_extended_memory_functions( result->timeout = 5000; result->idle_timeout = 0; + result->tcp_send_timeout = -1; result->follow_redirects = GETDNS_REDIRECTS_FOLLOW; result->dns_root_servers = NULL; #if defined(HAVE_LIBUNBOUND) && !defined(HAVE_UB_CTX_SET_STUB) @@ -2363,6 +2368,34 @@ getdns_context_set_idle_timeout(getdns_context *context, uint64_t timeout) return GETDNS_RETURN_GOOD; } /* getdns_context_set_timeout */ +/* + * getdns_context_unset_tcp_send_timeout + * + */ +getdns_return_t +getdns_context_unset_tcp_send_timeout(getdns_context *context) +{ + if (!context) + return GETDNS_RETURN_INVALID_PARAMETER; + + context->tcp_send_timeout = -1; + return GETDNS_RETURN_GOOD; +} + +/* + * getdns_context_set_tcp_send_timeout + * + */ +getdns_return_t +getdns_context_set_tcp_send_timeout(struct getdns_context *context, + uint32_t value) +{ + if (!context || value > INT_MAX) + return GETDNS_RETURN_INVALID_PARAMETER; + + context->tcp_send_timeout = value; + return GETDNS_RETURN_GOOD; +} /* * getdns_context_set_follow_redirects @@ -3728,7 +3761,7 @@ uint32_t getdns_context_get_num_pending_requests(const getdns_context* context, struct timeval* next_timeout) { - (void)next_timeout; + (void)next_timeout; /* unused parameter */ if (!context) return GETDNS_RETURN_INVALID_PARAMETER; @@ -3833,6 +3866,9 @@ _get_context_settings(const getdns_context* context) (context->timeout > 0xFFFFFFFFull) ? 0xFFFFFFFF: (uint32_t) context->timeout) || getdns_dict_set_int(result, "idle_timeout", (context->idle_timeout > 0xFFFFFFFFull) ? 0xFFFFFFFF : (uint32_t) context->idle_timeout) + || ( context->tcp_send_timeout != -1 + && getdns_dict_set_int(result, "tcp_send_timeout", + context->tcp_send_timeout)) || getdns_dict_set_int(result, "limit_outstanding_queries", context->limit_outstanding_queries) || getdns_dict_set_int(result, "dnssec_allowed_skew", @@ -3895,6 +3931,14 @@ _get_context_settings(const getdns_context* context) getdns_list_destroy(list); goto error; } + if (getdns_context_get_dns_root_servers(context, &list)) + ; /* pass */ + + else if (list && _getdns_dict_set_this_list( + result, "dns_root_servers", list)) { + getdns_list_destroy(list); + goto error; + } if (context->dns_transport_count > 0) { /* create a namespace list */ if (!(list = getdns_list_create_with_context(context))) @@ -4102,7 +4146,7 @@ getdns_context_set_use_threads(getdns_context* context, int use_threads) { else r = ub_ctx_async(context->unbound_ctx, 0); #else - (void)use_threads; + (void)use_threads; /* unused parameter */ #endif return r == 0 ? GETDNS_RETURN_GOOD : GETDNS_RETURN_CONTEXT_UPDATE_FAIL; } @@ -4296,6 +4340,16 @@ CONTEXT_GETTER(timeout , uint64_t) CONTEXT_GETTER(idle_timeout , uint64_t) CONTEXT_GETTER(follow_redirects , getdns_redirects_t) +getdns_return_t +getdns_context_get_tcp_send_timeout( + const getdns_context *context, uint32_t* value) +{ + if (!context || !value) return GETDNS_RETURN_INVALID_PARAMETER; + *value = context->tcp_send_timeout == -1 ? 0 + : context->tcp_send_timeout; + return GETDNS_RETURN_GOOD; +} + getdns_return_t getdns_context_get_dns_root_servers( const getdns_context *context, getdns_list **value) @@ -4635,6 +4689,7 @@ _getdns_context_config_setting(getdns_context *context, CONTEXT_SETTING_INT(dns_transport) CONTEXT_SETTING_ARRAY(dns_transport_list, transport_list) CONTEXT_SETTING_INT(idle_timeout) + CONTEXT_SETTING_INT(tcp_send_timeout) CONTEXT_SETTING_INT(limit_outstanding_queries) CONTEXT_SETTING_INT(timeout) CONTEXT_SETTING_INT(follow_redirects) @@ -4877,7 +4932,7 @@ FILE *_getdns_context_get_priv_fp( _getdns_log(&context->log , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO , "Error opening \"%s\": %s\n" - , path, _getdns_errnostr()); + , path, _getdns_fileerrnostr()); return f; } @@ -4956,31 +5011,31 @@ int _getdns_context_write_priv_file(getdns_context *context, _getdns_log(&context->log , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO , "Could not create temporary file \"%s\": %s\n" - , tmpfn, _getdns_errnostr()); + , tmpfn, _getdns_fileerrnostr()); else if (!(f = fdopen(fd, "w"))) _getdns_log(&context->log , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR , "Error opening temporary file \"%s\": %s\n" - , tmpfn, _getdns_errnostr()); + , tmpfn, _getdns_fileerrnostr()); else if (fwrite(content->data, 1, content->size, f) < content->size) _getdns_log(&context->log , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR , "Error writing to temporary file \"%s\": %s\n" - , tmpfn, _getdns_errnostr()); + , tmpfn, _getdns_fileerrnostr()); - else if (fclose(f) < 0) + else if (fclose(f)) _getdns_log(&context->log , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR - , "Error closing temporary file \"%s\": %s\n" - , tmpfn, _getdns_errnostr()); + , "Error closing temporary file \"%s\": %s (%p)\n" + , tmpfn, _getdns_fileerrnostr(), f); else if (rename(tmpfn, path) < 0) _getdns_log(&context->log , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR , "Error renaming temporary file \"%s\" to \"%s\"" - ": %s\n", tmpfn, path, _getdns_errnostr()); + ": %s\n", tmpfn, path, _getdns_fileerrnostr()); else { context->can_write_appdata = PROP_ABLE; return 1; @@ -5033,7 +5088,7 @@ int _getdns_context_can_write_appdata(getdns_context *context) _getdns_log(&context->log , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR , "Error unlinking write test file: \"%s\": %s\n" - , path, _getdns_errnostr()); + , path, _getdns_fileerrnostr()); return 1; } @@ -5346,7 +5401,7 @@ getdns_context_set_tls_curves_list( dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST); return GETDNS_RETURN_GOOD; #else - (void)tls_curves_list; + (void)tls_curves_list; /* unused parameter */ return GETDNS_RETURN_NOT_IMPLEMENTED; #endif } diff --git a/src/context.h b/src/context.h index f97884d3..6e7a8960 100644 --- a/src/context.h +++ b/src/context.h @@ -243,15 +243,13 @@ typedef struct getdns_upstream { unsigned is_sync_loop : 1; /* EDNS cookies */ - uint32_t secret; - uint8_t client_cookie[8]; - uint8_t prev_client_cookie[8]; - uint8_t server_cookie[32]; - - unsigned has_client_cookie : 1; - unsigned has_prev_client_cookie : 1; - unsigned has_server_cookie : 1; - unsigned server_cookie_len : 5; + uint8_t server_cookie[40]; + size_t server_cookie_len; + + uint64_t src_addr_checked; + struct sockaddr_storage src_addr; + socklen_t src_addr_len; + char src_addr_str[INET6_ADDRSTRLEN]; /* TSIG */ uint8_t tsig_dname[256]; @@ -327,6 +325,7 @@ struct getdns_context { size_t namespace_count; uint64_t timeout; uint64_t idle_timeout; + int tcp_send_timeout; /* -1 is unset */ getdns_redirects_t follow_redirects; getdns_list *dns_root_servers; diff --git a/src/convert.c b/src/convert.c index 55426da0..c97b7798 100644 --- a/src/convert.c +++ b/src/convert.c @@ -122,7 +122,7 @@ getdns_convert_ulabel_to_alabel(const char *ulabel) if (idn2_lookup_u8((uint8_t *)ulabel, &alabel, IDN2_TRANSITIONAL) == IDN2_OK) return (char *)alabel; #else - (void)ulabel; + (void)ulabel; /* unused parameter */ #endif return NULL; } @@ -149,7 +149,7 @@ getdns_convert_alabel_to_ulabel(const char *alabel) if (idn2_to_unicode_8z8z(alabel, &ulabel, 0) == IDN2_OK) return ulabel; #else - (void)alabel; + (void)alabel; /* unused parameter */ #endif return NULL; } @@ -744,6 +744,75 @@ getdns_wire2msg_dict_scan( else GLDNS_ ## Y ## _CLR(header); \ } +static getdns_return_t +_getdns_reply_dict2wire_hdr( + const getdns_dict *reply, gldns_buffer *gbuf, getdns_bindata *wf_reply) +{ + size_t pkt_start = gldns_buffer_position(gbuf); + size_t pkt_len = wf_reply->size; + uint8_t *header = gldns_buffer_current(gbuf); + uint8_t *pkt_end = header + pkt_len; + getdns_list *sec; + size_t sec_len; + uint32_t n, i; + _getdns_rr_iter rr_iter_storage, *rr_iter; + getdns_list *section; + size_t rrs2skip; + getdns_dict *rr_dict; + + gldns_buffer_write(gbuf, wf_reply->data, wf_reply->size); + + if (GLDNS_QDCOUNT(header) != 1 + || (GLDNS_ARCOUNT(header) != 0 && GLDNS_ARCOUNT(header) != 1)) + return GETDNS_RETURN_GENERIC_ERROR; + + sec_len = 0; + if (!getdns_dict_get_list(reply, "answer", &sec)) + (void) getdns_list_get_length(sec, &sec_len); + if (sec_len != GLDNS_ANCOUNT(header)) + return GETDNS_RETURN_GENERIC_ERROR; + + sec_len = 0; + if (!getdns_dict_get_list(reply, "authority", &sec)) + (void) getdns_list_get_length(sec, &sec_len); + if (sec_len != GLDNS_NSCOUNT(header)) + return GETDNS_RETURN_GENERIC_ERROR; + + rrs2skip = 1 + GLDNS_ANCOUNT(header) + GLDNS_NSCOUNT(header); + + SET_HEADER_INT(id, ID); + SET_HEADER_BIT(qr, QR); + SET_HEADER_BIT(aa, AA); + SET_HEADER_BIT(tc, TC); + SET_HEADER_BIT(rd, RD); + SET_HEADER_BIT(cd, CD); + SET_HEADER_BIT(ra, RA); + SET_HEADER_BIT(ad, AD); + SET_HEADER_INT(opcode, OPCODE); + SET_HEADER_INT(rcode, RCODE); + SET_HEADER_BIT(z, Z); + + for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage, header, pkt_len) + ; rr_iter + ; rr_iter = _getdns_rr_iter_next(rr_iter)) { + if (rr_iter->nxt > pkt_end) + return GETDNS_RETURN_GENERIC_ERROR; + if (!--rrs2skip) + break; + /* TODO: Delete sigs when do bit was off */ + } + gldns_buffer_set_position(gbuf, rr_iter->nxt - header); + if (!getdns_dict_get_list(reply, "additional", §ion)) { + for ( n = 0, i = 0 + ; !getdns_list_get_dict(section, i, &rr_dict); i++) { + if (!_getdns_rr_dict2wire(rr_dict, gbuf)) + n++; + } + gldns_buffer_write_u16_at(gbuf, pkt_start+GLDNS_ARCOUNT_OFF, n); + } + return GETDNS_RETURN_GOOD; +} + getdns_return_t _getdns_reply_dict2wire( const getdns_dict *reply, gldns_buffer *buf, int reuse_header) @@ -754,6 +823,7 @@ _getdns_reply_dict2wire( getdns_list *section; getdns_dict *rr_dict; getdns_bindata *qname; + name_cache_t name_cache = {0}; int remove_dnssec; pkt_start = gldns_buffer_position(buf); @@ -783,7 +853,7 @@ _getdns_reply_dict2wire( if (!getdns_dict_get_bindata(reply, "/question/qname", &qname) && !getdns_dict_get_int(reply, "/question/qtype", &qtype)) { (void)getdns_dict_get_int(reply, "/question/qclass", &qclass); - gldns_buffer_write(buf, qname->data, qname->size); + _getdns_rr_buffer_write_cached_name(buf, qname, &name_cache); gldns_buffer_write_u16(buf, (uint16_t)qtype); gldns_buffer_write_u16(buf, (uint16_t)qclass); gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_QDCOUNT_OFF, 1); @@ -806,7 +876,7 @@ _getdns_reply_dict2wire( !getdns_dict_get_int(rr_dict, "type", &rr_type) && rr_type == GETDNS_RRTYPE_RRSIG) continue; - if (!_getdns_rr_dict2wire(rr_dict, buf)) + if (!_getdns_rr_dict2wire_cache(rr_dict, buf, &name_cache)) n++; } gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ANCOUNT_OFF, n); @@ -848,8 +918,10 @@ getdns_return_t _getdns_msg_dict2wire_buf(const getdns_dict *msg_dict, gldns_buffer *gbuf) { getdns_return_t r; - getdns_list *replies; - getdns_dict *reply; + getdns_list *replies; + getdns_dict *reply; + getdns_list *wf_replies = NULL; + getdns_bindata *wf_reply; size_t i; if ((r = getdns_dict_get_list(msg_dict, "replies_tree", &replies))) { @@ -857,8 +929,23 @@ _getdns_msg_dict2wire_buf(const getdns_dict *msg_dict, gldns_buffer *gbuf) return r; return _getdns_reply_dict2wire(msg_dict, gbuf, 0); } + (void) getdns_dict_get_list(msg_dict, "replies_full", &wf_replies); for (i = 0; r == GETDNS_RETURN_GOOD; i++) { - if (!(r = getdns_list_get_dict(replies, i, &reply))) + if ((r = getdns_list_get_dict(replies, i, &reply))) + ; + else if (wf_replies + && !getdns_list_get_bindata(wf_replies, i, &wf_reply)) { + size_t pkt_start = gldns_buffer_position(gbuf); + + if (!gldns_buffer_reserve(gbuf, wf_reply->size)) + return GETDNS_RETURN_NEED_MORE_SPACE; + + if ((r = _getdns_reply_dict2wire_hdr( reply, gbuf + , wf_reply))) { + gldns_buffer_set_position(gbuf, pkt_start); + r = _getdns_reply_dict2wire(reply, gbuf, 0); + } + } else r = _getdns_reply_dict2wire(reply, gbuf, 0); } return r == GETDNS_RETURN_NO_SUCH_LIST_ITEM ? GETDNS_RETURN_GOOD : r; @@ -1814,8 +1901,8 @@ getdns_yaml2list(const char *str, getdns_list **list) return GETDNS_RETURN_GENERIC_ERROR; } #else /* USE_YAML_CONFIG */ - (void) str; - (void) list; + (void) str; /* unused parameter */ + (void) list; /* unused parameter */ return GETDNS_RETURN_NOT_IMPLEMENTED; #endif /* USE_YAML_CONFIG */ } @@ -1838,8 +1925,8 @@ getdns_yaml2bindata(const char *str, getdns_bindata **bindata) return GETDNS_RETURN_GENERIC_ERROR; } #else /* USE_YAML_CONFIG */ - (void) str; - (void) bindata; + (void) str; /* unused parameter */ + (void) bindata; /* unused parameter */ return GETDNS_RETURN_NOT_IMPLEMENTED; #endif /* USE_YAML_CONFIG */ } @@ -1862,8 +1949,8 @@ getdns_yaml2int(const char *str, uint32_t *value) return GETDNS_RETURN_GENERIC_ERROR; } #else /* USE_YAML_CONFIG */ - (void) str; - (void) value; + (void) str; /* unused parameter */ + (void) value; /* unused parameter */ return GETDNS_RETURN_NOT_IMPLEMENTED; #endif /* USE_YAML_CONFIG */ } diff --git a/src/dict.c b/src/dict.c index 66eabd46..9caee781 100644 --- a/src/dict.c +++ b/src/dict.c @@ -892,6 +892,7 @@ getdns_pp_list(gldns_buffer *buf, size_t indent, const getdns_list *list, struct getdns_bindata *bindata_item; uint32_t int_item; const char *strval; + char abuf[80]; if (list == NULL) return 0; @@ -933,7 +934,21 @@ getdns_pp_list(gldns_buffer *buf, size_t indent, const getdns_list *list, if (getdns_list_get_bindata(list, i, &bindata_item) != GETDNS_RETURN_GOOD) return -1; - if (getdns_pp_bindata( + + if (for_literals && (bindata_item->size == 4 || + bindata_item->size == 16 )) { + + if (gldns_buffer_printf(buf, + (json ? "\"%s\"" : " "), + inet_ntop(( bindata_item->size == 4 + ? AF_INET : AF_INET6) + , bindata_item->data + , abuf + , sizeof(abuf) - 1 + )) < 0) + return -1; + + } else if (getdns_pp_bindata( buf, bindata_item, 0, json) < 0) return -1; break; @@ -1021,21 +1036,21 @@ static int _getdns_print_rcode(gldns_buffer *buf, uint32_t rcode) { static const char *rcodes[] = { - " GETDNS_RCODE_NOERROR" , " GETDNS_RCODE_FORMERR" , - " GETDNS_RCODE_SERVFAIL", " GETDNS_RCODE_NXDOMAIN", - " GETDNS_RCODE_NOTIMP" , " GETDNS_RCODE_REFUSED" , - " GETDNS_RCODE_YXDOMAIN", " GETDNS_RCODE_YXRRSET" , - " GETDNS_RCODE_NXRRSET" , " GETDNS_RCODE_NOTAUTH" , + " GETDNS_RCODE_NOERROR" , " GETDNS_RCODE_FORMERR" , + " GETDNS_RCODE_SERVFAIL", " GETDNS_RCODE_NXDOMAIN" , + " GETDNS_RCODE_NOTIMP" , " GETDNS_RCODE_REFUSED" , + " GETDNS_RCODE_YXDOMAIN", " GETDNS_RCODE_YXRRSET" , + " GETDNS_RCODE_NXRRSET" , " GETDNS_RCODE_NOTAUTH" , " GETDNS_RCODE_NOTZONE" , - " GETDNS_RCODE_BADSIG" , " GETDNS_RCODE_BADKEY" , - " GETDNS_RCODE_BADTIME" , " GETDNS_RCODE_BADMODE" , - " GETDNS_RCODE_BADNAME" , " GETDNS_RCODE_BADALG" , - " GETDNS_RCODE_BADTRUNC" + " GETDNS_RCODE_BADSIG" , " GETDNS_RCODE_BADKEY" , + " GETDNS_RCODE_BADTIME" , " GETDNS_RCODE_BADMODE" , + " GETDNS_RCODE_BADNAME" , " GETDNS_RCODE_BADALG" , + " GETDNS_RCODE_BADTRUNC", " GETDNS_RCODE_BADCOOKIE" }; if (rcode <= 10) (void) gldns_buffer_printf(buf, "%s", rcodes[rcode]); - else if (rcode >= 16 && rcode <= 22) - (void) gldns_buffer_printf(buf, "%s", rcodes[rcode-6]); + else if (rcode >= 16 && rcode <= 23) + (void) gldns_buffer_printf(buf, "%s", rcodes[rcode-5]); else return 0; return 1; @@ -1141,6 +1156,11 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, if (!json && strcmp(item->node.key, "rcode") == 0 && _getdns_print_rcode(buf, item->i.data.n)) break; + if (!json && + strcmp(item->node.key, "extended_rcode") == 0 && + item->i.data.n >= 16 && + _getdns_print_rcode(buf, item->i.data.n)) + break; if (gldns_buffer_printf( buf,(json < 2 ? " %d" : "%d"), item->i.data.n) < 0) return -1; @@ -1164,7 +1184,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, , 40 )) < 0) return -1; - + } else if (!json && (strcmp(item->node.key, "pin-sha256") == 0 || strcmp(item->node.key, "value") == 0) && @@ -1199,8 +1219,9 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, if (getdns_pp_list(buf, indent, item->i.data.list, (strcmp(item->node.key, "namespaces") == 0 || strcmp(item->node.key, "dns_transport_list") == 0 - || strcmp(item->node.key, "bad_dns") == 0), - json) < 0) + || strcmp(item->node.key, "bad_dns") == 0 || + strcmp(item->node.key, "dns_root_servers") == 0 + ), json) < 0) return -1; break; diff --git a/src/dnssec.c b/src/dnssec.c index 25bdb2d0..6490bc5e 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -922,7 +922,7 @@ static getdns_dict *CD_extension(getdns_dns_req *dnsreq) ? dnssec_ok_checking_disabled_roadblock_avoidance : dnssec_ok_checking_disabled_avoid_roadblocks; #else - (void)dnsreq; + (void)dnsreq; /* unused parameter */ return dnssec_ok_checking_disabled; #endif } diff --git a/src/extension/libev.c b/src/extension/libev.c index ff36b5c2..f844f8bf 100644 --- a/src/extension/libev.c +++ b/src/extension/libev.c @@ -97,7 +97,7 @@ static void getdns_libev_read_cb(struct ev_loop *l, struct ev_io *io, int revents) { getdns_eventloop_event *el_ev = (getdns_eventloop_event *)io->data; - (void)l; (void)revents; + (void)l; (void)revents; /* unused parameters */ assert(el_ev->read_cb); el_ev->read_cb(el_ev->userarg); } @@ -106,7 +106,7 @@ static void getdns_libev_write_cb(struct ev_loop *l, struct ev_io *io, int revents) { getdns_eventloop_event *el_ev = (getdns_eventloop_event *)io->data; - (void)l; (void)revents; + (void)l; (void)revents; /* unused parameters */ assert(el_ev->write_cb); el_ev->write_cb(el_ev->userarg); } @@ -115,7 +115,7 @@ static void getdns_libev_timeout_cb(struct ev_loop *l, struct ev_timer *timer, int revents) { getdns_eventloop_event *el_ev = (getdns_eventloop_event *)timer->data; - (void)l; (void)revents; + (void)l; (void)revents; /* unused parameters */ assert(el_ev->timeout_cb); el_ev->timeout_cb(el_ev->userarg); } diff --git a/src/extension/libevent.c b/src/extension/libevent.c index 5f5b6221..a8b25892 100644 --- a/src/extension/libevent.c +++ b/src/extension/libevent.c @@ -99,7 +99,7 @@ static getdns_return_t getdns_libevent_clear(getdns_eventloop *loop, getdns_eventloop_event *el_ev) { struct event *my_ev = (struct event *)el_ev->ev; - (void)loop; + (void)loop; /* unused parameter */ assert(my_ev); @@ -115,7 +115,7 @@ static void getdns_libevent_callback(evutil_socket_t fd, short bits, void *arg) { getdns_eventloop_event *el_ev = (getdns_eventloop_event *)arg; - (void)fd; + (void)fd; /* unused parameter */ if (bits & EV_READ) { assert(el_ev->read_cb); diff --git a/src/extension/libuv.c b/src/extension/libuv.c index f1b7114e..61b33c69 100644 --- a/src/extension/libuv.c +++ b/src/extension/libuv.c @@ -73,8 +73,7 @@ getdns_libuv_cleanup(getdns_eventloop *loop) } typedef struct poll_timer { - uv_poll_t read; - uv_poll_t write; + uv_poll_t poll; uv_timer_t timer; int to_close; struct mem_funcs mf; @@ -104,22 +103,15 @@ getdns_libuv_clear(getdns_eventloop *loop, getdns_eventloop_event *el_ev) poll_timer *my_ev = (poll_timer *)el_ev->ev; uv_poll_t *my_poll; uv_timer_t *my_timer; - (void)loop; + (void)loop; /* unused parameter */ assert(my_ev); DEBUG_UV("enter libuv_clear(el_ev = %p, my_ev = %p, to_close = %d)\n" , el_ev, my_ev, my_ev->to_close); - if (el_ev->read_cb) { - my_poll = &my_ev->read; - uv_poll_stop(my_poll); - my_ev->to_close += 1; - my_poll->data = my_ev; - uv_close((uv_handle_t *)my_poll, getdns_libuv_close_cb); - } - if (el_ev->write_cb) { - my_poll = &my_ev->write; + if (el_ev->read_cb || el_ev->write_cb) { + my_poll = &my_ev->poll; uv_poll_stop(my_poll); my_ev->to_close += 1; my_poll->data = my_ev; @@ -139,29 +131,29 @@ getdns_libuv_clear(getdns_eventloop *loop, getdns_eventloop_event *el_ev) } static void -getdns_libuv_read_cb(uv_poll_t *poll, int status, int events) +getdns_libuv_cb(uv_poll_t *poll, int status, int events) { - getdns_eventloop_event *el_ev = (getdns_eventloop_event *)poll->data; - (void)status; (void)events; - assert(el_ev->read_cb); - DEBUG_UV("enter libuv_read_cb(el_ev = %p, el_ev->ev = %p)\n" - , el_ev, el_ev->ev); - el_ev->read_cb(el_ev->userarg); - DEBUG_UV("exit libuv_read_cb(el_ev = %p, el_ev->ev = %p)\n" - , el_ev, el_ev->ev); -} + getdns_eventloop_event *el_ev = (getdns_eventloop_event *)poll->data; -static void -getdns_libuv_write_cb(uv_poll_t *poll, int status, int events) -{ - getdns_eventloop_event *el_ev = (getdns_eventloop_event *)poll->data; - (void)status; (void)events; - assert(el_ev->write_cb); - DEBUG_UV("enter libuv_write_cb(el_ev = %p, el_ev->ev = %p)\n" - , el_ev, el_ev->ev); - el_ev->write_cb(el_ev->userarg); - DEBUG_UV("exit libuv_write_cb(el_ev = %p, el_ev->ev = %p)\n" - , el_ev, el_ev->ev); + if (status == 0) { + if (events & UV_READABLE) { + assert(el_ev->read_cb); + DEBUG_UV("enter libuv_read_cb(el_ev = %p, el_ev->ev = %p)\n" + , el_ev, el_ev->ev); + el_ev->read_cb(el_ev->userarg); + DEBUG_UV("exit libuv_read_cb(el_ev = %p, el_ev->ev = %p)\n" + , el_ev, el_ev->ev); + } else if (events & UV_WRITABLE) { + assert(el_ev->write_cb); + DEBUG_UV("enter libuv_write_cb(el_ev = %p, el_ev->ev = %p)\n" + , el_ev, el_ev->ev); + el_ev->write_cb(el_ev->userarg); + DEBUG_UV("exit libuv_write_cb(el_ev = %p, el_ev->ev = %p)\n" + , el_ev, el_ev->ev); + } else { + assert(ASSERT_UNREACHABLE); + } + } } static void @@ -173,7 +165,7 @@ getdns_libuv_timeout_cb(uv_timer_t *timer, int status) { getdns_eventloop_event *el_ev = (getdns_eventloop_event *)timer->data; #ifndef HAVE_NEW_UV_TIMER_CB - (void)status; + (void)status; /* unused parameter */ #endif assert(el_ev->timeout_cb); DEBUG_UV("enter libuv_timeout_cb(el_ev = %p, el_ev->ev = %p)\n" @@ -205,18 +197,15 @@ getdns_libuv_schedule(getdns_eventloop *loop, my_ev->to_close = 0; my_ev->mf = ext->mf; el_ev->ev = my_ev; - - if (el_ev->read_cb) { - my_poll = &my_ev->read; + + if (el_ev->read_cb || el_ev->write_cb) { + my_poll = &my_ev->poll; my_poll->data = el_ev; uv_poll_init(ext->loop, my_poll, fd); - uv_poll_start(my_poll, UV_READABLE, getdns_libuv_read_cb); - } - if (el_ev->write_cb) { - my_poll = &my_ev->write; - my_poll->data = el_ev; - uv_poll_init(ext->loop, my_poll, fd); - uv_poll_start(my_poll, UV_WRITABLE, getdns_libuv_write_cb); + int events = + (el_ev->read_cb ? UV_READABLE : 0) | + (el_ev->write_cb ? UV_WRITABLE : 0); + uv_poll_start(my_poll, events, getdns_libuv_cb); } if (el_ev->timeout_cb) { my_timer = &my_ev->timer; diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 743c6a81..aefa282a 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -288,7 +288,7 @@ static void poll_read_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG - (void)fd; + (void)fd; /* unused parameter */ #endif DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); if (event && event->read_cb) @@ -299,7 +299,7 @@ static void poll_write_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG - (void)fd; + (void)fd; /* unused parameter */ #endif DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); if (event && event->write_cb) diff --git a/src/extension/select_eventloop.c b/src/extension/select_eventloop.c index 7855c21d..ce9e0517 100644 --- a/src/extension/select_eventloop.c +++ b/src/extension/select_eventloop.c @@ -154,14 +154,14 @@ select_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) static void select_eventloop_cleanup(getdns_eventloop *loop) { - (void)loop; + (void)loop; /* unused parameter */ } static void select_read_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG - (void)fd; + (void)fd; /* unused parameter */ #endif DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); event->read_cb(event->userarg); @@ -171,7 +171,7 @@ static void select_write_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG - (void)fd; + (void)fd; /* unused parameter */ #endif DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); event->write_cb(event->userarg); @@ -181,7 +181,7 @@ static void select_timeout_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG - (void)fd; + (void)fd; /* unused parameter */ #endif DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); event->timeout_cb(event->userarg); @@ -244,7 +244,7 @@ select_eventloop_run_once(getdns_eventloop *loop, int blocking) } else { #endif if (select(max_fd + 1, &readfds, &writefds, NULL, - (timeout == TIMEOUT_FOREVER ? NULL : &tv)) < 0) { + ((blocking && timeout == TIMEOUT_FOREVER) ? NULL : &tv)) < 0) { if (_getdns_socketerror_wants_retry()) return; @@ -309,7 +309,7 @@ _getdns_select_eventloop_init(struct mem_funcs *mf, _getdns_select_eventloop *lo select_eventloop_run, select_eventloop_run_once }; - (void) mf; + (void) mf; /* unused parameter */ (void) memset(loop, 0, sizeof(_getdns_select_eventloop)); loop->loop.vmt = &select_eventloop_vmt; } diff --git a/src/general.c b/src/general.c index 682ebc62..66964585 100644 --- a/src/general.c +++ b/src/general.c @@ -256,7 +256,7 @@ static void ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len, int sec, char* why_bogus, int was_ratelimited) { - (void) was_ratelimited; + (void) was_ratelimited; /* unused parameter */ #else static void ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len, diff --git a/src/getdns/getdns.h.in b/src/getdns/getdns.h.in index b2702d43..9356469c 100644 --- a/src/getdns/getdns.h.in +++ b/src/getdns/getdns.h.in @@ -417,6 +417,8 @@ typedef enum getdns_callback_type_t { #define GETDNS_RRTYPE_OPENPGPKEY 61 #define GETDNS_RRTYPE_CSYNC 62 #define GETDNS_RRTYPE_ZONEMD 63 +#define GETDNS_RRTYPE_SVCB 64 +#define GETDNS_RRTYPE_HTTPS 65 #define GETDNS_RRTYPE_SPF 99 #define GETDNS_RRTYPE_UINFO 100 #define GETDNS_RRTYPE_UID 101 @@ -473,26 +475,26 @@ typedef enum getdns_callback_type_t { * \defgroup rcodes Rcodes * @{ */ -#define GETDNS_RCODE_NOERROR 0 -#define GETDNS_RCODE_FORMERR 1 -#define GETDNS_RCODE_SERVFAIL 2 -#define GETDNS_RCODE_NXDOMAIN 3 -#define GETDNS_RCODE_NOTIMP 4 -#define GETDNS_RCODE_REFUSED 5 -#define GETDNS_RCODE_YXDOMAIN 6 -#define GETDNS_RCODE_YXRRSET 7 -#define GETDNS_RCODE_NXRRSET 8 -#define GETDNS_RCODE_NOTAUTH 9 -#define GETDNS_RCODE_NOTZONE 10 -#define GETDNS_RCODE_BADVERS 16 -#define GETDNS_RCODE_BADSIG 16 -#define GETDNS_RCODE_BADKEY 17 -#define GETDNS_RCODE_BADTIME 18 -#define GETDNS_RCODE_BADMODE 19 -#define GETDNS_RCODE_BADNAME 20 -#define GETDNS_RCODE_BADALG 21 -#define GETDNS_RCODE_BADTRUNC 22 -#define GETDNS_RCODE_COOKIE 23 +#define GETDNS_RCODE_NOERROR 0 +#define GETDNS_RCODE_FORMERR 1 +#define GETDNS_RCODE_SERVFAIL 2 +#define GETDNS_RCODE_NXDOMAIN 3 +#define GETDNS_RCODE_NOTIMP 4 +#define GETDNS_RCODE_REFUSED 5 +#define GETDNS_RCODE_YXDOMAIN 6 +#define GETDNS_RCODE_YXRRSET 7 +#define GETDNS_RCODE_NXRRSET 8 +#define GETDNS_RCODE_NOTAUTH 9 +#define GETDNS_RCODE_NOTZONE 10 +#define GETDNS_RCODE_BADVERS 16 +#define GETDNS_RCODE_BADSIG 16 +#define GETDNS_RCODE_BADKEY 17 +#define GETDNS_RCODE_BADTIME 18 +#define GETDNS_RCODE_BADMODE 19 +#define GETDNS_RCODE_BADNAME 20 +#define GETDNS_RCODE_BADALG 21 +#define GETDNS_RCODE_BADTRUNC 22 +#define GETDNS_RCODE_BADCOOKIE 23 /** @} */ @@ -1514,6 +1516,24 @@ getdns_context_set_dns_transport_list(getdns_context *context, getdns_return_t getdns_context_set_idle_timeout(getdns_context *context, uint64_t timeout); +/** + * Set the number of milliseconds send data may remain unacknowledged by + * the peer in a TCP connection, if supported by the operation system. + * When not set (the default), the system default is left alone. + * + * @see getdns_context_get_tcp_send_timeout + * @see getdns_context_unset_tcp_send_timeout + * @param context The context to configure + * @param value The number of milliseconds the send data may remain + * unacknowledged by the peer in a TCP connection. + * @return GETDNS_RETURN_GOOD when successful. + * @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL or the + * value was too high. + */ +getdns_return_t +getdns_context_set_tcp_send_timeout(getdns_context *context, + uint32_t value); + /** * Limit the number of outstanding DNS queries. When more than limit requests * are scheduled, they are kept on an internal queue, to be rescheduled when diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index d515ef08..c4fcf561 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -540,6 +540,18 @@ getdns_context_set_tls_query_padding_blocksize(getdns_context *context, uint16_t getdns_return_t getdns_context_unset_edns_maximum_udp_payload_size(getdns_context *context); +/** + * Configure context to use the system default setting for the time + * send data may remain unacknowledged by the peer in a TCP connection. + * @see getdns_context_set_tcp_send_timeout + * @see getdns_context_get_tcp_send_timeout + * @param context The context to configure + * @return GETDNS_RETURN_GOOD on success + * @return GETDNS_RETURN_INVALID_PARAMETER if context is null. + */ +getdns_return_t +getdns_context_unset_tcp_send_timeout(getdns_context *context); + typedef enum getdns_loglevel_type { GETDNS_LOG_EMERG = 0, @@ -992,6 +1004,22 @@ getdns_return_t getdns_context_get_idle_timeout( const getdns_context *context, uint64_t *timeout); +/** + * Get the number of milliseconds send data may remain unacknowledged by + * the peer in a TCP connection setting from context. + * @see getdns_context_set_tcp_send_timeout + * @see getdns_context_unset_tcp_send_timeout + * @param[in] context The context from which to get the setting + * @param[out] value The number of milliseconds the send data may remain + * unacknowledged by the peer in a TCP connection. + * When the value is unset, 0 is returned. + * @return GETDNS_RETURN_GOOD when successful + * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. + */ +getdns_return_t +getdns_context_get_tcp_send_timeout(const getdns_context *context, + uint32_t *value); + /** * Get the setting that says whether or not DNS queries follow redirects. * @see getdns_context_set_follow_redirects diff --git a/src/gldns/gbuffer.h b/src/gldns/gbuffer.h index a8588348..f7516457 100644 --- a/src/gldns/gbuffer.h +++ b/src/gldns/gbuffer.h @@ -232,7 +232,6 @@ INLINE void gldns_buffer_clear(gldns_buffer *buffer) * the position is set to 0. * * \param[in] buffer the buffer to flip - * \return void */ INLINE void gldns_buffer_flip(gldns_buffer *buffer) { @@ -782,7 +781,6 @@ int gldns_buffer_printf(gldns_buffer *buffer, const char *format, ...) /** * frees the buffer. * \param[in] *buffer the buffer to be freed - * \return void */ void gldns_buffer_free(gldns_buffer *buffer); @@ -790,7 +788,6 @@ void gldns_buffer_free(gldns_buffer *buffer); * Makes the buffer fixed and returns a pointer to the data. The * caller is responsible for free'ing the result. * \param[in] *buffer the buffer to be exported - * \return void */ void *gldns_buffer_export(gldns_buffer *buffer); diff --git a/src/gldns/parse.c b/src/gldns/parse.c index 59d83b86..53dd7288 100644 --- a/src/gldns/parse.c +++ b/src/gldns/parse.c @@ -14,9 +14,6 @@ #include #include -#ifdef HAVE_STRINGS_H -#include -#endif gldns_lookup_table gldns_directive_types[] = { { GLDNS_DIR_TTL, "$TTL" }, @@ -123,7 +120,7 @@ gldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l if (line_nr) { *line_nr = *line_nr + 1; } - if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) { + if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) { *t = '\0'; return -1; } @@ -144,7 +141,8 @@ gldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l if (c != '\0' && c != '\n') { i++; } - if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) { + /* is there space for the character and the zero after it */ + if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) { *t = '\0'; return -1; } @@ -329,8 +327,8 @@ gldns_bget_token_par(gldns_buffer *b, char *token, const char *delim, /* in parentheses */ /* do not write ' ' if we want to skip spaces */ if(!(skipw && (strchr(skipw, c)||strchr(skipw, ' ')))) { - /* check for space for the space character */ - if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) { + /* check for space for the space character and a zero delimiter after that. */ + if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) { *t = '\0'; return -1; } @@ -357,7 +355,7 @@ gldns_bget_token_par(gldns_buffer *b, char *token, const char *delim, } i++; - if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) { + if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) { *t = '\0'; return -1; } diff --git a/src/gldns/parse.h b/src/gldns/parse.h index e2ea7cb9..69dfe74b 100644 --- a/src/gldns/parse.h +++ b/src/gldns/parse.h @@ -153,7 +153,6 @@ int gldns_bgetc(struct gldns_buffer *buffer); * the position to the first character that is not in *s. * \param[in] *buffer buffer to use * \param[in] *s characters to skip - * \return void */ void gldns_bskipcs(struct gldns_buffer *buffer, const char *s); @@ -162,7 +161,6 @@ void gldns_bskipcs(struct gldns_buffer *buffer, const char *s); * the position to the first character that is not in *s. * \param[in] *fp file to use * \param[in] *s characters to skip - * \return void */ void gldns_fskipcs(FILE *fp, const char *s); @@ -173,7 +171,6 @@ void gldns_fskipcs(FILE *fp, const char *s); * \param[in] *fp file to use * \param[in] *s characters to skip * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) - * \return void */ void gldns_fskipcs_l(FILE *fp, const char *s, int *line_nr); diff --git a/src/gldns/parseutil.c b/src/gldns/parseutil.c index 043fcfcd..e7fee906 100644 --- a/src/gldns/parseutil.c +++ b/src/gldns/parseutil.c @@ -171,7 +171,7 @@ gldns_gmtime64_r(int64_t clock, struct tm *result) static int64_t gldns_serial_arithmetics_time(int32_t time, time_t now) { - int32_t offset = time - (int32_t) now; + int32_t offset = (int32_t)((uint32_t) time - (uint32_t) now); return (int64_t) now + offset; } @@ -623,13 +623,18 @@ size_t gldns_b64_ntop_calculate_size(size_t srcsize) * * This routine does not insert spaces or linebreaks after 76 characters. */ -int gldns_b64_ntop(uint8_t const *src, size_t srclength, - char *target, size_t targsize) +static int gldns_b64_ntop_base(uint8_t const *src, size_t srclength, + char *target, size_t targsize, int base64url, int padding) { - const char* b64 = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + char* b64; const char pad64 = '='; size_t i = 0, o = 0; + if(base64url) + b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123" + "456789-_"; + else + b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123" + "456789+/"; if(targsize < gldns_b64_ntop_calculate_size(srclength)) return -1; /* whole chunks: xxxxxxyy yyyyzzzz zzwwwwww */ @@ -649,18 +654,26 @@ int gldns_b64_ntop(uint8_t const *src, size_t srclength, target[o] = b64[src[i] >> 2]; target[o+1] = b64[ ((src[i]&0x03)<<4) | (src[i+1]>>4) ]; target[o+2] = b64[ ((src[i+1]&0x0f)<<2) ]; - target[o+3] = pad64; - /* i += 2; */ - o += 4; + if(padding) { + target[o+3] = pad64; + /* i += 2; */ + o += 4; + } else { + o += 3; + } break; case 1: /* one at end, converted into A B = = */ target[o] = b64[src[i] >> 2]; target[o+1] = b64[ ((src[i]&0x03)<<4) ]; - target[o+2] = pad64; - target[o+3] = pad64; - /* i += 1; */ - o += 4; + if(padding) { + target[o+2] = pad64; + target[o+3] = pad64; + /* i += 1; */ + o += 4; + } else { + o += 2; + } break; case 0: default: @@ -673,19 +686,36 @@ int gldns_b64_ntop(uint8_t const *src, size_t srclength, return (int)o; } +int gldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, + size_t targsize) +{ + return gldns_b64_ntop_base(src, srclength, target, targsize, + 0 /* no base64url */, 1 /* padding */); +} + +int gldns_b64url_ntop(uint8_t const *src, size_t srclength, char *target, + size_t targsize) +{ + return gldns_b64_ntop_base(src, srclength, target, targsize, + 1 /* base64url */, 0 /* no padding */); +} + size_t gldns_b64_pton_calculate_size(size_t srcsize) { return (((((srcsize + 3) / 4) * 3)) + 1); } -int gldns_b64_pton(char const *src, uint8_t *target, size_t targsize) +/* padding not required if srcsize is set */ +static int gldns_b64_pton_base(char const *src, size_t srcsize, uint8_t *target, + size_t targsize, int base64url) { const uint8_t pad64 = 64; /* is 64th in the b64 array */ const char* s = src; uint8_t in[4]; size_t o = 0, incount = 0; + int check_padding = (srcsize) ? 0 : 1; - while(*s) { + while(*s && (check_padding || srcsize)) { /* skip any character that is not base64 */ /* conceptually we do: const char* b64 = pad'=' is appended to array @@ -694,30 +724,43 @@ int gldns_b64_pton(char const *src, uint8_t *target, size_t targsize) and use d-b64; */ char d = *s++; + srcsize--; if(d <= 'Z' && d >= 'A') d -= 'A'; else if(d <= 'z' && d >= 'a') d = d - 'a' + 26; else if(d <= '9' && d >= '0') d = d - '0' + 52; - else if(d == '+') + else if(!base64url && d == '+') d = 62; - else if(d == '/') + else if(base64url && d == '-') + d = 62; + else if(!base64url && d == '/') d = 63; - else if(d == '=') + else if(base64url && d == '_') + d = 63; + else if(d == '=') { + if(!check_padding) + continue; d = 64; - else continue; + } else continue; + in[incount++] = (uint8_t)d; - if(incount != 4) + /* work on block of 4, unless padding is not used and there are + * less than 4 chars left */ + if(incount != 4 && (check_padding || srcsize)) continue; + assert(!check_padding || incount==4); /* process whole block of 4 characters into 3 output bytes */ - if(in[3] == pad64 && in[2] == pad64) { /* A B = = */ + if((incount == 2 || + (incount == 4 && in[3] == pad64 && in[2] == pad64))) { /* A B = = */ if(o+1 > targsize) return -1; target[o] = (in[0]<<2) | ((in[1]&0x30)>>4); o += 1; break; /* we are done */ - } else if(in[3] == pad64) { /* A B C = */ + } else if(incount == 3 || + (incount == 4 && in[3] == pad64)) { /* A B C = */ if(o+2 > targsize) return -1; target[o] = (in[0]<<2) | ((in[1]&0x30)>>4); @@ -725,7 +768,7 @@ int gldns_b64_pton(char const *src, uint8_t *target, size_t targsize) o += 2; break; /* we are done */ } else { - if(o+3 > targsize) + if(incount != 4 || o+3 > targsize) return -1; /* write xxxxxxyy yyyyzzzz zzwwwwww */ target[o] = (in[0]<<2) | ((in[1]&0x30)>>4); @@ -737,3 +780,17 @@ int gldns_b64_pton(char const *src, uint8_t *target, size_t targsize) } return (int)o; } + +int gldns_b64_pton(char const *src, uint8_t *target, size_t targsize) +{ + return gldns_b64_pton_base(src, 0, target, targsize, 0); +} + +int gldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target, + size_t targsize) +{ + if(!srcsize) { + return 0; + } + return gldns_b64_pton_base(src, srcsize, target, targsize, 1); +} diff --git a/src/gldns/parseutil.h b/src/gldns/parseutil.h index 1546e8be..03bf06d9 100644 --- a/src/gldns/parseutil.h +++ b/src/gldns/parseutil.h @@ -92,13 +92,16 @@ size_t gldns_b64_ntop_calculate_size(size_t srcsize); int gldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize); +int gldns_b64url_ntop(uint8_t const *src, size_t srclength, char *target, + size_t targsize); /** * calculates the size needed to store the result of gldns_b64_pton */ size_t gldns_b64_pton_calculate_size(size_t srcsize); - int gldns_b64_pton(char const *src, uint8_t *target, size_t targsize); +int gldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target, + size_t targsize); /** * calculates the size needed to store the result of b32_ntop diff --git a/src/gldns/rrdef.h b/src/gldns/rrdef.h index ef3c8d9d..412394dd 100644 --- a/src/gldns/rrdef.h +++ b/src/gldns/rrdef.h @@ -195,7 +195,9 @@ enum gldns_enum_rr_type GLDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */ GLDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */ GLDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */ - GLDNS_RR_TYPE_ZONEMD = 63, /* draft-wessels-dns-zone-digest */ + GLDNS_RR_TYPE_ZONEMD = 63, /* RFC8976 */ + GLDNS_RR_TYPE_SVCB = 64, + GLDNS_RR_TYPE_HTTPS = 65, GLDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ @@ -432,7 +434,8 @@ enum gldns_enum_edns_option GLDNS_EDNS_N3U = 7, /* RFC6975 */ GLDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */ GLDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/ - GLDNS_EDNS_PADDING = 12 /* RFC7830 */ + GLDNS_EDNS_PADDING = 12, /* RFC7830 */ + GLDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */ }; typedef enum gldns_enum_edns_option gldns_edns_option; diff --git a/src/gldns/str2wire.c b/src/gldns/str2wire.c index 29de56d8..d78231fa 100644 --- a/src/gldns/str2wire.c +++ b/src/gldns/str2wire.c @@ -81,7 +81,7 @@ static int gldns_str2wire_dname_buf_rel(const char* str, uint8_t* buf, for (s = str; *s; s++, q++) { if (q >= buf + *olen) return RET_ERR(GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); - if (q > buf + GLDNS_MAX_DOMAINLEN) + if (q >= buf + GLDNS_MAX_DOMAINLEN) return RET_ERR(GLDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); switch (*s) { case '.': @@ -118,7 +118,7 @@ static int gldns_str2wire_dname_buf_rel(const char* str, uint8_t* buf, if(rel) *rel = 1; if (q >= buf + *olen) return RET_ERR(GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); - if (q > buf + GLDNS_MAX_DOMAINLEN) { + if (q >= buf + GLDNS_MAX_DOMAINLEN) { return RET_ERR(GLDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); } if (label_len > GLDNS_MAX_LABELLEN) { @@ -930,6 +930,10 @@ int gldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, memmove(parse_state->prev_rr, rr, *dname_len); parse_state->prev_rr_len = (*dname_len); } + if(r == GLDNS_WIREPARSE_ERR_OK && parse_state) { + parse_state->default_ttl = gldns_wirerr_get_ttl( + rr, *len, *dname_len); + } return r; } return GLDNS_WIREPARSE_ERR_OK; @@ -1494,13 +1498,17 @@ static int loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) { uint32_t meters = 0, cm = 0, val; + char* cm_endstr; while (isblank((unsigned char)*my_str)) { my_str++; } meters = (uint32_t)strtol(my_str, &my_str, 10); if (*my_str == '.') { my_str++; - cm = (uint32_t)strtol(my_str, &my_str, 10); + cm = (uint32_t)strtol(my_str, &cm_endstr, 10); + if(cm_endstr == my_str + 1) + cm *= 10; + my_str = cm_endstr; } if (meters >= 1) { *e = 2; diff --git a/src/gldns/wire2str.c b/src/gldns/wire2str.c index 427b156c..0620b0dc 100644 --- a/src/gldns/wire2str.c +++ b/src/gldns/wire2str.c @@ -14,6 +14,7 @@ * Contains functions to translate the wireformat to text * representation, as well as functions to print them. */ +#include #include "config.h" #include "gldns/wire2str.h" #include "gldns/str2wire.h" @@ -821,9 +822,12 @@ int gldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, if(!pkt || target >= pktlen) return w + gldns_str_print(s, slen, "ErrorComprPtrOutOfBounds"); - if(counter++ > maxcompr) + if(counter++ > maxcompr) { + if(comprloop && *comprloop < 10) + (*comprloop)++; return w + gldns_str_print(s, slen, "ErrorComprPtrLooped"); + } in_buf = 0; pos = pkt+target; continue; diff --git a/src/gnutls/tls.c b/src/gnutls/tls.c index 5ef1849f..b5280155 100644 --- a/src/gnutls/tls.c +++ b/src/gnutls/tls.c @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2019, NLnet Labs + * Copyright (c) 2018-2020, NLnet Labs * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -102,7 +102,18 @@ static int set_connection_ciphers(_getdns_tls_connection* conn) char* pri = NULL; int res; - pri = getdns_priappend(conn->mfs, pri, "NONE:+COMP-ALL:+SIGN-RSA-SHA384"); + pri = getdns_priappend(conn->mfs, pri, "NONE:+COMP-ALL:+SIGN-ALL" + /* Remove all the weak ones */ + ":-SIGN-RSA-MD5" + ":-SIGN-RSA-SHA1:-SIGN-RSA-SHA224:-SIGN-RSA-SHA256" + ":-SIGN-DSA-SHA1:-SIGN-DSA-SHA224:-SIGN-DSA-SHA256" +#if GNUTLS_VERSION_NUMBER >= 0x030505 + ":-SIGN-ECDSA-SHA1:-SIGN-ECDSA-SHA224:-SIGN-ECDSA-SHA256" +#endif +#if GNUTLS_VERSION_NUMBER >= 0x030601 + ":-SIGN-RSA-PSS-SHA256" +#endif + ); if (conn->cipher_suites) pri = getdns_priappend(conn->mfs, pri, conn->cipher_suites); @@ -119,7 +130,11 @@ static int set_connection_ciphers(_getdns_tls_connection* conn) else if (conn->ctx->curve_list) pri = getdns_priappend(conn->mfs, pri, conn->ctx->curve_list); else +#if GNUTLS_VERSION_NUMBER >= 0x030605 + pri = getdns_priappend(conn->mfs, pri, "+GROUP-EC-ALL"); +#else pri = getdns_priappend(conn->mfs, pri, "+CURVE-ALL"); +#endif gnutls_protocol_t min = conn->min_tls; gnutls_protocol_t max = conn->max_tls; @@ -134,18 +149,16 @@ static int set_connection_ciphers(_getdns_tls_connection* conn) for (gnutls_protocol_t i = min; i <= max; ++i) pri = getdns_priappend(conn->mfs, pri, _getdns_tls_priorities[i]); } - if (pri) { res = gnutls_priority_set_direct(conn->tls, pri, NULL); - if (res != GNUTLS_E_SUCCESS) { - _getdns_log(conn->log - , GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR - , "%s: %s %s (%s)\n" - , STUB_DEBUG_SETUP_TLS - , "Error configuring TLS connection with " - , pri - , gnutls_strerror(res)); - } + _getdns_log(conn->log + , GETDNS_LOG_UPSTREAM_STATS + , (res == GNUTLS_E_SUCCESS ? GETDNS_LOG_DEBUG : GETDNS_LOG_ERR) + , "%s: %s %s (%s)\n" + , STUB_DEBUG_SETUP_TLS + , "Configuring TLS connection with " + , pri + , gnutls_strerror(res)); } else res = gnutls_set_default_priority(conn->tls); @@ -165,7 +178,16 @@ static getdns_return_t error_may_want_read_write(_getdns_tls_connection* conn, i return GETDNS_RETURN_TLS_WANT_READ; else return GETDNS_RETURN_TLS_WANT_WRITE; - + case GNUTLS_E_FATAL_ALERT_RECEIVED: + _getdns_log( conn->log + , GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR + , "%s %s %d (%s)\n" + , STUB_DEBUG_SETUP_TLS + , "Error in TLS handshake" + , (int)gnutls_alert_get(conn->tls) + , gnutls_alert_get_name(gnutls_alert_get(conn->tls)) + ); + /* fallthrough */ default: return GETDNS_RETURN_GENERIC_ERROR; } @@ -249,7 +271,7 @@ getdns_return_t _getdns_tls_context_free(struct mem_funcs* mfs, _getdns_tls_cont void _getdns_tls_context_pinset_init(_getdns_tls_context* ctx) { - (void) ctx; + (void) ctx; /* unused parameter */ } getdns_return_t _getdns_tls_context_set_min_max_tls_version(_getdns_tls_context* ctx, getdns_tls_version_t min, getdns_tls_version_t max) @@ -319,6 +341,11 @@ getdns_return_t _getdns_tls_context_set_ca(_getdns_tls_context* ctx, const char* return GETDNS_RETURN_GOOD; } +void _getdns_gnutls_stub_log(int level, const char *msg) +{ + DEBUG_STUB("GnuTLS log (%.2d): %s", level, msg); +} + _getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd, const getdns_log_config* log) { _getdns_tls_connection* res; @@ -353,7 +380,9 @@ _getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdn gnutls_certificate_set_x509_trust_dir(res->cred, ctx->ca_trust_path, GNUTLS_X509_FMT_PEM); } - if (gnutls_init(&res->tls, GNUTLS_CLIENT | GNUTLS_NONBLOCK) != GNUTLS_E_SUCCESS) + gnutls_global_set_log_level(99); + gnutls_global_set_log_function(_getdns_gnutls_stub_log); + if (gnutls_init(&res->tls, GNUTLS_CLIENT | GNUTLS_NONBLOCK | GNUTLS_NO_SIGNAL) != GNUTLS_E_SUCCESS) goto failed; if (set_connection_ciphers(res) != GNUTLS_E_SUCCESS) { @@ -709,8 +738,11 @@ failsafe: GETDNS_FREE(*conn->mfs, new_cert_list); } - if (ret != DANE_E_SUCCESS) + if (ret != DANE_E_SUCCESS) { + *errnum = ret; + *errmsg = dane_strerror(ret); return GETDNS_RETURN_GENERIC_ERROR; + } if (verify != 0) { if (verify & DANE_VERIFY_CERT_DIFFERS) { @@ -764,6 +796,8 @@ getdns_return_t _getdns_tls_session_free(struct mem_funcs* mfs, _getdns_tls_sess { if (!s) return GETDNS_RETURN_INVALID_PARAMETER; + if (s->tls.data) + gnutls_free(s->tls.data); GETDNS_FREE(*mfs, s); return GETDNS_RETURN_GOOD; } diff --git a/src/libgetdns.symbols b/src/libgetdns.symbols index b8b6cffe..676400ce 100644 --- a/src/libgetdns.symbols +++ b/src/libgetdns.symbols @@ -30,6 +30,7 @@ getdns_context_get_resolution_type getdns_context_get_resolvconf getdns_context_get_round_robin_upstreams getdns_context_get_suffix +getdns_context_get_tcp_send_timeout getdns_context_get_timeout getdns_context_get_tls_authentication getdns_context_get_tls_backoff_time @@ -78,6 +79,7 @@ getdns_context_set_resolvconf getdns_context_set_return_dnssec_status getdns_context_set_round_robin_upstreams getdns_context_set_suffix +getdns_context_set_tcp_send_timeout getdns_context_set_timeout getdns_context_set_tls_authentication getdns_context_set_tls_backoff_time @@ -98,6 +100,7 @@ getdns_context_set_update_callback getdns_context_set_upstream_recursive_servers getdns_context_set_use_threads getdns_context_unset_edns_maximum_udp_payload_size +getdns_context_unset_tcp_send_timeout getdns_convert_alabel_to_ulabel getdns_convert_dns_name_to_fqdn getdns_convert_fqdn_to_dns_name diff --git a/src/openssl/keyraw-internal.c b/src/openssl/keyraw-internal.c index 6dab968a..99633e45 100644 --- a/src/openssl/keyraw-internal.c +++ b/src/openssl/keyraw-internal.c @@ -21,10 +21,10 @@ #include #include #ifdef HAVE_OPENSSL_CONF_H -# include +#include #endif #ifdef HAVE_OPENSSL_ENGINE_H -# include +#include #endif #ifdef HAVE_OPENSSL_BN_H #include @@ -35,6 +35,9 @@ #ifdef HAVE_OPENSSL_DSA_H #include #endif +#ifdef HAVE_OPENSSL_RSA_H +#include +#endif #endif /* HAVE_SSL */ #ifdef HAVE_SSL @@ -74,7 +77,6 @@ gldns_key_EVP_load_gost_id(void) if(!e) { /* load it ourself, in case statically linked */ ENGINE_load_builtin_engines(); - ENGINE_load_dynamic(); e = ENGINE_by_id("gost"); } if(!e) { diff --git a/src/openssl/tls.c b/src/openssl/tls.c index af1c3122..37ea19f3 100644 --- a/src/openssl/tls.c +++ b/src/openssl/tls.c @@ -48,19 +48,21 @@ #include "context.h" #include "const-info.h" -#ifdef USE_DANESSL +#if defined(USE_DANESSL) || defined(LIBRESSL_VERSION_NUMBER) # include "ssl_dane/danessl.h" #endif #include "tls.h" /* Double check configure has worked as expected. */ +#ifndef LIBRESSL_VERSION_NUMBER #if defined(USE_DANESSL) && \ (defined(HAVE_SSL_DANE_ENABLE) || \ defined(HAVE_OPENSSL_INIT_CRYPTO) || \ defined(HAVE_SSL_CTX_DANE_ENABLE)) #error Configure error USE_DANESSL defined with OpenSSL 1.1 functions! #endif +#endif /* Cipher suites recommended in RFC7525. */ static char const * const _getdns_tls_context_default_cipher_list = @@ -95,8 +97,8 @@ static int _getdns_tls_verify_always_ok(int ok, X509_STORE_CTX *ctx) strcpy(buf, ""); DEBUG_STUB("DEBUG Cert verify: depth=%d verify=%d err=%d subject=%s errorstr=%s\n", depth, ok, err, buf, X509_verify_cert_error_string(err)); # else /* defined(STUB_DEBUG) && STUB_DEBUG */ - (void)ok; - (void)ctx; + (void)ok; /* unused parameter */ + (void)ctx; /* unused parameter */ # endif /* #else defined(STUB_DEBUG) && STUB_DEBUG */ return 1; } @@ -425,7 +427,7 @@ getdns_return_t _getdns_tls_context_set_min_max_tls_version(_getdns_tls_context* * We've used TLSv1_2_client_method() creating the context, so * error if they asked for anything other than TLS 1.2 or better. */ - (void) ctx; + (void) ctx; /* unused parameter */ if ((!min || min == GETDNS_TLS1_2) && !max) return GETDNS_RETURN_GOOD; @@ -693,7 +695,7 @@ getdns_return_t _getdns_tls_connection_set_min_max_tls_version(_getdns_tls_conne * We've used TLSv1_2_client_method() creating the context, so * error if they asked for anything other than TLS 1.2 or better. */ - (void) conn; + (void) conn; /* unused parameter */ if ((!min || min == GETDNS_TLS1_2) && !max) return GETDNS_RETURN_GOOD; @@ -912,7 +914,7 @@ getdns_return_t _getdns_tls_connection_set_host_pinset(_getdns_tls_connection* c #if defined(HAVE_SSL_DANE_ENABLE) int osr = SSL_dane_enable(conn->ssl, *auth_name ? auth_name : NULL); - (void) osr; + (void) osr; /* unused parameter */ DEBUG_STUB("%s %-35s: DEBUG: SSL_dane_enable(\"%s\") -> %d\n" , STUB_DEBUG_SETUP_TLS, __FUNC__, auth_name, osr); SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, _getdns_tls_verify_always_ok); @@ -938,7 +940,7 @@ getdns_return_t _getdns_tls_connection_set_host_pinset(_getdns_tls_connection* c int osr = DANESSL_init(conn->ssl, *auth_name ? auth_name : NULL, *auth_name ? auth_names : NULL); - (void) osr; + (void) osr; /* unused parameter */ DEBUG_STUB("%s %-35s: DEBUG: DANESSL_init(\"%s\") -> %d\n" , STUB_DEBUG_SETUP_TLS, __FUNC__, auth_name, osr); SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, _getdns_tls_verify_always_ok); diff --git a/src/platform.c b/src/platform.c index 49a7e225..76ebd0ce 100644 --- a/src/platform.c +++ b/src/platform.c @@ -166,6 +166,11 @@ const char *_getdns_strerror(DWORD errnum) } } +const char *_getdns_filestrerror(int errnum) +{ + return strerror(errnum); +} + #else void _getdns_perror(const char *str) diff --git a/src/platform.h b/src/platform.h index c7ac17c2..a4da66cc 100644 --- a/src/platform.h +++ b/src/platform.h @@ -60,6 +60,7 @@ typedef u_short sa_family_t; #define _getdns_socketerror() (WSAGetLastError()) const char *_getdns_strerror(DWORD errnum); +const char *_getdns_filestrerror(int errnum); #else /* USE_WINSOCK */ #ifndef HAVE_SYS_POLL_H @@ -132,10 +133,13 @@ const char *_getdns_strerror(DWORD errnum); #define _getdns_socketerror() (errno) const char *_getdns_strerror(int errnum); +#define _getdns_filestrerror(errnum) (_getdns_strerror(errnum)) #endif void _getdns_perror(const char *str); +#define _getdns_fileerror() (errno) +#define _getdns_fileerrnostr() (_getdns_filestrerror(_getdns_fileerror())) #define _getdns_errnostr() (_getdns_strerror(_getdns_socketerror())) #define _getdns_error_wants_retry(X) ( (X) != 0 \ && ( (X) == _getdns_EINTR \ diff --git a/src/request-internal.c b/src/request-internal.c index eedea35c..52157e0b 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -147,6 +147,7 @@ netreq_reset(getdns_network_req *net_req) net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE; net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE; net_req->response_len = 0; + net_req->response_opt = NULL; /* Some fields to record info for return_call_reporting */ net_req->debug_start_time = 0; net_req->debug_end_time = 0; @@ -208,6 +209,9 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, net_req->transport_current = 0; memset(&net_req->event, 0, sizeof(net_req->event)); net_req->keepalive_sent = 0; + net_req->badcookie_retry = 0; + net_req->cookie_sent = 0; + memset(&net_req->client_cookie, 0, sizeof(net_req->client_cookie)); net_req->write_queue_tail = NULL; /* Some fields to record info for return_call_reporting */ net_req->debug_tls_auth_status = GETDNS_AUTH_NONE; @@ -308,6 +312,7 @@ _getdns_network_req_clear_upstream_options(getdns_network_req * req) req->response = req->opt + 11 + req->base_query_option_sz; pktlen = req->response - req->query; gldns_write_uint16(req->query - 2, (uint16_t) pktlen); + req->response_opt = NULL; } } @@ -317,6 +322,9 @@ _getdns_netreq_reinit(getdns_network_req *netreq) uint8_t *base_opt_backup; size_t base_opt_rr_sz; + if (netreq->response && (netreq->response < netreq->wire_data || + netreq->response > netreq->wire_data+ netreq->wire_data_sz)) + GETDNS_NULL_FREE(netreq->owner->my_mf, netreq->response); if (!netreq->query) { (void) netreq_reset(netreq); return; @@ -476,7 +484,7 @@ void _getdns_network_validate_tsig(getdns_network_req *req) { #if defined(HAVE_NSS) || defined(HAVE_NETTLE) - (void)req; + (void)req; /* unused parameter */ #else _getdns_rr_iter rr_spc, *rr; _getdns_rdf_iter rdf_spc, *rdf; diff --git a/src/rr-dict.c b/src/rr-dict.c index fc675830..e3c7f2df 100644 --- a/src/rr-dict.c +++ b/src/rr-dict.c @@ -47,7 +47,7 @@ static const uint8_t * apl_n_rdf_end(const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf) { - (void)pkt; + (void)pkt; /* unused parameter */ return rdf < pkt_end ? rdf + 1 : NULL; } static getdns_return_t @@ -91,7 +91,7 @@ apl_afdpart_rdf_end( const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf) { const uint8_t *end = rdf + (rdf[-1] & 0x7F); - (void)(pkt); + (void)pkt; /* unused parameter */ return end <= pkt_end ? end : NULL; } static getdns_return_t @@ -217,6 +217,7 @@ ipseckey_gateway_2wire( { assert(rdf - 2 >= rdata && rdf[-2] > 0); + (void)rdata; /* unused parameter */ switch (rdf[-2]) { case 1: if (!value || value->size != 4) return GETDNS_RETURN_INVALID_PARAMETER; @@ -280,7 +281,7 @@ static const uint8_t * hip_pk_algorithm_rdf_end( const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf) { - (void)(pkt); + (void)pkt; /* unused parameter */ return rdf + 4 > pkt_end ? NULL : rdf + 4 + *rdf + gldns_read_uint16(rdf + 2) > pkt_end ? NULL : rdf + 1; @@ -326,7 +327,7 @@ static _getdns_rdf_special hip_pk_algorithm = { static const uint8_t * hip_hit_rdf_end(const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf) { - (void)(pkt); + (void)pkt; /* unused parameter */ return rdf + 3 > pkt_end ? NULL : rdf + 3 + rdf[-1] + gldns_read_uint16(rdf + 1) > pkt_end ? NULL : rdf + 1; @@ -380,7 +381,7 @@ static const uint8_t * hip_public_key_rdf_end( const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf) { - (void)(pkt); + (void)pkt; /* unused parameter */ return rdf + 2 > pkt_end ? NULL : rdf + 2 + rdf[-2] + gldns_read_uint16(rdf) > pkt_end ? NULL : rdf + 2 + rdf[-2] + gldns_read_uint16(rdf); @@ -434,7 +435,7 @@ static _getdns_rdf_special hip_public_key = { static const uint8_t * amtrelay_D_rdf_end(const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf) { - (void)pkt; + (void)pkt; /* unused parameter */ return rdf < pkt_end ? rdf + 1 : NULL; } static getdns_return_t @@ -471,7 +472,8 @@ static const uint8_t * amtrelay_rtype_rdf_end( const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf) { - (void)pkt; (void)pkt_end; + (void)pkt; /* unused parameter */ + (void)pkt_end; /* unused parameter */ return rdf; } static getdns_return_t @@ -581,6 +583,7 @@ amtrelay_relay_2wire( { assert(rdf - 1 >= rdata && (rdf[-1] & 0x7F) > 0); + (void)rdata; /* unused parameter */ switch (rdf[-1] & 0x7F) { case 1: if (!value || value->size != 4) return GETDNS_RETURN_INVALID_PARAMETER; @@ -1293,8 +1296,39 @@ write_rdata_field(gldns_buffer *buf, uint8_t *rdata_start, return r != GETDNS_RETURN_NO_SUCH_LIST_ITEM ? r : GETDNS_RETURN_GOOD; } +void +_getdns_rr_buffer_write_cached_name(gldns_buffer *buf, getdns_bindata *name, name_cache_t *name_cache) +{ + size_t name_size = name->size; + uint8_t *name_data = name->data; + if((NULL != name_cache) && (name_size > 2)) { + unsigned count = name_cache->count; + name_cache_entry_t *entry_ptr = &name_cache->entry[(count < NAME_CACHE_ENTRIES)?count:NAME_CACHE_ENTRIES]; + name_cache_entry_t *table_start = &name_cache->entry[0]; + /* Search backward if name is already in cache */ + while(entry_ptr-- > table_start) { + if((entry_ptr->name->size == name_size) && + !memcmp(entry_ptr->name->data, name_data, name_size)) { + gldns_buffer_write_u16(buf, (uint16_t)(0xc000 | entry_ptr->name_offset)); + return; + } + } + unsigned name_offset = gldns_buffer_position(buf); + if (name_offset < 0xc000) { + /* Cache name */ + entry_ptr = &name_cache->entry[count % NAME_CACHE_ENTRIES]; + entry_ptr->name = name; + entry_ptr->name_offset = name_offset; + name_cache->count = count + 1; + } + } + gldns_buffer_write(buf, name_data, name_size); + return; +} + getdns_return_t -_getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf) +_getdns_rr_dict2wire_cache(const getdns_dict *rr_dict, gldns_buffer *buf, + name_cache_t *name_cache) { getdns_return_t r = GETDNS_RETURN_GOOD; getdns_bindata root = { 1, (void *)"" }; @@ -1325,7 +1359,7 @@ _getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf) } else return r; } - gldns_buffer_write(buf, name->data, name->size); + _getdns_rr_buffer_write_cached_name(buf, name, name_cache); gldns_buffer_write_u16(buf, (uint16_t)rr_type); (void) getdns_dict_get_int(rr_dict, "class", &rr_class); @@ -1378,42 +1412,51 @@ _getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf) gldns_buffer_skip(buf, 2); rdata_start = gldns_buffer_current(buf); - for ( rd_def = rr_def->rdata - , n_rdata_fields = rr_def->n_rdata_fields - ; n_rdata_fields ; n_rdata_fields-- , rd_def++ ) { + /* Special case CNAME payload */ + if((rr_type == GETDNS_RRTYPE_CNAME) && (n_rdata_fields == 1) && + (rd_def->type & GETDNS_RDF_BINDATA) && !(rd_def->type & GETDNS_RDF_REPEAT) && + (GETDNS_RETURN_GOOD == (r = getdns_dict_get_bindata(rdata, rd_def->name, &rdata_raw)))) { - if (rd_def->type == GETDNS_RDF_REPEAT) - break; + _getdns_rr_buffer_write_cached_name(buf, rdata_raw, name_cache); + } else { - if ((r = write_rdata_field(buf, - rdata_start, rd_def, rdata))) - break; - } - if (n_rdata_fields == 0 || r) { - /* pass */; + for ( rd_def = rr_def->rdata + , n_rdata_fields = rr_def->n_rdata_fields + ; n_rdata_fields ; n_rdata_fields-- , rd_def++ ) { - } else if ((r = getdns_dict_get_list( - rdata, rd_def->name, &list))) { - /* pass */; - - } else for ( i = 0 - ; r == GETDNS_RETURN_GOOD - ; i++) { - - if ((r = getdns_list_get_dict(list, i, &rdata))) { - if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM) - r = GETDNS_RETURN_GOOD; - break; - } - for ( rep_rd_def = rd_def + 1 - , rep_n_rdata_fields = n_rdata_fields - 1 - ; rep_n_rdata_fields - ; rep_n_rdata_fields--, rep_rd_def++ ) { + if (rd_def->type == GETDNS_RDF_REPEAT) + break; if ((r = write_rdata_field(buf, - rdata_start, rep_rd_def, rdata))) + rdata_start, rd_def, rdata))) break; } + if (n_rdata_fields == 0 || r) { + /* pass */; + + } else if ((r = getdns_dict_get_list( + rdata, rd_def->name, &list))) { + /* pass */; + + } else for ( i = 0 + ; r == GETDNS_RETURN_GOOD + ; i++) { + + if ((r = getdns_list_get_dict(list, i, &rdata))) { + if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM) + r = GETDNS_RETURN_GOOD; + break; + } + for ( rep_rd_def = rd_def + 1 + , rep_n_rdata_fields = n_rdata_fields - 1 + ; rep_n_rdata_fields + ; rep_n_rdata_fields--, rep_rd_def++ ) { + + if ((r = write_rdata_field(buf, + rdata_start, rep_rd_def, rdata))) + break; + } + } } gldns_buffer_write_u16_at(buf, rdata_size_mark, (uint16_t)(gldns_buffer_position(buf)-rdata_size_mark-2)); diff --git a/src/rr-dict.h b/src/rr-dict.h index e19e0387..f0788021 100644 --- a/src/rr-dict.h +++ b/src/rr-dict.h @@ -143,8 +143,25 @@ typedef struct _getdns_rr_def { const _getdns_rr_def *_getdns_rr_def_lookup(uint16_t rr_type); -getdns_return_t _getdns_rr_dict2wire( - const getdns_dict *rr_dict, gldns_buffer *buf); +#define NAME_CACHE_ENTRIES 4 + +typedef struct __name_cache_entry { + getdns_bindata *name; + unsigned name_offset; +} name_cache_entry_t; + +typedef struct __name_cache { + unsigned count; + name_cache_entry_t entry[NAME_CACHE_ENTRIES]; +} name_cache_t; + +void _getdns_rr_buffer_write_cached_name( + gldns_buffer *buf, getdns_bindata *name, name_cache_t *name_cache); + +getdns_return_t _getdns_rr_dict2wire_cache( + const getdns_dict *rr_dict, gldns_buffer *buf, name_cache_t *name_cache); + +#define _getdns_rr_dict2wire(d, b) _getdns_rr_dict2wire_cache((d),(b), NULL) const char *_getdns_rr_type_name(int rr_type); diff --git a/src/ssl_dane b/src/ssl_dane index 18783810..afd5b886 160000 --- a/src/ssl_dane +++ b/src/ssl_dane @@ -1 +1 @@ -Subproject commit 187838104f3cfc9634148ae41a717e00c0d68e67 +Subproject commit afd5b88687f05554513d9caf000f08904e32e6a4 diff --git a/src/stub.c b/src/stub.c index 5f52b866..78d83696 100644 --- a/src/stub.c +++ b/src/stub.c @@ -33,6 +33,10 @@ #include "config.h" +#ifndef USE_WINSOCK +#include +#endif + /* Intercept and do not sent out COM DS queries with TLS * For debugging purposes only. Never commit with this turned on. */ @@ -53,6 +57,7 @@ #include "general.h" #include "pubkey-pinning.h" + /* WSA TODO: * STUB_TCP_RETRY added to deal with edge triggered event loops (versus * level triggered). See also lines containing WSA TODO below... @@ -73,10 +78,6 @@ /* Arbritray number of message for EDNS keepalive resend*/ #define EDNS_KEEPALIVE_RESEND 5 -static time_t secret_rollover_time = 0; -static uint32_t secret = 0; -static uint32_t prev_secret = 0; - static void upstream_read_cb(void *userarg); static void upstream_write_cb(void *userarg); static void upstream_idle_timeout_cb(void *userarg); @@ -97,47 +98,6 @@ uint64_t _getdns_get_time_as_uintt64(); /* General utility functions */ /*****************************/ -static void -rollover_secret() -{ - time_t now = 0; - - /* Create and roll server secrets */ - if (time(&now) <= secret_rollover_time) - return; - - /* Remember previous secret, in to keep answering on rollover - * boundary with old cookie. - */ - prev_secret = secret; - secret = arc4random(); - - /* Next rollover over EDNS_COOKIE_ROLLOVER_TIME with 30% jitter, - * I.e. some offset + or - 15% of the future point in time. - */ - secret_rollover_time = now + (EDNS_COOKIE_ROLLOVER_TIME / 20 * 17) - + arc4random_uniform(EDNS_COOKIE_ROLLOVER_TIME / 10 * 3); -} - -static void -calc_new_cookie(getdns_upstream *upstream, uint8_t *cookie) -{ - unsigned char md_value[GETDNS_TLS_MAX_DIGEST_LENGTH]; - size_t md_len; - size_t i; - sa_family_t af = upstream->addr.ss_family; - void *sa_addr = ((struct sockaddr*)&upstream->addr)->sa_data; - size_t addr_len = ( af == AF_INET6 ? sizeof(struct sockaddr_in6) - : af == AF_INET ? sizeof(struct sockaddr_in) - : 0 ) - sizeof(sa_family_t); - - _getdns_tls_cookie_sha256(secret, sa_addr, addr_len, md_value, &md_len); - - (void) memset(cookie, 0, 8); - for (i = 0; i < md_len; i++) - cookie[i % 8] ^= md_value[i]; -} - static getdns_return_t attach_edns_client_subnet_private(getdns_network_req *req) { @@ -169,154 +129,269 @@ static getdns_return_t attach_edns_cookie(getdns_network_req *req) { getdns_upstream *upstream = req->upstream; - uint16_t sz; - void* val; - uint8_t buf[8 + 32]; /* server cookies can be no larger than 32 bytes */ - rollover_secret(); - if (!upstream->has_client_cookie) { - calc_new_cookie(upstream, upstream->client_cookie); - upstream->secret = secret; - upstream->has_client_cookie = 1; + if (upstream->server_cookie_len) { + if (!req->badcookie_retry && bind(req->fd, (struct sockaddr *) + &upstream->src_addr, upstream->src_addr_len)) { - sz = 8; - val = upstream->client_cookie; - } else if (upstream->secret != secret) { - memcpy( upstream->prev_client_cookie - , upstream->client_cookie, 8); - upstream->has_prev_client_cookie = 1; - calc_new_cookie(upstream, upstream->client_cookie); - upstream->secret = secret; + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_INFO, + "%-40s : Upstream : %s with source address: %s. " + "Renewing Client Cookie.\n", upstream->addr_str, + strerror(errno), upstream->src_addr_str); - sz = 8; - val = upstream->client_cookie; - } else if (!upstream->has_server_cookie) { - sz = 8; - val = upstream->client_cookie; - } else { - sz = 8 + upstream->server_cookie_len; - memcpy(buf, upstream->client_cookie, 8); - memcpy(buf+8, upstream->server_cookie, upstream->server_cookie_len); - val = buf; + upstream->server_cookie_len = 0; + upstream->src_addr_checked = 0; + } else + return _getdns_network_req_add_upstream_option( + req, EDNS_COOKIE_OPCODE, + upstream->server_cookie_len, + upstream->server_cookie); } - return _getdns_network_req_add_upstream_option(req, EDNS_COOKIE_OPCODE, sz, val); + if (_getdns_get_now_ms() - upstream->src_addr_checked < 3600000) { + /* This upstream has been registered to *not* support cookies. + * We will recheck one hour after this was registered. + */ + return 0; + } + /* Try to get a new server cookie for this upstream + * Explicitly connect on UDP only. + */ + if (req->fd >= 0 && connect(req->fd, + (struct sockaddr*)&upstream->addr, upstream->addr_len)) { + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING, + "%-40s : Upstream : Could not connect(): %s. " + "Required for privacy aware Cookies. Cookies disabled.\n", + upstream->addr_str, strerror(errno)); + /* Don't recheck for another hour */ + upstream->src_addr_checked = _getdns_get_now_ms(); + return 0; + } + /* Create new client cookie */ + req->cookie_sent = 1; + gldns_write_uint32(req->client_cookie, arc4random()); + gldns_write_uint32(req->client_cookie + 4, arc4random()); + return _getdns_network_req_add_upstream_option( + req, EDNS_COOKIE_OPCODE, 8, req->client_cookie); } /* Will find a matching OPT RR, but leaves the caller to validate it - * - * Returns 2 when found - * 0 when not found - * and 1 on FORMERR */ +#define MATCH_OPT_FOUND 2 +#define MATCH_OPT_NOT_FOUND 0 +#define MATCH_OPT_ERROR 1 static int -match_edns_opt_rr(uint16_t code, uint8_t *response, size_t response_len, +match_edns_opt_rr(uint16_t code, getdns_network_req *netreq, const uint8_t **position, uint16_t *option_len) { - _getdns_rr_iter rr_iter_storage, *rr_iter; - const uint8_t *pos; + const uint8_t *pos, *rdata_end; uint16_t rdata_len, opt_code = 0, opt_len = 0; + static uint8_t *NO_OPT_RR = (uint8_t *)"\x00\x00"; /* Search for the OPT RR (if any) */ - for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage - , response, response_len) - ; rr_iter - ; rr_iter = _getdns_rr_iter_next(rr_iter)) { + if (!netreq->response_opt) { + _getdns_rr_iter rr_iter_storage, *rr_iter; + for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage + , netreq->response, netreq->response_len) + ; rr_iter + ; rr_iter = _getdns_rr_iter_next(rr_iter)) { - if (_getdns_rr_iter_section(rr_iter) != SECTION_ADDITIONAL) - continue; + if (_getdns_rr_iter_section(rr_iter) != SECTION_ADDITIONAL) + continue; - if (gldns_read_uint16(rr_iter->rr_type) != GETDNS_RRTYPE_OPT) - continue; - - break; - } - if (! rr_iter) - return 0; /* No OPT, no cookie */ - - pos = rr_iter->rr_type + 8; + if (gldns_read_uint16(rr_iter->rr_type) != GETDNS_RRTYPE_OPT) + continue; + break; + } + if (! rr_iter) { + netreq->response_opt = NO_OPT_RR; + return MATCH_OPT_NOT_FOUND; + } + pos = netreq->response_opt = rr_iter->rr_type + 8; #if defined(STUB_DEBUG) && STUB_DEBUG - char str_spc[8192], *str = str_spc; - size_t str_len = sizeof(str_spc); - uint8_t *data = (uint8_t *)rr_iter->pos; - size_t data_len = rr_iter->nxt - rr_iter->pos; - (void) gldns_wire2str_rr_scan( - &data, &data_len, &str, &str_len, (uint8_t *)rr_iter->pkt, rr_iter->pkt_end - rr_iter->pkt, NULL); - DEBUG_STUB("%s %-35s: OPT RR: %s", - STUB_DEBUG_READ, __FUNC__, str_spc); + char str_spc[8192], *str = str_spc; + size_t str_len = sizeof(str_spc); + uint8_t *data = (uint8_t *)rr_iter->pos; + size_t data_len = rr_iter->nxt - rr_iter->pos; + (void) gldns_wire2str_rr_scan(&data, &data_len, &str, &str_len, + (uint8_t *)rr_iter->pkt, rr_iter->pkt_end - rr_iter->pkt, + NULL); + DEBUG_STUB("%s %-35s: OPT RR: %s", + STUB_DEBUG_READ, __FUNC__, str_spc); #endif + /* Check limits only the first time*/ + if (pos + 2 > rr_iter->nxt + || pos + 2 + gldns_read_uint16(pos) > rr_iter->nxt) { + netreq->response_opt = NO_OPT_RR; + return MATCH_OPT_ERROR; + } + } else if (netreq->response_opt == NO_OPT_RR) + return MATCH_OPT_NOT_FOUND; + else + /* Reuse earlier found option */ + pos = netreq->response_opt;; - /* OPT found, now search for the specified option */ - if (pos + 2 > rr_iter->nxt) - return 1; /* FORMERR */ + rdata_len = gldns_read_uint16(pos); + pos += 2; + rdata_end = pos + rdata_len; - rdata_len = gldns_read_uint16(pos); pos += 2; - if (pos + rdata_len > rr_iter->nxt) - return 1; /* FORMERR */ - - while (pos < rr_iter->nxt) { + while (pos < rdata_end) { opt_code = gldns_read_uint16(pos); pos += 2; opt_len = gldns_read_uint16(pos); pos += 2; - if (pos + opt_len > rr_iter->nxt) - return 1; /* FORMERR */ + if (pos + opt_len > rdata_end) + return MATCH_OPT_ERROR; if (opt_code == code) break; pos += opt_len; /* Skip unknown options */ } - if (pos >= rr_iter->nxt || opt_code != code) - return 0; /* Everything OK, just no cookie found. */ + if (pos >= rdata_end || opt_code != code) + return MATCH_OPT_NOT_FOUND; + *position = pos; *option_len = opt_len; - return 2; + return MATCH_OPT_FOUND; } /* TODO: Test combinations of EDNS0 options*/ static int match_and_process_server_cookie( - getdns_upstream *upstream, uint8_t *response, size_t response_len) + getdns_upstream *upstream, getdns_network_req *netreq) { const uint8_t *position = NULL; uint16_t option_len = 0; - int found = match_edns_opt_rr(EDNS_COOKIE_OPCODE, response, - response_len, &position, &option_len); - if (found != 2) - return found; + int gai_r; + int found = match_edns_opt_rr(EDNS_COOKIE_OPCODE, netreq, + &position, &option_len); + if (found == MATCH_OPT_ERROR) { + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING, + "%-40s : Upstream : Error getting Cookie option.\n", + upstream->addr_str); - if (option_len < 16 || option_len > 40) - return 1; /* FORMERR */ - - if (!upstream->has_client_cookie) - return 1; /* Cookie reply, but we didn't sent one */ - - if (memcmp(upstream->client_cookie, position, 8) != 0) { - if (!upstream->has_prev_client_cookie) - return 1; /* Cookie didn't match */ - if (memcmp(upstream->prev_client_cookie, position, 8) != 0) - return 1; /* Previous cookie didn't match either */ - - upstream->has_server_cookie = 0; - return 0; /* Don't store server cookie, because it - * is for our previous client cookie - */ + return 1; /* Discard and wait for better response */ + } + else if (found == MATCH_OPT_NOT_FOUND) { + /* Option not found, server does not support cookies */ + if (upstream->server_cookie_len > 8) { + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR, + "%-40s : Upstream : Server did not return " + " DNS Cookie. Response discarded.\n", + upstream->addr_str); + + return 1; /* Discard response */ + + } else if (netreq->cookie_sent) { + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_INFO, + "%-40s : Upstream : Does not support DNS Cookies" + ". Retrying in one hour.\n", upstream->addr_str); + + upstream->src_addr_checked = _getdns_get_now_ms(); + } + return 0; /* Use response */ + } + assert(found == MATCH_OPT_FOUND); + + if (option_len < 16 || option_len > 40) { + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING, + "%-40s : Upstream : " + "Unsupported Server Cookie size: %d.\n", + upstream->addr_str, (int)option_len); + + return 1; /* Discard and wait for better response */ + } + + if (upstream->server_cookie_len > 8) { + if (memcmp(upstream->server_cookie, position, 8)) { + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING, + "%-40s : Upstream : DNS Cookie did not match.\n", + upstream->addr_str); + + return 1; /* Discard and wait for better response */ + } + /* Update server cookie */ + upstream->server_cookie_len = option_len; + (void) memcpy(upstream->server_cookie, position, option_len); + return 0; /* Use response */ + + } else if (!netreq->cookie_sent) { + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING, + "%-40s : Upstream : " + "DNS Cookie received but none sent.\n",upstream->addr_str); + + return 1; /* Discard and wait for better response */ + } + if (memcmp(netreq->client_cookie, position, 8)) { + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING, + "%-40s : Upstream : DNS Cookie did not match.\n", + upstream->addr_str); + + return 1; /* Discard and wait for better response */ + } + /* A new client cookie matched, store server cookie but only if we + * can get the source IP address. + */ + upstream->src_addr_checked = _getdns_get_now_ms(); + + upstream->src_addr_len = sizeof(upstream->src_addr); + if (getsockname(netreq->fd,(struct sockaddr*) + &upstream->src_addr, &upstream->src_addr_len)) { + + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING, + "%-40s : Upstream : Could not get source address: %s. " + "Privacy aware DNS Cookies not supported.\n", + upstream->addr_str, strerror(errno)); + + } else if ((gai_r = getnameinfo((struct sockaddr *) + &upstream->src_addr, upstream->src_addr_len, + upstream->src_addr_str, sizeof(upstream->src_addr_str), + NULL, 0, NI_NUMERICHOST))) { + + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING, + "%-40s : Upstream : Could not print source address: %s. " + "Privacy aware DNS Cookies not supported.\n", + upstream->addr_str, gai_strerror(gai_r)); + } else { + switch (upstream->src_addr.ss_family) { + case AF_INET: + ((struct sockaddr_in *)&upstream->src_addr)->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6*)&upstream->src_addr)->sin6_port = 0; + break; + default: + return 0; + } + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, + "%-40s : Upstream : " + "Registering new Server Cookie for source address: %s.\n", + upstream->addr_str, upstream->src_addr_str); + + upstream->server_cookie_len = option_len; + (void) memcpy(upstream->server_cookie, position, option_len); + return 0; } - position += 8; - option_len -= 8; - upstream->has_server_cookie = 1; - upstream->server_cookie_len = option_len; - (void) memcpy(upstream->server_cookie, position, option_len); return 0; } static void -process_keepalive( - getdns_upstream *upstream, getdns_network_req *netreq, - uint8_t *response, size_t response_len) +process_keepalive( getdns_upstream *upstream, getdns_network_req *netreq) { const uint8_t *position = NULL; uint16_t option_len = 0; - int found = match_edns_opt_rr(GLDNS_EDNS_KEEPALIVE, response, - response_len, &position, &option_len); + int found = match_edns_opt_rr(GLDNS_EDNS_KEEPALIVE, netreq, + &position, &option_len); if (found != 2 || option_len != 2) { if (netreq->keepalive_sent == 1) { /* For TCP if no keepalive sent back, then we must use 0 idle timeout @@ -373,8 +448,27 @@ getdns_sock_nonblock(int sockfd) #endif } +/** best effort to set TCP send timeout */ +static void +getdns_sock_tcp_send_timeout(getdns_upstream *upstream, int sockfd, + int send_timeout) +{ +#if defined(HAVE_DECL_TCP_USER_TIMEOUT) + unsigned int val = send_timeout; + if (setsockopt(sockfd, IPPROTO_TCP, TCP_USER_TIMEOUT, + &val, sizeof(val)) != 0) { + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING, + "%-40s : Upstream : " + "Could not enable TCP send timeout\n", + upstream->addr_str); + } +#endif +} + static int -tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) +tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport, + int send_timeout) { #if defined(TCP_FASTOPEN) || defined(TCP_FASTOPEN_CONNECT) # ifdef USE_WINSOCK @@ -393,6 +487,8 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) return -1; getdns_sock_nonblock(fd); + if (send_timeout != -1) + getdns_sock_tcp_send_timeout(upstream, fd, send_timeout); #ifdef USE_OSX_TCP_FASTOPEN sa_endpoints_t endpoints; endpoints.sae_srcif = 0; @@ -409,7 +505,7 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) _getdns_socketerror() == _getdns_EWOULDBLOCK) return fd; - (void)transport; + (void)transport; /* unused parameter */ #else /* USE_OSX_TCP_FASTOPEN */ /* Note that error detection is different with TFO. Since the handshake doesn't start till the sendto() lack of connection is often delayed until @@ -457,7 +553,7 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) "%-40s : Upstream : Could not setup TCP TFO\n", upstream->addr_str); # else - (void)transport; + (void)transport; /* unused parameter */ # endif/* HAVE_DECL_TCP_FASTOPEN*/ # endif /* HAVE_DECL_TCP_FASTOPEN_CONNECT */ #endif /* USE_OSX_TCP_FASTOPEN */ @@ -957,7 +1053,9 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) } } - _getdns_tls_connection_set_host_pinset(tls, upstream->tls_auth_name, upstream->tls_pubkey_pinset); + if (upstream->tls_pubkey_pinset) + _getdns_tls_connection_set_host_pinset( + tls, upstream->tls_auth_name, upstream->tls_pubkey_pinset); /* Session resumption. There are trade-offs here. Want to do it when possible only if we have the right type of connection. Note a change @@ -982,7 +1080,7 @@ tls_do_handshake(getdns_upstream *upstream) int r; while ((r = _getdns_tls_connection_do_handshake(upstream->tls_obj)) != GETDNS_RETURN_GOOD) { - uint64_t timeout_tls = _getdns_ms_until_expiry(upstream->expires); + uint64_t timeout_tls = _getdns_ms_until_expiry(upstream->expires)/5*4; if (timeout_tls < MIN_TLS_HS_TIMEOUT) timeout_tls = MIN_TLS_HS_TIMEOUT; @@ -1035,8 +1133,8 @@ tls_do_handshake(getdns_upstream *upstream) : "*Failure*" )); upstream->tls_auth_state = GETDNS_AUTH_FAILED; } else { - long verify_errno; - const char* verify_errmsg; + long verify_errno = 0; + const char* verify_errmsg = "Unknown verify error (fix reporting!)"; if (_getdns_tls_connection_certificate_verify(upstream->tls_obj, &verify_errno, &verify_errmsg)) { upstream->tls_auth_state = GETDNS_AUTH_FAILED; @@ -1340,6 +1438,7 @@ _getdns_get_time_as_uintt64() { /**************************/ +static void stub_udp_write_cb(void *userarg); static void stub_udp_read_cb(void *userarg) { @@ -1385,14 +1484,15 @@ stub_udp_read_cb(void *userarg) if (GLDNS_ID_WIRE(netreq->response) != GLDNS_ID_WIRE(netreq->query)) return; /* Cache poisoning attempt ;) */ - if (netreq->owner->edns_cookies && match_and_process_server_cookie( - upstream, netreq->response, read)) - return; /* Client cookie didn't match? */ - + if (netreq->owner->edns_cookies) { + netreq->response_len = read; + if (match_and_process_server_cookie(upstream, netreq)) { + netreq->response_len = 0; /* 0 means error */ + return; /* Client cookie didn't match? */ + } + netreq->response_len = 0; /* 0 means error */ + } GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); - - _getdns_closesocket(netreq->fd); - netreq->fd = -1; while (GLDNS_TC_WIRE(netreq->response)) { DEBUG_STUB("%s %-35s: MSG: %p TC bit set in response \n", STUB_DEBUG_READ, __FUNC__, (void*)netreq); @@ -1403,6 +1503,9 @@ stub_udp_read_cb(void *userarg) if (next_transport != GETDNS_TRANSPORT_TCP && next_transport != GETDNS_TRANSPORT_TLS) break; + + _getdns_closesocket(netreq->fd); + netreq->fd = -1; /* For now, special case where fallback should be on the same upstream*/ if ((netreq->fd = upstream_connect(upstream, next_transport, dnsreq)) == -1) @@ -1412,10 +1515,27 @@ stub_udp_read_cb(void *userarg) _getdns_ms_until_expiry(dnsreq->expires), getdns_eventloop_event_init(&netreq->event, netreq, NULL, NULL, stub_timeout_cb)); - return; } netreq->response_len = read; + if (netreq->owner->edns_cookies + && !netreq->badcookie_retry + && netreq->response_opt /* actually: assert(netreq->response_opt) */ + && (netreq->response_opt[-4] << 4 | GLDNS_RCODE_WIRE(netreq->response)) + == GETDNS_RCODE_BADCOOKIE + && netreq->fd >= 0) { + + /* Retry over UDP with the newly learned Cookie */ + netreq->badcookie_retry = 1; + GETDNS_SCHEDULE_EVENT(dnsreq->loop, netreq->fd, + _getdns_ms_until_expiry(dnsreq->expires), + getdns_eventloop_event_init(&netreq->event, netreq, + NULL, stub_udp_write_cb, stub_timeout_cb)); + return; + } + _getdns_closesocket(netreq->fd); + netreq->fd = -1; + if (!dnsreq->context->round_robin_upstreams) dnsreq->upstreams->current_udp = 0; else { @@ -1426,7 +1546,7 @@ stub_udp_read_cb(void *userarg) netreq->debug_end_time = _getdns_get_time_as_uintt64(); _getdns_netreq_change_state(netreq, NET_REQ_FINISHED); upstream->udp_responses++; - upstream->back_off = 1; + upstream->back_off = 1; if (upstream->udp_responses == 1 || upstream->udp_responses % 100 == 0) _getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_INFO, @@ -1582,16 +1702,12 @@ upstream_read_cb(void *userarg) upstream->tcp.read_buf = NULL; upstream->responses_received++; - /* !THIS CODE NEEDS TESTING! */ if (netreq->owner->edns_cookies && - match_and_process_server_cookie( - netreq->upstream, upstream->tcp.read_buf, - upstream->tcp.read_pos - upstream->tcp.read_buf)) + match_and_process_server_cookie(netreq->upstream, netreq)) return; /* Client cookie didn't match (or FORMERR) */ if (netreq->owner->context->idle_timeout != 0) - process_keepalive(netreq->upstream, netreq, netreq->response, - netreq->response_len); + process_keepalive(netreq->upstream, netreq); netreq->debug_end_time = _getdns_get_time_as_uintt64(); /* This also reschedules events for the upstream*/ @@ -2053,7 +2169,8 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport, /* Use existing if available*/ if (upstream->fd != -1) return upstream->fd; - fd = tcp_connect(upstream, transport); + fd = tcp_connect(upstream, transport, + dnsreq->context->tcp_send_timeout); if (fd == -1) { upstream_failed(upstream, 1); return -1; diff --git a/src/sync.c b/src/sync.c index bcf66e6f..aae7fd81 100644 --- a/src/sync.c +++ b/src/sync.c @@ -154,7 +154,8 @@ getdns_sync_cb(getdns_context *context, getdns_callback_type_t callback_type, getdns_dict *response, void *userarg, getdns_transaction_t transaction_id) { getdns_sync_data *data = (getdns_sync_data *)userarg; - (void)context; (void)callback_type; (void)transaction_id; + (void)context; (void)callback_type; /* unused parameters */ + (void)transaction_id; /* unused parameter */ assert(data); diff --git a/src/test/check_getdns_cancel_callback.h b/src/test/check_getdns_cancel_callback.h index facf31bc..21e558cd 100644 --- a/src/test/check_getdns_cancel_callback.h +++ b/src/test/check_getdns_cancel_callback.h @@ -457,7 +457,7 @@ void *userarg, getdns_transaction_t transaction_id) { - (void)context; (void)response; (void)userarg; + (void)context; (void)response; (void)userarg; /* unused parameters */ callback_called++; @@ -466,23 +466,23 @@ callback_canceled++; ck_assert_msg(transaction_id % 2, "Only callbacks with odd transaction_ids were canceled, this one is even: %d", - transaction_id); + (int)transaction_id); } else if(callback_type == GETDNS_CALLBACK_COMPLETE) { callback_completed++; ck_assert_msg((transaction_id % 2) == 0, "One callbacks with even transaction_ids should complete, this one is odd: %d", - transaction_id); + (int)transaction_id); } else { if(transaction_id % 2) ck_abort_msg("callback_type should == GETDNS_CALLBACK_CANCEL for odd transaction_id (%d), got: %d", - transaction_id, callback_type); + (int)transaction_id, (int)callback_type); else ck_abort_msg("callback_type should == GETDNS_CALLBACK_COMPLETE for even transaction_id (%d), got %d", - transaction_id, callback_type); + (int)transaction_id, (int)callback_type); } } @@ -491,7 +491,7 @@ */ void verify_getdns_cancel_callback(struct extracted_response *ex_response) { - (void)ex_response; + (void)ex_response; /* unused parameter */ /* * increment callback_called global to prove callback was called. */ diff --git a/src/test/check_getdns_common.c b/src/test/check_getdns_common.c index 9816f8ff..6d0d05a5 100644 --- a/src/test/check_getdns_common.c +++ b/src/test/check_getdns_common.c @@ -57,6 +57,8 @@ int event_loop_type = 0; void extract_response(struct getdns_dict *response, struct extracted_response *ex_response) { int have_answer_type = 0; + int get_reply = 0; + uint32_t rcode; ck_assert_msg(response != NULL, "Response should not be NULL"); /* fprintf(stderr, "%s\n", getdns_pretty_print_dict(response)); */ @@ -103,10 +105,18 @@ void extract_response(struct getdns_dict *response, struct extracted_response *e ex_response->question = NULL; return; } + /* Work around dnsmasq issue in which NXDOMAIN AAAA responses + * are returned as NODATA. In such cases use the other A response + * which does have rcode NXDOMAIN. + */ + if (ex_response->status == GETDNS_RESPSTATUS_NO_NAME + && !getdns_dict_get_int(response, "/replies_tree/1/header/rcode", &rcode) + && rcode == GETDNS_RCODE_NXDOMAIN) + get_reply = 1; - ASSERT_RC(getdns_list_get_dict(ex_response->replies_tree, 0, &ex_response->replies_tree_sub_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree[0]\""); - ck_assert_msg(ex_response->replies_tree_sub_dict != NULL, "replies_tree[0] dict should not be NULL"); + ASSERT_RC(getdns_list_get_dict(ex_response->replies_tree, get_reply, &ex_response->replies_tree_sub_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree[#]\""); + ck_assert_msg(ex_response->replies_tree_sub_dict != NULL, "replies_tree[#] dict should not be NULL"); ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "additional", &ex_response->additional), GETDNS_RETURN_GOOD, "Failed to extract \"additional\""); @@ -186,7 +196,7 @@ void assert_nodata(struct extracted_response *ex_response) ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length); + ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", (int)length); ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_NO_NAME, "Unexpected value for \"status\""); } @@ -212,7 +222,7 @@ void assert_address_in_answer(struct extracted_response *ex_response, int a, int ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); + ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", (int)ancount, (int)length); for(i = 0; i < length; i++) { @@ -247,7 +257,7 @@ void assert_address_in_just_address_answers(struct extracted_response *ex_respon GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\" length"); if (length == 0) resp_str = getdns_pretty_print_dict(ex_response->response); - ck_assert_msg(length > 0, "Expected \"just_address_answers\" length > 0, got %d\n%s", length, resp_str); + ck_assert_msg(length > 0, "Expected \"just_address_answers\" length > 0, got %d\n%s", (int)length, resp_str); if (length == 0) free(resp_str); } @@ -284,7 +294,7 @@ void assert_soa_in_authority(struct extracted_response *ex_response) ASSERT_RC(getdns_list_get_length(ex_response->authority, &length), GETDNS_RETURN_GOOD, "Failed to extract \"authority\" length"); - ck_assert_msg(length == nscount, "Expected \"authority\" length == nscount: %d, got %d", nscount, length); + ck_assert_msg(length == nscount, "Expected \"authority\" length == nscount: %d, got %d", (int)nscount, (int)length); for(i = 0; i < length; i++) { @@ -318,7 +328,7 @@ void assert_ptr_in_answer(struct extracted_response *ex_response) ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); + ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", (int)ancount, (int)length); for(i = 0; i < length; i++) { @@ -339,7 +349,7 @@ void destroy_callbackfn(struct getdns_context *context, void *userarg, getdns_transaction_t transaction_id) { int* flag = (int*)userarg; - (void)callback_type; (void)transaction_id; + (void)callback_type; (void)transaction_id; /* unused parameters */ *flag = 1; getdns_dict_destroy(response); getdns_context_destroy(context); @@ -359,7 +369,7 @@ void callbackfn(struct getdns_context *context, { typedef void (*fn_ptr)(struct extracted_response *ex_response); fn_ptr fn = ((fn_cont *)userarg)->fn; - (void)context; (void)transaction_id; + (void)context; (void)transaction_id; /* unused parameters */ /* * If userarg is NULL, either a negative test case @@ -399,7 +409,7 @@ void callbackfn(struct getdns_context *context, void update_callbackfn(struct getdns_context *context, getdns_context_code_t changed_item) { - (void)context; + (void)context; /* unused parameter */ ck_assert_msg(changed_item == expected_changed_item, "Expected changed_item == %d, got %d", changed_item, expected_changed_item); diff --git a/src/test/check_getdns_context_destroy.h b/src/test/check_getdns_context_destroy.h index 65a0a8c3..fe3739dc 100644 --- a/src/test/check_getdns_context_destroy.h +++ b/src/test/check_getdns_context_destroy.h @@ -271,7 +271,7 @@ void verify_getdns_context_destroy(struct extracted_response *ex_response) { - (void)ex_response; + (void)ex_response; /* unused parameter */ /* * Sleep for a second to make getdns_context_destroy() wait. */ diff --git a/src/test/check_getdns_context_set_timeout.c b/src/test/check_getdns_context_set_timeout.c index edc0f346..e3a8de77 100644 --- a/src/test/check_getdns_context_set_timeout.c +++ b/src/test/check_getdns_context_set_timeout.c @@ -266,7 +266,7 @@ void timeout_3_cb(struct getdns_context *context, getdns_callback_type_t callback_type, struct getdns_dict * response, void *userarg, getdns_transaction_t transaction_id) { - (void)response; (void)transaction_id; + (void)response; (void)transaction_id; /* unused parameters */ timeout_thread_data *tdata = (timeout_thread_data*)userarg; tdata->num_callbacks++; if (callback_type == GETDNS_CALLBACK_TIMEOUT) { diff --git a/src/test/check_getdns_convert_alabel_to_ulabel.h b/src/test/check_getdns_convert_alabel_to_ulabel.h index b58ef41e..c3773c7f 100644 --- a/src/test/check_getdns_convert_alabel_to_ulabel.h +++ b/src/test/check_getdns_convert_alabel_to_ulabel.h @@ -44,7 +44,8 @@ char *alabel = NULL; ck_assert_msg( getdns_convert_alabel_to_ulabel( alabel ) == 0, - "Was not expecting %d from getdns_convert_alabel_to_ulabel()", getdns_convert_alabel_to_ulabel( alabel ) ); + "Was not expecting %p from getdns_convert_alabel_to_ulabel()", + (void *)getdns_convert_alabel_to_ulabel( alabel ) ); } END_TEST diff --git a/src/test/check_getdns_convert_ulabel_to_alabel.h b/src/test/check_getdns_convert_ulabel_to_alabel.h index 3af671f8..6a34c7d4 100644 --- a/src/test/check_getdns_convert_ulabel_to_alabel.h +++ b/src/test/check_getdns_convert_ulabel_to_alabel.h @@ -45,7 +45,8 @@ ck_assert_msg(( getdns_convert_ulabel_to_alabel( ulabel ) == 0 ), - "Was not expecting %d from getdns_convert_ulabel_to_alabel()", getdns_convert_ulabel_to_alabel( ulabel ) ); + "Was not expecting %p from getdns_convert_ulabel_to_alabel()", + (void *)getdns_convert_ulabel_to_alabel( ulabel ) ); } END_TEST diff --git a/src/test/check_getdns_dict_get_bindata.h b/src/test/check_getdns_dict_get_bindata.h index 60366983..874d124d 100644 --- a/src/test/check_getdns_dict_get_bindata.h +++ b/src/test/check_getdns_dict_get_bindata.h @@ -161,7 +161,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_bindata()"); ck_assert_msg(answer->size == bindata.size, "Expected bindata size == %d, got: %d", - bindata.size, answer->size); + (int)bindata.size, (int)answer->size); ck_assert_msg(strcmp((char *)answer->data, (char *)bindata.data) == 0, "Expected bindata data to be \"%s\", got: \"%s\"", (char *)bindata.data, (char *)answer->data); diff --git a/src/test/check_getdns_dict_get_names.h b/src/test/check_getdns_dict_get_names.h index 0881ad0f..4275d4fb 100644 --- a/src/test/check_getdns_dict_get_names.h +++ b/src/test/check_getdns_dict_get_names.h @@ -98,7 +98,7 @@ ASSERT_RC(getdns_list_get_length(answer, &length), GETDNS_RETURN_GOOD, "Return code from getdns_list_get_length()"); - ck_assert_msg(length == 3, "Expected length == 3, got %d", length); + ck_assert_msg(length == 3, "Expected length == 3, got %d", (int)length); for(i = 0; i < length; i++) { diff --git a/src/test/check_getdns_dict_set_bindata.h b/src/test/check_getdns_dict_set_bindata.h index ac51c3a5..c73030cf 100644 --- a/src/test/check_getdns_dict_set_bindata.h +++ b/src/test/check_getdns_dict_set_bindata.h @@ -112,9 +112,9 @@ ASSERT_RC(getdns_dict_get_bindata(this_dict, "bindata", &retrieved_bindata), GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_bindata()"); - ck_assert_msg(retrieved_bindata->size, second_bindata.size, + ck_assert_msg(retrieved_bindata->size == second_bindata.size, "Expected retrieved bindata size == %d, got: %d", - second_bindata.size, retrieved_bindata->size); + (int)second_bindata.size, (int)retrieved_bindata->size); ck_assert_msg(strcmp((char *)retrieved_bindata->data, (char *)second_bindata.data) == 0, "Expected retrieved bindata to be \"%s\", got: \"%s\"", @@ -152,7 +152,7 @@ ck_assert_msg(retrieved_bindata->size == bindata.size, "Expected retrieved bindata size == %d, got: %d", - bindata.size, retrieved_bindata->size); + (int)bindata.size, (int)retrieved_bindata->size); ck_assert_msg(strcmp((char *)retrieved_bindata->data, (char *)bindata.data) == 0, "Expected bindata data to be \"%s\", got: \"%s\"", diff --git a/src/test/check_getdns_display_ip_address.h b/src/test/check_getdns_display_ip_address.h index cc3694f6..cefb45a1 100644 --- a/src/test/check_getdns_display_ip_address.h +++ b/src/test/check_getdns_display_ip_address.h @@ -47,7 +47,7 @@ ptr = getdns_display_ip_address(NULL); ck_assert_msg(ptr == NULL, "Expected retrieved bindata == NULL, got: %p", - ptr); + (void *)ptr); } END_TEST @@ -64,7 +64,7 @@ ptr = getdns_display_ip_address(&bindata_of_ipv4_or_ipv6_address); ck_assert_msg(ptr == NULL, "Expected pointer == NULL, got: %p", - ptr); + (void *)ptr); } END_TEST diff --git a/src/test/check_getdns_libev.c b/src/test/check_getdns_libev.c index ffdc6e22..935e576b 100644 --- a/src/test/check_getdns_libev.c +++ b/src/test/check_getdns_libev.c @@ -53,7 +53,7 @@ void run_event_loop_impl(struct getdns_context* context, void* eventloop) { struct ev_loop* loop = (struct ev_loop*) eventloop; - (void)context; + (void)context; /* unused parameter */ ev_run(loop, 0); } diff --git a/src/test/check_getdns_libevent.c b/src/test/check_getdns_libevent.c index ee59854b..302b6895 100644 --- a/src/test/check_getdns_libevent.c +++ b/src/test/check_getdns_libevent.c @@ -49,7 +49,7 @@ void run_event_loop_impl(struct getdns_context* context, void* eventloop) { struct event_base* base = (struct event_base*) eventloop; - (void)context; + (void)context; /* unused parameter */ event_base_dispatch(base); } diff --git a/src/test/check_getdns_libuv.c b/src/test/check_getdns_libuv.c index 7aa88b51..96a1dcf4 100644 --- a/src/test/check_getdns_libuv.c +++ b/src/test/check_getdns_libuv.c @@ -49,7 +49,7 @@ void run_event_loop_impl(struct getdns_context* context, void* eventloop) { uv_loop_t* loop = (uv_loop_t*) eventloop; - (void)context; + (void)context; /* unused parameter */ uv_run(loop, UV_RUN_DEFAULT); } diff --git a/src/test/check_getdns_list_get_length.h b/src/test/check_getdns_list_get_length.h index 3ccb8551..e1bceb68 100644 --- a/src/test/check_getdns_list_get_length.h +++ b/src/test/check_getdns_list_get_length.h @@ -89,7 +89,7 @@ ASSERT_RC(getdns_list_get_length(list, &length), GETDNS_RETURN_GOOD, "Return code from getdns_list_get_length()"); - ck_assert_msg(length == 3, "Expected length == 3, got %d", length); + ck_assert_msg(length == 3, "Expected length == 3, got %d", (int)length); LIST_DESTROY(list); } @@ -110,7 +110,7 @@ ASSERT_RC(getdns_list_get_length(list, &length), GETDNS_RETURN_GOOD, "Return code from getdns_list_get_length()"); - ck_assert_msg(length == 0, "Expected length == 3, got %d", length); + ck_assert_msg(length == 0, "Expected length == 3, got %d", (int)length); LIST_DESTROY(list); } diff --git a/src/test/check_getdns_selectloop.c b/src/test/check_getdns_selectloop.c index c315b30c..a126e4db 100644 --- a/src/test/check_getdns_selectloop.c +++ b/src/test/check_getdns_selectloop.c @@ -37,11 +37,11 @@ #include "getdns/getdns_extra.h" void run_event_loop_impl(struct getdns_context* context, void* eventloop) { - (void)eventloop; + (void)eventloop; /* unused parameter */ getdns_context_run(context); } void* create_eventloop_impl(struct getdns_context* context) { - (void)context; + (void)context; /* unused parameter */ return NULL; } diff --git a/src/test/check_getdns_transport.c b/src/test/check_getdns_transport.c index 300abc4d..8013d3b2 100644 --- a/src/test/check_getdns_transport.c +++ b/src/test/check_getdns_transport.c @@ -211,8 +211,8 @@ void transport_cb(struct getdns_context *context, struct getdns_dict * response, void *userarg, getdns_transaction_t transaction_id) { /* Don't really care about the answer*/ - (void)context; (void)callback_type; (void)response; - (void)userarg; (void)transaction_id; + (void)context; (void)callback_type; (void)response; /* unused parameters */ + (void)userarg; (void)transaction_id; /* unused parameters */ return; } diff --git a/src/test/tests_stub_async.c b/src/test/tests_stub_async.c index 6d3f78ca..6a16c0fe 100644 --- a/src/test/tests_stub_async.c +++ b/src/test/tests_stub_async.c @@ -57,7 +57,7 @@ this_callbackfn(struct getdns_context *this_context, struct getdns_dict *this_response, void *this_userarg, getdns_transaction_t this_transaction_id) { - (void)this_context; (void)this_userarg; + (void)this_context; (void)this_userarg; /* unused parameters */ if (this_callback_type == GETDNS_CALLBACK_COMPLETE) { /* This is a callback with data */ char *res = getdns_pretty_print_dict(this_response); diff --git a/src/test/tpkg/200-stub-only-compile-install.tpkg/200-stub-only-compile-install.pre b/src/test/tpkg/200-stub-only-compile-install.tpkg/200-stub-only-compile-install.pre index 2f541a53..5e2c5d1c 100644 --- a/src/test/tpkg/200-stub-only-compile-install.tpkg/200-stub-only-compile-install.pre +++ b/src/test/tpkg/200-stub-only-compile-install.tpkg/200-stub-only-compile-install.pre @@ -17,4 +17,4 @@ rm -fr "${BUILDDIR}/build-stub-only" mkdir "${BUILDDIR}/build-stub-only" cd "${BUILDDIR}/build-stub-only" rm -f CMakeCache.txt -cmake -E env CXXFLAGS="-g" cmake -DENABLE_STUB_ONLY=ON -DENABLE_DEBUG_SERVER=ON -DENABLE_DEBUG_ANCHOR=ON -DCMAKE_INSTALL_PREFIX=../install-stub-only $* ${SRCROOT} +cmake -E env CXXFLAGS="-g" cmake -DUSE_GNUTLS=OFF -DENABLE_STUB_ONLY=ON -DENABLE_DEBUG_SERVER=ON -DENABLE_DEBUG_ANCHOR=ON -DCMAKE_INSTALL_PREFIX=../install-stub-only $* ${SRCROOT} diff --git a/src/test/tpkg/225-stub-only-valgrind-checks.tpkg/225-stub-only-valgrind-checks.queries b/src/test/tpkg/225-stub-only-valgrind-checks.tpkg/225-stub-only-valgrind-checks.queries index da6d6535..741a35cc 100644 --- a/src/test/tpkg/225-stub-only-valgrind-checks.tpkg/225-stub-only-valgrind-checks.queries +++ b/src/test/tpkg/225-stub-only-valgrind-checks.tpkg/225-stub-only-valgrind-checks.queries @@ -5,3 +5,5 @@ qwerlkjhasdfpuiqwyerm.1234kjhrqwersv.com -H 8.8.8.8 -H 2a04:b900:0:100::37 -A _acme-challenge.getdnsapi.net +@185.49.141.38 nlnetlabs.nl +edns_cookies +-L dnsprivacy.org diff --git a/src/test/tpkg/225-stub-only-valgrind-checks.tpkg/225-stub-only-valgrind-checks.supp b/src/test/tpkg/225-stub-only-valgrind-checks.tpkg/225-stub-only-valgrind-checks.supp index f9654d70..e73ee67e 100644 --- a/src/test/tpkg/225-stub-only-valgrind-checks.tpkg/225-stub-only-valgrind-checks.supp +++ b/src/test/tpkg/225-stub-only-valgrind-checks.tpkg/225-stub-only-valgrind-checks.supp @@ -100,3 +100,19 @@ obj:/usr/local/lib/libunbound.so.8.1.5 obj:/usr/local/lib/libunbound.so.8.1.5 } +{ + + Memcheck:Cond + obj:/usr/lib/x86_64-linux-gnu/libgnutls.so.* + obj:/usr/lib/x86_64-linux-gnu/libgnutls.so.* + obj:/usr/lib/x86_64-linux-gnu/libgnutls.so.* + obj:/usr/lib/x86_64-linux-gnu/libgnutls.so.* + obj:/usr/lib/x86_64-linux-gnu/libgnutls.so.* + fun:gnutls_x509_ext_import_subject_alt_names + fun:gnutls_x509_crt_import + fun:gnutls_x509_crt_list_import + fun:gnutls_x509_crt_list_import2 + fun:gnutls_x509_trust_list_add_trust_mem + fun:gnutls_x509_trust_list_add_trust_file + fun:gnutls_x509_trust_list_add_system_trust +} diff --git a/src/test/tpkg/265-supported-rrs.tpkg/265-supported-rrs.test b/src/test/tpkg/265-supported-rrs.tpkg/265-supported-rrs.test index 30636390..d97b013a 100644 --- a/src/test/tpkg/265-supported-rrs.tpkg/265-supported-rrs.test +++ b/src/test/tpkg/265-supported-rrs.tpkg/265-supported-rrs.test @@ -11,5 +11,5 @@ elif ! ( "./${TPKG_NAME}" "${TPKG_NAME}.net-dns.org" | tee out ) then exit 1 else - diff out "${TPKG_NAME}.good" + diff out "${TPKG_NAME}.good" --ignore-matching-lines=";; MSG SIZE rcvd: " fi diff --git a/src/test/tpkg/270-header-extension.tpkg/270-header-extension.c b/src/test/tpkg/270-header-extension.tpkg/270-header-extension.c index 8c344304..4d94a450 100644 --- a/src/test/tpkg/270-header-extension.tpkg/270-header-extension.c +++ b/src/test/tpkg/270-header-extension.tpkg/270-header-extension.c @@ -9,10 +9,6 @@ int main() getdns_return_t r; getdns_context *ctx = NULL; getdns_dict *extensions = NULL; - getdns_bindata ipv4 = { 4, (uint8_t*)"IPv4" }; - /* 185.49.141.37 */ - getdns_bindata nsip = { 4, (uint8_t*)"\xb9\x31\x8c\x3c" }; - getdns_dict *upstream = NULL; getdns_list *upstreams = NULL; getdns_dict *response = NULL; uint32_t value; @@ -21,39 +17,20 @@ int main() if ((r = getdns_context_create(&ctx, 1))) fprintf(stderr, "Could not create context"); - else if (!(extensions = getdns_dict_create_with_context(ctx))) { - fprintf(stderr, "Could not create dictionary"); - r = GETDNS_RETURN_MEMORY_ERROR; - - } else if ((r = getdns_dict_set_int(extensions, "/header/rd", 0))) - fprintf(stderr, "Could not set RD bit"); - - else if ((r = getdns_dict_set_int(extensions, "/add_opt_parameters/do_bit", 1))) - fprintf(stderr, "Could not set qtype"); - - else if (!(upstream = getdns_dict_create_with_context(ctx))) { - fprintf(stderr, "Could not create upstream dictionary"); - r = GETDNS_RETURN_MEMORY_ERROR; - - } else if ((r = getdns_dict_set_bindata(upstream, "address_type", &ipv4))) - fprintf(stderr, "Could set \"address_type\""); - - else if ((r = getdns_dict_set_bindata(upstream, "address_data", &nsip))) - fprintf(stderr, "Could set \"address_data\""); - - else if (!(upstreams = getdns_list_create_with_context(ctx))) { - fprintf(stderr, "Could not create upstreams list"); - r = GETDNS_RETURN_MEMORY_ERROR; - - } else if ((r = getdns_list_set_dict(upstreams, 0, upstream))) - fprintf(stderr, "Could not append upstream to upstreams list"); - else if ((r = getdns_context_set_resolution_type(ctx, GETDNS_RESOLUTION_STUB))) fprintf(stderr, "Could not set stub mode"); + else if ((r = getdns_str2list("[ 185.49.140.60 ]", &upstreams))) + fprintf(stderr, "Could not make upstreams list"); + else if ((r = getdns_context_set_upstream_recursive_servers(ctx, upstreams))) fprintf(stderr, "Could not set upstreams list"); + else if ((r = getdns_str2dict("{ header: { rd: 0 }" + ", add_opt_parameters: { do_bit: 1 }" + "}", &extensions))) + fprintf(stderr, "Could not create extensions"); + else if ((r = getdns_general_sync(ctx, "bogus.nlnetlabs.nl.", GETDNS_RRTYPE_TXT, extensions, &response))) fprintf(stderr, "Could not do lookup"); @@ -61,7 +38,8 @@ int main() fprintf(stderr, "Could not get status from response"); else if (value != GETDNS_RESPSTATUS_GOOD) { - fprintf(stderr, "response['status'] != GETDNS_RESPSTATUS_GOOD"); + fprintf(stderr, "response['status'] != GETDNS_RESPSTATUS_GOOD: %s" + , getdns_get_errorstr_by_id(value)); r = GETDNS_RETURN_GENERIC_ERROR; } else if ((r = getdns_dict_get_int(response, "/replies_tree/0/header/rd", &value))) @@ -100,8 +78,6 @@ int main() getdns_dict_destroy(response); if (upstreams) getdns_list_destroy(upstreams); - if (upstream) - getdns_dict_destroy(upstream); if (extensions) getdns_dict_destroy(extensions); if (ctx) diff --git a/src/test/tpkg/290-transports.tpkg/290-transports.test b/src/test/tpkg/290-transports.tpkg/290-transports.test index 28cef8e8..bbec46d6 100644 --- a/src/test/tpkg/290-transports.tpkg/290-transports.test +++ b/src/test/tpkg/290-transports.tpkg/290-transports.test @@ -199,7 +199,7 @@ for (( ii = 0; ii < 1; ii++)); do echo "*Success fallback cases:" for (( j = 0; j < $NUM_GOOD_FB_QUERIES; j+=1 )); do - check_good "`"${GETDNS_STUB_QUERY}" -V +return_call_reporting $SYNC_MODE ${GOOD_FALLBACK_QUERIES[$j*$NUM_ARGS]} 2>/dev/null`" ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+2]} + check_good "`"${GETDNS_STUB_QUERY}" '{tcp_send_timeout:1000}' -y 7 -V +return_call_reporting $SYNC_MODE ${GOOD_FALLBACK_QUERIES[$j*$NUM_ARGS]} 2>/dev/null`" ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+2]} echo "getdns_query $SYNC_MODE ${GOOD_FALLBACK_QUERIES[$j*$NUM_ARGS]} TESTS: ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+2]}" (( COUNT++ )) done diff --git a/src/tls/val_secalgo.c b/src/tls/val_secalgo.c index d8c44f6f..7e91f942 100644 --- a/src/tls/val_secalgo.c +++ b/src/tls/val_secalgo.c @@ -72,6 +72,10 @@ #include #endif +#if defined(HAVE_OPENSSL_DSA_H) && defined(USE_DSA) +#include +#endif + /** fake DSA support for unit tests */ int fake_dsa = 0; /** fake SHA1 support for unit tests */ @@ -138,6 +142,69 @@ secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) #endif } +/** hash structure for keeping track of running hashes */ +struct secalgo_hash { + /** the openssl message digest context */ + EVP_MD_CTX* ctx; +}; + +/** create secalgo hash with hash type */ +static struct secalgo_hash* secalgo_hash_create_md(const EVP_MD* md) +{ + struct secalgo_hash* h; + if(!md) + return NULL; + h = calloc(1, sizeof(*h)); + if(!h) + return NULL; + h->ctx = EVP_MD_CTX_create(); + if(!h->ctx) { + free(h); + return NULL; + } + if(!EVP_DigestInit_ex(h->ctx, md, NULL)) { + EVP_MD_CTX_destroy(h->ctx); + free(h); + return NULL; + } + return h; +} + +struct secalgo_hash* secalgo_hash_create_sha384(void) +{ + return secalgo_hash_create_md(EVP_sha384()); +} + +struct secalgo_hash* secalgo_hash_create_sha512(void) +{ + return secalgo_hash_create_md(EVP_sha512()); +} + +int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len) +{ + return EVP_DigestUpdate(hash->ctx, (unsigned char*)data, + (unsigned int)len); +} + +int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result, + size_t maxlen, size_t* resultlen) +{ + if(EVP_MD_CTX_size(hash->ctx) > (int)maxlen) { + *resultlen = 0; + log_err("secalgo_hash_final: hash buffer too small"); + return 0; + } + *resultlen = EVP_MD_CTX_size(hash->ctx); + return EVP_DigestFinal_ex(hash->ctx, result, NULL); +} + +void secalgo_hash_delete(struct secalgo_hash* hash) +{ + if(!hash) return; + EVP_MD_CTX_destroy(hash->ctx); + free(hash); +} + /** * Return size of DS digest according to its hash algorithm. * @param algo: DS digest algo. @@ -327,8 +394,10 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len) #ifdef HAVE_DSA_SIG_SET0 if(!DSA_SIG_set0(dsasig, R, S)) return 0; #else +# ifndef S_SPLINT_S dsasig->r = R; dsasig->s = S; +# endif /* S_SPLINT_S */ #endif *sig = NULL; newlen = i2d_DSA_SIG(dsasig, sig); @@ -818,6 +887,64 @@ secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) (void)HASH_HashBuf(HASH_AlgSHA256, res, buf, (unsigned long)len); } +/** the secalgo hash structure */ +struct secalgo_hash { + /** hash context */ + HASHContext* ctx; +}; + +/** create hash struct of type */ +static struct secalgo_hash* secalgo_hash_create_type(HASH_HashType tp) +{ + struct secalgo_hash* h = calloc(1, sizeof(*h)); + if(!h) + return NULL; + h->ctx = HASH_Create(tp); + if(!h->ctx) { + free(h); + return NULL; + } + return h; +} + +struct secalgo_hash* secalgo_hash_create_sha384(void) +{ + return secalgo_hash_create_type(HASH_AlgSHA384); +} + +struct secalgo_hash* secalgo_hash_create_sha512(void) +{ + return secalgo_hash_create_type(HASH_AlgSHA512); +} + +int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len) +{ + HASH_Update(hash->ctx, (unsigned char*)data, (unsigned int)len); + return 1; +} + +int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result, + size_t maxlen, size_t* resultlen) +{ + unsigned int reslen = 0; + if(HASH_ResultLenContext(hash->ctx) > (unsigned int)maxlen) { + *resultlen = 0; + log_err("secalgo_hash_final: hash buffer too small"); + return 0; + } + HASH_End(hash->ctx, (unsigned char*)result, &reslen, + (unsigned int)maxlen); + *resultlen = (size_t)reslen; + return 1; +} + +void secalgo_hash_delete(struct secalgo_hash* hash) +{ + if(!hash) return; + HASH_Destroy(hash->ctx); + free(hash); +} + size_t ds_digest_size_supported(int algo) { @@ -985,6 +1112,7 @@ static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo) return pk; } +#if defined(USE_DSA) && defined(USE_SHA1) static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len) { SECKEYPublicKey* pk; @@ -1045,6 +1173,7 @@ static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len) } return pk; } +#endif /* USE_DSA && USE_SHA1 */ static SECKEYPublicKey* nss_buf2rsa(unsigned char* key, size_t len) { @@ -1444,6 +1573,82 @@ secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) _digest_nettle(SHA256_DIGEST_SIZE, (uint8_t*)buf, len, res); } +/** secalgo hash structure */ +struct secalgo_hash { + /** if it is 384 or 512 */ + int active; + /** context for sha384 */ + struct sha384_ctx ctx384; + /** context for sha512 */ + struct sha512_ctx ctx512; +}; + +struct secalgo_hash* secalgo_hash_create_sha384(void) +{ + struct secalgo_hash* h = calloc(1, sizeof(*h)); + if(!h) + return NULL; + h->active = 384; + sha384_init(&h->ctx384); + return h; +} + +struct secalgo_hash* secalgo_hash_create_sha512(void) +{ + struct secalgo_hash* h = calloc(1, sizeof(*h)); + if(!h) + return NULL; + h->active = 512; + sha512_init(&h->ctx512); + return h; +} + +int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len) +{ + if(hash->active == 384) { + sha384_update(&hash->ctx384, len, data); + } else if(hash->active == 512) { + sha512_update(&hash->ctx512, len, data); + } else { + return 0; + } + return 1; +} + +int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result, + size_t maxlen, size_t* resultlen) +{ + if(hash->active == 384) { + if(SHA384_DIGEST_SIZE > maxlen) { + *resultlen = 0; + log_err("secalgo_hash_final: hash buffer too small"); + return 0; + } + *resultlen = SHA384_DIGEST_SIZE; + sha384_digest(&hash->ctx384, SHA384_DIGEST_SIZE, + (unsigned char*)result); + } else if(hash->active == 512) { + if(SHA512_DIGEST_SIZE > maxlen) { + *resultlen = 0; + log_err("secalgo_hash_final: hash buffer too small"); + return 0; + } + *resultlen = SHA512_DIGEST_SIZE; + sha512_digest(&hash->ctx512, SHA512_DIGEST_SIZE, + (unsigned char*)result); + } else { + *resultlen = 0; + return 0; + } + return 1; +} + +void secalgo_hash_delete(struct secalgo_hash* hash) +{ + if(!hash) return; + free(hash); +} + /** * Return size of DS digest according to its hash algorithm. * @param algo: DS digest algo. @@ -1508,13 +1713,21 @@ dnskey_algo_id_is_supported(int id) { /* uses libnettle */ switch(id) { -#if defined(USE_DSA) && defined(USE_SHA1) case LDNS_DSA: case LDNS_DSA_NSEC3: +#if defined(USE_DSA) && defined(USE_SHA1) + return 1; +#else + if(fake_dsa || fake_sha1) return 1; + return 0; #endif -#ifdef USE_SHA1 case LDNS_RSASHA1: case LDNS_RSASHA1_NSEC3: +#ifdef USE_SHA1 + return 1; +#else + if(fake_sha1) return 1; + return 0; #endif #ifdef USE_SHA2 case LDNS_RSASHA256: @@ -1741,6 +1954,7 @@ _verify_nettle_ecdsa(sldns_buffer* buf, unsigned int digest_size, unsigned char* res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature); mpz_clear(x); mpz_clear(y); + nettle_ecc_point_clear(&pubkey); break; } case SHA384_DIGEST_SIZE: @@ -1827,6 +2041,15 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, return sec_status_bogus; } +#ifndef USE_DSA + if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1)) + return sec_status_secure; +#endif +#ifndef USE_SHA1 + if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3)) + return sec_status_secure; +#endif + switch(algo) { #if defined(USE_DSA) && defined(USE_SHA1) case LDNS_DSA: diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 636292c5..013b9807 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -366,7 +366,7 @@ void callback(getdns_context *context, getdns_callback_type_t callback_type, getdns_dict *response, void *userarg, getdns_transaction_t trans_id) { char *response_str; - (void)context; (void)userarg; + (void)context; (void)userarg; /* unused parameters */ /* This is a callback with data */; if (response && !quiet && (response_str = json ? @@ -1440,7 +1440,7 @@ static void request_cb( dns_msg *msg = (dns_msg *)userarg; uint32_t qid; getdns_return_t r = GETDNS_RETURN_GOOD; - uint32_t n, rcode, dnssec_status; + uint32_t n, rcode, dnssec_status = GETDNS_DNSSEC_INDETERMINATE; #if defined(SERVER_DEBUG) && SERVER_DEBUG getdns_bindata *qname; @@ -1457,7 +1457,7 @@ static void request_cb( if (qname_str != unknown_qname) free(qname_str); #else - (void)transaction_id; + (void)transaction_id; /* unused parameter */ #endif assert(msg); @@ -1556,8 +1556,8 @@ static void incoming_request_handler(getdns_context *context, getdns_dict *rr; uint32_t rr_type; - (void)callback_type; - (void)userarg; + (void)callback_type; /* unused parameter */ + (void)userarg; /* unused parameter */ if (!query_extensions_spc && !(query_extensions_spc = getdns_dict_create())) @@ -1757,7 +1757,7 @@ static void _getdns_query_log(void *userarg, uint64_t system, gmtime_r(&tv.tv_sec, &tm); #endif strftime(buf, 10, "%H:%M:%S", &tm); - (void)userarg; (void)system; (void)level; + (void)userarg; (void)system; (void)level; /* unused parameters */ (void) fprintf(stderr, "[%s.%.6d] UPSTREAM ", buf, (int)tv.tv_usec); (void) vfprintf(stderr, fmt, ap); } diff --git a/src/tools/getdns_server_mon.c b/src/tools/getdns_server_mon.c index a11ed55e..5486268d 100644 --- a/src/tools/getdns_server_mon.c +++ b/src/tools/getdns_server_mon.c @@ -1569,10 +1569,10 @@ static void out_of_order_callback(getdns_context *context, void *userarg, getdns_transaction_t transaction_id) { - (void) context; - (void) callback_type; - (void) response; - (void) transaction_id; + (void) context; /* unused parameter */ + (void) callback_type; /* unused parameter */ + (void) response; /* unused parameter */ + (void) transaction_id; /* unused parameter */ struct async_query *query = (struct async_query *) userarg; static unsigned callback_no; @@ -1717,7 +1717,7 @@ int main(int ac, char *av[]) bool use_tcp = false; bool use_tls = false; - (void) ac; + (void) ac; /* unused parameter */ test_info.errout = stderr; atexit(exit_tidy); diff --git a/src/types-internal.h b/src/types-internal.h index 12489e9c..302595ce 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -233,8 +233,6 @@ typedef struct getdns_network_req int edns_maximum_udp_payload_size; uint16_t max_udp_payload_size; - size_t keepalive_sent; - /* Network requests scheduled to write after me */ struct getdns_network_req *write_queue_tail; @@ -244,7 +242,13 @@ typedef struct getdns_network_req getdns_auth_state_t debug_tls_auth_status; getdns_bindata debug_tls_peer_cert; const char *debug_tls_version; - size_t debug_udp; + + /* Some booleans */ + unsigned debug_udp : 1; + unsigned keepalive_sent : 1; + unsigned badcookie_retry: 1; + unsigned cookie_sent : 1; + uint8_t client_cookie[8]; /* When more space is needed for the wire_data response than is * available in wire_data[], it will be allocated separately. @@ -267,6 +271,7 @@ typedef struct getdns_network_req size_t base_query_option_sz; size_t response_len; uint8_t *response; + const uint8_t *response_opt; /* offset of OPT RR in response */ size_t wire_data_sz; uint8_t wire_data[]; diff --git a/src/ub_loop.c b/src/ub_loop.c index eaf55490..0bd48108 100644 --- a/src/ub_loop.c +++ b/src/ub_loop.c @@ -122,13 +122,13 @@ typedef struct my_event { static void my_event_base_free(struct ub_event_base* base) { /* We don't allocate our event base, so no need to free */ - (void)base; + (void)base; /* unused parameter */ return; } static int my_event_base_dispatch(struct ub_event_base* base) { - (void)base; + (void)base; /* unused parameter */ /* We run the event loop extension for which this ub_event_base is an * interface ourselfs, so no need to let libunbound call dispatch. */ @@ -138,7 +138,7 @@ static int my_event_base_dispatch(struct ub_event_base* base) static int my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv) { - (void)tv; + (void)tv; /* unused parameter */ /* Not sure when this will be called. But it is of no influence as we * run the event loop ourself. */ @@ -353,7 +353,7 @@ static int my_timer_del(struct ub_event* ev) static int my_signal_add(struct ub_event* ub_ev, struct timeval* tv) { - (void)ub_ev; (void)tv; + (void)ub_ev; (void)tv; /* unused parameters */ /* Only unbound daaemon workers use signals */ DEBUG_SCHED("UB_LOOP ERROR: signal_add()\n"); return -1; @@ -361,7 +361,7 @@ static int my_signal_add(struct ub_event* ub_ev, struct timeval* tv) static int my_signal_del(struct ub_event* ub_ev) { - (void)ub_ev; + (void)ub_ev; /* unused parameter */ /* Only unbound daaemon workers use signals */ DEBUG_SCHED("UB_LOOP ERROR: signal_del()\n"); return -1; @@ -370,13 +370,13 @@ static int my_signal_del(struct ub_event* ub_ev) static void my_winsock_unregister_wsaevent(struct ub_event* ev) { /* wsa events don't get registered with libunbound */ - (void)ev; + (void)ev; /* unused parameter */ } static void my_winsock_tcp_wouldblock(struct ub_event* ev, int bits) { #ifndef USE_WINSOCK - (void)ev; (void)bits; + (void)ev; (void)bits; /* unused parameters */ #else if (bits & UB_EV_READ) AS_MY_EVENT(ev)->read_wouldblock = 1; @@ -434,7 +434,7 @@ static struct ub_event* my_signal_new(struct ub_event_base* base, int fd, void (*cb)(int, short, void*), void* arg) { /* Not applicable, because in unbound used in the daemon only */ - (void)base; (void)fd; (void)cb; (void)arg; + (void)base; (void)fd; (void)cb; (void)arg; /* unused parameters */ return NULL; } @@ -442,7 +442,7 @@ static struct ub_event* my_winsock_register_wsaevent(struct ub_event_base *b, void* wsaevent, void (*cb)(int, short, void*), void* arg) { /* Not applicable, because in unbound used for tubes only */ - (void)b; (void)wsaevent; (void)cb; (void)arg; + (void)b; (void)wsaevent; (void)cb; (void)arg; /* unused parameters */ return NULL; } diff --git a/src/util-internal.c b/src/util-internal.c index 62aaf226..3b6971d8 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -299,9 +299,10 @@ _getdns_rr_iter2rr_dict_canonical( } } else if (rdf->rdd_pos->type == GETDNS_RDF_SPECIAL) val_type = wf_special; - else - assert(((val_type = wf_int), 0)); - + else { + val_type = wf_int; + assert(0); + } if (! rdf->rdd_repeat) { switch (val_type) { case wf_int: @@ -642,6 +643,12 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, rr_type == GETDNS_RRTYPE_RRSIG && rrsigs_in_answer) *rrsigs_in_answer = 1; + if (section == SECTION_ADDITIONAL && + rr_type == GETDNS_RRTYPE_OPT && + getdns_dict_set_int( result, "/header/extended_rcode" + , (uint32_t)rr_iter->rr_type[4] << 4 + | GLDNS_RCODE_WIRE(req->response))) + goto error; if (section != SECTION_ANSWER) { if (_getdns_list_append_this_dict( sections[section], rr_dict)) @@ -1402,7 +1409,7 @@ getdns_return_t getdns_apply_network_result(getdns_network_req* netreq, int rcode, void *pkt, int pkt_len, int sec, char* why_bogus) { - (void)why_bogus; + (void)why_bogus; /* unused parameter */ netreq->dnssec_status = sec == 0 ? GETDNS_DNSSEC_INSECURE : sec == 2 ? GETDNS_DNSSEC_SECURE diff --git a/src/util-internal.h b/src/util-internal.h index 8a1a6d82..af1e5b71 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -213,6 +213,17 @@ INLINE uint64_t _getdns_ms_until_expiry(uint64_t expires) return now_ms >= expires ? 0 : expires - now_ms; } +INLINE uint64_t _getdns_get_now_ms2(uint64_t *now_ms) +{ + struct timeval tv; + + if (!now_ms) return _getdns_get_now_ms(); + if (*now_ms) return *now_ms; + + (void) gettimeofday(&tv, NULL); + return (*now_ms = (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000); +} + INLINE uint64_t _getdns_ms_until_expiry2(uint64_t expires, uint64_t *now_ms) { if (*now_ms == 0) *now_ms = _getdns_get_now_ms(); diff --git a/src/util/import.sh b/src/util/import.sh index 49050268..08e38b9a 100755 --- a/src/util/import.sh +++ b/src/util/import.sh @@ -1,10 +1,10 @@ #!/bin/sh -REPO=http://unbound.net/svn/trunk +REPO=https://raw.githubusercontent.com/NLnetLabs/unbound/master wget -O rbtree.c ${REPO}/util/rbtree.c wget -O orig-headers/rbtree.h ${REPO}/util/rbtree.h -wget -O val_secalgo.c ${REPO}/validator/val_secalgo.c +wget -O ../tls/val_secalgo.c ${REPO}/validator/val_secalgo.c wget -O orig-headers/val_secalgo.h ${REPO}/validator/val_secalgo.h wget -O lruhash.c ${REPO}/util/storage/lruhash.c wget -O orig-headers/lruhash.h ${REPO}/util/storage/lruhash.h diff --git a/src/util/locks.c b/src/util/locks.c index e6e848a2..b65a02bd 100644 --- a/src/util/locks.c +++ b/src/util/locks.c @@ -42,7 +42,6 @@ #include "config.h" #include "util/locks.h" #include -#include #ifdef HAVE_SYS_WAIT_H #include #endif diff --git a/src/util/lookup3.c b/src/util/lookup3.c index 46e56271..5a826193 100644 --- a/src/util/lookup3.c +++ b/src/util/lookup3.c @@ -1,4 +1,7 @@ /* + May 2019(Wouter) patch to enable the valgrind clean implementation all the + time. This enables better security audit and checks, which is better + than the speedup. Git issue #30. Renamed the define ARRAY_CLEAN_ACCESS. February 2013(Wouter) patch defines for BSD endianness, from Brad Smith. January 2012(Wouter) added randomised initial value, fallout from 28c3. March 2007(Wouter) adapted from lookup3.c original, add config.h include. @@ -44,6 +47,7 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy. ------------------------------------------------------------------------------- */ /*#define SELF_TEST 1*/ +#define ARRAY_CLEAN_ACCESS 1 #include "config.h" #include "util/storage/lookup3.h" @@ -59,50 +63,8 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy. # define HASH_BIG_ENDIAN 0 # endif #else -#ifdef HAVE_SYS_TYPES_H -# include /* attempt to define endianness (solaris) */ -#endif -#if defined(linux) || defined(__OpenBSD__) -# ifdef HAVE_ENDIAN_H -# include /* attempt to define endianness */ -# else -# include /* on older OpenBSD */ -# endif -#endif -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -#include /* attempt to define endianness */ -#endif - -/* - * My best guess at if you are big-endian or little-endian. This may - * need adjustment. - */ -#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ - __BYTE_ORDER == __LITTLE_ENDIAN) || \ - (defined(i386) || defined(__i386__) || defined(__i486__) || \ - defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL) || defined(__x86)) -# define HASH_LITTLE_ENDIAN 1 -# define HASH_BIG_ENDIAN 0 -#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ - __BYTE_ORDER == __BIG_ENDIAN) || \ - (defined(sparc) || defined(__sparc) || defined(__sparc__) || defined(POWERPC) || defined(mc68000) || defined(sel)) -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 1 -#elif defined(_MACHINE_ENDIAN_H_) -/* test for machine_endian_h protects failure if some are empty strings */ -# if defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && _BYTE_ORDER == _BIG_ENDIAN -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 1 -# endif -# if defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && _BYTE_ORDER == _LITTLE_ENDIAN -# define HASH_LITTLE_ENDIAN 1 -# define HASH_BIG_ENDIAN 0 -# endif /* _MACHINE_ENDIAN_H_ */ -#else -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 0 -#endif -#endif /* defined(TARGET_IS_BIG_ENDIAN) */ +# error "Target endianness required." +#endif /* defined(HAVE_TARGET_ENDIANNESS) */ /* random initial value */ static uint32_t raninit = (uint32_t)0xdeadbeef; @@ -345,7 +307,7 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) u.ptr = key; if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ -#ifdef VALGRIND +#ifdef ARRAY_CLEAN_ACCESS const uint8_t *k8; #endif @@ -370,7 +332,7 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) * still catch it and complain. The masking trick does make the hash * noticeably faster for short strings (like English words). */ -#ifndef VALGRIND +#ifndef ARRAY_CLEAN_ACCESS switch(length) { diff --git a/src/util/lruhash.c b/src/util/lruhash.c index 2c21ad2d..0968663e 100644 --- a/src/util/lruhash.c +++ b/src/util/lruhash.c @@ -40,8 +40,6 @@ * */ -#include - #include "config.h" #include "util/storage/lruhash.h" #include "util/fptr_wlist.h" @@ -401,12 +399,12 @@ lruhash_remove(struct lruhash* table, hashvalue_type hash, void* key) } table->num--; table->space_used -= (*table->sizefunc)(entry->key, entry->data); - lock_quick_unlock(&table->lock); lock_rw_wrlock(&entry->lock); if(table->markdelfunc) (*table->markdelfunc)(entry->key); lock_rw_unlock(&entry->lock); lock_quick_unlock(&bin->lock); + lock_quick_unlock(&table->lock); /* finish removal */ d = entry->data; (*table->delkeyfunc)(entry->key, table->cb_arg); diff --git a/src/util/orig-headers/locks.h b/src/util/orig-headers/locks.h index 7e61bcc0..d86ee492 100644 --- a/src/util/orig-headers/locks.h +++ b/src/util/orig-headers/locks.h @@ -36,8 +36,6 @@ #ifndef UTIL_LOCKS_H #define UTIL_LOCKS_H -#include - /** * \file * Locking primitives. @@ -221,7 +219,6 @@ void* ub_thread_key_get(ub_thread_key_type key); #else /* we do not HAVE_SOLARIS_THREADS and no PTHREADS */ /******************* WINDOWS THREADS ************************/ #ifdef HAVE_WINDOWS_THREADS -#include #include /* Use a mutex */ diff --git a/src/util/orig-headers/val_secalgo.h b/src/util/orig-headers/val_secalgo.h index 52aaeb9f..8b6080dc 100644 --- a/src/util/orig-headers/val_secalgo.h +++ b/src/util/orig-headers/val_secalgo.h @@ -43,6 +43,7 @@ #ifndef VALIDATOR_VAL_SECALGO_H #define VALIDATOR_VAL_SECALGO_H struct sldns_buffer; +struct secalgo_hash; /** Return size of nsec3 hash algorithm, 0 if not supported */ size_t nsec3_hash_algo_size_supported(int id); @@ -67,6 +68,48 @@ int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, */ void secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res); +/** + * Start a hash of type sha384. Allocates structure, then inits it, + * so that a series of updates can be performed, before the final result. + * @return hash structure. NULL on malloc failure or no support. + */ +struct secalgo_hash* secalgo_hash_create_sha384(void); + +/** + * Start a hash of type sha512. Allocates structure, then inits it, + * so that a series of updates can be performed, before the final result. + * @return hash structure. NULL on malloc failure or no support. + */ +struct secalgo_hash* secalgo_hash_create_sha512(void); + +/** + * Update a hash with more information to add to it. + * @param hash: the hash that is updated. + * @param data: data to add. + * @param len: length of data. + * @return false on failure. + */ +int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len); + +/** + * Get the final result of the hash. + * @param hash: the hash that has had updates to it. + * @param result: where to store the result. + * @param maxlen: length of the result buffer, eg. size of the allocation. + * If not large enough the routine fails. + * @param resultlen: the length of the result, returned to the caller. + * How much of maxlen is used. + * @return false on failure. + */ +int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result, + size_t maxlen, size_t* resultlen); + +/** + * Delete the hash structure. + * @param hash: the hash to delete. + */ +void secalgo_hash_delete(struct secalgo_hash* hash); + /** * Return size of DS digest according to its hash algorithm. * @param algo: DS digest algo. diff --git a/src/util/rbtree.c b/src/util/rbtree.c index b1a94b78..ff4e3e46 100644 --- a/src/util/rbtree.c +++ b/src/util/rbtree.c @@ -39,8 +39,6 @@ * Implementation of a redblack tree. */ -#include - #include "config.h" #include "log.h" #include "fptr_wlist.h" diff --git a/stubby b/stubby index 70937487..40b6bf95 160000 --- a/stubby +++ b/stubby @@ -1 +1 @@ -Subproject commit 709374879bca5d77548df68fd91c51174a862229 +Subproject commit 40b6bf95391f639cc86e5d328e89011ef4c16437