aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2018-10-08 08:30:10 +0000
committerPeter Wemm <peter@FreeBSD.org>2018-10-08 08:30:10 +0000
commitd29ecdf27f1804b1c533a3739282650ed83dbe31 (patch)
tree2528d825a15b6f1f2926dd55d258d6d296c787cc
parentf5bbf7923e42e842c4c6d067e48b2a94bc40de0d (diff)
downloadsrc-vendor/apr-util/apr-util-1.6.1.tar.gz
src-vendor/apr-util/apr-util-1.6.1.zip
-rw-r--r--CHANGES157
-rw-r--r--CMakeLists.txt355
-rw-r--r--LICENSE16
-rw-r--r--Makefile.in8
-rw-r--r--Makefile.win33
-rw-r--r--NOTICE2
-rw-r--r--NWGNUmakefile4
-rw-r--r--README4
-rw-r--r--README.FREETDS11
-rw-r--r--README.cmake139
-rw-r--r--apr-util.spec20
-rw-r--r--aprutil.dsw36
-rw-r--r--apu-config.in4
-rw-r--r--buckets/apr_buckets_alloc.c32
-rw-r--r--buckets/apr_buckets_file.c20
-rw-r--r--build-outputs.mk22
-rw-r--r--build.conf14
-rwxr-xr-xbuildconf18
-rwxr-xr-xconfigure1366
-rw-r--r--configure.in54
-rw-r--r--crypto/apr_crypto.c95
-rw-r--r--crypto/apr_crypto_commoncrypto.c906
-rw-r--r--crypto/apr_crypto_nss.c421
-rw-r--r--crypto/apr_crypto_openssl.c357
-rw-r--r--crypto/apr_siphash.c196
-rw-r--r--crypto/crypt_blowfish.c6
-rw-r--r--dbd/NWGNUmakefile3
-rw-r--r--dbd/apr_dbd.c3
-rw-r--r--dbd/unsupported/NWGNUdbdfreetds (renamed from dbd/NWGNUdbdfreetds)0
-rw-r--r--dbd/unsupported/apr_dbd_freetds.c (renamed from dbd/apr_dbd_freetds.c)4
-rw-r--r--dbm/sdbm/sdbm.c78
-rw-r--r--dbm/sdbm/sdbm_pair.c3
-rw-r--r--include/apr_buckets.h27
-rw-r--r--include/apr_crypto.h116
-rw-r--r--include/apr_dbd.h3
-rw-r--r--include/apr_ldap.hwc197
-rw-r--r--include/apr_redis.h459
-rw-r--r--include/apr_siphash.h148
-rw-r--r--include/apr_xml.h2
-rw-r--r--include/apu.h.in2
-rw-r--r--include/apu.hnw2
-rw-r--r--include/apu.hw2
-rw-r--r--include/apu.hwc145
-rw-r--r--include/apu_version.h8
-rw-r--r--include/private/apr_crypto_internal.h23
-rw-r--r--include/private/apu_config.h.in17
-rw-r--r--memcache/apr_memcache.c151
-rw-r--r--redis/apr_redis.c1548
-rw-r--r--test/Makefile.in2
-rw-r--r--test/Makefile.win4
-rw-r--r--test/NWGNUaputest1
-rw-r--r--test/abts_tests.h4
-rw-r--r--test/testall.dsw17
-rw-r--r--test/testcrypto.c909
-rw-r--r--test/testredis.c552
-rw-r--r--test/testsiphash.c148
-rw-r--r--test/testutil.h2
-rw-r--r--xml/apr_xml.c91
58 files changed, 7395 insertions, 1572 deletions
diff --git a/CHANGES b/CHANGES
index a0dc3789a89d..1b2333bed223 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,141 +1,62 @@
-*- coding: utf-8 -*-
-Changes with APR-util 1.5.4
+Changes with APR-util 1.6.1
- *) MySQL driver: Fix incorrect handling of bad parameter in the
- driver support for apr_dbd_transaction_end(). PR 56330.
- [Weiqiang Li <weiqiang_li hotmail.com>]
+ *) Win32: Add function exports from new apr_crypto API's missing in 1.6.0.
- *) apr_crypto_get_driver(): Fix invalid storage reference on error path.
- [Philip Martin <philip.martin wandisco.com>]
+ *) Win32: Introduce XML_PARSER build-time variable to select the expat
+ library name to be linked to libaprutil-1.dll. See Makefile.win
- *) Fix compile failure for Android. PR 56627. [Fredrik Fornwall
- <fredrik fornwall.net>, Jeff Trawick]
+ *) Win32: Removed lingering xml/xml.dsp project forked from the expat
+ Project in the 1.9x era. Use expat's maintained build schema instead,
+ prior to building apr-util.
- *) Fix to let ODBC driver build with MSVC6, which does not have intptr_t
- [Tom Donovan]
+ *) apr_crypto: Fix compatibility with LibreSSL. PR 61596.
+ [Bernard Spil <brnrd freebsd.org>, Yann Ylavic]
- *) Windows cmake build: Fix incompatiblities with Visual Studio
- generators with all cmake versions, and the NMake Makefile generator
- with cmake 2.8.12 and later. PR 56616 and other bugs. [Jeff Trawick,
- Bert Huijben]
+ *) sdbm: better database/page validation to fail cleanly when corrupted.
+ [Yann Ylavic]
- *) Fix detection of Berkeley DB 6.0. PR 55277.
- [Lars Wendler <polynomial-c gentoo.org>]
+Changes with APR-util 1.6.0
- *) Improve platform detection for bundled expat by updating
- config.guess and config.sub. [Rainer Jung]
+ *) The expat dependency of apr-util is no longer built with apr-util.
+ Install expat (including development headers and libraries) first
+ before building apr-util. [https://libexpat.github.io/]
-Changes with APR-util 1.5.3
+ *) Mark apr_dbd_freetds as unsupported, and remove it from all builds
+ [Nick Kew]
- *) Cygwin: Use correct file extension when loading APR DSOs. PR 55587.
- [Carlo Bramini <carlo.bramix libero.it>]
+ *) Update MySQL build to stop using libmysqlclient_r.
+ [Petr Sumbera <petr.sumbera oracle.com>]
- *) Add experimental cmake-based build system for Windows. Refer to
- README.cmake for more information. [Jeff Trawick, Tom Donovan]
+ *) apr_buckets: Add apr_bucket_file_set_buf_size() which allows to configure
+ the size of the buffer used to read files. [Yann Ylavic]
- *) Fix warnings in odbc driver on 64bit systems.
- PR 55197 [Tom Donovan]
+ *) apr_crypto: avoid excessive iteration in bcrypt hash.
+ [Hanno Böck <hanno hboeck.de>]
- *) Add support to apr_memcache for unix domain sockets. PR 54573 [Remi
- Gacogne <rgacogne+asf aquaray.com>]
+ *) apr_siphash: Implement keyed hash function SipHash. [Yann Ylavic]
- *) Add support for Berkeley DB 6.0. [Rainer Jung]
+ *) apr_crypto: Add apr_crypto_key() function which supports keys
+ generated from a passphrase or a raw secret provided by the caller.
+ Deprecate apr_crypto_passphrase(). [Graham Leggett]
- *) Improve platform detection for bundled expat by updating
- config.guess and config.sub. [Rainer Jung]
+ *) apr_crypto_nss: Ensure the SECItem returned by PK11_ParamFromIV
+ is properly freed. [Graham Leggett]
-Changes with APR-util 1.5.2
+ *) apr_crypto: Don't cache the driver if initialisation fails. This
+ stops the second and subsequent attempt to use the API from failing
+ claiming the library is not initialised. [Graham Leggett]
- *) Windows: Add command line makefiles. [Gregg Smith]
+ *) apr_crypto: Add a native CommonCrypto implementation for iOS and OSX
+ where OpenSSL has been deprecated. [Graham Leggett]
- *) apr_uri_parse(): Do not accept invalid characters in the scheme.
- Per RFC 3986 3.3, enforce that the first segment of a relative path does
- not contain a colon. PR 52479. [Stefan Fritsch]
+ *) apr_xml_to_text: Add style APR_XML_X2T_PARSED to maintain a
+ consistent namespace prefix. [Jari Urpalainen
+ <jari.urpalainen nokia.com>]
- *) Fix memory leak in hook sorting function. PR 51256.
- [<horowity checkpoint com>]
+Changes with APR-util 1.5.x and later:
- *) Speedup md5 calculation by avoiding some copying on little endian
- architectures. PR 49011. [Stefan Fritsch, Stefan Fuhrmann
- <stefanfuhrmann alice-dsl de>]
-
- *) Use heap memory for crypt in apr_password_validate(), to reduce stack
- usage. PR 54572. [Stefan Fritsch]
-
- *) Fix password validation failure for all crypt and crypt_r based
- algorithms. PR 54603. [Harvey Eneman <harvey.eneman oracle.com>]
-
- *) Fix syntax error in crypto/apr_passwd.c on non-glibc systems. PR 54275.
- [Stefan Fritsch]
-
- *) Fix potential data corruption in apr_brigade_write() and friends if
- the last bucket of the brigade is a heap bucket that has been split,
- and there are still references to the next part of the original bucket
- in use. [Stefan Fritsch]
-
- *) Remove duplicated logic in apr_brigade_puts(). PR 53740. [Christophe
- Jaillet <christophe jaillet wanadoo fr>]
-
- *) apr_crypto: If --with-crypto is passed to configure but no crypto
- libraries are enabled, autodetect available libraries. [Jeff Trawick]
-
- *) memcache: Fix dead server retry logic. [Gavin Shelley <columbusmonkey me.com>]
-
-Changes with APR-util 1.5.1
-
- *) testmemcache: Fix crash. PR 52705. [Peter Poeml <peter poeml de>]
-
- *) MinGW: Support shared builds of apr-util when apr is shared.
- PR 46175. [Carlo Bramini <carlo.bramix libero.it>, Jeff Trawick]
-
- *) Add support for Berkeley DB 5.2 and 5.3. Simplify detection script.
- PR 53684. [Rainer Jung]
-
- *) configure: Allow to specify library specific custom linker flags
- via the LDADD_XXX variables. [Rainer Jung]
-
- *) apr_password_validate(): Fix intermittent errors on systems
- such as FreeBSD where the crypt() function is used.
- (Broken only in 1.5.0) [Jeff Trawick]
-
- *) Improve platform detection for bundled expat by updating
- config.guess and config.sub. [Rainer Jung]
-
-Changes with APR-util 1.5.0
-
- *) dbd_pgsql_escape: Use PQescapeStringConn. [Nick Kew]
-
- *) apr_password_validate, apr_bcrypt_encode: Add support for bcrypt encoded
- passwords. The bcrypt implementation uses code from crypt_blowfish
- written by Solar Designer <solar openwall com>. apr_bcrypt_encode creates
- hashes with "$2y$" prefix, but apr_password_validate also accepts the old
- prefix "$2a$". PR 49288. [Stefan Fritsch]
-
- *) APR dbd: Allow to use apr_dbd_get_row() with a different pool than
- apr_dbd_select(). PR 53533. [<arthur echo gmail com>]
-
- *) APR dbd FreeTDS support: Fix spurious API errors caused by uninitialized
- fields. [TROY.LIU 劉春偉 <TROY.LIU deltaww.com.cn>]
-
- *) apr_password_validate: Increase maximum hash string length to allow
- more than 9999 rounds with sha512-crypt. PR 53410. [Stefan Fritsch]
-
- *) Fix segfaults in crypt() and crypt_r() failure modes.
- PR 47272. [Arkadiusz Miskiewicz <arekm pld-linux.org>]
-
- *) apr_crypto: Ensure that the if/else that governs the static
- initialisation of each crypto driver works when the first driver
- isn't in use. [Graham Leggett]
-
- *) apr_crypto: Ensure the *driver variable is initialised when a statically
- compiled library is initialised for the first time. [Graham Leggett]
-
- *) apr_crypto: Ensure the *driver variable is initialised when the library
- has already been loaded. Fix ported from apr_dbd. [Graham Leggett]
-
- *) apr_crypto: Move the static initialisation of DRIVER_LOAD from
- apr_crypto_init() to apr_crypto_get_driver(), so that we don't lose
- the parameters. [Graham Leggett]
+ *) http://svn.apache.org/viewvc/apr/apr-util/branches/1.5.x/CHANGES?view=markup
Changes with APR-util 1.4.x and later:
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 000000000000..9ae90b19f97e
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,355 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Read README.cmake before using this.
+
+PROJECT(APR-Util C)
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+FIND_PACKAGE(OpenSSL)
+
+FIND_PACKAGE(expat)
+
+OPTION(APU_HAVE_CRYPTO "Crypto support" OFF)
+OPTION(APU_HAVE_ODBC "Build ODBC DBD driver" ON)
+OPTION(APR_HAS_LDAP "LDAP support" ON)
+OPTION(INSTALL_PDB "Install .pdb files (if generated)" ON)
+OPTION(APR_BUILD_TESTAPR "Build the test suite" OFF)
+OPTION(TEST_STATIC_LIBS "Test programs use APR static libraries instead of shared libraries?" OFF)
+SET(APR_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE STRING "Directory with APR include files")
+SET(APR_LIBRARIES "${CMAKE_INSTALL_PREFIX}/lib/libapr-1.lib" CACHE STRING "APR library to link with")
+
+IF(NOT EXISTS "${APR_INCLUDE_DIR}/apr.h")
+ MESSAGE(FATAL_ERROR "APR include directory ${APR_INCLUDE_DIR} is not correct.")
+ENDIF()
+FOREACH(onelib ${APR_LIBRARIES})
+ IF(NOT EXISTS ${onelib})
+ MESSAGE(FATAL_ERROR "APR library ${onelib} was not found.")
+ ENDIF()
+ENDFOREACH()
+
+IF(APU_HAVE_CRYPTO)
+IF(NOT OPENSSL_FOUND)
+ MESSAGE(FATAL_ERROR "OpenSSL is the only supported crypto implementation, and it wasn't found!")
+ENDIF()
+ENDIF()
+
+# create 1-or-0 representation of feature tests for apu.h
+
+SET(apu_have_crypto_10 0)
+SET(apu_have_apr_iconv_10 0) # not yet implemented
+SET(apr_has_ldap_10 0)
+
+IF(APU_HAVE_CRYPTO)
+ SET(apu_have_crypto_10 1)
+ENDIF()
+
+IF(APR_HAS_LDAP)
+ SET(apr_has_ldap_10 1)
+ENDIF()
+
+IF(NOT EXPAT_FOUND)
+ MESSAGE(FATAL_ERROR "Expat is required, and it wasn't found!")
+ENDIF()
+
+SET(XMLLIB_INCLUDE_DIR ${EXPAT_INCLUDE_DIRS})
+SET(XMLLIB_LIBRARIES ${EXPAT_LIBRARIES})
+
+SET(LDAP_LIBRARIES)
+IF(APR_HAS_LDAP)
+ SET(LDAP_LIBRARIES wldap32)
+ENDIF()
+
+CONFIGURE_FILE(include/apu.hwc
+ ${PROJECT_BINARY_DIR}/apu.h)
+CONFIGURE_FILE(include/apr_ldap.hwc
+ ${PROJECT_BINARY_DIR}/apr_ldap.h)
+# "COPYONLY" just because anything else isn't implemented ;)
+CONFIGURE_FILE(include/private/apu_config.hw
+ ${PROJECT_BINARY_DIR}/apu_config.h
+ COPYONLY)
+CONFIGURE_FILE(include/private/apu_select_dbm.hw
+ ${PROJECT_BINARY_DIR}/apu_select_dbm.h
+ COPYONLY)
+CONFIGURE_FILE(include/apu_want.hw
+ ${PROJECT_BINARY_DIR}/apu_want.h
+ COPYONLY)
+
+# Generated .h files are stored in PROJECT_BINARY_DIR, not the
+# source tree.
+#
+# BROKEN: not searching PROJECT_BINARY_DIR first, so you have to
+# manually delete apu.h in PROJECT_SOURCE_DIR/include if
+# you've generated apu.h before using a different build
+
+SET(APR_INCLUDE_DIRECTORIES
+ ${PROJECT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/private
+ ${APR_INCLUDE_DIR}
+)
+
+INCLUDE_DIRECTORIES(${APR_INCLUDE_DIRECTORIES} ${XMLLIB_INCLUDE_DIR})
+
+SET(APR_PUBLIC_HEADERS_STATIC
+ include/apr_anylock.h
+ include/apr_base64.h
+ include/apr_buckets.h
+ include/apr_crypto.h
+ include/apr_date.h
+ include/apr_dbd.h
+ include/apr_dbm.h
+ include/apr_hooks.h
+ include/apr_ldap_init.h
+ include/apr_ldap_option.h
+ include/apr_ldap_rebind.h
+ include/apr_ldap_url.h
+ include/apr_md4.h
+ include/apr_md5.h
+ include/apr_memcache.h
+ include/apr_optional.h
+ include/apr_optional_hooks.h
+ include/apr_queue.h
+ include/apr_redis.h
+ include/apr_reslist.h
+ include/apr_rmm.h
+ include/apr_sdbm.h
+ include/apr_sha1.h
+ include/apr_siphash.h
+ include/apr_strmatch.h
+ include/apr_thread_pool.h
+ include/apr_uri.h
+ include/apr_uuid.h
+ include/apr_xlate.h
+ include/apr_xml.h
+ include/apu_errno.h
+ include/apu_version.h
+)
+
+# apu_config.h and apu_select_dbm.h are private
+SET(APR_PUBLIC_HEADERS_GENERATED
+ ${PROJECT_BINARY_DIR}/apu.h
+ ${PROJECT_BINARY_DIR}/apr_ldap.h
+ ${PROJECT_BINARY_DIR}/apu_want.h
+)
+
+SET(APR_SOURCES
+ buckets/apr_brigade.c
+ buckets/apr_buckets.c
+ buckets/apr_buckets_alloc.c
+ buckets/apr_buckets_eos.c
+ buckets/apr_buckets_file.c
+ buckets/apr_buckets_flush.c
+ buckets/apr_buckets_heap.c
+ buckets/apr_buckets_mmap.c
+ buckets/apr_buckets_pipe.c
+ buckets/apr_buckets_pool.c
+ buckets/apr_buckets_refcount.c
+ buckets/apr_buckets_simple.c
+ buckets/apr_buckets_socket.c
+ crypto/apr_crypto.c
+ crypto/apr_md4.c
+ crypto/apr_md5.c
+ crypto/apr_passwd.c
+ crypto/apr_sha1.c
+ crypto/apr_siphash.c
+ crypto/crypt_blowfish.c
+ crypto/getuuid.c
+ crypto/uuid.c
+ dbd/apr_dbd.c
+ dbm/apr_dbm.c
+ dbm/apr_dbm_sdbm.c
+ dbm/sdbm/sdbm.c
+ dbm/sdbm/sdbm_hash.c
+ dbm/sdbm/sdbm_lock.c
+ dbm/sdbm/sdbm_pair.c
+ encoding/apr_base64.c
+ hooks/apr_hooks.c
+ memcache/apr_memcache.c
+ misc/apr_date.c
+ misc/apr_queue.c
+ misc/apr_reslist.c
+ misc/apr_rmm.c
+ misc/apr_thread_pool.c
+ misc/apu_dso.c
+ misc/apu_version.c
+ redis/apr_redis.c
+ strmatch/apr_strmatch.c
+ uri/apr_uri.c
+ xlate/xlate.c
+ xml/apr_xml.c
+)
+
+IF(APR_HAS_LDAP)
+ SET(APR_SOURCES ${APR_SOURCES} ldap/apr_ldap_stub.c ldap/apr_ldap_url.c)
+ENDIF()
+
+SET(APR_TEST_SOURCES
+ test/abts.c
+ test/testbuckets.c
+ test/testcrypto.c
+ test/testdate.c
+ test/testdbd.c
+ test/testdbm.c
+ test/testldap.c
+ test/testmd4.c
+ test/testmd5.c
+ test/testmemcache.c
+ test/testpass.c
+ test/testqueue.c
+ test/testredis.c
+ test/testreslist.c
+ test/testrmm.c
+ test/testsiphash.c
+ test/teststrmatch.c
+ test/testuri.c
+ test/testutil.c
+ test/testuuid.c
+ test/testxlate.c
+ test/testxml.c
+)
+
+SET(install_targets)
+SET(install_bin_pdb)
+SET(dbd_drivers)
+
+# Note: The WINNT definition on some targets is used only by libaprutil.rc.
+
+# libaprutil-1 is shared, aprutil-1 is static
+ADD_LIBRARY(libaprutil-1 SHARED ${APR_SOURCES} ${APR_PUBLIC_HEADERS_GENERATED} libaprutil.rc)
+SET(install_targets ${install_targets} libaprutil-1)
+SET(install_bin_pdb ${install_bin_pdb} ${PROJECT_BINARY_DIR}/libaprutil-1.pdb)
+TARGET_LINK_LIBRARIES(libaprutil-1 ${APR_LIBRARIES} ${XMLLIB_LIBRARIES})
+SET_TARGET_PROPERTIES(libaprutil-1 PROPERTIES COMPILE_DEFINITIONS "APU_DECLARE_EXPORT;APR_DECLARE_EXPORT;XML_STATIC;WINNT")
+
+ADD_LIBRARY(aprutil-1 STATIC ${APR_SOURCES} ${APR_PUBLIC_HEADERS_GENERATED})
+SET(install_targets ${install_targets} aprutil-1)
+TARGET_LINK_LIBRARIES(aprutil-1 ${APR_LIBRARIES} ${XMLLIB_LIBRARIES})
+SET_TARGET_PROPERTIES(aprutil-1 PROPERTIES COMPILE_DEFINITIONS "APU_DECLARE_STATIC;APR_DECLARE_STATIC;APU_DSO_MODULE_BUILD;XML_STATIC")
+
+IF(APU_HAVE_CRYPTO)
+ IF(NOT OPENSSL_FOUND)
+ MESSAGE(FATAL_ERROR "Only OpenSSL-based crypto is currently implemented in the cmake build")
+ ENDIF()
+ ADD_LIBRARY(apr_crypto_openssl-1 SHARED crypto/apr_crypto_openssl.c libaprutil.rc)
+ SET(install_targets ${install_targets} apr_crypto_openssl-1)
+ SET(install_bin_pdb ${install_bin_pdb} ${PROJECT_BINARY_DIR}/apr_crypto_openssl-1.pdb)
+ SET_TARGET_PROPERTIES(apr_crypto_openssl-1 PROPERTIES INCLUDE_DIRECTORIES "${APR_INCLUDE_DIRECTORIES};${OPENSSL_INCLUDE_DIR}")
+ SET_TARGET_PROPERTIES(apr_crypto_openssl-1 PROPERTIES COMPILE_DEFINITIONS "WINNT")
+ SET_TARGET_PROPERTIES(apr_crypto_openssl-1 PROPERTIES COMPILE_FLAGS "-DAPR_DECLARE_EXPORT=1 -DAPU_DECLARE_EXPORT=1 -DDLL_NAME=apr_crypto_openssl")
+ TARGET_LINK_LIBRARIES(apr_crypto_openssl-1 libaprutil-1 ${APR_LIBRARIES} ${OPENSSL_LIBRARIES})
+ENDIF()
+
+IF(APU_HAVE_ODBC)
+ ADD_LIBRARY(apr_dbd_odbc-1 SHARED dbd/apr_dbd_odbc.c libaprutil.rc)
+ SET(install_targets ${install_targets} apr_dbd_odbc-1)
+ SET(install_bin_pdb ${install_bin_pdb} ${PROJECT_BINARY_DIR}/apr_dbd_odbc-1.pdb)
+ SET(dbd_drivers ${dbd_drivers} odbc)
+ TARGET_LINK_LIBRARIES(apr_dbd_odbc-1 libaprutil-1 ${APR_LIBRARIES} odbc32 odbccp32)
+ SET_PROPERTY(TARGET apr_dbd_odbc-1 APPEND PROPERTY LINK_FLAGS /export:apr_dbd_odbc_driver)
+ SET_TARGET_PROPERTIES(apr_dbd_odbc-1 PROPERTIES COMPILE_DEFINITIONS "APU_HAVE_ODBC;HAVE_SQL_H;APU_DECLARE_EXPORT;APR_DECLARE_EXPORT;APU_DSO_MODULE_BUILD;WINNT")
+ SET_TARGET_PROPERTIES(apr_dbd_odbc-1 PROPERTIES COMPILE_FLAGS "-DAPR_DECLARE_EXPORT=1 -DAPU_DECLARE_EXPORT=1 -DDLL_NAME=apr_dbd_odbc")
+ENDIF()
+
+IF(APR_HAS_LDAP)
+ ADD_LIBRARY(apr_ldap-1 SHARED ldap/apr_ldap_init.c ldap/apr_ldap_option.c
+ ldap/apr_ldap_rebind.c libaprutil.rc)
+ SET(install_targets ${install_targets} apr_ldap-1)
+ SET(install_bin_pdb ${install_bin_pdb} ${PROJECT_BINARY_DIR}/apr_ldap-1.pdb)
+ TARGET_LINK_LIBRARIES(apr_ldap-1 libaprutil-1 ${APR_LIBRARIES} ${LDAP_LIBRARIES})
+ SET_TARGET_PROPERTIES(apr_ldap-1 PROPERTIES COMPILE_DEFINITIONS "WINNT")
+ SET_TARGET_PROPERTIES(apr_ldap-1 PROPERTIES COMPILE_FLAGS "-DAPR_DECLARE_EXPORT=1 -DAPU_DECLARE_EXPORT=1 -DDLL_NAME=apr_ldap")
+ SET(apr_ldap_libraries apr_ldap-1)
+ELSE()
+ SET(apr_ldap_libraries)
+ENDIF()
+
+IF(APR_BUILD_TESTAPR)
+ ENABLE_TESTING()
+ # Create a "check" target that displays test program output to the console.
+ ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND} --verbose)
+
+ # copy data files to build directory so that we can run programs from there
+ EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory
+ ${PROJECT_BINARY_DIR}/data)
+ EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${PROJECT_SOURCE_DIR}/test/data/billion-laughs.xml
+ ${PROJECT_BINARY_DIR}/data/billion-laughs.xml)
+
+ IF(TEST_STATIC_LIBS)
+ SET(whichapr aprutil-1)
+ SET(apiflag "-DAPR_DECLARE_STATIC -DAPU_DECLARE_STATIC")
+ ELSE()
+ SET(whichapr libaprutil-1)
+ SET(apiflag)
+ ENDIF()
+
+ ADD_EXECUTABLE(testall ${APR_TEST_SOURCES})
+ TARGET_LINK_LIBRARIES(testall ${whichapr} ${apr_ldap_libraries} ${XMLLIB_LIBRARIES} ${LDAP_LIBRARIES})
+ IF(apiflag)
+ SET_TARGET_PROPERTIES(testall PROPERTIES COMPILE_FLAGS ${apiflag})
+ ENDIF()
+ ADD_TEST(NAME testall COMMAND testall)
+
+ ADD_EXECUTABLE(dbd test/dbd.c)
+ TARGET_LINK_LIBRARIES(dbd ${whichapr})
+ IF(apiflag)
+ SET_TARGET_PROPERTIES(dbd PROPERTIES COMPILE_FLAGS ${apiflag})
+ ENDIF()
+
+ # dbd is run multiple times with different parameters.
+ FOREACH(somedbd ${dbd_drivers})
+ ADD_TEST(NAME dbd-${somedbd} COMMAND dbd ${somedbd})
+ ENDFOREACH()
+
+ENDIF (APR_BUILD_TESTAPR)
+
+# Installation
+
+INSTALL(TARGETS ${install_targets}
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+ )
+
+IF(INSTALL_PDB)
+ INSTALL(FILES ${install_bin_pdb}
+ DESTINATION bin
+ CONFIGURATIONS RelWithDebInfo Debug)
+ENDIF()
+
+INSTALL(FILES ${APR_PUBLIC_HEADERS_STATIC} ${APR_PUBLIC_HEADERS_GENERATED} DESTINATION include)
+
+STRING(TOUPPER "${CMAKE_BUILD_TYPE}" buildtype)
+MESSAGE(STATUS "")
+MESSAGE(STATUS "")
+MESSAGE(STATUS "APR-Util configuration summary:")
+MESSAGE(STATUS "")
+MESSAGE(STATUS " Build type ...................... : ${CMAKE_BUILD_TYPE}")
+MESSAGE(STATUS " Install .pdb (if available)...... : ${INSTALL_PDB}")
+MESSAGE(STATUS " Install prefix .................. : ${CMAKE_INSTALL_PREFIX}")
+MESSAGE(STATUS " C compiler ...................... : ${CMAKE_C_COMPILER}")
+MESSAGE(STATUS " APR include directory ........... : ${APR_INCLUDE_DIR}")
+MESSAGE(STATUS " APR libraries ................... : ${APR_LIBRARIES}")
+MESSAGE(STATUS " DBD ODBC driver ................. : ${APU_HAVE_ODBC}")
+MESSAGE(STATUS " APU_HAVE_CRYPTO ................. : ${APU_HAVE_CRYPTO}")
+MESSAGE(STATUS " APR_HAS_LDAP .................... : ${APR_HAS_LDAP}")
+MESSAGE(STATUS " Build test suite ................ : ${APR_BUILD_TESTAPR}")
+IF(TEST_STATIC_LIBS)
+MESSAGE(STATUS " (testing static libraries)")
+ELSE()
+MESSAGE(STATUS " (testing dynamic libraries)")
+ENDIF()
diff --git a/LICENSE b/LICENSE
index 7771972d8546..bfe78d537e43 100644
--- a/LICENSE
+++ b/LICENSE
@@ -312,6 +312,22 @@ For the crypto\apr_md4.c component:
* documentation and/or software.
*/
+For the crypto\crypt_blowfish.c(.h) component:
+
+ * Written by Solar Designer <solar at openwall.com> in 1998-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 1998-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+
+ See crypto/crypt_blowfish.c for more information.
+
For the include\apr_md4.h component:
*
diff --git a/Makefile.in b/Makefile.in
index 963feada79ad..208dd1cc1e65 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -15,8 +15,8 @@ APRUTIL_LDFLAGS = @APRUTIL_LDFLAGS@
APRUTIL_LIBS = @APRUTIL_LIBS@
TARGET_LIB = lib@APRUTIL_LIBNAME@.la
-INSTALL_SUBDIRS = @APR_ICONV_DIR@ @APR_XML_DIR@
-EXTRA_SOURCE_DIRS = @APR_ICONV_DIR@ @APR_XML_DIR@
+INSTALL_SUBDIRS = @APR_ICONV_DIR@
+EXTRA_SOURCE_DIRS = @APR_ICONV_DIR@
APRUTIL_PCFILE = apr-util-$(APRUTIL_MAJOR_VERSION).pc
APU_CONFIG = apu-$(APRUTIL_MAJOR_VERSION)-config
INSTALL = @INSTALL@
@@ -35,7 +35,6 @@ LDADD_dbd_oracle = @LDADD_dbd_oracle@
LDADD_dbd_sqlite2 = @LDADD_dbd_sqlite2@
LDADD_dbd_sqlite3 = @LDADD_dbd_sqlite3@
LDADD_dbd_mysql = @LDADD_dbd_mysql@
-LDADD_dbd_freetds = @LDADD_dbd_freetds@
LDADD_dbd_odbc = @LDADD_dbd_odbc@
LDADD_dbm_db = @LDADD_dbm_db@
LDADD_dbm_gdbm = @LDADD_dbm_gdbm@
@@ -43,6 +42,7 @@ LDADD_dbm_ndbm = @LDADD_dbm_ndbm@
LDADD_ldap = @LDADD_ldap@
LDADD_crypto_openssl = @LDADD_crypto_openssl@
LDADD_crypto_nss = @LDADD_crypto_nss@
+LDADD_crypto_commoncrypto = @LDADD_crypto_commoncrypto@
TARGETS = $(TARGET_LIB) aprutil.exp apu-config.out $(APU_MODULES)
@@ -50,7 +50,7 @@ TARGETS = $(TARGET_LIB) aprutil.exp apu-config.out $(APU_MODULES)
@INCLUDE_RULES@
@INCLUDE_OUTPUTS@
-CLEAN_SUBDIRS = test @APR_ICONV_DIR@ @APR_XML_DIR@
+CLEAN_SUBDIRS = test @APR_ICONV_DIR@
CLEAN_TARGETS = exports.c export_vars.c aprutil.exp .make.dirs apu-config.out
DISTCLEAN_TARGETS = config.cache config.log config.status libtool \
diff --git a/Makefile.win b/Makefile.win
index b4b420e1c2e6..454b4fecdbf1 100644
--- a/Makefile.win
+++ b/Makefile.win
@@ -51,6 +51,13 @@
#
# CRYPTO_LIST="nss openssl"
#
+# Provide the XML_PARSER argument after configuring LIB and INCLUDE with
+# the expat path of the corresponding xml parser, e.g. libexpatMT to choose
+# static, or libexpat (default) to choose the dynamic library for aprutil-1.dll
+# (Static libaprutil-1.lib always presumes libexpatMT with XML_STATIC flag.)
+#
+# XML_PARSER="libexpat"
+#
# For example;
#
# nmake -f Makefile.win PREFIX=C:\APR buildall checkall installall clean
@@ -73,6 +80,20 @@ USEDSW=1
PREFIX=..\apr-dist
+!IF EXIST("..\openssl")
+!IF EXIST("..\openssl\libcrypto.lib")
+SSLOPT=_HAVE_OSSL110=1
+!ENDIF
+!ENDIF
+
+# Legacy default (and unwise alternative) for libapr-1.dll is libexpatMT
+XML_PARSER="libexpat"
+!IF "$(XML_PARSER)" == "libexpat"
+XMLOPT=XML_PARSER=$(XML_PARSER)
+!ELSE
+XMLOPT=XML_PARSER=$(XML_PARSER) XML_OPTIONS="/D XML_STATIC"
+!ENDIF
+
!IF [$(COMSPEC) /c cl /nologo /? \
| $(SystemRoot)\System32\find.exe "x64" >NUL ] == 0
ARCH=x64 Release
@@ -197,11 +218,9 @@ buildall:
BUILD_MODE="$(ARCH)" BIND_MODE=shared
cd ..
!ENDIF
- cd $(APU_PATH)\xml\expat\lib
- $(MAKE) $(MAKEOPT) -f xml.mak CFG="xml - $(ARCH)" RECURSE=0 $(CTARGET)
- cd ..\..\..
- $(MAKE) $(MAKEOPT) -f aprutil.mak CFG="aprutil - $(ARCH)" RECURSE=0 $(CTARGET)
- $(MAKE) $(MAKEOPT) -f libaprutil.mak CFG="libaprutil - $(ARCH)" RECURSE=0 $(CTARGET)
+ cd $(APU_PATH)
+ $(MAKE) $(MAKEOPT) $(SSLOPT) $(XMLOPT) -f aprutil.mak CFG="aprutil - $(ARCH)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) $(SSLOPT) $(XMLOPT) -f libaprutil.mak CFG="libaprutil - $(ARCH)" RECURSE=0 $(CTARGET)
cd ldap
$(MAKE) $(MAKEOPT) -f apr_ldap.mak CFG="apr_ldap - $(ARCH)" RECURSE=0 $(CTARGET)
cd ..
@@ -215,7 +234,7 @@ buildall:
cd ..
cd crypto
for %d in ($(CRYPTO_LIST) x) do if not %d == x \
- $(MAKE) $(MAKEOPT) -f apr_crypto_%d.mak CFG="apr_crypto_%d - $(ARCH)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) $(SSLOPT) -f apr_crypto_%d.mak CFG="apr_crypto_%d - $(ARCH)" RECURSE=0 $(CTARGET)
cd ..
!ELSEIF $(USESLN) == 1
@@ -306,7 +325,7 @@ checkapr:
checkapu:
cd $(APU_PATH)
cd test
- $(MAKE) $(MAKEOPT) -f Makefile.win MODEL=static \
+ $(MAKE) $(MAKEOPT) -f Makefile.win MODEL=static \
OUTDIR=$(LIBSPATH) APROUTDIR=$(LIBSOSPATH) \
APR_PATH=..\$(APR_PATH) API_PATH=..\$(API_PATH) check
$(MAKE) $(MAKEOPT) -f Makefile.win MODEL=dynamic \
diff --git a/NOTICE b/NOTICE
index a107139ef37e..3ae54e128be8 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
Apache Portable Runtime Utility Library
-Copyright (c) 2000-2014 The Apache Software Foundation.
+Copyright (c) 2000-2016 The Apache Software Foundation.
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git a/NWGNUmakefile b/NWGNUmakefile
index e089b6fc7f36..cef05ee0dc2e 100644
--- a/NWGNUmakefile
+++ b/NWGNUmakefile
@@ -261,9 +261,11 @@ FILES_lib_objs = \
$(OBJDIR)/apr_memcache.o \
$(OBJDIR)/apr_passwd.o \
$(OBJDIR)/apr_queue.o \
+ $(OBJDIR)/apr_redis.o \
$(OBJDIR)/apr_reslist.o \
$(OBJDIR)/apr_rmm.o \
$(OBJDIR)/apr_sha1.o \
+ $(OBJDIR)/apr_siphash.o \
$(OBJDIR)/apu_version.o \
$(OBJDIR)/getuuid.o \
$(OBJDIR)/uuid.o \
@@ -296,7 +298,7 @@ install :: nlms FORCE
# Any specialized rules here
#
-vpath %.c buckets:crypto:dbd:dbm:dbm/sdbm:encoding:hooks:ldap:memcache:misc:strmatch:uri:xlate:xml
+vpath %.c buckets:crypto:dbd:dbm:dbm/sdbm:encoding:hooks:ldap:memcache:redis:misc:strmatch:uri:xlate:xml
#
# Include the 'tail' makefile that has targets that depend on variables defined
diff --git a/README b/README
index 3a685698bee8..9ea474d8faba 100644
--- a/README
+++ b/README
@@ -34,7 +34,7 @@ Apache Portable Runtime Utility Library README
String filename-style pattern matching
URI Parsing
Charset translation (iconv based)
- XML parsing (expat based)
+ XML parsing (expat)
For a more complete list, please refer to the following URLs:
@@ -66,7 +66,7 @@ for your compiled code. Similarly, the bindings for propritary drivers
such as Oracle (--with-oracle option) must also be explicitly enabled.
On windows, selection of supported drivers is via the environment values
-DBD_LIST (for freetds, mysql, oracle, pgsql, sqlite2 and/or sqlite3)
+DBD_LIST (for mysql, oracle, pgsql, sqlite2 and/or sqlite3)
and DBM_LIST (db and/or gdbm). DBD odbc and DBM sdbm are unconditionally
compiled and installed, do not include these in the list.
diff --git a/README.FREETDS b/README.FREETDS
new file mode 100644
index 000000000000..4066a9c78b38
--- /dev/null
+++ b/README.FREETDS
@@ -0,0 +1,11 @@
+The APR DBD Driver for FreeTDS has been removed from the build.
+It is known to have problems, and we are not able to maintain it.
+
+The source code is still available. If you want it and are able
+to manage maintenance for yourself, you can patch the build and
+work through issues that affect you, but you're on your own.
+
+We expect that for most users, the ODBC driver will serve as
+an alternative.
+
+Sorry.
diff --git a/README.cmake b/README.cmake
new file mode 100644
index 000000000000..85de33a21e95
--- /dev/null
+++ b/README.cmake
@@ -0,0 +1,139 @@
+Experimental cmake-based build support for APR-Util on Microsoft Windows
+
+Status
+------
+
+This build support is currently intended only for Microsoft Windows.
+Only Windows NT-based systems can be targeted. (The traditional
+Windows build support for APR can target Windows 9x as well.)
+
+This build support is experimental. Specifically,
+
+* It does not support all features of APR-Util.
+* Some components may not be built correctly and/or in a manner
+ compatible with the previous Windows build support.
+* Build interfaces, such as the mechanisms which are used to enable
+ optional functionality or specify prerequisites, may change from
+ release to release as feedback is received from users and bugs and
+ limitations are resolved.
+
+Important: Refer to the "Known Bugs and Limitations" section for further
+ information.
+
+ It is beyond the scope of this document to document or explain
+ how to utilize the various cmake features, such as different
+ build backends or provisions for finding support libraries.
+
+ Please refer to the cmake documentation for additional information
+ that applies to building any project with cmake.
+
+Prerequisites
+-------------
+
+The following tools must be in PATH:
+
+* cmake, version 2.8 or later
+ cmake version 3.1.3 or later is required to work with current OpenSSL
+ releases. (OpenSSL is an optional prerequisite of APR-Util.)
+* If using a command-line compiler: compiler and linker and related tools
+ (Refer to the cmake documentation for more information.)
+
+The following support libraries are mandatory:
+
+* APR 1.4.x or APR 1.5.x, built with cmake
+
+Optional support libraries allow optional features of APR to be enabled:
+
+* OpenSSL
+* many others potentially, though the build support isn't currently
+ implemented
+
+How to build
+------------
+
+1. cd to a clean directory for building (i.e., don't build in your
+ source tree)
+
+2. Some cmake backends may want your compile tools in PATH. (Hint: "Visual
+ Studio Command Prompt")
+
+3. set CMAKE_LIBRARY_PATH=d:\path\to\prereq1\lib;d:\path\to\prereq2\lib;...
+
+4. set CMAKE_INCLUDE_PATH=d:\path\to\prereq1\include;d:\path\to\prereq2\include;...
+
+5. cmake -G "some backend, like 'NMake Makefiles'"
+ -DCMAKE_INSTALL_PREFIX=d:/path/to/aprinst
+ -DAPR-Util-specific-flags
+ d:/path/to/aprutilsource
+
+ If APR 1.x was installed to a different directory than APR-Util,
+ also pass these additional arguments:
+
+ -DAPR_INCLUDE_DIR=d:/path/to/apr1inst/include
+ -DAPR_LIBRARIES=d:/path/to/apr1inst/lib/libapr-1.lib
+
+ Alternately, use cmake-gui and update settings in the GUI.
+
+ APR-Util feature flags:
+
+ APU_HAVE_CRYPTO Build crypt support (only the OpenSSL
+ implementation is currently supported)
+ Default: OFF
+ APU_HAVE_ODBC Build ODBC DBD driver
+ Default: ON
+ APR_BUILD_TESTAPR Build APR-Util test suite
+ Default: OFF
+ TEST_STATIC_LIBS Build the test suite to test the APR static
+ library instead of the APR dynamic library.
+ Default: OFF
+ In order to build the test suite against both
+ static and dynamic libraries, separate builds
+ will be required, one with TEST_STATIC_LIBS
+ set to ON.
+ INSTALL_PDB Install .pdb files if generated.
+ Default: ON
+
+ CMAKE_C_FLAGS_RELEASE, _DEBUG, _RELWITHDEBINFO, _MINSIZEREL
+
+ CMAKE_BUILD_TYPE
+
+ For NMake Makefiles the choices are at least DEBUG, RELEASE,
+ RELWITHDEBINFO, and MINSIZEREL
+ Other backends make have other selections.
+
+6. build using chosen backend (e.g., "nmake install")
+
+Known Bugs and Limitations
+--------------------------
+
+* If include/apu.h or other generated files have been created in the source
+ directory by another build system, they will be used unexpectedly and
+ cause the build to fail.
+* Options should be provided for remaining features, along with finding any
+ necessary libraries
+ + DBM:
+ . APU_HAVE_GDBM
+ . APU_HAVE_NDBM
+ . APU_HAVE_DB
+ + DBD:
+ . APU_HAVE_PGSQL
+ . APU_HAVE_MYSQL
+ . APU_HAVE_SQLITE3
+ . APU_HAVE_SQLITE2
+ . APU_HAVE_ORACLE
+ + CRYPTO:
+ . APU_HAVE_NSS
+ + XLATE, APU_HAVE_ICONV (no way to consume an apr-iconv build yet)
+* Static builds of APR modules are not supported.
+* CHANGES/LICENSE/NOTICE is not installed, unlike Makefile.win.
+ (But unlike Makefile.win we want to call them APR-Util-CHANGES.txt
+ and so on.) But perhaps that is a job for a higher-level script.
+
+Generally:
+
+* Many APR-Util features have not been tested with this build.
+* Developers need to examine the existing Windows build in great detail and see
+ what is missing from the cmake-based build, whether a feature or some build
+ nuance.
+* Any feedback you can provide on your experiences with this build will be
+ helpful.
diff --git a/apr-util.spec b/apr-util.spec
index e9dc24b08da7..18fdea1c529f 100644
--- a/apr-util.spec
+++ b/apr-util.spec
@@ -3,7 +3,7 @@
Summary: Apache Portable Runtime Utility library
Name: apr-util
-Version: 1.5.4
+Version: 1.6.1
Release: 1
License: Apache Software License
Group: System Environment/Libraries
@@ -70,16 +70,6 @@ Requires: apr-util = %{version}-%{release}
This package provides the SQLite driver for the apr-util DBD
(database abstraction) interface.
-%package freetds
-Group: Development/Libraries
-Summary: APR utility library FreeTDS DBD driver
-BuildRequires: freetds-devel
-Requires: apr-util = %{version}-%{release}
-
-%description freetds
-This package provides the FreeTDS driver for the apr-util DBD
-(database abstraction) interface.
-
%package odbc
Group: Development/Libraries
Summary: APR utility library ODBC DBD driver
@@ -124,7 +114,7 @@ This package provides crypto support for apr-util based on Mozilla NSS.
%configure --with-apr=%{_prefix} \
--includedir=%{_includedir}/apr-%{apuver} \
--with-ldap --without-gdbm \
- --with-sqlite3 --with-pgsql --with-mysql --with-freetds --with-odbc \
+ --with-sqlite3 --with-pgsql --with-mysql --with-odbc \
--with-berkeley-db \
--with-crypto --with-openssl --with-nss \
--without-sqlite2
@@ -176,10 +166,6 @@ rm -rf $RPM_BUILD_ROOT
%defattr(-,root,root,-)
%{_libdir}/apr-util-%{apuver}/apr_dbd_sqlite*
-%files freetds
-%defattr(-,root,root,-)
-%{_libdir}/apr-util-%{apuver}/apr_dbd_freetds*
-
%files odbc
%defattr(-,root,root,-)
%{_libdir}/apr-util-%{apuver}/apr_dbd_odbc*
@@ -203,7 +189,7 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/libaprutil-%{apuver}.so
%{_libdir}/pkgconfig/apr-util-%{apuver}.pc
%{_includedir}/apr-%{apuver}/*.h
-%doc --parents html
+%doc html
%changelog
* Tue Jun 22 2004 Graham Leggett <minfrin@sharp.fm> 1.0.0-1
diff --git a/aprutil.dsw b/aprutil.dsw
index 9d60aff83a8e..a2976ccc5989 100644
--- a/aprutil.dsw
+++ b/aprutil.dsw
@@ -51,24 +51,6 @@ Package=<4>
###############################################################################
-Project: "apr_dbd_freetds"=".\dbd\apr_dbd_freetds.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name libapr
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name libaprutil
- End Project Dependency
-}}}
-
-###############################################################################
-
Project: "apr_dbd_mysql"=".\dbd\apr_dbd_mysql.dsp" - Package Owner=<4>
Package=<5>
@@ -275,9 +257,6 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name apriconv
End Project Dependency
- Begin Project Dependency
- Project_Dep_Name xml
- End Project Dependency
}}}
###############################################################################
@@ -383,9 +362,6 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name libapriconv_ces_modules
End Project Dependency
- Begin Project Dependency
- Project_Dep_Name xml
- End Project Dependency
}}}
###############################################################################
@@ -453,18 +429,6 @@ Package=<4>
###############################################################################
-Project: "xml"=".\xml\expat\lib\xml.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
Global:
Package=<5>
diff --git a/apu-config.in b/apu-config.in
index e181e44ae319..82109e52d065 100644
--- a/apu-config.in
+++ b/apu-config.in
@@ -85,10 +85,6 @@ fi
if test "$location" = "installed"; then
LA_FILE="$libdir/lib${APRUTIL_LIBNAME}.la"
-
- LIBS=`echo "$LIBS" | sed -e "s $APU_BUILD_DIR/xml/expat $prefix g" -e "s $prefix/libexpat.la -lexpat g"`
- LDFLAGS=`echo "$LDFLAGS" | sed -e "s $APU_BUILD_DIR/xml/expat $prefix g"`
- INCLUDES=`echo "$INCLUDES" | sed -e "s $APU_BUILD_DIR/xml/expat $prefix g" -e "s -I$prefix/lib g"`
else
LA_FILE="$APU_BUILD_DIR/lib${APRUTIL_LIBNAME}.la"
fi
diff --git a/buckets/apr_buckets_alloc.c b/buckets/apr_buckets_alloc.c
index 15baa3396655..e5838dd016ec 100644
--- a/buckets/apr_buckets_alloc.c
+++ b/buckets/apr_buckets_alloc.c
@@ -18,6 +18,7 @@
#include "apr_buckets.h"
#include "apr_allocator.h"
+#include "apr_version.h"
#define ALLOC_AMT (8192 - APR_MEMNODE_T_SIZE)
@@ -121,6 +122,37 @@ APU_DECLARE_NONSTD(void) apr_bucket_alloc_destroy(apr_bucket_alloc_t *list)
#endif
}
+APU_DECLARE_NONSTD(apr_size_t) apr_bucket_alloc_aligned_floor(apr_bucket_alloc_t *list,
+ apr_size_t size)
+{
+ if (size <= SMALL_NODE_SIZE) {
+ size = SMALL_NODE_SIZE;
+ }
+ else {
+#if APR_VERSION_AT_LEAST(1,6,0)
+ if (size < APR_MEMNODE_T_SIZE) {
+ size = apr_allocator_align(list->allocator, 0);
+ }
+ else {
+ size = apr_allocator_align(list->allocator,
+ size - APR_MEMNODE_T_SIZE);
+ }
+#else
+ /* Assumes the minimum (default) allocator's boundary of 4K and
+ * minimum (immutable before APR-1.6.x) allocation size of 8K,
+ * hence possibly (yet unlikely) under-estimating the floor...
+ */
+ size = APR_ALIGN(size, 4096);
+ if (size < 8192) {
+ size = 8192;
+ }
+#endif
+ size -= APR_MEMNODE_T_SIZE;
+ }
+ size -= SIZEOF_NODE_HEADER_T;
+ return size;
+}
+
APU_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t size,
apr_bucket_alloc_t *list)
{
diff --git a/buckets/apr_buckets_file.c b/buckets/apr_buckets_file.c
index 0644cd82ce7a..06b7cf0039f1 100644
--- a/buckets/apr_buckets_file.c
+++ b/buckets/apr_buckets_file.c
@@ -108,10 +108,8 @@ static apr_status_t file_bucket_read(apr_bucket *e, const char **str,
}
#endif
- *len = (filelength > APR_BUCKET_BUFF_SIZE)
- ? APR_BUCKET_BUFF_SIZE
- : filelength;
*str = NULL; /* in case we die prematurely */
+ *len = (filelength > a->read_size) ? a->read_size : filelength;
buf = apr_bucket_alloc(*len, e->list);
/* Handle offset ... */
@@ -165,6 +163,7 @@ APU_DECLARE(apr_bucket *) apr_bucket_file_make(apr_bucket *b, apr_file_t *fd,
#if APR_HAS_MMAP
f->can_mmap = 1;
#endif
+ f->read_size = APR_BUCKET_BUFF_SIZE;
b = apr_bucket_shared_make(b, f, offset, len);
b->type = &apr_bucket_type_file;
@@ -197,6 +196,21 @@ APU_DECLARE(apr_status_t) apr_bucket_file_enable_mmap(apr_bucket *e,
#endif /* APR_HAS_MMAP */
}
+APU_DECLARE(apr_status_t) apr_bucket_file_set_buf_size(apr_bucket *e,
+ apr_size_t size)
+{
+ apr_bucket_file *a = e->data;
+
+ if (size <= APR_BUCKET_BUFF_SIZE) {
+ a->read_size = APR_BUCKET_BUFF_SIZE;
+ }
+ else {
+ apr_size_t floor = apr_bucket_alloc_aligned_floor(e->list, size);
+ a->read_size = (size < floor) ? size : floor;
+ }
+
+ return APR_SUCCESS;
+}
static apr_status_t file_bucket_setaside(apr_bucket *data, apr_pool_t *reqpool)
{
diff --git a/build-outputs.mk b/build-outputs.mk
index b624532ebd2b..f6042d6b8ce1 100644
--- a/build-outputs.mk
+++ b/build-outputs.mk
@@ -18,6 +18,7 @@ crypto/apr_md4.lo: crypto/apr_md4.c .make.dirs include/apr_md4.h include/apr_xla
crypto/apr_md5.lo: crypto/apr_md5.c .make.dirs include/apr_md5.h include/apr_xlate.h
crypto/apr_passwd.lo: crypto/apr_passwd.c .make.dirs include/apr_md5.h include/apr_sha1.h include/apr_xlate.h
crypto/apr_sha1.lo: crypto/apr_sha1.c .make.dirs include/apr_base64.h include/apr_sha1.h include/apr_xlate.h
+crypto/apr_siphash.lo: crypto/apr_siphash.c .make.dirs include/apr_siphash.h
crypto/crypt_blowfish.lo: crypto/crypt_blowfish.c .make.dirs
crypto/getuuid.lo: crypto/getuuid.c .make.dirs include/apr_md5.h include/apr_uuid.h include/apr_xlate.h
crypto/uuid.lo: crypto/uuid.c .make.dirs include/apr_uuid.h
@@ -40,12 +41,13 @@ misc/apr_rmm.lo: misc/apr_rmm.c .make.dirs include/apr_anylock.h include/apr_rmm
misc/apr_thread_pool.lo: misc/apr_thread_pool.c .make.dirs include/apr_thread_pool.h
misc/apu_dso.lo: misc/apu_dso.c .make.dirs include/apu_version.h include/private/apu_internal.h
misc/apu_version.lo: misc/apu_version.c .make.dirs include/apu_version.h
+redis/apr_redis.lo: redis/apr_redis.c .make.dirs include/apr_buckets.h include/apr_redis.h include/apr_reslist.h
strmatch/apr_strmatch.lo: strmatch/apr_strmatch.c .make.dirs include/apr_strmatch.h
uri/apr_uri.lo: uri/apr_uri.c .make.dirs include/apr_uri.h
xlate/xlate.lo: xlate/xlate.c .make.dirs include/apr_xlate.h
xml/apr_xml.lo: xml/apr_xml.c .make.dirs include/apr_xlate.h include/apr_xml.h
-OBJECTS_all = buckets/apr_brigade.lo buckets/apr_buckets.lo buckets/apr_buckets_alloc.lo buckets/apr_buckets_eos.lo buckets/apr_buckets_file.lo buckets/apr_buckets_flush.lo buckets/apr_buckets_heap.lo buckets/apr_buckets_mmap.lo buckets/apr_buckets_pipe.lo buckets/apr_buckets_pool.lo buckets/apr_buckets_refcount.lo buckets/apr_buckets_simple.lo buckets/apr_buckets_socket.lo crypto/apr_crypto.lo crypto/apr_md4.lo crypto/apr_md5.lo crypto/apr_passwd.lo crypto/apr_sha1.lo crypto/crypt_blowfish.lo crypto/getuuid.lo crypto/uuid.lo dbd/apr_dbd.lo dbm/apr_dbm.lo dbm/apr_dbm_sdbm.lo dbm/sdbm/sdbm.lo dbm/sdbm/sdbm_hash.lo dbm/sdbm/sdbm_lock.lo dbm/sdbm/sdbm_pair.lo encoding/apr_base64.lo hooks/apr_hooks.lo ldap/apr_ldap_stub.lo ldap/apr_ldap_url.lo memcache/apr_memcache.lo misc/apr_date.lo misc/apr_queue.lo misc/apr_reslist.lo misc/apr_rmm.lo misc/apr_thread_pool.lo misc/apu_dso.lo misc/apu_version.lo strmatch/apr_strmatch.lo uri/apr_uri.lo xlate/xlate.lo xml/apr_xml.lo
+OBJECTS_all = buckets/apr_brigade.lo buckets/apr_buckets.lo buckets/apr_buckets_alloc.lo buckets/apr_buckets_eos.lo buckets/apr_buckets_file.lo buckets/apr_buckets_flush.lo buckets/apr_buckets_heap.lo buckets/apr_buckets_mmap.lo buckets/apr_buckets_pipe.lo buckets/apr_buckets_pool.lo buckets/apr_buckets_refcount.lo buckets/apr_buckets_simple.lo buckets/apr_buckets_socket.lo crypto/apr_crypto.lo crypto/apr_md4.lo crypto/apr_md5.lo crypto/apr_passwd.lo crypto/apr_sha1.lo crypto/apr_siphash.lo crypto/crypt_blowfish.lo crypto/getuuid.lo crypto/uuid.lo dbd/apr_dbd.lo dbm/apr_dbm.lo dbm/apr_dbm_sdbm.lo dbm/sdbm/sdbm.lo dbm/sdbm/sdbm_hash.lo dbm/sdbm/sdbm_lock.lo dbm/sdbm/sdbm_pair.lo encoding/apr_base64.lo hooks/apr_hooks.lo ldap/apr_ldap_stub.lo ldap/apr_ldap_url.lo memcache/apr_memcache.lo misc/apr_date.lo misc/apr_queue.lo misc/apr_reslist.lo misc/apr_rmm.lo misc/apr_thread_pool.lo misc/apu_dso.lo misc/apu_version.lo redis/apr_redis.lo strmatch/apr_strmatch.lo uri/apr_uri.lo xlate/xlate.lo xml/apr_xml.lo
OBJECTS_unix = $(OBJECTS_all)
@@ -59,9 +61,9 @@ OBJECTS_os390 = $(OBJECTS_all)
OBJECTS_win32 = $(OBJECTS_all)
-HEADERS = $(top_srcdir)/include/apr_anylock.h $(top_srcdir)/include/apr_base64.h $(top_srcdir)/include/apr_buckets.h $(top_srcdir)/include/apr_crypto.h $(top_srcdir)/include/apr_date.h $(top_srcdir)/include/apr_dbd.h $(top_srcdir)/include/apr_dbm.h $(top_srcdir)/include/apr_hooks.h $(top_srcdir)/include/apr_ldap_init.h $(top_srcdir)/include/apr_ldap_option.h $(top_srcdir)/include/apr_ldap_rebind.h $(top_srcdir)/include/apr_ldap_url.h $(top_srcdir)/include/apr_md4.h $(top_srcdir)/include/apr_md5.h $(top_srcdir)/include/apr_memcache.h $(top_srcdir)/include/apr_optional.h $(top_srcdir)/include/apr_optional_hooks.h $(top_srcdir)/include/apr_queue.h $(top_srcdir)/include/apr_reslist.h $(top_srcdir)/include/apr_rmm.h $(top_srcdir)/include/apr_sdbm.h $(top_srcdir)/include/apr_sha1.h $(top_srcdir)/include/apr_strmatch.h $(top_srcdir)/include/apr_thread_pool.h $(top_srcdir)/include/apr_uri.h $(top_srcdir)/include/apr_uuid.h $(top_srcdir)/include/apr_xlate.h $(top_srcdir)/include/apr_xml.h $(top_srcdir)/include/apu_errno.h $(top_srcdir)/include/apu_version.h $(top_srcdir)/include/private/apr_crypto_internal.h $(top_srcdir)/include/private/apr_dbd_internal.h $(top_srcdir)/include/private/apr_dbd_odbc_v2.h $(top_srcdir)/include/private/apr_dbm_private.h $(top_srcdir)/include/private/apu_internal.h
+HEADERS = $(top_srcdir)/include/apr_anylock.h $(top_srcdir)/include/apr_base64.h $(top_srcdir)/include/apr_buckets.h $(top_srcdir)/include/apr_crypto.h $(top_srcdir)/include/apr_date.h $(top_srcdir)/include/apr_dbd.h $(top_srcdir)/include/apr_dbm.h $(top_srcdir)/include/apr_hooks.h $(top_srcdir)/include/apr_ldap_init.h $(top_srcdir)/include/apr_ldap_option.h $(top_srcdir)/include/apr_ldap_rebind.h $(top_srcdir)/include/apr_ldap_url.h $(top_srcdir)/include/apr_md4.h $(top_srcdir)/include/apr_md5.h $(top_srcdir)/include/apr_memcache.h $(top_srcdir)/include/apr_optional.h $(top_srcdir)/include/apr_optional_hooks.h $(top_srcdir)/include/apr_queue.h $(top_srcdir)/include/apr_redis.h $(top_srcdir)/include/apr_reslist.h $(top_srcdir)/include/apr_rmm.h $(top_srcdir)/include/apr_sdbm.h $(top_srcdir)/include/apr_sha1.h $(top_srcdir)/include/apr_siphash.h $(top_srcdir)/include/apr_strmatch.h $(top_srcdir)/include/apr_thread_pool.h $(top_srcdir)/include/apr_uri.h $(top_srcdir)/include/apr_uuid.h $(top_srcdir)/include/apr_xlate.h $(top_srcdir)/include/apr_xml.h $(top_srcdir)/include/apu_errno.h $(top_srcdir)/include/apu_version.h $(top_srcdir)/include/private/apr_crypto_internal.h $(top_srcdir)/include/private/apr_dbd_internal.h $(top_srcdir)/include/private/apr_dbd_odbc_v2.h $(top_srcdir)/include/private/apr_dbm_private.h $(top_srcdir)/include/private/apu_internal.h
-SOURCE_DIRS = xml dbm encoding hooks buckets uri misc crypto dbd strmatch memcache dbm/sdbm ldap xlate $(EXTRA_SOURCE_DIRS)
+SOURCE_DIRS = xml redis dbm encoding hooks buckets uri misc crypto dbd strmatch memcache dbm/sdbm ldap xlate $(EXTRA_SOURCE_DIRS)
ldap/apr_ldap_init.lo: ldap/apr_ldap_init.c .make.dirs include/private/apu_internal.h
ldap/apr_ldap_option.lo: ldap/apr_ldap_option.c .make.dirs
@@ -83,6 +85,12 @@ MODULE_crypto_nss = crypto/apr_crypto_nss.la
crypto/apr_crypto_nss.la: crypto/apr_crypto_nss.lo
$(LINK_MODULE) -o $@ $(OBJECTS_crypto_nss) $(LDADD_crypto_nss)
+crypto/apr_crypto_commoncrypto.lo: crypto/apr_crypto_commoncrypto.c .make.dirs include/apr_buckets.h include/apr_crypto.h include/apu_errno.h include/private/apr_crypto_internal.h
+OBJECTS_crypto_commoncrypto = crypto/apr_crypto_commoncrypto.lo
+MODULE_crypto_commoncrypto = crypto/apr_crypto_commoncrypto.la
+crypto/apr_crypto_commoncrypto.la: crypto/apr_crypto_commoncrypto.lo
+ $(LINK_MODULE) -o $@ $(OBJECTS_crypto_commoncrypto) $(LDADD_crypto_commoncrypto)
+
dbd/apr_dbd_pgsql.lo: dbd/apr_dbd_pgsql.c .make.dirs include/apr_buckets.h include/apr_dbd.h include/private/apr_dbd_internal.h
OBJECTS_dbd_pgsql = dbd/apr_dbd_pgsql.lo
MODULE_dbd_pgsql = dbd/apr_dbd_pgsql.la
@@ -113,12 +121,6 @@ MODULE_dbd_mysql = dbd/apr_dbd_mysql.la
dbd/apr_dbd_mysql.la: dbd/apr_dbd_mysql.lo
$(LINK_MODULE) -o $@ $(OBJECTS_dbd_mysql) $(LDADD_dbd_mysql)
-dbd/apr_dbd_freetds.lo: dbd/apr_dbd_freetds.c .make.dirs include/apr_dbd.h include/private/apr_dbd_internal.h
-OBJECTS_dbd_freetds = dbd/apr_dbd_freetds.lo
-MODULE_dbd_freetds = dbd/apr_dbd_freetds.la
-dbd/apr_dbd_freetds.la: dbd/apr_dbd_freetds.lo
- $(LINK_MODULE) -o $@ $(OBJECTS_dbd_freetds) $(LDADD_dbd_freetds)
-
dbd/apr_dbd_odbc.lo: dbd/apr_dbd_odbc.c .make.dirs include/apr_buckets.h include/apr_dbd.h include/apu_version.h include/private/apr_dbd_internal.h include/private/apr_dbd_odbc_v2.h
OBJECTS_dbd_odbc = dbd/apr_dbd_odbc.lo
MODULE_dbd_odbc = dbd/apr_dbd_odbc.la
@@ -143,7 +145,7 @@ MODULE_dbm_ndbm = dbm/apr_dbm_ndbm.la
dbm/apr_dbm_ndbm.la: dbm/apr_dbm_ndbm.lo
$(LINK_MODULE) -o $@ $(OBJECTS_dbm_ndbm) $(LDADD_dbm_ndbm)
-BUILD_DIRS = buckets crypto dbd dbm dbm/sdbm encoding hooks ldap memcache misc strmatch uri xlate xml
+BUILD_DIRS = buckets crypto dbd dbm dbm/sdbm encoding hooks ldap memcache misc redis strmatch uri xlate xml
.make.dirs: $(srcdir)/build-outputs.mk
@for d in $(BUILD_DIRS); do test -d $$d || mkdir $$d; done
diff --git a/build.conf b/build.conf
index d34d004fe33a..86e8c346df47 100644
--- a/build.conf
+++ b/build.conf
@@ -12,6 +12,7 @@ paths =
crypto/apr_md5.c
crypto/apr_passwd.c
crypto/apr_sha1.c
+ crypto/apr_siphash.c
crypto/getuuid.c
crypto/uuid.c
crypto/crypt_blowfish.c
@@ -24,6 +25,7 @@ paths =
ldap/apr_ldap_url.c
misc/*.c
memcache/*.c
+ redis/*.c
uri/apr_uri.c
xml/*.c
strmatch/*.c
@@ -37,8 +39,8 @@ platform_dirs =
headers = include/*.h include/private/*.h
modules =
- ldap crypto_openssl crypto_nss dbd_pgsql
- dbd_sqlite2 dbd_sqlite3 dbd_oracle dbd_mysql dbd_freetds dbd_odbc
+ ldap crypto_openssl crypto_nss crypto_commoncrypto dbd_pgsql
+ dbd_sqlite2 dbd_sqlite3 dbd_oracle dbd_mysql dbd_odbc
dbm_db dbm_gdbm dbm_ndbm
# gen_uri_delim.c
@@ -46,6 +48,10 @@ modules =
# we have a recursive makefile for the test files (for now)
# test/*.c
+[crypto_commoncrypto]
+paths = crypto/apr_crypto_commoncrypto.c
+target = crypto/apr_crypto_commoncrypto.la
+
[crypto_openssl]
paths = crypto/apr_crypto_openssl.c
target = crypto/apr_crypto_openssl.la
@@ -74,10 +80,6 @@ target = dbd/apr_dbd_oracle.la
paths = dbd/apr_dbd_mysql.c
target = dbd/apr_dbd_mysql.la
-[dbd_freetds]
-paths = dbd/apr_dbd_freetds.c
-target = dbd/apr_dbd_freetds.la
-
[dbd_odbc]
paths = dbd/apr_dbd_odbc.c
target = dbd/apr_dbd_odbc.la
diff --git a/buildconf b/buildconf
index 5d6536f5cf32..3abfe105f6ee 100755
--- a/buildconf
+++ b/buildconf
@@ -89,14 +89,6 @@ fi
echo "Generating 'make' outputs ..."
$apr_src_dir/build/gen-build.py $verbose make
-#
-# If Expat has been bundled, then go and configure the thing
-#
-if [ -f xml/expat/buildconf.sh ]; then
- echo "Invoking xml/expat/buildconf.sh ..."
- (cd xml/expat; ./buildconf.sh $verbose)
-fi
-
# Remove autoconf cache again
rm -rf autom4te*.cache
@@ -114,3 +106,13 @@ if [ -f `which cut` ]; then
./build/rpm/apr-util.spec.in > apr-util.spec
fi
+# Verify the tree was clean, notify user if not (normal in development)
+#
+if [ -f "include/apu.h" -o -f "include/private/apu_config.h" -o \
+ -f "include/apu_want.h" -o -f "include/private/apu_select_dbm.h" ]; then
+ echo ""
+ echo "Generated include files already exist, the tree is not clean."
+ echo "The resulting build-outputs.mk file is incorrect"
+fi
+
+exit 0
diff --git a/configure b/configure
index 8ddd0e88f058..7a1f02696076 100755
--- a/configure
+++ b/configure
@@ -637,13 +637,10 @@ lib_target
so_ext
have_apr_iconv
have_iconv
-APR_XML_DIR
apu_dbd_tests
LDADD_dbd_odbc
apu_have_odbc
ODBC_CONFIG
-LDADD_dbd_freetds
-apu_have_freetds
LDADD_dbd_oracle
apu_have_oracle
LDADD_dbd_sqlite2
@@ -690,6 +687,8 @@ apu_has_ldapssl_client_init
ldap_ssl_h
lber_h
ldap_h
+LDADD_crypto_commoncrypto
+apu_have_commoncrypto
LDADD_crypto_nss
apu_have_nss
PKG_CONFIG
@@ -781,6 +780,7 @@ with_apr_iconv
with_crypto
with_openssl
with_nss
+with_commoncrypto
with_lber
with_ldap_include
with_ldap_lib
@@ -795,7 +795,6 @@ with_sqlite3
with_sqlite2
with_oracle_include
with_oracle
-with_freetds
with_odbc
with_expat
with_iconv
@@ -1435,6 +1434,7 @@ Optional Packages:
--with-crypto enable crypto support
--with-openssl=DIR specify location of OpenSSL
--with-nss=DIR specify location of NSS
+ --with-commoncrypto=DIR specify location of CommonCrypto
--with-lber=library lber library to use
--with-ldap-include=path path to ldap include files with trailing slash
--with-ldap-lib=path path to ldap lib file
@@ -1463,9 +1463,8 @@ Optional Packages:
--with-oracle-include=DIR
path to Oracle include files
--with-oracle=DIR enable Oracle DBD driver; giving ORACLE_HOME as DIR
- --with-freetds=DIR specify FreeTDS location
--with-odbc=DIR specify ODBC location
- --with-expat=DIR specify Expat location, or 'builtin'
+ --with-expat=DIR specify Expat location
--with-iconv=DIR path to iconv installation
Some influential environment variables:
@@ -2510,6 +2509,8 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
rm -f config.nice
cat >config.nice<<EOF
#! /bin/sh
@@ -4739,6 +4740,7 @@ done
apu_have_crypto=0
apu_have_openssl=0
apu_have_nss=0
+ apu_have_commoncrypto=0
old_libs="$LIBS"
old_cppflags="$CPPFLAGS"
@@ -4748,7 +4750,7 @@ done
# Check whether --with-crypto was given.
if test "${with_crypto+set}" = set; then :
withval=$with_crypto;
- cryptolibs="openssl nss"
+ cryptolibs="openssl nss commoncrypto"
if test "$withval" = "yes"; then
@@ -4801,9 +4803,9 @@ fi
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BN_init in -lcrypto" >&5
-$as_echo_n "checking for BN_init in -lcrypto... " >&6; }
-if ${ac_cv_lib_crypto_BN_init+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_CIPHER_CTX_new in -lcrypto" >&5
+$as_echo_n "checking for EVP_CIPHER_CTX_new in -lcrypto... " >&6; }
+if ${ac_cv_lib_crypto_EVP_CIPHER_CTX_new+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
@@ -4817,27 +4819,27 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char BN_init ();
+char EVP_CIPHER_CTX_new ();
int
main ()
{
-return BN_init ();
+return EVP_CIPHER_CTX_new ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_crypto_BN_init=yes
+ ac_cv_lib_crypto_EVP_CIPHER_CTX_new=yes
else
- ac_cv_lib_crypto_BN_init=no
+ ac_cv_lib_crypto_EVP_CIPHER_CTX_new=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_BN_init" >&5
-$as_echo "$ac_cv_lib_crypto_BN_init" >&6; }
-if test "x$ac_cv_lib_crypto_BN_init" = xyes; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EVP_CIPHER_CTX_new" >&5
+$as_echo "$ac_cv_lib_crypto_EVP_CIPHER_CTX_new" >&6; }
+if test "x$ac_cv_lib_crypto_EVP_CIPHER_CTX_new" = xyes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_accept in -lssl" >&5
$as_echo_n "checking for SSL_accept in -lssl... " >&6; }
if ${ac_cv_lib_ssl_SSL_accept+:} false; then :
@@ -4947,9 +4949,9 @@ fi
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BN_init in -lcrypto" >&5
-$as_echo_n "checking for BN_init in -lcrypto... " >&6; }
-if ${ac_cv_lib_crypto_BN_init+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_CIPHER_CTX_new in -lcrypto" >&5
+$as_echo_n "checking for EVP_CIPHER_CTX_new in -lcrypto... " >&6; }
+if ${ac_cv_lib_crypto_EVP_CIPHER_CTX_new+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
@@ -4963,27 +4965,27 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char BN_init ();
+char EVP_CIPHER_CTX_new ();
int
main ()
{
-return BN_init ();
+return EVP_CIPHER_CTX_new ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_crypto_BN_init=yes
+ ac_cv_lib_crypto_EVP_CIPHER_CTX_new=yes
else
- ac_cv_lib_crypto_BN_init=no
+ ac_cv_lib_crypto_EVP_CIPHER_CTX_new=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_BN_init" >&5
-$as_echo "$ac_cv_lib_crypto_BN_init" >&6; }
-if test "x$ac_cv_lib_crypto_BN_init" = xyes; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EVP_CIPHER_CTX_new" >&5
+$as_echo "$ac_cv_lib_crypto_EVP_CIPHER_CTX_new" >&6; }
+if test "x$ac_cv_lib_crypto_EVP_CIPHER_CTX_new" = xyes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_accept in -lssl" >&5
$as_echo_n "checking for SSL_accept in -lssl... " >&6; }
if ${ac_cv_lib_ssl_SSL_accept+:} false; then :
@@ -5072,145 +5074,6 @@ fi
fi
- if test "$apu_have_openssl" != "1"; then
- for ac_header in openssl/x509.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "openssl/x509.h" "ac_cv_header_openssl_x509_h" "$ac_includes_default"
-if test "x$ac_cv_header_openssl_x509_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_OPENSSL_X509_H 1
-_ACEOF
- openssl_have_headers=1
-fi
-
-done
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BN_init in -lcrypto" >&5
-$as_echo_n "checking for BN_init in -lcrypto... " >&6; }
-if ${ac_cv_lib_crypto_BN_init+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypto $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char BN_init ();
-int
-main ()
-{
-return BN_init ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_crypto_BN_init=yes
-else
- ac_cv_lib_crypto_BN_init=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_BN_init" >&5
-$as_echo "$ac_cv_lib_crypto_BN_init" >&6; }
-if test "x$ac_cv_lib_crypto_BN_init" = xyes; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_accept in -lssl" >&5
-$as_echo_n "checking for SSL_accept in -lssl... " >&6; }
-if ${ac_cv_lib_ssl_SSL_accept+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lssl -lcrypto $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char SSL_accept ();
-int
-main ()
-{
-return SSL_accept ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_ssl_SSL_accept=yes
-else
- ac_cv_lib_ssl_SSL_accept=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_accept" >&5
-$as_echo "$ac_cv_lib_ssl_SSL_accept" >&6; }
-if test "x$ac_cv_lib_ssl_SSL_accept" = xyes; then :
- openssl_have_libs=1
-fi
-
-fi
-
- if test "$openssl_have_headers" != "0" && test "$openssl_have_libs" != "0"; then
- apu_have_openssl=1
-
- if test "x$APRUTIL_LDFLAGS" = "x"; then
- test "x$silent" != "xyes" && echo " setting APRUTIL_LDFLAGS to \"-L$withval/lib\""
- APRUTIL_LDFLAGS="-L$withval/lib"
- else
- apr_addto_bugger="-L$withval/lib"
- for i in $apr_addto_bugger; do
- apr_addto_duplicate="0"
- for j in $APRUTIL_LDFLAGS; do
- if test "x$i" = "x$j"; then
- apr_addto_duplicate="1"
- break
- fi
- done
- if test $apr_addto_duplicate = "0"; then
- test "x$silent" != "xyes" && echo " adding \"$i\" to APRUTIL_LDFLAGS"
- APRUTIL_LDFLAGS="$APRUTIL_LDFLAGS $i"
- fi
- done
- fi
-
-
- if test "x$APRUTIL_INCLUDES" = "x"; then
- test "x$silent" != "xyes" && echo " setting APRUTIL_INCLUDES to \"-I$withval/include\""
- APRUTIL_INCLUDES="-I$withval/include"
- else
- apr_addto_bugger="-I$withval/include"
- for i in $apr_addto_bugger; do
- apr_addto_duplicate="0"
- for j in $APRUTIL_INCLUDES; do
- if test "x$i" = "x$j"; then
- apr_addto_duplicate="1"
- break
- fi
- done
- if test $apr_addto_duplicate = "0"; then
- test "x$silent" != "xyes" && echo " adding \"$i\" to APRUTIL_INCLUDES"
- APRUTIL_INCLUDES="$APRUTIL_INCLUDES $i"
- fi
- done
- fi
-
- fi
- fi
-
ac_fn_c_check_decl "$LINENO" "EVP_PKEY_CTX_new" "ac_cv_have_decl_EVP_PKEY_CTX_new" "#include <openssl/evp.h>
"
if test "x$ac_cv_have_decl_EVP_PKEY_CTX_new" = xyes; then :
@@ -5824,8 +5687,325 @@ fi
CPPFLAGS="$old_cppflags"
LDFLAGS="$old_ldflags"
+
+ apu_have_commoncrypto=0
+ commoncrypto_have_headers=0
+ commoncrypto_have_libs=0
+
+ old_libs="$LIBS"
+ old_cppflags="$CPPFLAGS"
+ old_ldflags="$LDFLAGS"
+
+
+# Check whether --with-commoncrypto was given.
+if test "${with_commoncrypto+set}" = set; then :
+ withval=$with_commoncrypto;
+ if test "$withval" = "yes"; then
+ for ac_header in CommonCrypto/CommonKeyDerivation.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "CommonCrypto/CommonKeyDerivation.h" "ac_cv_header_CommonCrypto_CommonKeyDerivation_h" "$ac_includes_default"
+if test "x$ac_cv_header_CommonCrypto_CommonKeyDerivation_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_COMMONCRYPTO_COMMONKEYDERIVATION_H 1
+_ACEOF
+ commoncrypto_have_headers=1
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CCKeyDerivationPBKDF in -lSystem" >&5
+$as_echo_n "checking for CCKeyDerivationPBKDF in -lSystem... " >&6; }
+if ${ac_cv_lib_System_CCKeyDerivationPBKDF+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lSystem $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char CCKeyDerivationPBKDF ();
+int
+main ()
+{
+return CCKeyDerivationPBKDF ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_System_CCKeyDerivationPBKDF=yes
+else
+ ac_cv_lib_System_CCKeyDerivationPBKDF=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_System_CCKeyDerivationPBKDF" >&5
+$as_echo "$ac_cv_lib_System_CCKeyDerivationPBKDF" >&6; }
+if test "x$ac_cv_lib_System_CCKeyDerivationPBKDF" = xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CCCryptorCreate in -lSystem" >&5
+$as_echo_n "checking for CCCryptorCreate in -lSystem... " >&6; }
+if ${ac_cv_lib_System_CCCryptorCreate+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lSystem -lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char CCCryptorCreate ();
+int
+main ()
+{
+return CCCryptorCreate ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_System_CCCryptorCreate=yes
+else
+ ac_cv_lib_System_CCCryptorCreate=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_System_CCCryptorCreate" >&5
+$as_echo "$ac_cv_lib_System_CCCryptorCreate" >&6; }
+if test "x$ac_cv_lib_System_CCCryptorCreate" = xyes; then :
+ commoncrypto_have_libs=1
+fi
+
+fi
+
+ if test "$commoncrypto_have_headers" != "0" && test "$commoncrypto_have_libs" != "0"; then
+ apu_have_commoncrypto=1
+ fi
+ elif test "$withval" = "no"; then
+ apu_have_commoncrypto=0
+ else
+
+ commoncrypto_CPPFLAGS="-I$withval/include"
+ commoncrypto_LDFLAGS="-L$withval/lib "
+
+
+ if test "x$CPPFLAGS" = "x"; then
+ test "x$silent" != "xyes" && echo " setting CPPFLAGS to \"$commoncrypto_CPPFLAGS\""
+ CPPFLAGS="$commoncrypto_CPPFLAGS"
+ else
+ apr_addto_bugger="$commoncrypto_CPPFLAGS"
+ for i in $apr_addto_bugger; do
+ apr_addto_duplicate="0"
+ for j in $CPPFLAGS; do
+ if test "x$i" = "x$j"; then
+ apr_addto_duplicate="1"
+ break
+ fi
+ done
+ if test $apr_addto_duplicate = "0"; then
+ test "x$silent" != "xyes" && echo " adding \"$i\" to CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $i"
+ fi
+ done
+ fi
+
+
+ if test "x$LDFLAGS" = "x"; then
+ test "x$silent" != "xyes" && echo " setting LDFLAGS to \"$commoncrypto_LDFLAGS\""
+ LDFLAGS="$commoncrypto_LDFLAGS"
+ else
+ apr_addto_bugger="$commoncrypto_LDFLAGS"
+ for i in $apr_addto_bugger; do
+ apr_addto_duplicate="0"
+ for j in $LDFLAGS; do
+ if test "x$i" = "x$j"; then
+ apr_addto_duplicate="1"
+ break
+ fi
+ done
+ if test $apr_addto_duplicate = "0"; then
+ test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS"
+ LDFLAGS="$LDFLAGS $i"
+ fi
+ done
+ fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for commoncrypto in $withval" >&5
+$as_echo "$as_me: checking for commoncrypto in $withval" >&6;}
+ for ac_header in CommonCrypto/CommonKeyDerivation.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "CommonCrypto/CommonKeyDerivation.h" "ac_cv_header_CommonCrypto_CommonKeyDerivation_h" "$ac_includes_default"
+if test "x$ac_cv_header_CommonCrypto_CommonKeyDerivation_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_COMMONCRYPTO_COMMONKEYDERIVATION_H 1
+_ACEOF
+ commoncrypto_have_headers=1
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CCKeyDerivationPBKDF in -lSystem" >&5
+$as_echo_n "checking for CCKeyDerivationPBKDF in -lSystem... " >&6; }
+if ${ac_cv_lib_System_CCKeyDerivationPBKDF+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lSystem $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char CCKeyDerivationPBKDF ();
+int
+main ()
+{
+return CCKeyDerivationPBKDF ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_System_CCKeyDerivationPBKDF=yes
+else
+ ac_cv_lib_System_CCKeyDerivationPBKDF=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_System_CCKeyDerivationPBKDF" >&5
+$as_echo "$ac_cv_lib_System_CCKeyDerivationPBKDF" >&6; }
+if test "x$ac_cv_lib_System_CCKeyDerivationPBKDF" = xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CCCryptorCreate in -lSystem" >&5
+$as_echo_n "checking for CCCryptorCreate in -lSystem... " >&6; }
+if ${ac_cv_lib_System_CCCryptorCreate+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lSystem -lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char CCCryptorCreate ();
+int
+main ()
+{
+return CCCryptorCreate ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_System_CCCryptorCreate=yes
+else
+ ac_cv_lib_System_CCCryptorCreate=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_System_CCCryptorCreate" >&5
+$as_echo "$ac_cv_lib_System_CCCryptorCreate" >&6; }
+if test "x$ac_cv_lib_System_CCCryptorCreate" = xyes; then :
+ commoncrypto_have_libs=1
+fi
+
+fi
+
+ if test "$commoncrypto_have_headers" != "0" && test "$commoncrypto_have_libs" != "0"; then
+ apu_have_commoncrypto=1
+
+ if test "x$LDFLAGS" = "x"; then
+ test "x$silent" != "xyes" && echo " setting LDFLAGS to \"-L$withval/lib\""
+ LDFLAGS="-L$withval/lib"
+ else
+ apr_addto_bugger="-L$withval/lib"
+ for i in $apr_addto_bugger; do
+ apr_addto_duplicate="0"
+ for j in $LDFLAGS; do
+ if test "x$i" = "x$j"; then
+ apr_addto_duplicate="1"
+ break
+ fi
+ done
+ if test $apr_addto_duplicate = "0"; then
+ test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS"
+ LDFLAGS="$LDFLAGS $i"
+ fi
+ done
+ fi
+
+
+ if test "x$INCLUDES" = "x"; then
+ test "x$silent" != "xyes" && echo " setting INCLUDES to \"-I$withval/include\""
+ INCLUDES="-I$withval/include"
+ else
+ apr_addto_bugger="-I$withval/include"
+ for i in $apr_addto_bugger; do
+ apr_addto_duplicate="0"
+ for j in $INCLUDES; do
+ if test "x$i" = "x$j"; then
+ apr_addto_duplicate="1"
+ break
+ fi
+ done
+ if test $apr_addto_duplicate = "0"; then
+ test "x$silent" != "xyes" && echo " adding \"$i\" to INCLUDES"
+ INCLUDES="$INCLUDES $i"
+ fi
+ done
+ fi
+
+ fi
+
+ fi
+
+else
+
+ apu_have_commoncrypto=0
+
+fi
+
+
+ if test "$apu_have_commoncrypto" = "1"; then
+ apu_have_crypto=1
+ fi
+
+
+
+
+ LIBS="$old_libs"
+ CPPFLAGS="$old_cppflags"
+ LDFLAGS="$old_ldflags"
+
if test "$apu_have_crypto" = "0"; then
- as_fn_error $? "Crypto was requested but no crypto library could be enabled; specify the location of a crypto library using --with-openssl, --with-nss, etc." "$LINENO" 5
+ as_fn_error $? "Crypto was requested but no crypto library could be enabled; specify the location of a crypto library using --with-openssl, --with-nss, and/or --with-commoncrypto." "$LINENO" 5
fi
fi
@@ -19946,13 +20126,13 @@ if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient_r" >&5
-$as_echo_n "checking for mysql_init in -lmysqlclient_r... " >&6; }
-if ${ac_cv_lib_mysqlclient_r_mysql_init+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient" >&5
+$as_echo_n "checking for mysql_init in -lmysqlclient... " >&6; }
+if ${ac_cv_lib_mysqlclient_mysql_init+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
-LIBS="-lmysqlclient_r $LIBS"
+LIBS="-lmysqlclient $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -19972,17 +20152,17 @@ return mysql_init ();
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_mysqlclient_r_mysql_init=yes
+ ac_cv_lib_mysqlclient_mysql_init=yes
else
- ac_cv_lib_mysqlclient_r_mysql_init=no
+ ac_cv_lib_mysqlclient_mysql_init=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_r_mysql_init" >&5
-$as_echo "$ac_cv_lib_mysqlclient_r_mysql_init" >&6; }
-if test "x$ac_cv_lib_mysqlclient_r_mysql_init" = xyes; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_init" >&5
+$as_echo "$ac_cv_lib_mysqlclient_mysql_init" >&6; }
+if test "x$ac_cv_lib_mysqlclient_mysql_init" = xyes; then :
apu_have_mysql=1
fi
@@ -20002,13 +20182,13 @@ if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient_r" >&5
-$as_echo_n "checking for mysql_init in -lmysqlclient_r... " >&6; }
-if ${ac_cv_lib_mysqlclient_r_mysql_init+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient" >&5
+$as_echo_n "checking for mysql_init in -lmysqlclient... " >&6; }
+if ${ac_cv_lib_mysqlclient_mysql_init+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
-LIBS="-lmysqlclient_r $LIBS"
+LIBS="-lmysqlclient $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -20028,17 +20208,17 @@ return mysql_init ();
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_mysqlclient_r_mysql_init=yes
+ ac_cv_lib_mysqlclient_mysql_init=yes
else
- ac_cv_lib_mysqlclient_r_mysql_init=no
+ ac_cv_lib_mysqlclient_mysql_init=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_r_mysql_init" >&5
-$as_echo "$ac_cv_lib_mysqlclient_r_mysql_init" >&6; }
-if test "x$ac_cv_lib_mysqlclient_r_mysql_init" = xyes; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_init" >&5
+$as_echo "$ac_cv_lib_mysqlclient_mysql_init" >&6; }
+if test "x$ac_cv_lib_mysqlclient_mysql_init" = xyes; then :
apu_have_mysql=1
fi
@@ -20199,13 +20379,13 @@ if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient_r" >&5
-$as_echo_n "checking for mysql_init in -lmysqlclient_r... " >&6; }
-if ${ac_cv_lib_mysqlclient_r_mysql_init+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient" >&5
+$as_echo_n "checking for mysql_init in -lmysqlclient... " >&6; }
+if ${ac_cv_lib_mysqlclient_mysql_init+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
-LIBS="-lmysqlclient_r $LIBS"
+LIBS="-lmysqlclient $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -20225,17 +20405,17 @@ return mysql_init ();
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_mysqlclient_r_mysql_init=yes
+ ac_cv_lib_mysqlclient_mysql_init=yes
else
- ac_cv_lib_mysqlclient_r_mysql_init=no
+ ac_cv_lib_mysqlclient_mysql_init=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_r_mysql_init" >&5
-$as_echo "$ac_cv_lib_mysqlclient_r_mysql_init" >&6; }
-if test "x$ac_cv_lib_mysqlclient_r_mysql_init" = xyes; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_init" >&5
+$as_echo "$ac_cv_lib_mysqlclient_mysql_init" >&6; }
+if test "x$ac_cv_lib_mysqlclient_mysql_init" = xyes; then :
apu_have_mysql=1
fi
@@ -20256,13 +20436,13 @@ if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient_r" >&5
-$as_echo_n "checking for mysql_init in -lmysqlclient_r... " >&6; }
-if ${ac_cv_lib_mysqlclient_r_mysql_init+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient" >&5
+$as_echo_n "checking for mysql_init in -lmysqlclient... " >&6; }
+if ${ac_cv_lib_mysqlclient_mysql_init+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
-LIBS="-lmysqlclient_r $LIBS"
+LIBS="-lmysqlclient $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -20282,17 +20462,17 @@ return mysql_init ();
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_mysqlclient_r_mysql_init=yes
+ ac_cv_lib_mysqlclient_mysql_init=yes
else
- ac_cv_lib_mysqlclient_r_mysql_init=no
+ ac_cv_lib_mysqlclient_mysql_init=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_r_mysql_init" >&5
-$as_echo "$ac_cv_lib_mysqlclient_r_mysql_init" >&6; }
-if test "x$ac_cv_lib_mysqlclient_r_mysql_init" = xyes; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_init" >&5
+$as_echo "$ac_cv_lib_mysqlclient_mysql_init" >&6; }
+if test "x$ac_cv_lib_mysqlclient_mysql_init" = xyes; then :
apu_have_mysql=1
fi
@@ -20336,10 +20516,10 @@ fi
if test "$apu_have_mysql" = "1"; then
if test "x$LDADD_dbd_mysql" = "x"; then
- test "x$silent" != "xyes" && echo " setting LDADD_dbd_mysql to \"$mysql_LDFLAGS -lmysqlclient_r $mysql_LIBS\""
- LDADD_dbd_mysql="$mysql_LDFLAGS -lmysqlclient_r $mysql_LIBS"
+ test "x$silent" != "xyes" && echo " setting LDADD_dbd_mysql to \"$mysql_LDFLAGS -lmysqlclient $mysql_LIBS\""
+ LDADD_dbd_mysql="$mysql_LDFLAGS -lmysqlclient $mysql_LIBS"
else
- apr_addto_bugger="$mysql_LDFLAGS -lmysqlclient_r $mysql_LIBS"
+ apr_addto_bugger="$mysql_LDFLAGS -lmysqlclient $mysql_LIBS"
for i in $apr_addto_bugger; do
apr_addto_duplicate="0"
for j in $LDADD_dbd_mysql; do
@@ -21549,443 +21729,6 @@ fi
LDFLAGS="$old_ldflags"
- apu_have_freetds=0
-
- old_libs="$LIBS"
- old_cppflags="$CPPFLAGS"
- old_ldflags="$LDFLAGS"
-
-
-# Check whether --with-freetds was given.
-if test "${with_freetds+set}" = set; then :
- withval=$with_freetds;
- if test "$withval" = "yes"; then
- for ac_header in sybdb.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "sybdb.h" "ac_cv_header_sybdb_h" "$ac_includes_default"
-if test "x$ac_cv_header_sybdb_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SYBDB_H 1
-_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tdsdbopen in -lsybdb" >&5
-$as_echo_n "checking for tdsdbopen in -lsybdb... " >&6; }
-if ${ac_cv_lib_sybdb_tdsdbopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsybdb $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char tdsdbopen ();
-int
-main ()
-{
-return tdsdbopen ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_sybdb_tdsdbopen=yes
-else
- ac_cv_lib_sybdb_tdsdbopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sybdb_tdsdbopen" >&5
-$as_echo "$ac_cv_lib_sybdb_tdsdbopen" >&6; }
-if test "x$ac_cv_lib_sybdb_tdsdbopen" = xyes; then :
- apu_have_freetds=1
-fi
-
-fi
-
-done
-
- if test "$apu_have_freetds" = "0"; then
- for ac_header in freetds/sybdb.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "freetds/sybdb.h" "ac_cv_header_freetds_sybdb_h" "$ac_includes_default"
-if test "x$ac_cv_header_freetds_sybdb_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_FREETDS_SYBDB_H 1
-_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tdsdbopen in -lsybdb" >&5
-$as_echo_n "checking for tdsdbopen in -lsybdb... " >&6; }
-if ${ac_cv_lib_sybdb_tdsdbopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsybdb $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char tdsdbopen ();
-int
-main ()
-{
-return tdsdbopen ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_sybdb_tdsdbopen=yes
-else
- ac_cv_lib_sybdb_tdsdbopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sybdb_tdsdbopen" >&5
-$as_echo "$ac_cv_lib_sybdb_tdsdbopen" >&6; }
-if test "x$ac_cv_lib_sybdb_tdsdbopen" = xyes; then :
- apu_have_freetds=1
-fi
-
-fi
-
-done
-
- fi
- elif test "$withval" = "no"; then
- :
- else
- sybdb_CPPFLAGS="-I$withval/include"
- sybdb_LDFLAGS="-L$withval/lib "
-
-
- if test "x$CPPFLAGS" = "x"; then
- test "x$silent" != "xyes" && echo " setting CPPFLAGS to \"$sybdb_CPPFLAGS\""
- CPPFLAGS="$sybdb_CPPFLAGS"
- else
- apr_addto_bugger="$sybdb_CPPFLAGS"
- for i in $apr_addto_bugger; do
- apr_addto_duplicate="0"
- for j in $CPPFLAGS; do
- if test "x$i" = "x$j"; then
- apr_addto_duplicate="1"
- break
- fi
- done
- if test $apr_addto_duplicate = "0"; then
- test "x$silent" != "xyes" && echo " adding \"$i\" to CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $i"
- fi
- done
- fi
-
-
- if test "x$LDFLAGS" = "x"; then
- test "x$silent" != "xyes" && echo " setting LDFLAGS to \"$sybdb_LDFLAGS\""
- LDFLAGS="$sybdb_LDFLAGS"
- else
- apr_addto_bugger="$sybdb_LDFLAGS"
- for i in $apr_addto_bugger; do
- apr_addto_duplicate="0"
- for j in $LDFLAGS; do
- if test "x$i" = "x$j"; then
- apr_addto_duplicate="1"
- break
- fi
- done
- if test $apr_addto_duplicate = "0"; then
- test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS"
- LDFLAGS="$LDFLAGS $i"
- fi
- done
- fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetds in $withval" >&5
-$as_echo "$as_me: checking for freetds in $withval" >&6;}
- for ac_header in sybdb.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "sybdb.h" "ac_cv_header_sybdb_h" "$ac_includes_default"
-if test "x$ac_cv_header_sybdb_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SYBDB_H 1
-_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tdsdbopen in -lsybdb" >&5
-$as_echo_n "checking for tdsdbopen in -lsybdb... " >&6; }
-if ${ac_cv_lib_sybdb_tdsdbopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsybdb $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char tdsdbopen ();
-int
-main ()
-{
-return tdsdbopen ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_sybdb_tdsdbopen=yes
-else
- ac_cv_lib_sybdb_tdsdbopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sybdb_tdsdbopen" >&5
-$as_echo "$ac_cv_lib_sybdb_tdsdbopen" >&6; }
-if test "x$ac_cv_lib_sybdb_tdsdbopen" = xyes; then :
- apu_have_freetds=1
-fi
-
-fi
-
-done
-
- if test "$apu_have_freetds" = "0"; then
- for ac_header in freetds/sybdb.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "freetds/sybdb.h" "ac_cv_header_freetds_sybdb_h" "$ac_includes_default"
-if test "x$ac_cv_header_freetds_sybdb_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_FREETDS_SYBDB_H 1
-_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tdsdbopen in -lsybdb" >&5
-$as_echo_n "checking for tdsdbopen in -lsybdb... " >&6; }
-if ${ac_cv_lib_sybdb_tdsdbopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsybdb $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char tdsdbopen ();
-int
-main ()
-{
-return tdsdbopen ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_sybdb_tdsdbopen=yes
-else
- ac_cv_lib_sybdb_tdsdbopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sybdb_tdsdbopen" >&5
-$as_echo "$ac_cv_lib_sybdb_tdsdbopen" >&6; }
-if test "x$ac_cv_lib_sybdb_tdsdbopen" = xyes; then :
- apu_have_freetds=1
-fi
-
-fi
-
-done
-
- fi
- if test "$apu_have_freetds" != "0"; then
-
- if test "x$APRUTIL_PRIV_INCLUDES" = "x"; then
- test "x$silent" != "xyes" && echo " setting APRUTIL_PRIV_INCLUDES to \"-I$withval/include\""
- APRUTIL_PRIV_INCLUDES="-I$withval/include"
- else
- apr_addto_bugger="-I$withval/include"
- for i in $apr_addto_bugger; do
- apr_addto_duplicate="0"
- for j in $APRUTIL_PRIV_INCLUDES; do
- if test "x$i" = "x$j"; then
- apr_addto_duplicate="1"
- break
- fi
- done
- if test $apr_addto_duplicate = "0"; then
- test "x$silent" != "xyes" && echo " adding \"$i\" to APRUTIL_PRIV_INCLUDES"
- APRUTIL_PRIV_INCLUDES="$APRUTIL_PRIV_INCLUDES $i"
- fi
- done
- fi
-
- fi
- fi
-
-else
-
- for ac_header in sybdb.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "sybdb.h" "ac_cv_header_sybdb_h" "$ac_includes_default"
-if test "x$ac_cv_header_sybdb_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SYBDB_H 1
-_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tdsdbopen in -lsybdb" >&5
-$as_echo_n "checking for tdsdbopen in -lsybdb... " >&6; }
-if ${ac_cv_lib_sybdb_tdsdbopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsybdb $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char tdsdbopen ();
-int
-main ()
-{
-return tdsdbopen ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_sybdb_tdsdbopen=yes
-else
- ac_cv_lib_sybdb_tdsdbopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sybdb_tdsdbopen" >&5
-$as_echo "$ac_cv_lib_sybdb_tdsdbopen" >&6; }
-if test "x$ac_cv_lib_sybdb_tdsdbopen" = xyes; then :
- apu_have_freetds=1
-fi
-
-fi
-
-done
-
- if test "$apu_have_freetds" = "0"; then
- for ac_header in freetds/sybdb.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "freetds/sybdb.h" "ac_cv_header_freetds_sybdb_h" "$ac_includes_default"
-if test "x$ac_cv_header_freetds_sybdb_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_FREETDS_SYBDB_H 1
-_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tdsdbopen in -lsybdb" >&5
-$as_echo_n "checking for tdsdbopen in -lsybdb... " >&6; }
-if ${ac_cv_lib_sybdb_tdsdbopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsybdb $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char tdsdbopen ();
-int
-main ()
-{
-return tdsdbopen ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_sybdb_tdsdbopen=yes
-else
- ac_cv_lib_sybdb_tdsdbopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sybdb_tdsdbopen" >&5
-$as_echo "$ac_cv_lib_sybdb_tdsdbopen" >&6; }
-if test "x$ac_cv_lib_sybdb_tdsdbopen" = xyes; then :
- apu_have_freetds=1
-fi
-
-fi
-
-done
-
- fi
-
-fi
-
-
-
-
- if test "$apu_have_freetds" = "1"; then
-
- if test "x$LDADD_dbd_freetds" = "x"; then
- test "x$silent" != "xyes" && echo " setting LDADD_dbd_freetds to \"$sybdb_LDFLAGS -lsybdb\""
- LDADD_dbd_freetds="$sybdb_LDFLAGS -lsybdb"
- else
- apr_addto_bugger="$sybdb_LDFLAGS -lsybdb"
- for i in $apr_addto_bugger; do
- apr_addto_duplicate="0"
- for j in $LDADD_dbd_freetds; do
- if test "x$i" = "x$j"; then
- apr_addto_duplicate="1"
- break
- fi
- done
- if test $apr_addto_duplicate = "0"; then
- test "x$silent" != "xyes" && echo " adding \"$i\" to LDADD_dbd_freetds"
- LDADD_dbd_freetds="$LDADD_dbd_freetds $i"
- fi
- done
- fi
-
- fi
-
-
- LIBS="$old_libs"
- CPPFLAGS="$old_cppflags"
- LDFLAGS="$old_ldflags"
-
-
apu_have_odbc=0
old_libs="$LIBS"
@@ -22765,7 +22508,6 @@ fi
test $apu_have_mysql = 1 && apu_dbd_tests="$apu_dbd_tests mysql"
test $apu_have_sqlite2 = 1 && apu_dbd_tests="$apu_dbd_tests sqlite2"
test $apu_have_sqlite3 = 1 && apu_dbd_tests="$apu_dbd_tests sqlite3"
- test $apu_have_freetds = 1 && apu_dbd_tests="$apu_dbd_tests freetds"
test $apu_have_odbc = 1 && apu_dbd_tests="$apu_dbd_tests odbc"
@@ -22776,9 +22518,7 @@ save_ldflags="$LDFLAGS"
apu_has_expat=0
-# Default: will use either external or bundled expat.
apu_try_external_expat=1
-apu_try_builtin_expat=1
# Check whether --with-expat was given.
@@ -22788,8 +22528,6 @@ if test "${with_expat+set}" = set; then :
as_fn_error $? "a directory must be specified for --with-expat" "$LINENO" 5
elif test "$withval" = "no"; then
as_fn_error $? "Expat cannot be disabled (at this time)" "$LINENO" 5
- elif test "$withval" = "builtin"; then
- apu_try_external_expat=0
else
# Add given path to standard search paths if appropriate:
if test "$withval" != "/usr"; then
@@ -22878,8 +22616,6 @@ if test "${with_expat+set}" = set; then :
fi
fi
- # ...and refuse to fall back on the builtin expat.
- apu_try_builtin_expat=0
fi
fi
@@ -23258,196 +22994,6 @@ fi
fi
-if test "${apu_has_expat}${apu_try_builtin_expat}" = "01"; then
- bundled_subdir="xml/expat"
-
- # save our work to this point; this allows the sub-package to use it
- cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems. If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, we kill variables containing newlines.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(
- for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
- eval ac_val=\$$ac_var
- case $ac_val in #(
- *${as_nl}*)
- case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
- esac
- case $ac_var in #(
- _ | IFS | as_nl) ;; #(
- BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
- *) { eval $ac_var=; unset $ac_var;} ;;
- esac ;;
- esac
- done
-
- (set) 2>&1 |
- case $as_nl`(ac_space=' '; set) 2>&1` in #(
- *${as_nl}ac_space=\ *)
- # `set' does not quote correctly, so add quotes: double-quote
- # substitution turns \\\\ into \\, and sed turns \\ into \.
- sed -n \
- "s/'/'\\\\''/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
- ;; #(
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
- ;;
- esac |
- sort
-) |
- sed '
- /^ac_cv_env_/b end
- t clear
- :clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
- t end
- s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
- :end' >>confcache
-if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
- if test -w "$cache_file"; then
- if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
- if test ! -f "$cache_file" || test -h "$cache_file"; then
- cat confcache >"$cache_file"
- else
- case $cache_file in #(
- */* | ?:*)
- mv -f confcache "$cache_file"$$ &&
- mv -f "$cache_file"$$ "$cache_file" ;; #(
- *)
- mv -f confcache "$cache_file" ;;
- esac
- fi
- fi
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
- fi
-fi
-rm -f confcache
-
- echo "configuring package in $bundled_subdir now"
- ac_popdir=`pwd`
- apr_config_subdirs="$bundled_subdir"
- test -d $bundled_subdir || $mkdir_p $bundled_subdir
- ac_abs_srcdir=`(cd $srcdir/$bundled_subdir && pwd)`
- cd $bundled_subdir
-
- # A "../" for each directory in /$config_subdirs.
- ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'`
-
- # Make the cache file pathname absolute for the subdirs
- # required to correctly handle subdirs that might actually
- # be symlinks
- case "$cache_file" in
- /*) # already absolute
- ac_sub_cache_file=$cache_file ;;
- *) # Was relative path.
- ac_sub_cache_file="$ac_popdir/$cache_file" ;;
- esac
-
- apr_configure_args=$ac_configure_args
-
- test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent"
-
- apr_configure_args="--disable-option-checking $apr_configure_args"
-
- if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir --prefix=$prefix --exec-prefix=$exec_prefix --libdir=$libdir --includedir=$includedir --bindir=$bindir
- then :
- echo "$bundled_subdir configured properly"
- else
- echo "configure failed for $bundled_subdir"
- exit 1
- fi
-
- cd $ac_popdir
-
- # grab any updates from the sub-package
- if test -r "$cache_file"; then
- # Some versions of bash will fail to source /dev/null (special files
- # actually), so we avoid doing that. DJGPP emulates it as a regular file.
- if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
- case $cache_file in
- [\\/]* | ?:[\\/]* ) . "$cache_file";;
- *) . "./$cache_file";;
- esac
- fi
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
- >$cache_file
-fi
-
-
-
- if test "x$APRUTIL_INCLUDES" = "x"; then
- test "x$silent" != "xyes" && echo " setting APRUTIL_INCLUDES to \"-I$abs_srcdir/$bundled_subdir/lib\""
- APRUTIL_INCLUDES="-I$abs_srcdir/$bundled_subdir/lib"
- else
- apr_addto_bugger="-I$abs_srcdir/$bundled_subdir/lib"
- for i in $apr_addto_bugger; do
- apr_addto_duplicate="0"
- for j in $APRUTIL_INCLUDES; do
- if test "x$i" = "x$j"; then
- apr_addto_duplicate="1"
- break
- fi
- done
- if test $apr_addto_duplicate = "0"; then
- test "x$silent" != "xyes" && echo " adding \"$i\" to APRUTIL_INCLUDES"
- APRUTIL_INCLUDES="$APRUTIL_INCLUDES $i"
- fi
- done
- fi
-
-
- if test "x$LDFLAGS" = "x"; then
- test "x$silent" != "xyes" && echo " setting LDFLAGS to \"-L$top_builddir/$bundled_subdir/lib\""
- LDFLAGS="-L$top_builddir/$bundled_subdir/lib"
- else
- apr_addto_bugger="-L$top_builddir/$bundled_subdir/lib"
- for i in $apr_addto_bugger; do
- apr_addto_duplicate="0"
- for j in $LDFLAGS; do
- if test "x$i" = "x$j"; then
- apr_addto_duplicate="1"
- break
- fi
- done
- if test $apr_addto_duplicate = "0"; then
- test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS"
- LDFLAGS="$LDFLAGS $i"
- fi
- done
- fi
-
- apu_expat_libs="$top_builddir/$bundled_subdir/libexpat.la"
-fi
-
if test "x$APRUTIL_EXPORT_LIBS" = "x"; then
test "x$silent" != "xyes" && echo " setting APRUTIL_EXPORT_LIBS to \"$apu_expat_libs\""
@@ -23491,9 +23037,6 @@ fi
fi
-APR_XML_DIR=$bundled_subdir
-
-
CPPFLAGS=$save_cppflags
LDFLAGS=$save_ldflags
@@ -24037,12 +23580,12 @@ $as_echo "$apu_cv_aprdso" >&6; }
objs=
test $apu_have_openssl = 1 && objs="$objs crypto/apr_crypto_openssl.lo"
test $apu_have_nss = 1 && objs="$objs crypto/apr_crypto_nss.lo"
+ test $apu_have_commoncrypto = 1 && objs="$objs crypto/apr_crypto_commoncrypto.lo"
test $apu_have_oracle = 1 && objs="$objs dbd/apr_dbd_oracle.lo"
test $apu_have_pgsql = 1 && objs="$objs dbd/apr_dbd_pgsql.lo"
test $apu_have_mysql = 1 && objs="$objs dbd/apr_dbd_mysql.lo"
test $apu_have_sqlite2 = 1 && objs="$objs dbd/apr_dbd_sqlite2.lo"
test $apu_have_sqlite3 = 1 && objs="$objs dbd/apr_dbd_sqlite3.lo"
- test $apu_have_freetds = 1 && objs="$objs dbd/apr_dbd_freetds.lo"
test $apu_have_odbc = 1 && objs="$objs dbd/apr_dbd_odbc.lo"
test $apu_have_db = 1 && objs="$objs dbm/apr_dbm_berkeleydb.lo"
test $apu_have_gdbm = 1 && objs="$objs dbm/apr_dbm_gdbm.lo"
@@ -24066,12 +23609,12 @@ $as_echo "$apu_cv_aprdso" >&6; }
done
fi
- APRUTIL_LIBS="$APRUTIL_LIBS $LDADD_crypto_openssl $LDADD_crypto_nss"
- APRUTIL_LIBS="$APRUTIL_LIBS $LDADD_dbd_pgsql $LDADD_dbd_sqlite2 $LDADD_dbd_sqlite3 $LDADD_dbd_oracle $LDADD_dbd_mysql $LDADD_dbd_freetds $LDADD_dbd_odbc"
+ APRUTIL_LIBS="$APRUTIL_LIBS $LDADD_crypto_openssl $LDADD_crypto_nss $LDADD_crypto_commoncrypto"
+ APRUTIL_LIBS="$APRUTIL_LIBS $LDADD_dbd_pgsql $LDADD_dbd_sqlite2 $LDADD_dbd_sqlite3 $LDADD_dbd_oracle $LDADD_dbd_mysql $LDADD_dbd_odbc"
APRUTIL_LIBS="$APRUTIL_LIBS $LDADD_dbm_db $LDADD_dbm_gdbm $LDADD_dbm_ndbm"
APRUTIL_LIBS="$APRUTIL_LIBS $LDADD_ldap"
- APRUTIL_EXPORT_LIBS="$APRUTIL_EXPORT_LIBS $LDADD_crypto_openssl $LDADD_crypto_nss"
- APRUTIL_EXPORT_LIBS="$APRUTIL_EXPORT_LIBS $LDADD_dbd_pgsql $LDADD_dbd_sqlite2 $LDADD_dbd_sqlite3 $LDADD_dbd_oracle $LDADD_dbd_mysql $LDADD_dbd_freetds $LDADD_dbd_odbc"
+ APRUTIL_EXPORT_LIBS="$APRUTIL_EXPORT_LIBS $LDADD_crypto_openssl $LDADD_crypto_nss $LDADD_crypto_commoncrypto"
+ APRUTIL_EXPORT_LIBS="$APRUTIL_EXPORT_LIBS $LDADD_dbd_pgsql $LDADD_dbd_sqlite2 $LDADD_dbd_sqlite3 $LDADD_dbd_oracle $LDADD_dbd_mysql $LDADD_dbd_odbc"
APRUTIL_EXPORT_LIBS="$APRUTIL_EXPORT_LIBS $LDADD_dbm_db $LDADD_dbm_gdbm $LDADD_dbm_ndbm"
APRUTIL_EXPORT_LIBS="$APRUTIL_EXPORT_LIBS $LDADD_ldap"
@@ -24081,12 +23624,12 @@ $as_echo "$apu_cv_aprdso" >&6; }
dsos=
test $apu_have_openssl = 1 && dsos="$dsos crypto/apr_crypto_openssl.la"
test $apu_have_nss = 1 && dsos="$dsos crypto/apr_crypto_nss.la"
+ test $apu_have_commoncrypto = 1 && dsos="$dsos crypto/apr_crypto_commoncrypto.la"
test $apu_have_oracle = 1 && dsos="$dsos dbd/apr_dbd_oracle.la"
test $apu_have_pgsql = 1 && dsos="$dsos dbd/apr_dbd_pgsql.la"
test $apu_have_mysql = 1 && dsos="$dsos dbd/apr_dbd_mysql.la"
test $apu_have_sqlite2 = 1 && dsos="$dsos dbd/apr_dbd_sqlite2.la"
test $apu_have_sqlite3 = 1 && dsos="$dsos dbd/apr_dbd_sqlite3.la"
- test $apu_have_freetds = 1 && dsos="$dsos dbd/apr_dbd_freetds.la"
test $apu_have_odbc = 1 && dsos="$dsos dbd/apr_dbd_odbc.la"
test $apu_have_db = 1 && dsos="$dsos dbm/apr_dbm_db.la"
test $apu_have_gdbm = 1 && dsos="$dsos dbm/apr_dbm_gdbm.la"
@@ -24247,6 +23790,131 @@ fi
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler handles weak symbols" >&5
+$as_echo_n "checking whether the compiler handles weak symbols... " >&6; }
+if ${apu_cv_weak_symbols+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ apu_cv_weak_symbols=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+__attribute__ ((weak))
+int weak_noop(void)
+{
+ return 0;
+}
+int main()
+{
+ return weak_noop();
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ apu_cv_weak_symbols=yes
+else
+ apu_cv_weak_symbols=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $apu_cv_weak_symbols" >&5
+$as_echo "$apu_cv_weak_symbols" >&6; }
+
+if test "$apu_cv_weak_symbols" = "yes"; then
+
+$as_echo "#define HAVE_WEAK_SYMBOLS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for memset_s support" >&5
+$as_echo_n "checking for memset_s support... " >&6; }
+if ${apu_cv_memset_s+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ apu_cv_memset_s=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifdef HAVE_STRING_H
+#define __STDC_WANT_LIB_EXT1__ 1
+#include <string.h>
+#endif
+
+int main(int argc, const char **argv)
+{
+ char buf[1] = {1};
+ return memset_s(buf, sizeof buf, 0, sizeof buf) != 0 || *buf != '\0';
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ apu_cv_memset_s=yes
+else
+ apu_cv_memset_s=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $apu_cv_memset_s" >&5
+$as_echo "$apu_cv_memset_s" >&6; }
+
+if test "$apu_cv_memset_s" = "yes"; then
+
+$as_echo "#define HAVE_MEMSET_S 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for explicit_bzero support" >&5
+$as_echo_n "checking for explicit_bzero support... " >&6; }
+if ${apu_cv_explicit_bzero+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ apu_cv_explicit_bzero=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+int main(int argc, const char **argv)
+{
+ char buf[1] = {1};
+ explicit_bzero(buf, sizeof buf);
+ return *buf != '\0';
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ apu_cv_explicit_bzero=yes
+else
+ apu_cv_explicit_bzero=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $apu_cv_explicit_bzero" >&5
+$as_echo "$apu_cv_explicit_bzero" >&6; }
+
+if test "$apu_cv_explicit_bzero" = "yes"; then
+
+$as_echo "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h
+
+fi
+
so_ext=$APR_SO_EXT
lib_target=$APR_LIB_TARGET
diff --git a/configure.in b/configure.in
index 30028102e460..6f9755a6f24d 100644
--- a/configure.in
+++ b/configure.in
@@ -165,7 +165,6 @@ APU_CHECK_DBD_MYSQL
APU_CHECK_DBD_SQLITE3
APU_CHECK_DBD_SQLITE2
APU_CHECK_DBD_ORACLE
-APU_CHECK_DBD_FREETDS
APU_CHECK_DBD_ODBC
APU_FIND_EXPAT
APU_FIND_ICONV
@@ -188,6 +187,59 @@ if test "$crypt_r" = "1"; then
APU_CHECK_CRYPT_R_STYLE
fi
+AC_CACHE_CHECK([whether the compiler handles weak symbols], [apu_cv_weak_symbols],
+[AC_TRY_RUN([
+__attribute__ ((weak))
+int weak_noop(void)
+{
+ return 0;
+}
+int main()
+{
+ return weak_noop();
+}], [apu_cv_weak_symbols=yes], [apu_cv_weak_symbols=no], [apu_cv_weak_symbols=no])])
+
+if test "$apu_cv_weak_symbols" = "yes"; then
+ AC_DEFINE(HAVE_WEAK_SYMBOLS, 1, [Define if compiler handles weak symbols])
+fi
+
+AC_CACHE_CHECK([for memset_s support], [apu_cv_memset_s],
+[AC_TRY_RUN([
+#ifdef HAVE_STRING_H
+#define __STDC_WANT_LIB_EXT1__ 1
+#include <string.h>
+#endif
+
+int main(int argc, const char **argv)
+{
+ char buf[1] = {1};
+ return memset_s(buf, sizeof buf, 0, sizeof buf) != 0 || *buf != '\0';
+}], [apu_cv_memset_s=yes], [apu_cv_memset_s=no], [apu_cv_memset_s=no])])
+
+if test "$apu_cv_memset_s" = "yes"; then
+ AC_DEFINE([HAVE_MEMSET_S], 1, [Define if memset_s function is supported])
+fi
+
+AC_CACHE_CHECK([for explicit_bzero support], [apu_cv_explicit_bzero],
+[AC_TRY_RUN([
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+int main(int argc, const char **argv)
+{
+ char buf[1] = {1};
+ explicit_bzero(buf, sizeof buf);
+ return *buf != '\0';
+}], [apu_cv_explicit_bzero=yes], [apu_cv_explicit_bzero=no], [apu_cv_explicit_bzero=no])])
+
+if test "$apu_cv_explicit_bzero" = "yes"; then
+ AC_DEFINE([HAVE_EXPLICIT_BZERO], 1, [Define if explicit_bzero function is supported])
+fi
+
so_ext=$APR_SO_EXT
lib_target=$APR_LIB_TARGET
AC_SUBST(so_ext)
diff --git a/crypto/apr_crypto.c b/crypto/apr_crypto.c
index fe66582d124f..9e6e0beebec6 100644
--- a/crypto/apr_crypto.c
+++ b/crypto/apr_crypto.c
@@ -120,7 +120,7 @@ static apr_status_t crypto_clear(void *ptr)
{
apr_crypto_clear_t *clear = (apr_crypto_clear_t *)ptr;
- memset(clear->buffer, 0, clear->size);
+ apr_crypto_memzero(clear->buffer, clear->size);
clear->buffer = NULL;
clear->size = 0;
@@ -141,6 +141,53 @@ APU_DECLARE(apr_status_t) apr_crypto_clear(apr_pool_t *pool,
return APR_SUCCESS;
}
+#if defined(HAVE_WEAK_SYMBOLS)
+void apr__memzero_explicit(void *buffer, apr_size_t size);
+
+__attribute__ ((weak))
+void apr__memzero_explicit(void *buffer, apr_size_t size)
+{
+ memset(buffer, 0, size);
+}
+#endif
+
+APU_DECLARE(apr_status_t) apr_crypto_memzero(void *buffer, apr_size_t size)
+{
+#if defined(WIN32)
+ SecureZeroMemory(buffer, size);
+#elif defined(HAVE_MEMSET_S)
+ if (size) {
+ return memset_s(buffer, (rsize_t)size, 0, (rsize_t)size);
+ }
+#elif defined(HAVE_EXPLICIT_BZERO)
+ explicit_bzero(buffer, size);
+#elif defined(HAVE_WEAK_SYMBOLS)
+ apr__memzero_explicit(buffer, size);
+#else
+ apr_size_t i;
+ volatile unsigned char *volatile ptr = buffer;
+ for (i = 0; i < size; ++i) {
+ ptr[i] = 0;
+ }
+#endif
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(int) apr_crypto_equals(const void *buf1, const void *buf2,
+ apr_size_t size)
+{
+ const unsigned char *p1 = buf1;
+ const unsigned char *p2 = buf2;
+ unsigned char diff = 0;
+ apr_size_t i;
+
+ for (i = 0; i < size; ++i) {
+ diff |= p1[i] ^ p2[i];
+ }
+
+ return 1 & ((diff - 1) >> 8);
+}
+
APU_DECLARE(apr_status_t) apr_crypto_get_driver(
const apr_crypto_driver_t **driver, const char *name,
const char *params, const apu_err_t **result, apr_pool_t *pool)
@@ -188,12 +235,15 @@ APU_DECLARE(apr_status_t) apr_crypto_get_driver(
apr_snprintf(symname, sizeof(symname), "apr_crypto_%s_driver", name);
rv = apu_dso_load(&dso, &symbol, modname, symname, pool);
if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
- *driver = symbol;
- name = apr_pstrdup(pool, name);
- apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver);
+ apr_crypto_driver_t *d = symbol;
rv = APR_SUCCESS;
- if ((*driver)->init) {
- rv = (*driver)->init(pool, params, result);
+ if (d->init) {
+ rv = d->init(pool, params, result);
+ }
+ if (APR_SUCCESS == rv) {
+ *driver = symbol;
+ name = apr_pstrdup(pool, name);
+ apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver);
}
}
apu_dso_mutex_unlock();
@@ -223,6 +273,11 @@ APU_DECLARE(apr_status_t) apr_crypto_get_driver(
DRIVER_LOAD("nss", apr_crypto_nss_driver, pool, params, rv, result);
}
#endif
+#if APU_HAVE_COMMONCRYPTO
+ if (name[0] == 'c' && !strcmp(name, "commoncrypto")) {
+ DRIVER_LOAD("commoncrypto", apr_crypto_commoncrypto_driver, pool, params, rv, result);
+ }
+#endif
#if APU_HAVE_MSCAPI
if (name[0] == 'm' && !strcmp(name, "mscapi")) {
DRIVER_LOAD("mscapi", apr_crypto_mscapi_driver, pool, params, rv, result);
@@ -287,7 +342,8 @@ APU_DECLARE(apr_status_t) apr_crypto_make(apr_crypto_t **f,
/**
* @brief Get a hash table of key types, keyed by the name of the type against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_type_t, which in turn begins with an
+ * integer.
*
* @param types - hashtable of key types keyed to constants.
* @param f - encryption context
@@ -301,7 +357,8 @@ APU_DECLARE(apr_status_t) apr_crypto_get_block_key_types(apr_hash_t **types,
/**
* @brief Get a hash table of key modes, keyed by the name of the mode against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_mode_t, which in turn begins with an
+ * integer.
*
* @param modes - hashtable of key modes keyed to constants.
* @param f - encryption context
@@ -314,6 +371,28 @@ APU_DECLARE(apr_status_t) apr_crypto_get_block_key_modes(apr_hash_t **modes,
}
/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ * up when the context is cleaned, and may be reused with multiple encryption
+ * or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_key(apr_crypto_key_t **key,
+ const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+ return f->provider->key(key, rec, f, p);
+}
+
+/**
* @brief Create a key from the given passphrase. By default, the PBKDF2
* algorithm is used to generate the key from the passphrase. It is expected
* that the same pass phrase will generate the same key, regardless of the
diff --git a/crypto/apr_crypto_commoncrypto.c b/crypto/apr_crypto_commoncrypto.c
new file mode 100644
index 000000000000..81b02995843e
--- /dev/null
+++ b/crypto/apr_crypto_commoncrypto.c
@@ -0,0 +1,906 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_lib.h"
+#include "apu.h"
+#include "apu_errno.h"
+
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "apr_buckets.h"
+#include "apr_random.h"
+
+#include "apr_crypto_internal.h"
+
+#if APU_HAVE_CRYPTO
+
+#include <CommonCrypto/CommonCrypto.h>
+
+#define LOG_PREFIX "apr_crypto_commoncrypto: "
+
+struct apr_crypto_t
+{
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ apu_err_t *result;
+ apr_hash_t *types;
+ apr_hash_t *modes;
+ apr_random_t *rng;
+};
+
+struct apr_crypto_key_t
+{
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ const apr_crypto_t *f;
+ CCAlgorithm algorithm;
+ CCOptions options;
+ unsigned char *key;
+ int keyLen;
+ int ivSize;
+ apr_size_t blockSize;
+};
+
+struct apr_crypto_block_t
+{
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ const apr_crypto_t *f;
+ const apr_crypto_key_t *key;
+ CCCryptorRef ref;
+};
+
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
+
+/**
+ * Fetch the most recent error from this driver.
+ */
+static apr_status_t crypto_error(const apu_err_t **result,
+ const apr_crypto_t *f)
+{
+ *result = f->result;
+ return APR_SUCCESS;
+}
+
+/**
+ * Shutdown the crypto library and release resources.
+ */
+static apr_status_t crypto_shutdown(void)
+{
+ return APR_SUCCESS;
+}
+
+static apr_status_t crypto_shutdown_helper(void *data)
+{
+ return crypto_shutdown();
+}
+
+/**
+ * Initialise the crypto library and perform one time initialisation.
+ */
+static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
+ const apu_err_t **result)
+{
+
+ apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
+ apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param ctx The block context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_block_cleanup(apr_crypto_block_t *ctx)
+{
+
+ if (ctx->ref) {
+ CCCryptorRelease(ctx->ref);
+ ctx->ref = NULL;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_block_cleanup_helper(void *data)
+{
+ apr_crypto_block_t *block = (apr_crypto_block_t *) data;
+ return crypto_block_cleanup(block);
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_cleanup(apr_crypto_t *f)
+{
+
+ return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_cleanup_helper(void *data)
+{
+ apr_crypto_t *f = (apr_crypto_t *) data;
+ return crypto_cleanup(f);
+}
+
+/**
+ * @brief Create a context for supporting encryption. Keys, certificates,
+ * algorithms and other parameters will be set per context. More than
+ * one context can be created at one time. A cleanup will be automatically
+ * registered with the given pool to guarantee a graceful shutdown.
+ * @param f - context pointer will be written here
+ * @param provider - provider to use
+ * @param params - array of key parameters
+ * @param pool - process pool
+ * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+ * if the engine cannot be initialised.
+ */
+static apr_status_t crypto_make(apr_crypto_t **ff,
+ const apr_crypto_driver_t *provider, const char *params,
+ apr_pool_t *pool)
+{
+ apr_crypto_t *f = apr_pcalloc(pool, sizeof(apr_crypto_t));
+ apr_status_t rv;
+
+ if (!f) {
+ return APR_ENOMEM;
+ }
+ *ff = f;
+ f->pool = pool;
+ f->provider = provider;
+
+ /* seed the secure random number generator */
+ f->rng = apr_random_standard_new(pool);
+ if (!f->rng) {
+ return APR_ENOMEM;
+ }
+ do {
+ unsigned char seed[8];
+ rv = apr_generate_random_bytes(seed, sizeof(seed));
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ apr_random_add_entropy(f->rng, seed, sizeof(seed));
+ rv = apr_random_secure_ready(f->rng);
+ } while (rv == APR_ENOTENOUGHENTROPY);
+
+ f->result = apr_pcalloc(pool, sizeof(apu_err_t));
+ if (!f->result) {
+ return APR_ENOMEM;
+ }
+
+ f->types = apr_hash_make(pool);
+ if (!f->types) {
+ return APR_ENOMEM;
+ }
+ apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+ apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+ apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+ apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
+
+ f->modes = apr_hash_make(pool);
+ if (!f->modes) {
+ return APR_ENOMEM;
+ }
+ apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+ apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
+
+ apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Get a hash table of key types, keyed by the name of the type against
+ * a pointer to apr_crypto_block_key_type_t.
+ *
+ * @param types - hashtable of key types keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
+ const apr_crypto_t *f)
+{
+ *types = f->types;
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Get a hash table of key modes, keyed by the name of the mode against
+ * a pointer to apr_crypto_block_key_mode_t.
+ *
+ * @param modes - hashtable of key modes keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
+ const apr_crypto_t *f)
+{
+ *modes = f->modes;
+ return APR_SUCCESS;
+}
+
+/*
+ * Work out which mechanism to use.
+ */
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+ const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad, apr_pool_t *p)
+{
+ /* handle padding */
+ key->options = doPad ? kCCOptionPKCS7Padding : 0;
+
+ /* determine the algorithm to be used */
+ switch (type) {
+
+ case (APR_KEY_3DES_192):
+
+ /* A 3DES key */
+ if (mode == APR_MODE_CBC) {
+ key->algorithm = kCCAlgorithm3DES;
+ key->keyLen = kCCKeySize3DES;
+ key->ivSize = kCCBlockSize3DES;
+ key->blockSize = kCCBlockSize3DES;
+ }
+ else {
+ key->algorithm = kCCAlgorithm3DES;
+ key->options += kCCOptionECBMode;
+ key->keyLen = kCCKeySize3DES;
+ key->ivSize = 0;
+ key->blockSize = kCCBlockSize3DES;
+ }
+ break;
+
+ case (APR_KEY_AES_128):
+
+ if (mode == APR_MODE_CBC) {
+ key->algorithm = kCCAlgorithmAES128;
+ key->keyLen = kCCKeySizeAES128;
+ key->ivSize = kCCBlockSizeAES128;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ else {
+ key->algorithm = kCCAlgorithmAES128;
+ key->options += kCCOptionECBMode;
+ key->keyLen = kCCKeySizeAES128;
+ key->ivSize = 0;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ break;
+
+ case (APR_KEY_AES_192):
+
+ if (mode == APR_MODE_CBC) {
+ key->algorithm = kCCAlgorithmAES128;
+ key->keyLen = kCCKeySizeAES192;
+ key->ivSize = kCCBlockSizeAES128;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ else {
+ key->algorithm = kCCAlgorithmAES128;
+ key->options += kCCOptionECBMode;
+ key->keyLen = kCCKeySizeAES192;
+ key->ivSize = 0;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ break;
+
+ case (APR_KEY_AES_256):
+
+ if (mode == APR_MODE_CBC) {
+ key->algorithm = kCCAlgorithmAES128;
+ key->keyLen = kCCKeySizeAES256;
+ key->ivSize = kCCBlockSizeAES128;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ else {
+ key->algorithm = kCCAlgorithmAES128;
+ key->options += kCCOptionECBMode;
+ key->keyLen = kCCKeySizeAES256;
+ key->ivSize = 0;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ break;
+
+ default:
+
+ /* TODO: Support CAST, Blowfish */
+
+ /* unknown key type, give up */
+ return APR_EKEYTYPE;
+
+ }
+
+ /* make space for the key */
+ key->key = apr_palloc(p, key->keyLen);
+ if (!key->key) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(p, key->key, key->keyLen);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ * up when the context is cleaned, and may be reused with multiple encryption
+ * or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+ const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_status_t rv;
+ apr_crypto_key_t *key = *k;
+
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ }
+ if (!key) {
+ return APR_ENOMEM;
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
+ switch (rec->ktype) {
+
+ case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+ /* generate the key */
+ if ((f->result->rc = CCKeyDerivationPBKDF(kCCPBKDF2,
+ rec->k.passphrase.pass, rec->k.passphrase.passLen,
+ rec->k.passphrase.salt, rec->k.passphrase.saltLen,
+ kCCPRFHmacAlgSHA1, rec->k.passphrase.iterations, key->key,
+ key->keyLen)) == kCCParamError) {
+ return APR_ENOKEY;
+ }
+
+ break;
+ }
+
+ case APR_CRYPTO_KTYPE_SECRET: {
+
+ /* sanity check - key correct size? */
+ if (rec->k.secret.secretLen != key->keyLen) {
+ return APR_EKEYLENGTH;
+ }
+
+ /* copy the key */
+ memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
+
+ break;
+ }
+
+ default: {
+
+ return APR_ENOKEY;
+
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ * algorithm is used to generate the key from the passphrase. It is expected
+ * that the same pass phrase will generate the same key, regardless of the
+ * backend crypto platform used. The key is cleaned up when the context
+ * is cleaned, and may be reused with multiple encryption or decryption
+ * operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ * on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+ const char *pass, apr_size_t passLen, const unsigned char * salt,
+ apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad,
+ const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_status_t rv;
+ apr_crypto_key_t *key = *k;
+
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, type, mode, doPad, p);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
+ /* generate the key */
+ if ((f->result->rc = CCKeyDerivationPBKDF(kCCPBKDF2, pass, passLen, salt,
+ saltLen, kCCPRFHmacAlgSHA1, iterations, key->key, key->keyLen))
+ == kCCParamError) {
+ return APR_ENOKEY;
+ }
+
+ if (ivSize) {
+ *ivSize = key->ivSize;
+ }
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Initialise a context for encrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ * *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ * an IV will be created at random, in space allocated from the pool.
+ * If the buffer pointed to is not NULL, the IV in the buffer will be
+ * used.
+ * @param key The key structure.
+ * @param blockSize The block size of the cipher.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ * Returns APR_EINIT if the backend failed to initialise the context. Returns
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
+ const unsigned char **iv, const apr_crypto_key_t *key,
+ apr_size_t *blockSize, apr_pool_t *p)
+{
+ unsigned char *usedIv;
+ apr_crypto_block_t *block = *ctx;
+ if (!block) {
+ *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+ }
+ if (!block) {
+ return APR_ENOMEM;
+ }
+ block->f = key->f;
+ block->pool = p;
+ block->provider = key->provider;
+ block->key = key;
+
+ apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ /* generate an IV, if necessary */
+ usedIv = NULL;
+ if (key->ivSize) {
+ if (iv == NULL) {
+ return APR_ENOIV;
+ }
+ if (*iv == NULL) {
+ apr_status_t status;
+ usedIv = apr_pcalloc(p, key->ivSize);
+ if (!usedIv) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(p, usedIv, key->ivSize);
+ status = apr_random_secure_bytes(block->f->rng, usedIv,
+ key->ivSize);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ *iv = usedIv;
+ }
+ else {
+ usedIv = (unsigned char *) *iv;
+ }
+ }
+
+ /* create a new context for encryption */
+ switch ((block->f->result->rc = CCCryptorCreate(kCCEncrypt, key->algorithm,
+ key->options, key->key, key->keyLen, usedIv, &block->ref))) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCParamError: {
+ return APR_EINIT;
+ }
+ case kCCMemoryFailure: {
+ return APR_ENOMEM;
+ }
+ case kCCAlignmentError: {
+ return APR_EPADDING;
+ }
+ case kCCUnimplemented: {
+ return APR_ENOTIMPL;
+ }
+ default: {
+ return APR_EINIT;
+ }
+ }
+
+ if (blockSize) {
+ *blockSize = key->blockSize;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ * out is NULL, outlen will contain the maximum size of the
+ * buffer needed to hold the data, including any data
+ * generated by apr_crypto_block_encrypt_finish below. If *out points
+ * to NULL, a buffer sufficiently large will be created from
+ * the pool provided. If *out points to a not-NULL value, this
+ * value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ * see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ * not implemented.
+ */
+static apr_status_t crypto_block_encrypt(unsigned char **out,
+ apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+ apr_crypto_block_t *ctx)
+{
+ apr_size_t outl = *outlen;
+ unsigned char *buffer;
+
+ /* are we after the maximum size of the out buffer? */
+ if (!out) {
+ *outlen = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+ return APR_SUCCESS;
+ }
+
+ /* must we allocate the output buffer from a pool? */
+ if (!*out) {
+ outl = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+ buffer = apr_palloc(ctx->pool, outl);
+ if (!buffer) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(ctx->pool, buffer, outl);
+ *out = buffer;
+ }
+
+ switch ((ctx->f->result->rc = CCCryptorUpdate(ctx->ref, in, inlen, (*out),
+ outl, &outl))) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCBufferTooSmall: {
+ return APR_ENOSPACE;
+ }
+ default: {
+ return APR_ECRYPT;
+ }
+ }
+ *outlen = outl;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ * padded. Typically the final block will be written to the
+ * same buffer used by apr_crypto_block_encrypt, offset by the
+ * number of bytes returned as actually written by the
+ * apr_crypto_block_encrypt() call. After this call, the context
+ * is cleaned and can be reused by apr_crypto_block_encrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ * buffer must already exist, and is usually the same
+ * buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ * formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
+ apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+ apr_size_t len = *outlen;
+
+ ctx->f->result->rc = CCCryptorFinal(ctx->ref, out,
+ CCCryptorGetOutputLength(ctx->ref, 0, 1), &len);
+
+ /* always clean up */
+ crypto_block_cleanup(ctx);
+
+ switch (ctx->f->result->rc) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCBufferTooSmall: {
+ return APR_ENOSPACE;
+ }
+ case kCCAlignmentError: {
+ return APR_EPADDING;
+ }
+ case kCCDecodeError: {
+ return APR_ECRYPT;
+ }
+ default: {
+ return APR_ECRYPT;
+ }
+ }
+ *outlen = len;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Initialise a context for decrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ * *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param blockSize The block size of the cipher.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ * an IV will be created at random, in space allocated from the pool.
+ * If the buffer is not NULL, the IV in the buffer will be used.
+ * @param key The key structure.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ * Returns APR_EINIT if the backend failed to initialise the context. Returns
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
+ apr_size_t *blockSize, const unsigned char *iv,
+ const apr_crypto_key_t *key, apr_pool_t *p)
+{
+ apr_crypto_block_t *block = *ctx;
+ if (!block) {
+ *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+ }
+ if (!block) {
+ return APR_ENOMEM;
+ }
+ block->f = key->f;
+ block->pool = p;
+ block->provider = key->provider;
+
+ apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ /* generate an IV, if necessary */
+ if (key->ivSize) {
+ if (iv == NULL) {
+ return APR_ENOIV;
+ }
+ }
+
+ /* create a new context for decryption */
+ switch ((block->f->result->rc = CCCryptorCreate(kCCDecrypt, key->algorithm,
+ key->options, key->key, key->keyLen, iv, &block->ref))) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCParamError: {
+ return APR_EINIT;
+ }
+ case kCCMemoryFailure: {
+ return APR_ENOMEM;
+ }
+ case kCCAlignmentError: {
+ return APR_EPADDING;
+ }
+ case kCCUnimplemented: {
+ return APR_ENOTIMPL;
+ }
+ default: {
+ return APR_EINIT;
+ }
+ }
+
+ if (blockSize) {
+ *blockSize = key->blockSize;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ * out is NULL, outlen will contain the maximum size of the
+ * buffer needed to hold the data, including any data
+ * generated by apr_crypto_block_decrypt_finish below. If *out points
+ * to NULL, a buffer sufficiently large will be created from
+ * the pool provided. If *out points to a not-NULL value, this
+ * value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ * see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ * not implemented.
+ */
+static apr_status_t crypto_block_decrypt(unsigned char **out,
+ apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+ apr_crypto_block_t *ctx)
+{
+ apr_size_t outl = *outlen;
+ unsigned char *buffer;
+
+ /* are we after the maximum size of the out buffer? */
+ if (!out) {
+ *outlen = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+ return APR_SUCCESS;
+ }
+
+ /* must we allocate the output buffer from a pool? */
+ if (!*out) {
+ outl = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+ buffer = apr_palloc(ctx->pool, outl);
+ if (!buffer) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(ctx->pool, buffer, outl);
+ *out = buffer;
+ }
+
+ switch ((ctx->f->result->rc = CCCryptorUpdate(ctx->ref, in, inlen, (*out),
+ outl, &outl))) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCBufferTooSmall: {
+ return APR_ENOSPACE;
+ }
+ default: {
+ return APR_ECRYPT;
+ }
+ }
+ *outlen = outl;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ * padded. Typically the final block will be written to the
+ * same buffer used by apr_crypto_block_decrypt, offset by the
+ * number of bytes returned as actually written by the
+ * apr_crypto_block_decrypt() call. After this call, the context
+ * is cleaned and can be reused by apr_crypto_block_decrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ * buffer must already exist, and is usually the same
+ * buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ * formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
+ apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+ apr_size_t len = *outlen;
+
+ ctx->f->result->rc = CCCryptorFinal(ctx->ref, out,
+ CCCryptorGetOutputLength(ctx->ref, 0, 1), &len);
+
+ /* always clean up */
+ crypto_block_cleanup(ctx);
+
+ switch (ctx->f->result->rc) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCBufferTooSmall: {
+ return APR_ENOSPACE;
+ }
+ case kCCAlignmentError: {
+ return APR_EPADDING;
+ }
+ case kCCDecodeError: {
+ return APR_ECRYPT;
+ }
+ default: {
+ return APR_ECRYPT;
+ }
+ }
+ *outlen = len;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * OSX Common Crypto module.
+ */
+APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_commoncrypto_driver =
+{
+ "commoncrypto", crypto_init, crypto_make, crypto_get_block_key_types,
+ crypto_get_block_key_modes, crypto_passphrase,
+ crypto_block_encrypt_init, crypto_block_encrypt,
+ crypto_block_encrypt_finish, crypto_block_decrypt_init,
+ crypto_block_decrypt, crypto_block_decrypt_finish, crypto_block_cleanup,
+ crypto_cleanup, crypto_shutdown, crypto_error, crypto_key
+};
+
+#endif
diff --git a/crypto/apr_crypto_nss.c b/crypto/apr_crypto_nss.c
index b345953de73d..47d164094614 100644
--- a/crypto/apr_crypto_nss.c
+++ b/crypto/apr_crypto_nss.c
@@ -50,7 +50,6 @@ struct apr_crypto_t {
apr_pool_t *pool;
const apr_crypto_driver_t *provider;
apu_err_t *result;
- apr_array_header_t *keys;
apr_crypto_config_t *config;
apr_hash_t *types;
apr_hash_t *modes;
@@ -68,6 +67,7 @@ struct apr_crypto_key_t {
SECOidTag cipherOid;
PK11SymKey *symKey;
int ivSize;
+ int keyLength;
};
struct apr_crypto_block_t {
@@ -76,16 +76,24 @@ struct apr_crypto_block_t {
const apr_crypto_t *f;
PK11Context *ctx;
apr_crypto_key_t *key;
+ SECItem *secParam;
int blockSize;
};
-static int key_3des_192 = APR_KEY_3DES_192;
-static int key_aes_128 = APR_KEY_AES_128;
-static int key_aes_192 = APR_KEY_AES_192;
-static int key_aes_256 = APR_KEY_AES_256;
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
-static int mode_ecb = APR_MODE_ECB;
-static int mode_cbc = APR_MODE_CBC;
+/* sufficient space to wrap a key */
+#define BUFFER_SIZE 128
/**
* Fetch the most recent error from this driver.
@@ -107,6 +115,8 @@ static apr_status_t crypto_shutdown(void)
if (NSS_IsInitialized()) {
SECStatus s = NSS_Shutdown();
if (s != SECSuccess) {
+ fprintf(stderr, "NSS failed to shutdown, possible leak: %d: %s",
+ PR_GetError(), PR_ErrorToName(s));
return APR_EINIT;
}
}
@@ -197,9 +207,6 @@ static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
return APR_EREINIT;
}
- apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
- apr_pool_cleanup_null);
-
if (keyPrefix || certPrefix || secmod) {
s = NSS_Initialize(dir, certPrefix, keyPrefix, secmod, flags);
}
@@ -211,15 +218,20 @@ static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
}
if (s != SECSuccess) {
if (result) {
+ /* Note: all memory must be owned by the caller, in case we're unloaded */
apu_err_t *err = apr_pcalloc(pool, sizeof(apu_err_t));
err->rc = PR_GetError();
- err->msg = PR_ErrorToName(s);
- err->reason = "Error during 'nss' initialisation";
+ err->msg = apr_pstrdup(pool, PR_ErrorToName(s));
+ err->reason = apr_pstrdup(pool, "Error during 'nss' initialisation");
*result = err;
}
+
return APR_ECRYPT;
}
+ apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
+ apr_pool_cleanup_null);
+
return APR_SUCCESS;
}
@@ -233,6 +245,11 @@ static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
static apr_status_t crypto_block_cleanup(apr_crypto_block_t *block)
{
+ if (block->secParam) {
+ SECITEM_FreeItem(block->secParam, PR_TRUE);
+ block->secParam = NULL;
+ }
+
if (block->ctx) {
PK11_DestroyContext(block->ctx, PR_TRUE);
block->ctx = NULL;
@@ -248,6 +265,15 @@ static apr_status_t crypto_block_cleanup_helper(void *data)
return crypto_block_cleanup(block);
}
+static apr_status_t crypto_key_cleanup(void *data)
+{
+ apr_crypto_key_t *key = data;
+ if (key->symKey) {
+ PK11_FreeSymKey(key->symKey);
+ key->symKey = NULL;
+ }
+ return APR_SUCCESS;
+}
/**
* @brief Clean encryption / decryption context.
* @note After cleanup, a context is free to be reused if necessary.
@@ -256,15 +282,6 @@ static apr_status_t crypto_block_cleanup_helper(void *data)
*/
static apr_status_t crypto_cleanup(apr_crypto_t *f)
{
- apr_crypto_key_t *key;
- if (f->keys) {
- while ((key = apr_array_pop(f->keys))) {
- if (key->symKey) {
- PK11_FreeSymKey(key->symKey);
- key->symKey = NULL;
- }
- }
- }
return APR_SUCCESS;
}
@@ -308,23 +325,22 @@ static apr_status_t crypto_make(apr_crypto_t **ff,
if (!f->result) {
return APR_ENOMEM;
}
- f->keys = apr_array_make(pool, 10, sizeof(apr_crypto_key_t));
f->types = apr_hash_make(pool);
if (!f->types) {
return APR_ENOMEM;
}
- apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_3des_192));
- apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_aes_128));
- apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_aes_192));
- apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_aes_256));
+ apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+ apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+ apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+ apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
f->modes = apr_hash_make(pool);
if (!f->modes) {
return APR_ENOMEM;
}
- apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(mode_ecb));
- apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(mode_cbc));
+ apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+ apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
apr_pool_cleanup_null);
@@ -335,7 +351,7 @@ static apr_status_t crypto_make(apr_crypto_t **ff,
/**
* @brief Get a hash table of key types, keyed by the name of the type against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_type_t.
*
* @param types - hashtable of key types keyed to constants.
* @param f - encryption context
@@ -350,7 +366,7 @@ static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
/**
* @brief Get a hash table of key modes, keyed by the name of the mode against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_mode_t.
*
* @param modes - hashtable of key modes keyed to constants.
* @param f - encryption context
@@ -363,57 +379,13 @@ static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
return APR_SUCCESS;
}
-/**
- * @brief Create a key from the given passphrase. By default, the PBKDF2
- * algorithm is used to generate the key from the passphrase. It is expected
- * that the same pass phrase will generate the same key, regardless of the
- * backend crypto platform used. The key is cleaned up when the context
- * is cleaned, and may be reused with multiple encryption or decryption
- * operations.
- * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
- * *key is not NULL, *key must point at a previously created structure.
- * @param key The key returned, see note.
- * @param ivSize The size of the initialisation vector will be returned, based
- * on whether an IV is relevant for this type of crypto.
- * @param pass The passphrase to use.
- * @param passLen The passphrase length in bytes
- * @param salt The salt to use.
- * @param saltLen The salt length in bytes
- * @param type 3DES_192, AES_128, AES_192, AES_256.
- * @param mode Electronic Code Book / Cipher Block Chaining.
- * @param doPad Pad if necessary.
- * @param iterations Iteration count
- * @param f The context to use.
- * @param p The pool to use.
- * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
- * error occurred while generating the key. APR_ENOCIPHER if the type or mode
- * is not supported by the particular backend. APR_EKEYTYPE if the key type is
- * not known. APR_EPADDING if padding was requested but is not supported.
- * APR_ENOTIMPL if not implemented.
+/*
+ * Work out which mechanism to use.
*/
-static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
- const char *pass, apr_size_t passLen, const unsigned char * salt,
- apr_size_t saltLen, const apr_crypto_block_key_type_e type,
- const apr_crypto_block_key_mode_e mode, const int doPad,
- const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+ const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad)
{
- apr_status_t rv = APR_SUCCESS;
- PK11SlotInfo * slot;
- SECItem passItem;
- SECItem saltItem;
- SECAlgorithmID *algid;
- void *wincx = NULL; /* what is wincx? */
- apr_crypto_key_t *key = *k;
-
- if (!key) {
- *k = key = apr_array_push(f->keys);
- }
- if (!key) {
- return APR_ENOMEM;
- }
-
- key->f = f;
- key->provider = f->provider;
/* decide on what cipher mechanism we will be using */
switch (type) {
@@ -426,6 +398,7 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
return APR_ENOCIPHER;
/* No OID for CKM_DES3_ECB; */
}
+ key->keyLength = 24;
break;
case (APR_KEY_AES_128):
if (APR_MODE_CBC == mode) {
@@ -434,6 +407,7 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
else {
key->cipherOid = SEC_OID_AES_128_ECB;
}
+ key->keyLength = 16;
break;
case (APR_KEY_AES_192):
if (APR_MODE_CBC == mode) {
@@ -442,6 +416,7 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
else {
key->cipherOid = SEC_OID_AES_192_ECB;
}
+ key->keyLength = 24;
break;
case (APR_KEY_AES_256):
if (APR_MODE_CBC == mode) {
@@ -450,6 +425,7 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
else {
key->cipherOid = SEC_OID_AES_256_ECB;
}
+ key->keyLength = 32;
break;
default:
/* unknown key type, give up */
@@ -464,13 +440,266 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
if (doPad) {
CK_MECHANISM_TYPE paddedMech;
paddedMech = PK11_GetPadMechanism(key->cipherMech);
- if (CKM_INVALID_MECHANISM == paddedMech || key->cipherMech
- == paddedMech) {
+ if (CKM_INVALID_MECHANISM == paddedMech
+ || key->cipherMech == paddedMech) {
return APR_EPADDING;
}
key->cipherMech = paddedMech;
}
+ key->ivSize = PK11_GetIVLength(key->cipherMech);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ * up when the context is cleaned, and may be reused with multiple encryption
+ * or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+ const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_status_t rv = APR_SUCCESS;
+ PK11SlotInfo *slot, *tslot;
+ PK11SymKey *tkey;
+ SECItem secretItem;
+ SECItem wrappedItem;
+ SECItem *secParam;
+ PK11Context *ctx;
+ SECStatus s;
+ SECItem passItem;
+ SECItem saltItem;
+ SECAlgorithmID *algid;
+ void *wincx = NULL; /* what is wincx? */
+ apr_crypto_key_t *key;
+ int blockSize;
+ int remainder;
+
+ key = *k;
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ apr_pool_cleanup_register(p, key, crypto_key_cleanup,
+ apr_pool_cleanup_null);
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
+ switch (rec->ktype) {
+
+ case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+ /* Turn the raw passphrase and salt into SECItems */
+ passItem.data = (unsigned char*) rec->k.passphrase.pass;
+ passItem.len = rec->k.passphrase.passLen;
+ saltItem.data = (unsigned char*) rec->k.passphrase.salt;
+ saltItem.len = rec->k.passphrase.saltLen;
+
+ /* generate the key */
+ /* pbeAlg and cipherAlg are the same. */
+ algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
+ SEC_OID_HMAC_SHA1, key->keyLength,
+ rec->k.passphrase.iterations, &saltItem);
+ if (algid) {
+ slot = PK11_GetBestSlot(key->cipherMech, wincx);
+ if (slot) {
+ key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE,
+ wincx);
+ PK11_FreeSlot(slot);
+ }
+ SECOID_DestroyAlgorithmID(algid, PR_TRUE);
+ }
+
+ break;
+ }
+
+ case APR_CRYPTO_KTYPE_SECRET: {
+
+ /*
+ * NSS is by default in FIPS mode, which disallows the use of unencrypted
+ * symmetrical keys. As per http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947
+ * we do the following:
+ *
+ * 1. Generate a (temporary) symmetric key in NSS.
+ * 2. Use that symmetric key to encrypt your symmetric key as data.
+ * 3. Unwrap your wrapped symmetric key, using the symmetric key
+ * you generated in Step 1 as the unwrapping key.
+ *
+ * http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947
+ */
+
+ /* generate the key */
+ slot = PK11_GetBestSlot(key->cipherMech, NULL);
+ if (slot) {
+ unsigned char data[BUFFER_SIZE];
+
+ /* sanity check - key correct size? */
+ if (rec->k.secret.secretLen != key->keyLength) {
+ PK11_FreeSlot(slot);
+ return APR_EKEYLENGTH;
+ }
+
+ tslot = PK11_GetBestSlot(CKM_AES_ECB, NULL);
+ if (tslot) {
+
+ /* generate a temporary wrapping key */
+ tkey = PK11_KeyGen(tslot, CKM_AES_ECB, 0, PK11_GetBestKeyLength(tslot, CKM_AES_ECB), 0);
+
+ /* prepare the key to wrap */
+ secretItem.data = (unsigned char *) rec->k.secret.secret;
+ secretItem.len = rec->k.secret.secretLen;
+
+ /* ensure our key matches the blocksize */
+ secParam = PK11_GenerateNewParam(CKM_AES_ECB, tkey);
+ blockSize = PK11_GetBlockSize(CKM_AES_ECB, secParam);
+ remainder = rec->k.secret.secretLen % blockSize;
+ if (remainder) {
+ secretItem.data =
+ apr_pcalloc(p, rec->k.secret.secretLen + remainder);
+ apr_crypto_clear(p, secretItem.data,
+ rec->k.secret.secretLen);
+ memcpy(secretItem.data, rec->k.secret.secret,
+ rec->k.secret.secretLen);
+ secretItem.len += remainder;
+ }
+
+ /* prepare a space for the wrapped key */
+ wrappedItem.data = data;
+
+ /* wrap the key */
+ ctx = PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, tkey,
+ secParam);
+ if (ctx) {
+ s = PK11_CipherOp(ctx, wrappedItem.data,
+ (int *) (&wrappedItem.len), BUFFER_SIZE,
+ secretItem.data, secretItem.len);
+ if (s == SECSuccess) {
+
+ /* unwrap the key again */
+ key->symKey = PK11_UnwrapSymKeyWithFlags(tkey,
+ CKM_AES_ECB, NULL, &wrappedItem,
+ key->cipherMech, CKA_ENCRYPT,
+ rec->k.secret.secretLen, 0);
+
+ }
+
+ PK11_DestroyContext(ctx, PR_TRUE);
+ }
+
+ /* clean up */
+ SECITEM_FreeItem(secParam, PR_TRUE);
+ PK11_FreeSymKey(tkey);
+ PK11_FreeSlot(tslot);
+
+ }
+
+ PK11_FreeSlot(slot);
+ }
+
+ break;
+ }
+
+ default: {
+
+ return APR_ENOKEY;
+
+ }
+ }
+
+ /* sanity check? */
+ if (!key->symKey) {
+ PRErrorCode perr = PORT_GetError();
+ if (perr) {
+ f->result->rc = perr;
+ f->result->msg = PR_ErrorToName(perr);
+ rv = APR_ENOKEY;
+ }
+ }
+
+ return rv;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ * algorithm is used to generate the key from the passphrase. It is expected
+ * that the same pass phrase will generate the same key, regardless of the
+ * backend crypto platform used. The key is cleaned up when the context
+ * is cleaned, and may be reused with multiple encryption or decryption
+ * operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ * on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+ const char *pass, apr_size_t passLen, const unsigned char * salt,
+ apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad,
+ const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_status_t rv = APR_SUCCESS;
+ PK11SlotInfo * slot;
+ SECItem passItem;
+ SECItem saltItem;
+ SECAlgorithmID *algid;
+ void *wincx = NULL; /* what is wincx? */
+ apr_crypto_key_t *key = *k;
+
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ apr_pool_cleanup_register(p, key, crypto_key_cleanup,
+ apr_pool_cleanup_null);
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, type, mode, doPad);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
/* Turn the raw passphrase and salt into SECItems */
passItem.data = (unsigned char*) pass;
passItem.len = passLen;
@@ -478,9 +707,9 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
saltItem.len = saltLen;
/* generate the key */
- /* pbeAlg and cipherAlg are the same. NSS decides the keylength. */
+ /* pbeAlg and cipherAlg are the same. */
algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
- SEC_OID_HMAC_SHA1, 0, iterations, &saltItem);
+ SEC_OID_HMAC_SHA1, key->keyLength, iterations, &saltItem);
if (algid) {
slot = PK11_GetBestSlot(key->cipherMech, wincx);
if (slot) {
@@ -501,7 +730,6 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
}
}
- key->ivSize = PK11_GetIVLength(key->cipherMech);
if (ivSize) {
*ivSize = key->ivSize;
}
@@ -530,7 +758,6 @@ static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
apr_size_t *blockSize, apr_pool_t *p)
{
PRErrorCode perr;
- SECItem * secParam;
SECItem ivItem;
unsigned char * usedIv;
apr_crypto_block_t *block = *ctx;
@@ -569,14 +796,14 @@ static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
}
ivItem.data = usedIv;
ivItem.len = key->ivSize;
- secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
+ block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
}
else {
- secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
+ block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
}
- block->blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
+ block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_ENCRYPT,
- key->symKey, secParam);
+ key->symKey, block->secParam);
/* did an error occur? */
perr = PORT_GetError();
@@ -587,7 +814,7 @@ static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
}
if (blockSize) {
- *blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
+ *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
}
return APR_SUCCESS;
@@ -711,7 +938,6 @@ static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
const apr_crypto_key_t *key, apr_pool_t *p)
{
PRErrorCode perr;
- SECItem * secParam;
apr_crypto_block_t *block = *ctx;
if (!block) {
*ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
@@ -733,14 +959,14 @@ static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
}
ivItem.data = (unsigned char*) iv;
ivItem.len = key->ivSize;
- secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
+ block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
}
else {
- secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
+ block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
}
- block->blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
+ block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_DECRYPT,
- key->symKey, secParam);
+ key->symKey, block->secParam);
/* did an error occur? */
perr = PORT_GetError();
@@ -751,7 +977,7 @@ static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
}
if (blockSize) {
- *blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
+ *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
}
return APR_SUCCESS;
@@ -864,7 +1090,8 @@ APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_nss_driver = {
crypto_block_encrypt_init, crypto_block_encrypt,
crypto_block_encrypt_finish, crypto_block_decrypt_init,
crypto_block_decrypt, crypto_block_decrypt_finish,
- crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error
+ crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
+ crypto_key
};
#endif
diff --git a/crypto/apr_crypto_openssl.c b/crypto/apr_crypto_openssl.c
index 0740f93f6349..310bb2c762b1 100644
--- a/crypto/apr_crypto_openssl.c
+++ b/crypto/apr_crypto_openssl.c
@@ -31,15 +31,27 @@
#if APU_HAVE_CRYPTO
#include <openssl/evp.h>
+#include <openssl/rand.h>
#include <openssl/engine.h>
#define LOG_PREFIX "apr_crypto_openssl: "
+#ifndef APR_USE_OPENSSL_PRE_1_1_API
+#if defined(LIBRESSL_VERSION_NUMBER)
+/* LibreSSL declares OPENSSL_VERSION_NUMBER == 2.0 but does not include most
+ * changes from OpenSSL >= 1.1 (new functions, macros, deprecations, ...), so
+ * we have to work around this...
+ */
+#define APR_USE_OPENSSL_PRE_1_1_API (1)
+#else
+#define APR_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
+#endif
+#endif
+
struct apr_crypto_t {
apr_pool_t *pool;
const apr_crypto_driver_t *provider;
apu_err_t *result;
- apr_array_header_t *keys;
apr_crypto_config_t *config;
apr_hash_t *types;
apr_hash_t *modes;
@@ -64,20 +76,27 @@ struct apr_crypto_block_t {
apr_pool_t *pool;
const apr_crypto_driver_t *provider;
const apr_crypto_t *f;
- EVP_CIPHER_CTX cipherCtx;
+ EVP_CIPHER_CTX *cipherCtx;
int initialised;
int ivSize;
int blockSize;
int doPad;
};
-static int key_3des_192 = APR_KEY_3DES_192;
-static int key_aes_128 = APR_KEY_AES_128;
-static int key_aes_192 = APR_KEY_AES_192;
-static int key_aes_256 = APR_KEY_AES_256;
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
-static int mode_ecb = APR_MODE_ECB;
-static int mode_cbc = APR_MODE_CBC;
+/* sufficient space to wrap a key */
+#define BUFFER_SIZE 128
/**
* Fetch the most recent error from this driver.
@@ -111,7 +130,11 @@ static apr_status_t crypto_shutdown_helper(void *data)
static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
const apu_err_t **result)
{
- CRYPTO_malloc_init();
+#if APR_USE_OPENSSL_PRE_1_1_API
+ (void)CRYPTO_malloc_init();
+#else
+ OPENSSL_malloc_init();
+#endif
ERR_load_crypto_strings();
/* SSL_load_error_strings(); */
OpenSSL_add_all_algorithms();
@@ -124,6 +147,30 @@ static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
return APR_SUCCESS;
}
+#if OPENSSL_VERSION_NUMBER < 0x0090802fL
+
+/* Code taken from OpenSSL 0.9.8b, see
+ * https://github.com/openssl/openssl/commit/cf6bc84148cb15af09b292394aaf2b45f0d5af0d
+ */
+
+EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void)
+{
+ EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof *ctx);
+ if (ctx)
+ EVP_CIPHER_CTX_init(ctx);
+ return ctx;
+}
+
+void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
+{
+ if (ctx) {
+ EVP_CIPHER_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+#endif
+
/**
* @brief Clean encryption / decryption context.
* @note After cleanup, a context is free to be reused if necessary.
@@ -134,7 +181,7 @@ static apr_status_t crypto_block_cleanup(apr_crypto_block_t *ctx)
{
if (ctx->initialised) {
- EVP_CIPHER_CTX_cleanup(&ctx->cipherCtx);
+ EVP_CIPHER_CTX_free(ctx->cipherCtx);
ctx->initialised = 0;
}
@@ -256,26 +303,21 @@ static apr_status_t crypto_make(apr_crypto_t **ff,
return APR_ENOMEM;
}
- f->keys = apr_array_make(pool, 10, sizeof(apr_crypto_key_t));
- if (!f->keys) {
- return APR_ENOMEM;
- }
-
f->types = apr_hash_make(pool);
if (!f->types) {
return APR_ENOMEM;
}
- apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_3des_192));
- apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_aes_128));
- apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_aes_192));
- apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_aes_256));
+ apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+ apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+ apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+ apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
f->modes = apr_hash_make(pool);
if (!f->modes) {
return APR_ENOMEM;
}
- apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(mode_ecb));
- apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(mode_cbc));
+ apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+ apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
apr_pool_cleanup_null);
@@ -298,7 +340,7 @@ static apr_status_t crypto_make(apr_crypto_t **ff,
/**
* @brief Get a hash table of key types, keyed by the name of the type against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_type_t.
*
* @param types - hashtable of key types keyed to constants.
* @param f - encryption context
@@ -313,7 +355,7 @@ static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
/**
* @brief Get a hash table of key modes, keyed by the name of the mode against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_mode_t.
*
* @param modes - hashtable of key modes keyed to constants.
* @param f - encryption context
@@ -326,52 +368,13 @@ static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
return APR_SUCCESS;
}
-/**
- * @brief Create a key from the given passphrase. By default, the PBKDF2
- * algorithm is used to generate the key from the passphrase. It is expected
- * that the same pass phrase will generate the same key, regardless of the
- * backend crypto platform used. The key is cleaned up when the context
- * is cleaned, and may be reused with multiple encryption or decryption
- * operations.
- * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
- * *key is not NULL, *key must point at a previously created structure.
- * @param key The key returned, see note.
- * @param ivSize The size of the initialisation vector will be returned, based
- * on whether an IV is relevant for this type of crypto.
- * @param pass The passphrase to use.
- * @param passLen The passphrase length in bytes
- * @param salt The salt to use.
- * @param saltLen The salt length in bytes
- * @param type 3DES_192, AES_128, AES_192, AES_256.
- * @param mode Electronic Code Book / Cipher Block Chaining.
- * @param doPad Pad if necessary.
- * @param iterations Iteration count
- * @param f The context to use.
- * @param p The pool to use.
- * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
- * error occurred while generating the key. APR_ENOCIPHER if the type or mode
- * is not supported by the particular backend. APR_EKEYTYPE if the key type is
- * not known. APR_EPADDING if padding was requested but is not supported.
- * APR_ENOTIMPL if not implemented.
+/*
+ * Work out which mechanism to use.
*/
-static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
- const char *pass, apr_size_t passLen, const unsigned char * salt,
- apr_size_t saltLen, const apr_crypto_block_key_type_e type,
- const apr_crypto_block_key_mode_e mode, const int doPad,
- const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+ const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad, apr_pool_t *p)
{
- apr_crypto_key_t *key = *k;
-
- if (!key) {
- *k = key = apr_array_push(f->keys);
- }
- if (!key) {
- return APR_ENOMEM;
- }
-
- key->f = f;
- key->provider = f->provider;
-
/* determine the cipher to be used */
switch (type) {
@@ -433,6 +436,148 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
}
apr_crypto_clear(p, key->key, key->keyLen);
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ * up when the context is cleaned, and may be reused with multiple encryption
+ * or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+ const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_crypto_key_t *key = *k;
+ apr_status_t rv;
+
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
+ switch (rec->ktype) {
+
+ case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+ /* generate the key */
+ if (PKCS5_PBKDF2_HMAC_SHA1(rec->k.passphrase.pass,
+ rec->k.passphrase.passLen,
+ (unsigned char *) rec->k.passphrase.salt,
+ rec->k.passphrase.saltLen, rec->k.passphrase.iterations,
+ key->keyLen, key->key) == 0) {
+ return APR_ENOKEY;
+ }
+
+ break;
+ }
+
+ case APR_CRYPTO_KTYPE_SECRET: {
+
+ /* sanity check - key correct size? */
+ if (rec->k.secret.secretLen != key->keyLen) {
+ return APR_EKEYLENGTH;
+ }
+
+ /* copy the key */
+ memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
+
+ break;
+ }
+
+ default: {
+
+ return APR_ENOKEY;
+
+ }
+ }
+
+ key->doPad = rec->pad;
+
+ /* note: openssl incorrectly returns non zero IV size values for ECB
+ * algorithms, so work around this by ignoring the IV size.
+ */
+ if (APR_MODE_ECB != rec->mode) {
+ key->ivSize = EVP_CIPHER_iv_length(key->cipher);
+ }
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ * algorithm is used to generate the key from the passphrase. It is expected
+ * that the same pass phrase will generate the same key, regardless of the
+ * backend crypto platform used. The key is cleaned up when the context
+ * is cleaned, and may be reused with multiple encryption or decryption
+ * operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ * on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+ const char *pass, apr_size_t passLen, const unsigned char * salt,
+ apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad,
+ const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_crypto_key_t *key = *k;
+ apr_status_t rv;
+
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, type, mode, doPad, p);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
/* generate the key */
if (PKCS5_PBKDF2_HMAC_SHA1(pass, passLen, (unsigned char *) salt, saltLen,
iterations, key->keyLen, key->key) == 0) {
@@ -491,8 +636,10 @@ static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
apr_pool_cleanup_null);
/* create a new context for encryption */
- EVP_CIPHER_CTX_init(&block->cipherCtx);
- block->initialised = 1;
+ if (!block->initialised) {
+ block->cipherCtx = EVP_CIPHER_CTX_new();
+ block->initialised = 1;
+ }
/* generate an IV, if necessary */
usedIv = NULL;
@@ -519,16 +666,16 @@ static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
/* set up our encryption context */
#if CRYPTO_OPENSSL_CONST_BUFFERS
- if (!EVP_EncryptInit_ex(&block->cipherCtx, key->cipher, config->engine,
+ if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine,
key->key, usedIv)) {
#else
- if (!EVP_EncryptInit_ex(&block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) usedIv)) {
+ if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) usedIv)) {
#endif
return APR_EINIT;
}
/* Clear up any read padding */
- if (!EVP_CIPHER_CTX_set_padding(&block->cipherCtx, key->doPad)) {
+ if (!EVP_CIPHER_CTX_set_padding(block->cipherCtx, key->doPad)) {
return APR_EPADDING;
}
@@ -582,11 +729,16 @@ static apr_status_t crypto_block_encrypt(unsigned char **out,
}
#if CRYPT_OPENSSL_CONST_BUFFERS
- if (!EVP_EncryptUpdate(&ctx->cipherCtx, (*out), &outl, in, inlen)) {
+ if (!EVP_EncryptUpdate(ctx->cipherCtx, (*out), &outl, in, inlen)) {
#else
- if (!EVP_EncryptUpdate(&ctx->cipherCtx, (*out), &outl,
+ if (!EVP_EncryptUpdate(ctx->cipherCtx, (*out), &outl,
(unsigned char *) in, inlen)) {
#endif
+#if APR_USE_OPENSSL_PRE_1_1_API
+ EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+ EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
return APR_ECRYPT;
}
*outlen = outl;
@@ -616,14 +768,22 @@ static apr_status_t crypto_block_encrypt(unsigned char **out,
static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
apr_size_t *outlen, apr_crypto_block_t *ctx)
{
+ apr_status_t rc = APR_SUCCESS;
int len = *outlen;
- if (EVP_EncryptFinal_ex(&ctx->cipherCtx, out, &len) == 0) {
- return APR_EPADDING;
+ if (EVP_EncryptFinal_ex(ctx->cipherCtx, out, &len) == 0) {
+ rc = APR_EPADDING;
+ }
+ else {
+ *outlen = len;
}
- *outlen = len;
+#if APR_USE_OPENSSL_PRE_1_1_API
+ EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+ EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
- return APR_SUCCESS;
+ return rc;
}
@@ -662,8 +822,10 @@ static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
apr_pool_cleanup_null);
/* create a new context for encryption */
- EVP_CIPHER_CTX_init(&block->cipherCtx);
- block->initialised = 1;
+ if (!block->initialised) {
+ block->cipherCtx = EVP_CIPHER_CTX_new();
+ block->initialised = 1;
+ }
/* generate an IV, if necessary */
if (key->ivSize) {
@@ -674,16 +836,16 @@ static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
/* set up our encryption context */
#if CRYPTO_OPENSSL_CONST_BUFFERS
- if (!EVP_DecryptInit_ex(&block->cipherCtx, key->cipher, config->engine,
+ if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine,
key->key, iv)) {
#else
- if (!EVP_DecryptInit_ex(&block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) iv)) {
+ if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) iv)) {
#endif
return APR_EINIT;
}
/* Clear up any read padding */
- if (!EVP_CIPHER_CTX_set_padding(&block->cipherCtx, key->doPad)) {
+ if (!EVP_CIPHER_CTX_set_padding(block->cipherCtx, key->doPad)) {
return APR_EPADDING;
}
@@ -737,11 +899,16 @@ static apr_status_t crypto_block_decrypt(unsigned char **out,
}
#if CRYPT_OPENSSL_CONST_BUFFERS
- if (!EVP_DecryptUpdate(&ctx->cipherCtx, *out, &outl, in, inlen)) {
+ if (!EVP_DecryptUpdate(ctx->cipherCtx, *out, &outl, in, inlen)) {
#else
- if (!EVP_DecryptUpdate(&ctx->cipherCtx, *out, &outl, (unsigned char *) in,
+ if (!EVP_DecryptUpdate(ctx->cipherCtx, *out, &outl, (unsigned char *) in,
inlen)) {
#endif
+#if APR_USE_OPENSSL_PRE_1_1_API
+ EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+ EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
return APR_ECRYPT;
}
*outlen = outl;
@@ -771,15 +938,22 @@ static apr_status_t crypto_block_decrypt(unsigned char **out,
static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
apr_size_t *outlen, apr_crypto_block_t *ctx)
{
-
+ apr_status_t rc = APR_SUCCESS;
int len = *outlen;
- if (EVP_DecryptFinal_ex(&ctx->cipherCtx, out, &len) == 0) {
- return APR_EPADDING;
+ if (EVP_DecryptFinal_ex(ctx->cipherCtx, out, &len) == 0) {
+ rc = APR_EPADDING;
+ }
+ else {
+ *outlen = len;
}
- *outlen = len;
+#if APR_USE_OPENSSL_PRE_1_1_API
+ EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+ EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
- return APR_SUCCESS;
+ return rc;
}
@@ -792,7 +966,8 @@ APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_openssl_driver = {
crypto_block_encrypt_init, crypto_block_encrypt,
crypto_block_encrypt_finish, crypto_block_decrypt_init,
crypto_block_decrypt, crypto_block_decrypt_finish,
- crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error
+ crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
+ crypto_key
};
#endif
diff --git a/crypto/apr_siphash.c b/crypto/apr_siphash.c
new file mode 100644
index 000000000000..c9cabe2d2d4c
--- /dev/null
+++ b/crypto/apr_siphash.c
@@ -0,0 +1,196 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * SipHash (C reference implementation, APR-ized), originating from:
+ * https://131002.net/siphash/siphash24.c.
+ */
+
+#include "apr_siphash.h"
+
+#define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
+
+#define U8TO64_LE(p) \
+ (((apr_uint64_t)((p)[0]) ) | \
+ ((apr_uint64_t)((p)[1]) << 8) | \
+ ((apr_uint64_t)((p)[2]) << 16) | \
+ ((apr_uint64_t)((p)[3]) << 24) | \
+ ((apr_uint64_t)((p)[4]) << 32) | \
+ ((apr_uint64_t)((p)[5]) << 40) | \
+ ((apr_uint64_t)((p)[6]) << 48) | \
+ ((apr_uint64_t)((p)[7]) << 56))
+
+#define U64TO8_LE(p, v) \
+do { \
+ (p)[0] = (unsigned char)((v) ); \
+ (p)[1] = (unsigned char)((v) >> 8); \
+ (p)[2] = (unsigned char)((v) >> 16); \
+ (p)[3] = (unsigned char)((v) >> 24); \
+ (p)[4] = (unsigned char)((v) >> 32); \
+ (p)[5] = (unsigned char)((v) >> 40); \
+ (p)[6] = (unsigned char)((v) >> 48); \
+ (p)[7] = (unsigned char)((v) >> 56); \
+} while (0)
+
+#define SIPROUND() \
+do { \
+ v0 += v1; v1=ROTL64(v1,13); v1 ^= v0; v0=ROTL64(v0,32); \
+ v2 += v3; v3=ROTL64(v3,16); v3 ^= v2; \
+ v0 += v3; v3=ROTL64(v3,21); v3 ^= v0; \
+ v2 += v1; v1=ROTL64(v1,17); v1 ^= v2; v2=ROTL64(v2,32); \
+} while(0)
+
+#define SIPHASH(r, s, n, k) \
+do { \
+ const unsigned char *ptr, *end; \
+ apr_uint64_t v0, v1, v2, v3, m; \
+ apr_uint64_t k0, k1; \
+ unsigned int rem; \
+ \
+ k0 = U8TO64_LE(k + 0); \
+ k1 = U8TO64_LE(k + 8); \
+ v3 = k1 ^ (apr_uint64_t)0x7465646279746573ULL; \
+ v2 = k0 ^ (apr_uint64_t)0x6c7967656e657261ULL; \
+ v1 = k1 ^ (apr_uint64_t)0x646f72616e646f6dULL; \
+ v0 = k0 ^ (apr_uint64_t)0x736f6d6570736575ULL; \
+ \
+ rem = (unsigned int)(n & 0x7); \
+ for (ptr = s, end = ptr + n - rem; ptr < end; ptr += 8) { \
+ m = U8TO64_LE(ptr); \
+ v3 ^= m; \
+ cROUNDS \
+ v0 ^= m; \
+ } \
+ m = (apr_uint64_t)(n & 0xff) << 56; \
+ switch (rem) { \
+ case 7: m |= (apr_uint64_t)ptr[6] << 48; \
+ case 6: m |= (apr_uint64_t)ptr[5] << 40; \
+ case 5: m |= (apr_uint64_t)ptr[4] << 32; \
+ case 4: m |= (apr_uint64_t)ptr[3] << 24; \
+ case 3: m |= (apr_uint64_t)ptr[2] << 16; \
+ case 2: m |= (apr_uint64_t)ptr[1] << 8; \
+ case 1: m |= (apr_uint64_t)ptr[0]; \
+ case 0: break; \
+ } \
+ v3 ^= m; \
+ cROUNDS \
+ v0 ^= m; \
+ \
+ v2 ^= 0xff; \
+ dROUNDS \
+ \
+ r = v0 ^ v1 ^ v2 ^ v3; \
+} while (0)
+
+APU_DECLARE(apr_uint64_t) apr_siphash(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE],
+ unsigned int c, unsigned int d)
+{
+ apr_uint64_t h;
+ unsigned int i;
+
+#undef cROUNDS
+#define cROUNDS \
+ for (i = 0; i < c; ++i) { \
+ SIPROUND(); \
+ }
+
+#undef dROUNDS
+#define dROUNDS \
+ for (i = 0; i < d; ++i) { \
+ SIPROUND(); \
+ }
+
+ SIPHASH(h, src, len, key);
+ return h;
+}
+
+APU_DECLARE(void) apr_siphash_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE],
+ unsigned int c, unsigned int d)
+{
+ apr_uint64_t h;
+ h = apr_siphash(src, len, key, c, d);
+ U64TO8_LE(out, h);
+}
+
+APU_DECLARE(apr_uint64_t) apr_siphash24(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+
+#undef cROUNDS
+#define cROUNDS \
+ SIPROUND(); \
+ SIPROUND();
+
+#undef dROUNDS
+#define dROUNDS \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND();
+
+ SIPHASH(h, src, len, key);
+ return h;
+}
+
+APU_DECLARE(void) apr_siphash24_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+ h = apr_siphash24(src, len, key);
+ U64TO8_LE(out, h);
+}
+
+APU_DECLARE(apr_uint64_t) apr_siphash48(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+
+#undef cROUNDS
+#define cROUNDS \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND();
+
+#undef dROUNDS
+#define dROUNDS \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND();
+
+ SIPHASH(h, src, len, key);
+ return h;
+}
+
+APU_DECLARE(void) apr_siphash48_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+ h = apr_siphash48(src, len, key);
+ U64TO8_LE(out, h);
+}
+
diff --git a/crypto/crypt_blowfish.c b/crypto/crypt_blowfish.c
index ec9a188b3a28..3d306cf8d3f4 100644
--- a/crypto/crypt_blowfish.c
+++ b/crypto/crypt_blowfish.c
@@ -675,9 +675,9 @@ static char *BF_crypt(const char *key, const char *setting,
setting[2] < 'a' || setting[2] > 'z' ||
!flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] ||
setting[3] != '$' ||
- setting[4] < '0' || setting[4] > '3' ||
+ setting[4] < '0' || setting[4] > '1' ||
setting[5] < '0' || setting[5] > '9' ||
- (setting[4] == '3' && setting[5] > '1') ||
+ (setting[4] == '1' && setting[5] > '7') ||
setting[6] != '$') {
__set_errno(EINVAL);
return NULL;
@@ -877,7 +877,7 @@ char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
const char *input, int size, char *output, int output_size)
{
if (size < 16 || output_size < 7 + 22 + 1 ||
- (count && (count < 4 || count > 31)) ||
+ (count && (count < 4 || count > 17)) ||
prefix[0] != '$' || prefix[1] != '2' ||
(prefix[2] != 'a' && prefix[2] != 'y')) {
if (output_size > 0) output[0] = '\0';
diff --git a/dbd/NWGNUmakefile b/dbd/NWGNUmakefile
index b1e3e532678a..a96d7f6fca0c 100644
--- a/dbd/NWGNUmakefile
+++ b/dbd/NWGNUmakefile
@@ -168,9 +168,6 @@ endif
ifeq "$(APU_HAVE_SQLITE3)" "1"
TARGET_nlm += $(OBJDIR)/dbdsqli3.nlm $(OBJDIR)/dbdsqli3.nlm $(EOLIST)
endif
-ifeq "$(APU_HAVE_FREETDS)" "1"
-TARGET_nlm += $(OBJDIR)/dbdfreetds.nlm $(OBJDIR)/dbdfreetds.nlm $(EOLIST)
-endif
#
# If there is an LIB target, put it here
diff --git a/dbd/apr_dbd.c b/dbd/apr_dbd.c
index bfa97d9e380a..abf858c95e5b 100644
--- a/dbd/apr_dbd.c
+++ b/dbd/apr_dbd.c
@@ -136,9 +136,6 @@ APU_DECLARE(apr_status_t) apr_dbd_init(apr_pool_t *pool)
#if APU_HAVE_ORACLE
DRIVER_LOAD("oracle", apr_dbd_oracle_driver, pool);
#endif
-#if APU_HAVE_FREETDS
- DRIVER_LOAD("freetds", apr_dbd_freetds_driver, pool);
-#endif
#if APU_HAVE_ODBC
DRIVER_LOAD("odbc", apr_dbd_odbc_driver, pool);
#endif
diff --git a/dbd/NWGNUdbdfreetds b/dbd/unsupported/NWGNUdbdfreetds
index fcac2271d194..fcac2271d194 100644
--- a/dbd/NWGNUdbdfreetds
+++ b/dbd/unsupported/NWGNUdbdfreetds
diff --git a/dbd/apr_dbd_freetds.c b/dbd/unsupported/apr_dbd_freetds.c
index d0b4b20025ec..2c34ede73bf2 100644
--- a/dbd/apr_dbd_freetds.c
+++ b/dbd/unsupported/apr_dbd_freetds.c
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#ifdef I_CAN_DEAL_WITH_THIS_PARTIAL_DRIVER_AND_UNMAINTAINED_CODE_FOR_FREETDS
+
#include "apu.h"
#include "apu_config.h"
@@ -803,3 +805,5 @@ APU_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_freetds_driver = {
#endif
};
#endif
+
+#endif
diff --git a/dbm/sdbm/sdbm.c b/dbm/sdbm/sdbm.c
index a1ce69531315..a62b009e5cb7 100644
--- a/dbm/sdbm/sdbm.c
+++ b/dbm/sdbm/sdbm.c
@@ -40,7 +40,7 @@
*/
static int getdbit (apr_sdbm_t *, long);
static apr_status_t setdbit(apr_sdbm_t *, long);
-static apr_status_t getpage(apr_sdbm_t *db, long);
+static apr_status_t getpage(apr_sdbm_t *db, long, int, int);
static apr_status_t getnext(apr_sdbm_datum_t *key, apr_sdbm_t *db);
static apr_status_t makroom(apr_sdbm_t *, long, int);
@@ -93,6 +93,7 @@ static apr_status_t prep(apr_sdbm_t **pdb, const char *dirname, const char *pagn
db = malloc(sizeof(*db));
memset(db, 0, sizeof(*db));
+ db->pagbno = -1L;
db->pool = p;
@@ -193,7 +194,7 @@ APU_DECLARE(apr_status_t) apr_sdbm_fetch(apr_sdbm_t *db, apr_sdbm_datum_t *val,
if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)
return status;
- if ((status = getpage(db, exhash(key))) == APR_SUCCESS) {
+ if ((status = getpage(db, exhash(key), 0, 1)) == APR_SUCCESS) {
*val = getpair(db->pagbuf, key);
/* ### do we want a not-found result? */
}
@@ -227,7 +228,7 @@ APU_DECLARE(apr_status_t) apr_sdbm_delete(apr_sdbm_t *db,
if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)
return status;
- if ((status = getpage(db, exhash(key))) == APR_SUCCESS) {
+ if ((status = getpage(db, exhash(key), 0, 1)) == APR_SUCCESS) {
if (!delpair(db->pagbuf, key))
/* ### should we define some APRUTIL codes? */
status = APR_EGENERAL;
@@ -261,7 +262,7 @@ APU_DECLARE(apr_status_t) apr_sdbm_store(apr_sdbm_t *db, apr_sdbm_datum_t key,
if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)
return status;
- if ((status = getpage(db, (hash = exhash(key)))) == APR_SUCCESS) {
+ if ((status = getpage(db, (hash = exhash(key)), 0, 1)) == APR_SUCCESS) {
/*
* if we need to replace, delete the key/data pair
@@ -376,17 +377,19 @@ static apr_status_t makroom(apr_sdbm_t *db, long hash, int need)
/* Reads 'len' bytes from file 'f' at offset 'off' into buf.
* 'off' is given relative to the start of the file.
- * If EOF is returned while reading, this is taken as success.
+ * If 'create' is asked and EOF is returned while reading, this is taken
+ * as success (i.e. a cleared buffer is returned).
*/
static apr_status_t read_from(apr_file_t *f, void *buf,
- apr_off_t off, apr_size_t len)
+ apr_off_t off, apr_size_t len,
+ int create)
{
apr_status_t status;
if ((status = apr_file_seek(f, APR_SET, &off)) != APR_SUCCESS ||
((status = apr_file_read_full(f, buf, len, NULL)) != APR_SUCCESS)) {
/* if EOF is reached, pretend we read all zero's */
- if (status == APR_EOF) {
+ if (status == APR_EOF && create) {
memset(buf, 0, len);
status = APR_SUCCESS;
}
@@ -410,9 +413,7 @@ APU_DECLARE(apr_status_t) apr_sdbm_firstkey(apr_sdbm_t *db,
/*
* start at page 0
*/
- if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(0), PBLKSIZ))
- == APR_SUCCESS) {
- db->pagbno = 0;
+ if ((status = getpage(db, 0, 1, 1)) == APR_SUCCESS) {
db->blkptr = 0;
db->keyptr = 0;
status = getnext(key, db);
@@ -441,24 +442,28 @@ APU_DECLARE(apr_status_t) apr_sdbm_nextkey(apr_sdbm_t *db,
/*
* all important binary tree traversal
*/
-static apr_status_t getpage(apr_sdbm_t *db, long hash)
+static apr_status_t getpage(apr_sdbm_t *db, long hash, int by_num, int create)
{
- register int hbit;
- register long dbit;
- register long pagb;
apr_status_t status;
+ register long pagb;
- dbit = 0;
- hbit = 0;
- while (dbit < db->maxbno && getdbit(db, dbit))
- dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
+ if (by_num) {
+ pagb = hash;
+ }
+ else {
+ register int hbit = 0;
+ register long dbit = 0;
- debug(("dbit: %d...", dbit));
+ while (dbit < db->maxbno && getdbit(db, dbit))
+ dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
+ debug(("dbit: %d...", dbit));
- db->curbit = dbit;
- db->hmask = masks[hbit];
+ db->curbit = dbit;
+ db->hmask = masks[hbit];
+
+ pagb = hash & db->hmask;
+ }
- pagb = hash & db->hmask;
/*
* see if the block we need is already in memory.
* note: this lookaside cache has about 10% hit rate.
@@ -470,12 +475,14 @@ static apr_status_t getpage(apr_sdbm_t *db, long hash)
* ### joe: this assumption was surely never correct? but
* ### we make it so in read_from anyway.
*/
- if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(pagb), PBLKSIZ))
- != APR_SUCCESS)
+ if ((status = read_from(db->pagf, db->pagbuf,
+ OFF_PAG(pagb), PBLKSIZ,
+ create)) != APR_SUCCESS)
return status;
if (!chkpage(db->pagbuf))
return APR_ENOSPC; /* ### better error? */
+
db->pagbno = pagb;
debug(("pag read: %d\n", pagb));
@@ -492,8 +499,9 @@ static int getdbit(apr_sdbm_t *db, long dbit)
dirb = c / DBLKSIZ;
if (dirb != db->dirbno) {
- if (read_from(db->dirf, db->dirbuf, OFF_DIR(dirb), DBLKSIZ)
- != APR_SUCCESS)
+ if (read_from(db->dirf, db->dirbuf,
+ OFF_DIR(dirb), DBLKSIZ,
+ 1) != APR_SUCCESS)
return 0;
db->dirbno = dirb;
@@ -515,8 +523,9 @@ static apr_status_t setdbit(apr_sdbm_t *db, long dbit)
dirb = c / DBLKSIZ;
if (dirb != db->dirbno) {
- if ((status = read_from(db->dirf, db->dirbuf, OFF_DIR(dirb), DBLKSIZ))
- != APR_SUCCESS)
+ if ((status = read_from(db->dirf, db->dirbuf,
+ OFF_DIR(dirb), DBLKSIZ,
+ 1)) != APR_SUCCESS)
return status;
db->dirbno = dirb;
@@ -553,21 +562,12 @@ static apr_status_t getnext(apr_sdbm_datum_t *key, apr_sdbm_t *db)
* try the next one... If we lost our position on the
* file, we will have to seek.
*/
+ db->blkptr++;
db->keyptr = 0;
- if (db->pagbno != db->blkptr++) {
- apr_off_t off = OFF_PAG(db->blkptr);
- if ((status = apr_file_seek(db->pagf, APR_SET, &off))
- != APR_SUCCESS)
- return status;
- }
- db->pagbno = db->blkptr;
/* ### EOF acceptable here too? */
- if ((status = apr_file_read_full(db->pagf, db->pagbuf, PBLKSIZ, NULL))
- != APR_SUCCESS)
+ if ((status = getpage(db, db->blkptr, 1, 0)) != APR_SUCCESS)
return status;
- if (!chkpage(db->pagbuf))
- return APR_EGENERAL; /* ### need better error */
}
/* NOTREACHED */
diff --git a/dbm/sdbm/sdbm_pair.c b/dbm/sdbm/sdbm_pair.c
index 2130200734e8..50d7965b1415 100644
--- a/dbm/sdbm/sdbm_pair.c
+++ b/dbm/sdbm/sdbm_pair.c
@@ -308,7 +308,8 @@ char *pag;
if (n > 0) {
off = PBLKSIZ;
for (ino++; n > 0; ino += 2) {
- if (ino[0] > off || ino[1] > off ||
+ if (ino[0] < 0 || ino[0] > off ||
+ ino[1] < 0 || ino[1] > off ||
ino[1] > ino[0])
return 0;
off = ino[1];
diff --git a/include/apr_buckets.h b/include/apr_buckets.h
index 025292b98658..ce64b78da116 100644
--- a/include/apr_buckets.h
+++ b/include/apr_buckets.h
@@ -622,6 +622,8 @@ struct apr_bucket_file {
* a caller tries to read from it */
int can_mmap;
#endif /* APR_HAS_MMAP */
+ /** File read block size */
+ apr_size_t read_size;
};
/** @see apr_bucket_structs */
@@ -962,6 +964,18 @@ APU_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create_ex(apr_allocato
APU_DECLARE_NONSTD(void) apr_bucket_alloc_destroy(apr_bucket_alloc_t *list);
/**
+ * Get the aligned size corresponding to the requested size, but minus the
+ * allocator(s) overhead such that the allocation would remain in the
+ * same boundary.
+ * @param list The allocator from which to the memory would be allocated.
+ * @param size The requested size.
+ * @return The corresponding aligned/floored size.
+ */
+APU_DECLARE_NONSTD(apr_size_t) apr_bucket_alloc_aligned_floor(apr_bucket_alloc_t *list,
+ apr_size_t size)
+ __attribute__((nonnull(1)));
+
+/**
* Allocate memory for use by the buckets.
* @param size The amount to allocate.
* @param list The allocator from which to allocate the memory.
@@ -1563,6 +1577,19 @@ APU_DECLARE(apr_bucket *) apr_bucket_file_make(apr_bucket *b, apr_file_t *fd,
APU_DECLARE(apr_status_t) apr_bucket_file_enable_mmap(apr_bucket *b,
int enabled);
+/**
+ * Set the size of the read buffer allocated by a FILE bucket (default
+ * is @a APR_BUCKET_BUFF_SIZE)
+ * memory-mapping is disabled only)
+ * @param b The bucket
+ * @param size Size of the allocated buffers
+ * @return APR_SUCCESS normally, or an error code if the operation fails
+ * @remark Relevant/used only when memory-mapping is disabled (@see
+ * apr_bucket_file_enable_mmap)
+ */
+APU_DECLARE(apr_status_t) apr_bucket_file_set_buf_size(apr_bucket *e,
+ apr_size_t size);
+
/** @} */
#ifdef __cplusplus
}
diff --git a/include/apr_crypto.h b/include/apr_crypto.h
index ed0982dbdd91..b90f3fec5ec7 100644
--- a/include/apr_crypto.h
+++ b/include/apr_crypto.h
@@ -40,6 +40,9 @@ extern "C" {
#if APU_HAVE_CRYPTO
#ifndef APU_CRYPTO_RECOMMENDED_DRIVER
+#if APU_HAVE_COMMONCRYPTO
+#define APU_CRYPTO_RECOMMENDED_DRIVER "commoncrypto"
+#else
#if APU_HAVE_OPENSSL
#define APU_CRYPTO_RECOMMENDED_DRIVER "openssl"
#else
@@ -57,6 +60,7 @@ extern "C" {
#endif
#endif
#endif
+#endif
/**
* Symmetric Key types understood by the library.
@@ -84,16 +88,16 @@ extern "C" {
* the chosen cipher. Padded data is data that is not aligned by block
* size and must be padded by the crypto library.
*
- * OpenSSL NSS Interop
- * Align Pad Align Pad Align Pad
- * 3DES_192/CBC X X X X X X
- * 3DES_192/ECB X X
- * AES_256/CBC X X X X X X
- * AES_256/ECB X X X X
- * AES_192/CBC X X X X
- * AES_192/ECB X X X
- * AES_128/CBC X X X X
- * AES_128/ECB X X X
+ * OpenSSL CommonCrypto NSS Interop
+ * Align Pad Align Pad Align Pad Align Pad
+ * 3DES_192/CBC X X X X X X X X
+ * 3DES_192/ECB X X X X
+ * AES_256/CBC X X X X X X X X
+ * AES_256/ECB X X X X X X
+ * AES_192/CBC X X X X X X
+ * AES_192/ECB X X X X X
+ * AES_128/CBC X X X X X X
+ * AES_128/ECB X X X X X
*
* Conclusion: for padded data, use 3DES_192/CBC or AES_256/CBC. For
* aligned data, use 3DES_192/CBC, AES_256/CBC or AES_256/ECB.
@@ -123,6 +127,48 @@ typedef struct apr_crypto_config_t apr_crypto_config_t;
typedef struct apr_crypto_key_t apr_crypto_key_t;
typedef struct apr_crypto_block_t apr_crypto_block_t;
+typedef struct apr_crypto_block_key_type_t {
+ apr_crypto_block_key_type_e type;
+ int keysize;
+ int blocksize;
+ int ivsize;
+} apr_crypto_block_key_type_t;
+
+typedef struct apr_crypto_block_key_mode_t {
+ apr_crypto_block_key_mode_e mode;
+} apr_crypto_block_key_mode_t;
+
+typedef struct apr_crypto_passphrase_t {
+ const char *pass;
+ apr_size_t passLen;
+ const unsigned char * salt;
+ apr_size_t saltLen;
+ int iterations;
+} apr_crypto_passphrase_t;
+
+typedef struct apr_crypto_secret_t {
+ const unsigned char *secret;
+ apr_size_t secretLen;
+} apr_crypto_secret_t;
+
+typedef enum {
+ /** Key is derived from a passphrase */
+ APR_CRYPTO_KTYPE_PASSPHRASE = 1,
+ /** Key is derived from a raw key */
+ APR_CRYPTO_KTYPE_SECRET = 2,
+} apr_crypto_key_type;
+
+typedef struct apr_crypto_key_rec_t {
+ apr_crypto_key_type ktype;
+ apr_crypto_block_key_type_e type;
+ apr_crypto_block_key_mode_e mode;
+ int pad;
+ union {
+ apr_crypto_passphrase_t passphrase;
+ apr_crypto_secret_t secret;
+ } k;
+} apr_crypto_key_rec_t;
+
/**
* @brief Perform once-only initialisation. Call once only.
*
@@ -132,8 +178,7 @@ typedef struct apr_crypto_block_t apr_crypto_block_t;
APU_DECLARE(apr_status_t) apr_crypto_init(apr_pool_t *pool);
/**
- * @brief Register a cleanup to zero out the buffer provided
- * when the pool is cleaned up.
+ * @brief Zero out the buffer provided when the pool is cleaned up.
*
* @param pool - pool to register the cleanup
* @param buffer - buffer to zero out
@@ -143,6 +188,27 @@ APU_DECLARE(apr_status_t) apr_crypto_clear(apr_pool_t *pool, void *buffer,
apr_size_t size);
/**
+ * @brief Always zero out the buffer provided, without being optimized out by
+ * the compiler.
+ *
+ * @param buffer - buffer to zero out
+ * @param size - size of the buffer to zero out
+ */
+APU_DECLARE(apr_status_t) apr_crypto_memzero(void *buffer, apr_size_t size);
+
+/**
+ * @brief Timing attacks safe buffers comparison, where the executing time does
+ * not depend on the bytes compared but solely on the number of bytes.
+ *
+ * @param buf1 - first buffer to compare
+ * @param buf2 - second buffer to compare
+ * @param size - size of the buffers to compare
+ * @return 1 if the buffers are equals, 0 otherwise.
+ */
+APU_DECLARE(int) apr_crypto_equals(const void *buf1, const void *buf2,
+ apr_size_t size);
+
+/**
* @brief Get the driver struct for a name
*
* @param driver - pointer to driver struct.
@@ -205,7 +271,8 @@ APU_DECLARE(apr_status_t) apr_crypto_make(apr_crypto_t **f,
/**
* @brief Get a hash table of key types, keyed by the name of the type against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_type_t, which in turn begins with an
+ * integer.
*
* @param types - hashtable of key types keyed to constants.
* @param f - encryption context
@@ -216,7 +283,8 @@ APU_DECLARE(apr_status_t) apr_crypto_get_block_key_types(apr_hash_t **types,
/**
* @brief Get a hash table of key modes, keyed by the name of the mode against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_mode_t, which in turn begins with an
+ * integer.
*
* @param modes - hashtable of key modes keyed to constants.
* @param f - encryption context
@@ -226,6 +294,25 @@ APU_DECLARE(apr_status_t) apr_crypto_get_block_key_modes(apr_hash_t **modes,
const apr_crypto_t *f);
/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ * up when the context is cleaned, and may be reused with multiple encryption
+ * or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_key(apr_crypto_key_t **key,
+ const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p);
+
+/**
* @brief Create a key from the given passphrase. By default, the PBKDF2
* algorithm is used to generate the key from the passphrase. It is expected
* that the same pass phrase will generate the same key, regardless of the
@@ -252,6 +339,7 @@ APU_DECLARE(apr_status_t) apr_crypto_get_block_key_modes(apr_hash_t **modes,
* is not supported by the particular backend. APR_EKEYTYPE if the key type is
* not known. APR_EPADDING if padding was requested but is not supported.
* APR_ENOTIMPL if not implemented.
+ * @deprecated Replaced by apr_crypto_key().
*/
APU_DECLARE(apr_status_t) apr_crypto_passphrase(apr_crypto_key_t **key,
apr_size_t *ivSize, const char *pass, apr_size_t passLen,
diff --git a/include/apr_dbd.h b/include/apr_dbd.h
index 3a334b73e2b3..9912612b9aff 100644
--- a/include/apr_dbd.h
+++ b/include/apr_dbd.h
@@ -136,9 +136,6 @@ APU_DECLARE(apr_status_t) apr_dbd_get_driver(apr_pool_t *pool, const char *name,
* "group" determines which group from configuration file to use (see
* MYSQL_READ_DEFAULT_GROUP option of mysql_options() in MySQL manual).
* Reconnect is set to 1 by default (i.e. true).
- * @remarks FreeTDS: the params can have "username", "password", "appname",
- * "dbname", "host", "charset", "lang" and "server" keys, each followed by an
- * equal sign and a value.
*/
APU_DECLARE(apr_status_t) apr_dbd_open_ex(const apr_dbd_driver_t *driver,
apr_pool_t *pool, const char *params,
diff --git a/include/apr_ldap.hwc b/include/apr_ldap.hwc
new file mode 100644
index 000000000000..7922515edaa8
--- /dev/null
+++ b/include/apr_ldap.hwc
@@ -0,0 +1,197 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * apr_ldap.h is generated from apr_ldap.h.in by configure -- do not edit apr_ldap.h
+ */
+/**
+ * @file apr_ldap.h
+ * @brief APR-UTIL LDAP
+ */
+#ifndef APU_LDAP_H
+#define APU_LDAP_H
+
+/**
+ * @defgroup APR_Util_LDAP LDAP
+ * @ingroup APR_Util
+ * @{
+ */
+
+/* this will be defined if LDAP support was compiled into apr-util */
+#define APR_HAS_LDAP @apr_has_ldap_10@
+
+/* identify the LDAP toolkit used */
+#define APR_HAS_NETSCAPE_LDAPSDK 0
+#define APR_HAS_SOLARIS_LDAPSDK 0
+#define APR_HAS_NOVELL_LDAPSDK 0
+#define APR_HAS_MOZILLA_LDAPSDK 0
+#define APR_HAS_OPENLDAP_LDAPSDK 0
+#define APR_HAS_MICROSOFT_LDAPSDK 1
+#define APR_HAS_TIVOLI_LDAPSDK 0
+#define APR_HAS_ZOS_LDAPSDK 0
+#define APR_HAS_OTHER_LDAPSDK 0
+
+
+/*
+ * Handle the case when LDAP is enabled
+ */
+#if APR_HAS_LDAP
+
+/*
+ * The following #defines are DEPRECATED and should not be used for
+ * anything. They remain to maintain binary compatibility.
+ * The original code defined the OPENLDAP SDK as present regardless
+ * of what really was there, which was way bogus. In addition, the
+ * apr_ldap_url_parse*() functions have been rewritten specifically for
+ * APR, so the APR_HAS_LDAP_URL_PARSE macro is forced to zero.
+ */
+#if APR_HAS_TIVOLI_LDAPSDK
+#define APR_HAS_LDAP_SSL 0
+#else
+#define APR_HAS_LDAP_SSL 1
+#endif
+#define APR_HAS_LDAP_URL_PARSE 0
+
+#if APR_HAS_OPENLDAP_LDAPSDK && !defined(LDAP_DEPRECATED)
+/* Ensure that the "deprecated" interfaces are still exposed
+ * with OpenLDAP >= 2.3; these were exposed by default in earlier
+ * releases. */
+#define LDAP_DEPRECATED 1
+#endif
+
+/*
+ * Include the standard LDAP header files.
+ */
+
+#include <winldap.h>
+
+
+/*
+ * Detected standard functions
+ */
+#define APR_HAS_LDAPSSL_CLIENT_INIT 0
+#define APR_HAS_LDAPSSL_CLIENT_DEINIT 0
+#define APR_HAS_LDAPSSL_ADD_TRUSTED_CERT 0
+#define APR_HAS_LDAP_START_TLS_S 0
+#define APR_HAS_LDAP_SSLINIT 1
+#define APR_HAS_LDAPSSL_INIT 0
+#define APR_HAS_LDAPSSL_INSTALL_ROUTINES 0
+
+
+/*
+ * Make sure the secure LDAP port is defined
+ */
+#ifndef LDAPS_PORT
+#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */
+#endif
+
+
+/*
+ * For ldap function calls that input a size limit on the number of returned elements
+ * Some SDKs do not have the define for LDAP_DEFAULT_LIMIT (-1) or LDAP_NO_LIMIT (0)
+ * LDAP_DEFAULT_LIMIT is preferred as it allows inheritance from whatever the SDK
+ * or process is configured for.
+ */
+#ifdef LDAP_DEFAULT_LIMIT
+#define APR_LDAP_SIZELIMIT LDAP_DEFAULT_LIMIT
+#else
+#ifdef LDAP_NO_LIMIT
+#define APR_LDAP_SIZELIMIT LDAP_NO_LIMIT
+#endif
+#endif
+
+#ifndef APR_LDAP_SIZELIMIT
+#define APR_LDAP_SIZELIMIT 0 /* equivalent to LDAP_NO_LIMIT, and what goes on the wire */
+#endif
+
+/*
+ * z/OS is missing some defines
+ */
+#ifndef LDAP_VERSION_MAX
+#define LDAP_VERSION_MAX LDAP_VERSION
+#endif
+#if APR_HAS_ZOS_LDAPSDK
+#define LDAP_VENDOR_NAME "IBM z/OS"
+#endif
+
+/* Note: Macros defining const casting has been removed in APR v1.0,
+ * pending real support for LDAP v2.0 toolkits.
+ *
+ * In the mean time, please use an LDAP v3.0 toolkit.
+ */
+#if LDAP_VERSION_MAX <= 2
+#error Support for LDAP v2.0 toolkits has been removed from apr-util. Please use an LDAP v3.0 toolkit.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * This structure allows the C LDAP API error codes to be returned
+ * along with plain text error messages that explain to us mere mortals
+ * what really happened.
+ */
+typedef struct apr_ldap_err_t {
+ const char *reason;
+ const char *msg;
+ int rc;
+} apr_ldap_err_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* The MS SDK returns LDAP_UNAVAILABLE when the backend has closed the connection
+ * between LDAP calls. Protect with APR_HAS_MICROSOFT_LDAPSDK in case someone
+ * manually chooses another SDK on Windows
+ */
+#if APR_HAS_MICROSOFT_LDAPSDK
+#define APR_LDAP_IS_SERVER_DOWN(s) ((s) == LDAP_SERVER_DOWN \
+ || (s) == LDAP_UNAVAILABLE)
+#else
+#define APR_LDAP_IS_SERVER_DOWN(s) ((s) == LDAP_SERVER_DOWN)
+#endif
+
+/* These symbols are not actually exported in a DSO build, but mapped into
+ * a private exported function array for apr_ldap_stub to bind dynamically.
+ * Rename them appropriately to protect the global namespace.
+ */
+#ifdef APU_DSO_LDAP_BUILD
+
+#define apr_ldap_info apr__ldap_info
+#define apr_ldap_init apr__ldap_init
+#define apr_ldap_ssl_init apr__ldap_ssl_init
+#define apr_ldap_ssl_deinit apr__ldap_ssl_deinit
+#define apr_ldap_get_option apr__ldap_get_option
+#define apr_ldap_set_option apr__ldap_set_option
+#define apr_ldap_rebind_init apr__ldap_rebind_init
+#define apr_ldap_rebind_add apr__ldap_rebind_add
+#define apr_ldap_rebind_remove apr__ldap_rebind_remove
+
+#define APU_DECLARE_LDAP(type) type
+#else
+#define APU_DECLARE_LDAP(type) APU_DECLARE(type)
+#endif
+
+#include "apr_ldap_url.h"
+#include "apr_ldap_init.h"
+#include "apr_ldap_option.h"
+#include "apr_ldap_rebind.h"
+
+/** @} */
+#endif /* APR_HAS_LDAP */
+#endif /* APU_LDAP_H */
diff --git a/include/apr_redis.h b/include/apr_redis.h
new file mode 100644
index 000000000000..66a828b0a901
--- /dev/null
+++ b/include/apr_redis.h
@@ -0,0 +1,459 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file apr_redis.h
+ * @brief Client interface for redis
+ * @remark To use this interface you must have a separate redis
+ * for more information.
+ */
+
+#ifndef APR_REDIS_H
+#define APR_REDIS_H
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+#include "apr_strings.h"
+#include "apr_network_io.h"
+#include "apr_ring.h"
+#include "apr_buckets.h"
+#include "apr_reslist.h"
+#include "apr_hash.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef RC_DEFAULT_SERVER_PORT
+#define RC_DEFAULT_SERVER_PORT 6379
+#endif
+
+#ifndef RC_DEFAULT_SERVER_MIN
+#define RC_DEFAULT_SERVER_MIN 0
+#endif
+
+#ifndef RC_DEFAULT_SERVER_SMAX
+#define RC_DEFAULT_SERVER_SMAX 1
+#endif
+
+#ifndef RC_DEFAULT_SERVER_TTL
+#define RC_DEFAULT_SERVER_TTL 600
+#endif
+
+/**
+ * @defgroup APR_Util_RC Redis Client Routines
+ * @ingroup APR_Util
+ * @{
+ */
+
+/** Specifies the status of a redis server */
+typedef enum
+{
+ APR_RC_SERVER_LIVE, /**< Server is alive and responding to requests */
+ APR_RC_SERVER_DEAD /**< Server is not responding to requests */
+} apr_redis_server_status_t;
+
+/** Opaque redis client connection object */
+typedef struct apr_redis_conn_t apr_redis_conn_t;
+
+/** Redis Server Info Object */
+typedef struct apr_redis_server_t apr_redis_server_t;
+struct apr_redis_server_t
+{
+ const char *host; /**< Hostname of this Server */
+ apr_port_t port; /**< Port of this Server */
+ apr_redis_server_status_t status; /**< @see apr_redis_server_status_t */
+#if APR_HAS_THREADS || defined(DOXYGEN)
+ apr_reslist_t *conns; /**< Resource list of actual client connections */
+#else
+ apr_redis_conn_t *conn;
+#endif
+ apr_pool_t *p; /** Pool to use for private allocations */
+#if APR_HAS_THREADS
+ apr_thread_mutex_t *lock;
+#endif
+ apr_time_t btime;
+ apr_uint32_t rwto;
+ struct
+ {
+ int major;
+ int minor;
+ int patch;
+ char *number;
+ } version;
+};
+
+typedef struct apr_redis_t apr_redis_t;
+
+/* Custom hash callback function prototype, user for server selection.
+* @param baton user selected baton
+* @param data data to hash
+* @param data_len length of data
+*/
+typedef apr_uint32_t (*apr_redis_hash_func)(void *baton,
+ const char *data,
+ const apr_size_t data_len);
+/* Custom Server Select callback function prototype.
+* @param baton user selected baton
+* @param rc redis instance, use rc->live_servers to select a node
+* @param hash hash of the selected key.
+*/
+typedef apr_redis_server_t* (*apr_redis_server_func)(void *baton,
+ apr_redis_t *rc,
+ const apr_uint32_t hash);
+
+/** Container for a set of redis servers */
+struct apr_redis_t
+{
+ apr_uint32_t flags; /**< Flags, Not currently used */
+ apr_uint16_t nalloc; /**< Number of Servers Allocated */
+ apr_uint16_t ntotal; /**< Number of Servers Added */
+ apr_redis_server_t **live_servers; /**< Array of Servers */
+ apr_pool_t *p; /** Pool to use for allocations */
+ void *hash_baton;
+ apr_redis_hash_func hash_func;
+ void *server_baton;
+ apr_redis_server_func server_func;
+};
+
+/**
+ * Creates a crc32 hash used to split keys between servers
+ * @param rc The redis client object to use
+ * @param data Data to be hashed
+ * @param data_len Length of the data to use
+ * @return crc32 hash of data
+ * @remark The crc32 hash is not compatible with old redisd clients.
+ */
+APU_DECLARE(apr_uint32_t) apr_redis_hash(apr_redis_t *rc,
+ const char *data,
+ const apr_size_t data_len);
+
+/**
+ * Pure CRC32 Hash. Used by some clients.
+ */
+APU_DECLARE(apr_uint32_t) apr_redis_hash_crc32(void *baton,
+ const char *data,
+ const apr_size_t data_len);
+
+/**
+ * hash compatible with the standard Perl Client.
+ */
+APU_DECLARE(apr_uint32_t) apr_redis_hash_default(void *baton,
+ const char *data,
+ const apr_size_t data_len);
+
+/**
+ * Picks a server based on a hash
+ * @param rc The redis client object to use
+ * @param hash Hashed value of a Key
+ * @return server that controls specified hash
+ * @see apr_redis_hash
+ */
+APU_DECLARE(apr_redis_server_t *) apr_redis_find_server_hash(apr_redis_t *rc,
+ const apr_uint32_t hash);
+
+/**
+ * server selection compatible with the standard Perl Client.
+ */
+APU_DECLARE(apr_redis_server_t *) apr_redis_find_server_hash_default(void *baton,
+ apr_redis_t *rc,
+ const apr_uint32_t hash);
+
+/**
+ * Adds a server to a client object
+ * @param rc The redis client object to use
+ * @param server Server to add
+ * @remark Adding servers is not thread safe, and should be done once at startup.
+ * @warning Changing servers after startup may cause keys to go to
+ * different servers.
+ */
+APU_DECLARE(apr_status_t) apr_redis_add_server(apr_redis_t *rc,
+ apr_redis_server_t *server);
+
+
+/**
+ * Finds a Server object based on a hostname/port pair
+ * @param rc The redis client object to use
+ * @param host Hostname of the server
+ * @param port Port of the server
+ * @return Server with matching Hostname and Port, or NULL if none was found.
+ */
+APU_DECLARE(apr_redis_server_t *) apr_redis_find_server(apr_redis_t *rc,
+ const char *host,
+ apr_port_t port);
+
+/**
+ * Enables a Server for use again
+ * @param rc The redis client object to use
+ * @param rs Server to Activate
+ */
+APU_DECLARE(apr_status_t) apr_redis_enable_server(apr_redis_t *rc,
+ apr_redis_server_t *rs);
+
+
+/**
+ * Disable a Server
+ * @param rc The redis client object to use
+ * @param rs Server to Disable
+ */
+APU_DECLARE(apr_status_t) apr_redis_disable_server(apr_redis_t *rc,
+ apr_redis_server_t *rs);
+
+/**
+ * Creates a new Server Object
+ * @param p Pool to use
+ * @param host hostname of the server
+ * @param port port of the server
+ * @param min minimum number of client sockets to open
+ * @param smax soft maximum number of client connections to open
+ * @param max hard maximum number of client connections
+ * @param ttl time to live in microseconds of a client connection
+ * @param rwto r/w timeout value in seconds of a client connection
+ * @param ns location of the new server object
+ * @see apr_reslist_create
+ * @remark min, smax, and max are only used when APR_HAS_THREADS
+ */
+APU_DECLARE(apr_status_t) apr_redis_server_create(apr_pool_t *p,
+ const char *host,
+ apr_port_t port,
+ apr_uint32_t min,
+ apr_uint32_t smax,
+ apr_uint32_t max,
+ apr_uint32_t ttl,
+ apr_uint32_t rwto,
+ apr_redis_server_t **ns);
+/**
+ * Creates a new redisd client object
+ * @param p Pool to use
+ * @param max_servers maximum number of servers
+ * @param flags Not currently used
+ * @param rc location of the new redis client object
+ */
+APU_DECLARE(apr_status_t) apr_redis_create(apr_pool_t *p,
+ apr_uint16_t max_servers,
+ apr_uint32_t flags,
+ apr_redis_t **rc);
+
+/**
+ * Gets a value from the server, allocating the value out of p
+ * @param rc client to use
+ * @param p Pool to use
+ * @param key null terminated string containing the key
+ * @param baton location of the allocated value
+ * @param len length of data at baton
+ * @param flags any flags set by the client for this key
+ * @return
+ */
+APU_DECLARE(apr_status_t) apr_redis_getp(apr_redis_t *rc,
+ apr_pool_t *p,
+ const char* key,
+ char **baton,
+ apr_size_t *len,
+ apr_uint16_t *flags);
+
+/**
+ * Sets a value by key on the server
+ * @param rc client to use
+ * @param key null terminated string containing the key
+ * @param baton data to store on the server
+ * @param data_size length of data at baton
+ * @param flags any flags set by the client for this key
+ */
+APU_DECLARE(apr_status_t) apr_redis_set(apr_redis_t *rc,
+ const char *key,
+ char *baton,
+ const apr_size_t data_size,
+ apr_uint16_t flags);
+
+/**
+ * Sets a value by key on the server
+ * @param rc client to use
+ * @param key null terminated string containing the key
+ * @param baton data to store on the server
+ * @param data_size length of data at baton
+ * @param timeout time in seconds for the data to live on the server
+ * @param flags any flags set by the client for this key
+ */
+APU_DECLARE(apr_status_t) apr_redis_setex(apr_redis_t *rc,
+ const char *key,
+ char *baton,
+ const apr_size_t data_size,
+ apr_uint32_t timeout,
+ apr_uint16_t flags);
+
+/**
+ * Deletes a key from a server
+ * @param rc client to use
+ * @param key null terminated string containing the key
+ * @param timeout time for the delete to stop other clients from adding
+ */
+APU_DECLARE(apr_status_t) apr_redis_delete(apr_redis_t *rc,
+ const char *key,
+ apr_uint32_t timeout);
+
+/**
+ * Query a server's version
+ * @param rs server to query
+ * @param p Pool to allocate answer from
+ * @param baton location to store server version string
+ */
+APU_DECLARE(apr_status_t) apr_redis_version(apr_redis_server_t *rs,
+ apr_pool_t *p,
+ char **baton);
+
+/**
+ * Query a server's INFO
+ * @param rs server to query
+ * @param p Pool to allocate answer from
+ * @param baton location to store server INFO response string
+ */
+APU_DECLARE(apr_status_t) apr_redis_info(apr_redis_server_t *rs,
+ apr_pool_t *p,
+ char **baton);
+
+/**
+ * Increments a value
+ * @param rc client to use
+ * @param key null terminated string containing the key
+ * @param inc number to increment by
+ * @param new_value new value after incrementing
+ */
+APU_DECLARE(apr_status_t) apr_redis_incr(apr_redis_t *rc,
+ const char *key,
+ apr_int32_t inc,
+ apr_uint32_t *new_value);
+/**
+ * Decrements a value
+ * @param rc client to use
+ * @param key null terminated string containing the key
+ * @param inc number to decrement by
+ * @param new_value new value after decrementing
+ */
+APU_DECLARE(apr_status_t) apr_redis_decr(apr_redis_t *rc,
+ const char *key,
+ apr_int32_t inc,
+ apr_uint32_t *new_value);
+
+
+/**
+ * Pings the server
+ * @param rs Server to ping
+ */
+APU_DECLARE(apr_status_t) apr_redis_ping(apr_redis_server_t *rs);
+
+/**
+ * Gets multiple values from the server, allocating the values out of p
+ * @param rc client to use
+ * @param temp_pool Pool used for temporary allocations. May be cleared inside this
+ * call.
+ * @param data_pool Pool used to allocate data for the returned values.
+ * @param values hash of apr_redis_value_t keyed by strings, contains the
+ * result of the multiget call.
+ * @return
+ */
+APU_DECLARE(apr_status_t) apr_redis_multgetp(apr_redis_t *rc,
+ apr_pool_t *temp_pool,
+ apr_pool_t *data_pool,
+ apr_hash_t *values);
+
+typedef enum
+{
+ APR_RS_SERVER_MASTER, /**< Server is a master */
+ APR_RS_SERVER_SLAVE, /**< Server is a slave */
+ APR_RS_SERVER_UNKNOWN /**< Server role is unknown */
+} apr_redis_server_role_t;
+
+typedef struct
+{
+/* # Server */
+ /** Major version number of this server */
+ apr_uint32_t major;
+ /** Minor version number of this server */
+ apr_uint32_t minor;
+ /** Patch version number of this server */
+ apr_uint32_t patch;
+ /** Process id of this server process */
+ apr_uint32_t process_id;
+ /** Number of seconds this server has been running */
+ apr_uint32_t uptime_in_seconds;
+ /** Bitsize of the arch on the current machine */
+ apr_uint32_t arch_bits;
+
+/* # Clients */
+ /** Number of connected clients */
+ apr_uint32_t connected_clients;
+ /** Number of blocked clients */
+ apr_uint32_t blocked_clients;
+
+/* # Memory */
+ /** Max memory of this server */
+ apr_uint64_t maxmemory;
+ /** Amount of used memory */
+ apr_uint64_t used_memory;
+ /** Total memory available on this server */
+ apr_uint64_t total_system_memory;
+
+/* # Stats */
+ /** Total connections received */
+ apr_uint64_t total_connections_received;
+ /** Total commands processed */
+ apr_uint64_t total_commands_processed;
+ /** Total commands rejected */
+ apr_uint64_t rejected_connections;
+ /** Total net input bytes */
+ apr_uint64_t total_net_input_bytes;
+ /** Total net output bytes */
+ apr_uint64_t total_net_output_bytes;
+ /** Keyspace hits */
+ apr_uint64_t keyspace_hits;
+ /** Keyspace misses */
+ apr_uint64_t keyspace_misses;
+
+/* # Replication */
+ /** Role */
+ apr_redis_server_role_t role;
+ /** Number of connected slave */
+ apr_uint32_t connected_slaves;
+
+/* # CPU */
+ /** Accumulated CPU user time for this process */
+ apr_uint32_t used_cpu_sys;
+ /** Accumulated CPU system time for this process */
+ apr_uint32_t used_cpu_user;
+
+/* # Cluster */
+ /** Is cluster enabled */
+ apr_uint32_t cluster_enabled;
+} apr_redis_stats_t;
+
+/**
+ * Query a server for statistics
+ * @param rs server to query
+ * @param p Pool to allocate answer from
+ * @param stats location of the new statistics structure
+ */
+APU_DECLARE(apr_status_t) apr_redis_stats(apr_redis_server_t *rs,
+ apr_pool_t *p,
+ apr_redis_stats_t **stats);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_REDIS_H */
diff --git a/include/apr_siphash.h b/include/apr_siphash.h
new file mode 100644
index 000000000000..42aa8874b0be
--- /dev/null
+++ b/include/apr_siphash.h
@@ -0,0 +1,148 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ SipHash reference C implementation
+ Copyright (c) 2012-2014 Jean-Philippe Aumasson
+ <jeanphilippe.aumasson@gmail.com>
+ Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
+ To the extent possible under law, the author(s) have dedicated all copyright
+ and related and neighboring rights to this software to the public domain
+ worldwide. This software is distributed without any warranty.
+ You should have received a copy of the CC0 Public Domain Dedication along
+ with this software. If not, see
+ <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef APR_SIPHASH_H
+#define APR_SIPHASH_H
+
+#include "apr.h"
+#include "apu.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file apr_siphash.h
+ * @brief APR-UTIL siphash library
+ * "SipHash-c-d is a family of pseudorandom functions (a.k.a. keyed
+ * hash functions) optimized for speed on short messages", designed by
+ * Jean-Philippe Aumasson and Daniel J. Bernstein. It generates a 64bit
+ * hash (or MAC) from the message and a 128bit key.
+ * See http://cr.yp.to/siphash/siphash-20120620.pdf for the details,
+ * c is the number of compression rounds, d the number of finalization
+ * rounds; we also define fast implementations for c = 2 with d = 4 (aka
+ * siphash-2-4), and c = 4 with d = 8 (aka siphash-4-8), as recommended
+ * parameters per the authors.
+ */
+
+/** size of the siphash digest */
+#define APR_SIPHASH_DSIZE 8
+
+/** size of the siphash key */
+#define APR_SIPHASH_KSIZE 16
+
+
+/**
+ * @brief Computes SipHash-c-d, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key.
+ * @param src The message
+ * @param len The length of the message
+ * @param key The secret key
+ * @param c The number of compression rounds
+ * @param d The number of finalization rounds
+ * @return The hash value as a 64bit unsigned integer
+ */
+APU_DECLARE(apr_uint64_t) apr_siphash(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE],
+ unsigned int c, unsigned int d);
+
+/**
+ * @brief Computes SipHash-c-d, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key, into a possibly
+ * unaligned buffer (using the little endian representation as defined by the
+ * authors for interoperabilty) usable as a MAC.
+ * @param out The output buffer (or MAC)
+ * @param src The message
+ * @param len The length of the message
+ * @param key The secret key
+ * @param c The number of compression rounds
+ * @param d The number of finalization rounds
+ * @return The hash value as a 64bit unsigned integer
+ */
+APU_DECLARE(void) apr_siphash_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE],
+ unsigned int c, unsigned int d);
+
+/**
+ * @brief Computes SipHash-2-4, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key.
+ * @param src The message to hash
+ * @param len The length of the message
+ * @param key The secret key
+ * @return The hash value as a 64bit unsigned integer
+ */
+APU_DECLARE(apr_uint64_t) apr_siphash24(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE]);
+
+/**
+ * @brief Computes SipHash-2-4, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key, into a possibly
+ * unaligned buffer (using the little endian representation as defined by the
+ * authors for interoperabilty) usable as a MAC.
+ * @param out The output buffer (or MAC)
+ * @param src The message
+ * @param len The length of the message
+ * @param key The secret key
+ * @return The hash value as a 64bit unsigned integer
+ */
+APU_DECLARE(void) apr_siphash24_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE]);
+
+/**
+ * @brief Computes SipHash-4-8, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key.
+ * @param src The message
+ * @param len The length of the message
+ * @param key The secret key
+ * @return The hash value as a 64bit unsigned integer
+ */
+APU_DECLARE(apr_uint64_t) apr_siphash48(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE]);
+
+/**
+ * @brief Computes SipHash-4-8, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key, into a possibly
+ * unaligned buffer (using the little endian representation as defined by the
+ * authors for interoperabilty) usable as a MAC.
+ * @param out The output buffer (or MAC)
+ * @param src The message
+ * @param len The length of the message
+ * @param key The secret key
+ * @return The hash value as a 64bit unsigned integer
+ */
+APU_DECLARE(void) apr_siphash48_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_SIPHASH_H */
diff --git a/include/apr_xml.h b/include/apr_xml.h
index ac7f003b42df..87a696cca739 100644
--- a/include/apr_xml.h
+++ b/include/apr_xml.h
@@ -276,6 +276,7 @@ APU_DECLARE(char *) apr_xml_parser_geterror(apr_xml_parser *parser,
* APR_XML_X2T_INNER contents only
* APR_XML_X2T_LANG_INNER xml:lang + inner contents
* APR_XML_X2T_FULL_NS_LANG FULL + ns defns + xml:lang
+ * APR_XML_X2T_PARSED original prefixes
* </PRE>
* @param namespaces The namespace of the current XML element
* @param ns_map Namespace mapping
@@ -292,6 +293,7 @@ APU_DECLARE(void) apr_xml_to_text(apr_pool_t *p, const apr_xml_elem *elem,
#define APR_XML_X2T_INNER 1 /**< contents only */
#define APR_XML_X2T_LANG_INNER 2 /**< xml:lang + inner contents */
#define APR_XML_X2T_FULL_NS_LANG 3 /**< FULL + ns defns + xml:lang */
+#define APR_XML_X2T_PARSED 4 /**< original prefixes */
/**
* empty XML element
diff --git a/include/apu.h.in b/include/apu.h.in
index 82380cc21bd5..184682d31c15 100644
--- a/include/apu.h.in
+++ b/include/apu.h.in
@@ -113,12 +113,12 @@
#define APU_HAVE_SQLITE3 @apu_have_sqlite3@
#define APU_HAVE_SQLITE2 @apu_have_sqlite2@
#define APU_HAVE_ORACLE @apu_have_oracle@
-#define APU_HAVE_FREETDS @apu_have_freetds@
#define APU_HAVE_ODBC @apu_have_odbc@
#define APU_HAVE_CRYPTO @apu_have_crypto@
#define APU_HAVE_OPENSSL @apu_have_openssl@
#define APU_HAVE_NSS @apu_have_nss@
+#define APU_HAVE_COMMONCRYPTO @apu_have_commoncrypto@
#define APU_HAVE_APR_ICONV @have_apr_iconv@
#define APU_HAVE_ICONV @have_iconv@
diff --git a/include/apu.hnw b/include/apu.hnw
index 31c0dfb41553..0bc3a2cb9b04 100644
--- a/include/apu.hnw
+++ b/include/apu.hnw
@@ -104,7 +104,6 @@
#define APU_HAVE_SQLITE3 0
#define APU_HAVE_SQLITE2 0
#define APU_HAVE_ORACLE 0
-#define APU_HAVE_FREETDS 0
#define APU_HAVE_ODBC 0
#endif
@@ -113,6 +112,7 @@
#ifndef APU_DSO_MODULE_BUILD
#define APU_HAVE_OPENSSL 0
#define APU_HAVE_NSS 0
+#define APU_HAVE_COMMONCRYPTO 0
#endif
#define APU_HAVE_APR_ICONV 0
diff --git a/include/apu.hw b/include/apu.hw
index a6cde01a3a84..21fbedff1aa1 100644
--- a/include/apu.hw
+++ b/include/apu.hw
@@ -127,7 +127,6 @@
#define APU_HAVE_SQLITE3 0
#define APU_HAVE_SQLITE2 0
#define APU_HAVE_ORACLE 0
-#define APU_HAVE_FREETDS 0
#define APU_HAVE_ODBC 1
#endif
@@ -136,6 +135,7 @@
#ifndef APU_DSO_MODULE_BUILD
#define APU_HAVE_OPENSSL 0
#define APU_HAVE_NSS 0
+#define APU_HAVE_COMMONCRYPTO 0
#endif
#define APU_HAVE_APR_ICONV 1
diff --git a/include/apu.hwc b/include/apu.hwc
new file mode 100644
index 000000000000..2c3fa00a59ba
--- /dev/null
+++ b/include/apu.hwc
@@ -0,0 +1,145 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * apu.h is duplicated from apu.hwc at build time -- do not edit apu.h
+ */
+/* @file apu.h
+ * @brief APR-Utility main file
+ */
+/**
+ * @defgroup APR_Util APR Utility Functions
+ * @{
+ */
+
+
+#ifndef APU_H
+#define APU_H
+
+/**
+ * APU_DECLARE_EXPORT is defined when building the APR-UTIL dynamic library,
+ * so that all public symbols are exported.
+ *
+ * APU_DECLARE_STATIC is defined when including the APR-UTIL public headers,
+ * to provide static linkage when the dynamic library may be unavailable.
+ *
+ * APU_DECLARE_STATIC and APU_DECLARE_EXPORT are left undefined when
+ * including the APR-UTIL public headers, to import and link the symbols from
+ * the dynamic APR-UTIL library and assure appropriate indirection and calling
+ * conventions at compile time.
+ */
+
+/* Make sure we have our platform identifier macro defined we ask for later.
+ */
+#if defined(_WIN32) && !defined(WIN32)
+#define WIN32 1
+#endif
+
+#if defined(DOXYGEN) || !defined(WIN32)
+/**
+ * The public APR-UTIL functions are declared with APU_DECLARE(), so they may
+ * use the most appropriate calling convention. Public APR functions with
+ * variable arguments must use APU_DECLARE_NONSTD().
+ *
+ * @fn APU_DECLARE(rettype) apr_func(args);
+ */
+#define APU_DECLARE(type) type
+/**
+ * The public APR-UTIL functions using variable arguments are declared with
+ * APU_DECLARE_NONSTD(), as they must use the C language calling convention.
+ *
+ * @fn APU_DECLARE_NONSTD(rettype) apr_func(args, ...);
+ */
+#define APU_DECLARE_NONSTD(type) type
+/**
+ * The public APR-UTIL variables are declared with APU_DECLARE_DATA.
+ * This assures the appropriate indirection is invoked at compile time.
+ *
+ * @fn APU_DECLARE_DATA type apr_variable;
+ * @note extern APU_DECLARE_DATA type apr_variable; syntax is required for
+ * declarations within headers to properly import the variable.
+ */
+#define APU_DECLARE_DATA
+#elif defined(APU_DECLARE_STATIC)
+#define APU_DECLARE(type) type __stdcall
+#define APU_DECLARE_NONSTD(type) type __cdecl
+#define APU_DECLARE_DATA
+#elif defined(APU_DECLARE_EXPORT)
+#define APU_DECLARE(type) __declspec(dllexport) type __stdcall
+#define APU_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl
+#define APU_DECLARE_DATA __declspec(dllexport)
+#else
+#define APU_DECLARE(type) __declspec(dllimport) type __stdcall
+#define APU_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl
+#define APU_DECLARE_DATA __declspec(dllimport)
+#endif
+
+#if !defined(WIN32) || defined(APU_MODULE_DECLARE_STATIC)
+/**
+ * Declare a dso module's exported module structure as APU_MODULE_DECLARE_DATA.
+ *
+ * Unless APU_MODULE_DECLARE_STATIC is defined at compile time, symbols
+ * declared with APU_MODULE_DECLARE_DATA are always exported.
+ * @code
+ * module APU_MODULE_DECLARE_DATA mod_tag
+ * @endcode
+ */
+#define APU_MODULE_DECLARE_DATA
+#else
+#define APU_MODULE_DECLARE_DATA __declspec(dllexport)
+#endif
+
+/*
+ * we always have SDBM (it's in our codebase)
+ */
+#define APU_HAVE_SDBM 1
+
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_GDBM 0
+#define APU_HAVE_NDBM 0
+#define APU_HAVE_DB 0
+
+#if APU_HAVE_DB
+#define APU_HAVE_DB_VERSION 0
+#endif
+#endif
+
+/*
+ * we always enable dynamic driver loads within apr_dbd
+ * Win32 always has odbc (it's always installed)
+ */
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_PGSQL 0
+#define APU_HAVE_MYSQL 0
+#define APU_HAVE_SQLITE3 0
+#define APU_HAVE_SQLITE2 0
+#define APU_HAVE_ORACLE 0
+#define APU_HAVE_ODBC 1
+#endif
+
+#define APU_HAVE_CRYPTO @apu_have_crypto_10@
+
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_OPENSSL 0
+#define APU_HAVE_NSS 0
+#endif
+
+#define APU_HAVE_APR_ICONV @apu_have_apr_iconv_10@
+#define APU_HAVE_ICONV 0
+#define APR_HAS_XLATE (APU_HAVE_APR_ICONV || APU_HAVE_ICONV)
+
+#endif /* APU_H */
+/** @} */
diff --git a/include/apu_version.h b/include/apu_version.h
index 8d976291ff6d..e4fb2e64e9ec 100644
--- a/include/apu_version.h
+++ b/include/apu_version.h
@@ -38,7 +38,7 @@
*/
-#define APU_COPYRIGHT "Copyright (c) 2000-2014 The Apache Software " \
+#define APU_COPYRIGHT "Copyright (c) 2000-2016 The Apache Software " \
"Foundation or its licensors, as applicable."
/* The numeric compile-time version constants. These constants are the
@@ -56,20 +56,20 @@
* Minor API changes that do not cause binary compatibility problems.
* Reset to 0 when upgrading APU_MAJOR_VERSION
*/
-#define APU_MINOR_VERSION 5
+#define APU_MINOR_VERSION 6
/** patch level
* The Patch Level never includes API changes, simply bug fixes.
* Reset to 0 when upgrading APR_MINOR_VERSION
*/
-#define APU_PATCH_VERSION 4
+#define APU_PATCH_VERSION 1
/**
* The symbol APU_IS_DEV_VERSION is only defined for internal,
* "development" copies of APU. It is undefined for released versions
* of APU.
*/
-/* #define APU_IS_DEV_VERSION */
+/* #undef APU_IS_DEV_VERSION */
#if defined(APU_IS_DEV_VERSION) || defined(DOXYGEN)
diff --git a/include/private/apr_crypto_internal.h b/include/private/apr_crypto_internal.h
index 5da92e558879..1ea838bfb7d1 100644
--- a/include/private/apr_crypto_internal.h
+++ b/include/private/apr_crypto_internal.h
@@ -59,7 +59,7 @@ struct apr_crypto_driver_t {
/**
* @brief Get a hash table of key types, keyed by the name of the type against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_type_t.
*
* @param types - hashtable of key types keyed to constants.
* @param f - encryption context
@@ -70,7 +70,7 @@ struct apr_crypto_driver_t {
/**
* @brief Get a hash table of key modes, keyed by the name of the mode against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_mode_t.
*
* @param modes - hashtable of key modes keyed to constants.
* @param f - encryption context
@@ -267,6 +267,25 @@ struct apr_crypto_driver_t {
*/
apr_status_t (*error)(const apu_err_t **result, const apr_crypto_t *f);
+ /**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ * up when the context is cleaned, and may be reused with multiple encryption
+ * or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+ apr_status_t (*key)(apr_crypto_key_t **key, const apr_crypto_key_rec_t *rec,
+ const apr_crypto_t *f, apr_pool_t *p);
+
};
#endif
diff --git a/include/private/apu_config.h.in b/include/private/apu_config.h.in
index 4d39f8a09475..0e008d04941f 100644
--- a/include/private/apu_config.h.in
+++ b/include/private/apu_config.h.in
@@ -24,6 +24,10 @@
/* Define if CODESET is defined in langinfo.h */
#undef HAVE_CODESET
+/* Define to 1 if you have the <CommonCrypto/CommonKeyDerivation.h> header
+ file. */
+#undef HAVE_COMMONCRYPTO_COMMONKEYDERIVATION_H
+
/* Define to 1 if you have the `crypt_r' function. */
#undef HAVE_CRYPT_R
@@ -34,8 +38,8 @@
/* Define if expat.h is available */
#undef HAVE_EXPAT_H
-/* Define to 1 if you have the <freetds/sybdb.h> header file. */
-#undef HAVE_FREETDS_SYBDB_H
+/* Define if explicit_bzero function is supported */
+#undef HAVE_EXPLICIT_BZERO
/* Define to 1 if you have the <iconv.h> header file. */
#undef HAVE_ICONV_H
@@ -61,6 +65,9 @@
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
+/* Define if memset_s function is supported */
+#undef HAVE_MEMSET_S
+
/* Define to 1 if you have the <mysql.h> header file. */
#undef HAVE_MYSQL_H
@@ -130,9 +137,6 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
-/* Define to 1 if you have the <sybdb.h> header file. */
-#undef HAVE_SYBDB_H
-
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
@@ -142,6 +146,9 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* Define if compiler handles weak symbols */
+#undef HAVE_WEAK_SYMBOLS
+
/* Define if xmlparse/xmlparse.h is available */
#undef HAVE_XMLPARSE_XMLPARSE_H
diff --git a/memcache/apr_memcache.c b/memcache/apr_memcache.c
index b9922fb767a0..ae41b2efd41a 100644
--- a/memcache/apr_memcache.c
+++ b/memcache/apr_memcache.c
@@ -356,7 +356,7 @@ mc_conn_construct(void **conn_, void *params, apr_pool_t *pool)
return rv;
}
- conn->buffer = apr_palloc(conn->p, BUFFER_SIZE);
+ conn->buffer = apr_palloc(conn->p, BUFFER_SIZE + 1);
conn->blen = 0;
conn->ms = ms;
@@ -728,6 +728,26 @@ apr_memcache_replace(apr_memcache_t *mc,
}
+/*
+ * Parses a decimal size from size_str, returning the value in *size.
+ * Returns 1 if parsing was successful, 0 if parsing failed.
+ */
+static int parse_size(const char *size_str, apr_size_t *size)
+{
+ char *endptr;
+ long size_as_long;
+
+ errno = 0;
+ size_as_long = strtol(size_str, &endptr, 10);
+ if ((size_as_long < 0) || (errno != 0) || (endptr == size_str) ||
+ (endptr[0] != ' ' && (endptr[0] != '\r' || endptr[1] != '\n'))) {
+ return 0;
+ }
+
+ *size = (unsigned long)size_as_long;
+ return 1;
+}
+
APU_DECLARE(apr_status_t)
apr_memcache_getp(apr_memcache_t *mc,
apr_pool_t *p,
@@ -796,13 +816,10 @@ apr_memcache_getp(apr_memcache_t *mc,
}
length = apr_strtok(NULL, " ", &last);
- if (length) {
- len = strtol(length, (char **)NULL, 10);
- }
-
- if (len == 0 ) {
- *new_length = 0;
- *baton = NULL;
+ if (!length || !parse_size(length, &len)) {
+ ms_bad_conn(ms, conn);
+ apr_memcache_disable_server(mc, ms);
+ return APR_EGENERAL;
}
else {
apr_bucket_brigade *bbb;
@@ -810,7 +827,6 @@ apr_memcache_getp(apr_memcache_t *mc,
/* eat the trailing \r\n */
rv = apr_brigade_partition(conn->bb, len+2, &e);
-
if (rv != APR_SUCCESS) {
ms_bad_conn(ms, conn);
apr_memcache_disable_server(mc, ms);
@@ -820,17 +836,14 @@ apr_memcache_getp(apr_memcache_t *mc,
bbb = apr_brigade_split(conn->bb, e);
rv = apr_brigade_pflatten(conn->bb, baton, &len, p);
-
if (rv != APR_SUCCESS) {
ms_bad_conn(ms, conn);
- apr_memcache_disable_server(mc, ms);
return rv;
}
rv = apr_brigade_destroy(conn->bb);
if (rv != APR_SUCCESS) {
ms_bad_conn(ms, conn);
- apr_memcache_disable_server(mc, ms);
return rv;
}
@@ -848,14 +861,18 @@ apr_memcache_getp(apr_memcache_t *mc,
}
if (strncmp(MS_END, conn->buffer, MS_END_LEN) != 0) {
- rv = APR_EGENERAL;
+ ms_bad_conn(ms, conn);
+ apr_memcache_disable_server(mc, ms);
+ return APR_EGENERAL;
}
}
else if (strncmp(MS_END, conn->buffer, MS_END_LEN) == 0) {
rv = APR_NOTFOUND;
}
else {
- rv = APR_EGENERAL;
+ ms_bad_conn(ms, conn);
+ apr_memcache_disable_server(mc, ms);
+ return APR_EGENERAL;
}
ms_release_conn(ms, conn);
@@ -1358,74 +1375,68 @@ apr_memcache_multgetp(apr_memcache_t *mc,
char *last;
char *data;
apr_size_t len = 0;
+ apr_bucket *e = NULL;
key = apr_strtok(conn->buffer, " ", &last); /* just the VALUE, ignore */
key = apr_strtok(NULL, " ", &last);
flags = apr_strtok(NULL, " ", &last);
-
-
length = apr_strtok(NULL, " ", &last);
- if (length) {
- len = strtol(length, (char **) NULL, 10);
+
+ if (!length || !parse_size(length, &len)) {
+ rv = APR_EGENERAL;
+ }
+ else {
+ /* eat the trailing \r\n */
+ rv = apr_brigade_partition(conn->bb, len+2, &e);
+ }
+ if (rv != APR_SUCCESS) {
+ apr_pollset_remove (pollset, &activefds[i]);
+ mget_conn_result(TRUE, FALSE, rv, mc, ms, conn,
+ server_query, values, server_queries);
+ queries_sent--;
+ continue;
}
value = apr_hash_get(values, key, strlen(key));
-
-
if (value) {
- if (len != 0) {
- apr_bucket_brigade *bbb;
- apr_bucket *e;
-
- /* eat the trailing \r\n */
- rv = apr_brigade_partition(conn->bb, len+2, &e);
-
- if (rv != APR_SUCCESS) {
- apr_pollset_remove (pollset, &activefds[i]);
- mget_conn_result(FALSE, FALSE, rv, mc, ms, conn,
- server_query, values, server_queries);
- queries_sent--;
- continue;
- }
-
- bbb = apr_brigade_split(conn->bb, e);
-
- rv = apr_brigade_pflatten(conn->bb, &data, &len, data_pool);
-
- if (rv != APR_SUCCESS) {
- apr_pollset_remove (pollset, &activefds[i]);
- mget_conn_result(FALSE, FALSE, rv, mc, ms, conn,
- server_query, values, server_queries);
- queries_sent--;
- continue;
- }
-
- rv = apr_brigade_destroy(conn->bb);
- if (rv != APR_SUCCESS) {
- apr_pollset_remove (pollset, &activefds[i]);
- mget_conn_result(FALSE, FALSE, rv, mc, ms, conn,
- server_query, values, server_queries);
- queries_sent--;
- continue;
- }
-
- conn->bb = bbb;
-
- value->len = len - 2;
- data[value->len] = '\0';
- value->data = data;
+ apr_bucket_brigade *bbb;
+
+ bbb = apr_brigade_split(conn->bb, e);
+
+ rv = apr_brigade_pflatten(conn->bb, &data, &len, data_pool);
+ if (rv != APR_SUCCESS) {
+ apr_pollset_remove (pollset, &activefds[i]);
+ mget_conn_result(TRUE, FALSE, rv, mc, ms, conn,
+ server_query, values, server_queries);
+ queries_sent--;
+ continue;
+ }
+
+ rv = apr_brigade_destroy(conn->bb);
+ if (rv != APR_SUCCESS) {
+ apr_pollset_remove (pollset, &activefds[i]);
+ mget_conn_result(TRUE, FALSE, rv, mc, ms, conn,
+ server_query, values, server_queries);
+ queries_sent--;
+ continue;
}
-
+
+ conn->bb = bbb;
+
+ value->len = len - 2;
+ data[value->len] = '\0';
+ value->data = data;
+
value->status = rv;
value->flags = atoi(flags);
-
+
/* stay on the server */
i--;
-
}
else {
- /* TODO: Server Sent back a key I didn't ask for or my
- * hash is corrupt */
+ /* Server Sent back a key I didn't ask for or my
+ * hash is corrupt */
+ rv = APR_EGENERAL;
}
}
else if (strncmp(MS_END, conn->buffer, MS_END_LEN) == 0) {
@@ -1433,14 +1444,18 @@ apr_memcache_multgetp(apr_memcache_t *mc,
apr_pollset_remove (pollset, &activefds[i]);
ms_release_conn(ms, conn);
apr_hash_set(server_queries, &ms, sizeof(ms), NULL);
-
queries_sent--;
}
else {
/* unknown reply? */
rv = APR_EGENERAL;
}
-
+ if (rv != APR_SUCCESS) {
+ apr_pollset_remove (pollset, &activefds[i]);
+ mget_conn_result(TRUE, FALSE, rv, mc, ms, conn,
+ server_query, values, server_queries);
+ queries_sent--;
+ }
} /* /for */
} /* /while */
diff --git a/redis/apr_redis.c b/redis/apr_redis.c
new file mode 100644
index 000000000000..8d01fdd67cdc
--- /dev/null
+++ b/redis/apr_redis.c
@@ -0,0 +1,1548 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_redis.h"
+#include "apr_poll.h"
+#include "apr_version.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define BUFFER_SIZE 512
+#define LILBUFF_SIZE 64
+struct apr_redis_conn_t
+{
+ char *buffer;
+ apr_size_t blen;
+ apr_pool_t *p;
+ apr_pool_t *tp;
+ apr_socket_t *sock;
+ apr_bucket_brigade *bb;
+ apr_bucket_brigade *tb;
+ apr_redis_server_t *rs;
+};
+
+/* Strings for Client Commands */
+
+#define RC_EOL "\r\n"
+#define RC_EOL_LEN (sizeof(RC_EOL)-1)
+
+#define RC_WS " "
+#define RC_WS_LEN (sizeof(RC_WS)-1)
+
+#define RC_RESP_1 "*1\r\n"
+#define RC_RESP_1_LEN (sizeof(RC_RESP_1)-1)
+
+#define RC_RESP_2 "*2\r\n"
+#define RC_RESP_2_LEN (sizeof(RC_RESP_2)-1)
+
+#define RC_RESP_3 "*3\r\n"
+#define RC_RESP_3_LEN (sizeof(RC_RESP_3)-1)
+
+#define RC_RESP_4 "*4\r\n"
+#define RC_RESP_4_LEN (sizeof(RC_RESP_4)-1)
+
+#define RC_GET "GET\r\n"
+#define RC_GET_LEN (sizeof(RC_GET)-1)
+
+#define RC_GET_SIZE "$3\r\n"
+#define RC_GET_SIZE_LEN (sizeof(RC_GET_SIZE)-1)
+
+#define RC_SET "SET\r\n"
+#define RC_SET_LEN (sizeof(RC_SET)-1)
+
+#define RC_SET_SIZE "$3\r\n"
+#define RC_SET_SIZE_LEN (sizeof(RC_SET_SIZE)-1)
+
+#define RC_SETEX "SETEX\r\n"
+#define RC_SETEX_LEN (sizeof(RC_SETEX)-1)
+
+#define RC_SETEX_SIZE "$5\r\n"
+#define RC_SETEX_SIZE_LEN (sizeof(RC_SETEX_SIZE)-1)
+
+#define RC_DEL "DEL\r\n"
+#define RC_DEL_LEN (sizeof(RC_DEL)-1)
+
+#define RC_DEL_SIZE "$3\r\n"
+#define RC_DEL_SIZE_LEN (sizeof(RC_DEL_SIZE)-1)
+
+#define RC_QUIT "QUIT\r\n"
+#define RC_QUIT_LEN (sizeof(RC_QUIT)-1)
+
+#define RC_QUIT_SIZE "$4\r\n"
+#define RC_QUIT_SIZE_LEN (sizeof(RC_QUIT_SIZE)-1)
+
+#define RC_PING "PING\r\n"
+#define RC_PING_LEN (sizeof(RC_PING)-1)
+
+#define RC_PING_SIZE "$4\r\n"
+#define RC_PING_SIZE_LEN (sizeof(RC_PING_SIZE)-1)
+
+#define RC_INFO "INFO\r\n"
+#define RC_INFO_LEN (sizeof(RC_INFO)-1)
+
+#define RC_INFO_SIZE "$4\r\n"
+#define RC_INFO_SIZE_LEN (sizeof(RC_INFO_SIZE)-1)
+
+/* Strings for Server Replies */
+
+#define RS_STORED "+OK"
+#define RS_STORED_LEN (sizeof(RS_STORED)-1)
+
+#define RS_NOT_STORED "$-1"
+#define RS_NOT_STORED_LEN (sizeof(RS_NOT_STORED)-1)
+
+#define RS_DELETED ":1"
+#define RS_DELETED_LEN (sizeof(RS_DELETED)-1)
+
+#define RS_NOT_FOUND_GET "$-1"
+#define RS_NOT_FOUND_GET_LEN (sizeof(RS_NOT_FOUND_GET)-1)
+
+#define RS_NOT_FOUND_DEL ":0"
+#define RS_NOT_FOUND_DEL_LEN (sizeof(RS_NOT_FOUND_DEL)-1)
+
+#define RS_TYPE_STRING "$"
+#define RS_TYPE_STRING_LEN (sizeof(RS_TYPE_STRING)-1)
+
+#define RS_END "\r\n"
+#define RS_END_LEN (sizeof(RS_END)-1)
+
+static apr_status_t make_server_dead(apr_redis_t *rc,
+ apr_redis_server_t *rs)
+{
+#if APR_HAS_THREADS
+ apr_thread_mutex_lock(rs->lock);
+#endif
+ rs->status = APR_RC_SERVER_DEAD;
+ rs->btime = apr_time_now();
+#if APR_HAS_THREADS
+ apr_thread_mutex_unlock(rs->lock);
+#endif
+ return APR_SUCCESS;
+}
+
+static apr_status_t make_server_live(apr_redis_t *rc,
+ apr_redis_server_t *rs)
+{
+ rs->status = APR_RC_SERVER_LIVE;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_redis_add_server(apr_redis_t *rc,
+ apr_redis_server_t *rs)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ if (rc->ntotal >= rc->nalloc) {
+ return APR_ENOMEM;
+ }
+ rc->live_servers[rc->ntotal] = rs;
+ rc->ntotal++;
+ make_server_live(rc, rs);
+ return rv;
+}
+
+APU_DECLARE(apr_redis_server_t *)
+apr_redis_find_server_hash(apr_redis_t *rc, const apr_uint32_t hash)
+{
+ if (rc->server_func) {
+ return rc->server_func(rc->server_baton, rc, hash);
+ }
+ else {
+ return apr_redis_find_server_hash_default(NULL, rc, hash);
+ }
+}
+
+APU_DECLARE(apr_redis_server_t *)
+apr_redis_find_server_hash_default(void *baton, apr_redis_t *rc,
+ const apr_uint32_t hash)
+{
+ apr_redis_server_t *rs = NULL;
+ apr_uint32_t h = hash ? hash : 1;
+ apr_uint32_t i = 0;
+ apr_time_t curtime = 0;
+
+ if (rc->ntotal == 0) {
+ return NULL;
+ }
+
+ do {
+ rs = rc->live_servers[h % rc->ntotal];
+ if (rs->status == APR_RC_SERVER_LIVE) {
+ break;
+ }
+ else {
+ if (curtime == 0) {
+ curtime = apr_time_now();
+ }
+#if APR_HAS_THREADS
+ apr_thread_mutex_lock(rs->lock);
+#endif
+ /* Try the dead server, every 5 seconds */
+ if (curtime - rs->btime > apr_time_from_sec(5)) {
+ rs->btime = curtime;
+ if (apr_redis_ping(rs) == APR_SUCCESS) {
+ make_server_live(rc, rs);
+#if APR_HAS_THREADS
+ apr_thread_mutex_unlock(rs->lock);
+#endif
+ break;
+ }
+ }
+#if APR_HAS_THREADS
+ apr_thread_mutex_unlock(rs->lock);
+#endif
+ }
+ h++;
+ i++;
+ } while (i < rc->ntotal);
+
+ if (i == rc->ntotal) {
+ rs = NULL;
+ }
+
+ return rs;
+}
+
+APU_DECLARE(apr_redis_server_t *) apr_redis_find_server(apr_redis_t *rc,
+ const char *host,
+ apr_port_t port)
+{
+ int i;
+
+ for (i = 0; i < rc->ntotal; i++) {
+ if (strcmp(rc->live_servers[i]->host, host) == 0
+ && rc->live_servers[i]->port == port) {
+
+ return rc->live_servers[i];
+ }
+ }
+
+ return NULL;
+}
+
+static apr_status_t rs_find_conn(apr_redis_server_t *rs,
+ apr_redis_conn_t ** conn)
+{
+ apr_status_t rv;
+ apr_bucket_alloc_t *balloc;
+ apr_bucket *e;
+
+#if APR_HAS_THREADS
+ rv = apr_reslist_acquire(rs->conns, (void **) conn);
+#else
+ *conn = rs->conn;
+ rv = APR_SUCCESS;
+#endif
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ balloc = apr_bucket_alloc_create((*conn)->tp);
+ (*conn)->bb = apr_brigade_create((*conn)->tp, balloc);
+ (*conn)->tb = apr_brigade_create((*conn)->tp, balloc);
+
+ e = apr_bucket_socket_create((*conn)->sock, balloc);
+ APR_BRIGADE_INSERT_TAIL((*conn)->bb, e);
+
+ return rv;
+}
+
+static apr_status_t rs_bad_conn(apr_redis_server_t *rs,
+ apr_redis_conn_t *conn)
+{
+#if APR_HAS_THREADS
+ return apr_reslist_invalidate(rs->conns, conn);
+#else
+ return APR_SUCCESS;
+#endif
+}
+
+static apr_status_t rs_release_conn(apr_redis_server_t *rs,
+ apr_redis_conn_t *conn)
+{
+ apr_pool_clear(conn->tp);
+#if APR_HAS_THREADS
+ return apr_reslist_release(rs->conns, conn);
+#else
+ return APR_SUCCESS;
+#endif
+}
+
+APU_DECLARE(apr_status_t) apr_redis_enable_server(apr_redis_t *rc,
+ apr_redis_server_t *rs)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ if (rs->status == APR_RC_SERVER_LIVE) {
+ return rv;
+ }
+ rv = make_server_live(rc, rs);
+ return rv;
+}
+
+APU_DECLARE(apr_status_t) apr_redis_disable_server(apr_redis_t *rc,
+ apr_redis_server_t *rs)
+{
+ return make_server_dead(rc, rs);
+}
+
+static apr_status_t conn_connect(apr_redis_conn_t *conn)
+{
+ apr_status_t rv = APR_SUCCESS;
+ apr_sockaddr_t *sa;
+#if APR_HAVE_SOCKADDR_UN
+ apr_int32_t family = conn->rs->host[0] != '/' ? APR_INET : APR_UNIX;
+#else
+ apr_int32_t family = APR_INET;
+#endif
+
+ rv = apr_sockaddr_info_get(&sa, conn->rs->host, family, conn->rs->port, 0,
+ conn->p);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_socket_timeout_set(conn->sock, 1 * APR_USEC_PER_SEC);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_socket_connect(conn->sock, sa);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_socket_timeout_set(conn->sock,
+ conn->rs->rwto * APR_USEC_PER_SEC);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ return rv;
+}
+
+static apr_status_t
+rc_conn_construct(void **conn_, void *params, apr_pool_t *pool)
+{
+ apr_status_t rv = APR_SUCCESS;
+ apr_redis_conn_t *conn;
+ apr_pool_t *np;
+ apr_pool_t *tp;
+ apr_redis_server_t *rs = params;
+#if APR_HAVE_SOCKADDR_UN
+ apr_int32_t family = rs->host[0] != '/' ? APR_INET : APR_UNIX;
+#else
+ apr_int32_t family = APR_INET;
+#endif
+
+ rv = apr_pool_create(&np, pool);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_pool_create(&tp, np);
+ if (rv != APR_SUCCESS) {
+ apr_pool_destroy(np);
+ return rv;
+ }
+
+ conn = apr_palloc(np, sizeof(apr_redis_conn_t));
+
+ conn->p = np;
+ conn->tp = tp;
+
+ rv = apr_socket_create(&conn->sock, family, SOCK_STREAM, 0, np);
+
+ if (rv != APR_SUCCESS) {
+ apr_pool_destroy(np);
+ return rv;
+ }
+
+ conn->buffer = apr_palloc(conn->p, BUFFER_SIZE + 1);
+ conn->blen = 0;
+ conn->rs = rs;
+
+ rv = conn_connect(conn);
+ if (rv != APR_SUCCESS) {
+ apr_pool_destroy(np);
+ }
+ else {
+ *conn_ = conn;
+ }
+
+ return rv;
+}
+
+#if APR_HAS_THREADS
+static apr_status_t
+rc_conn_destruct(void *conn_, void *params, apr_pool_t *pool)
+{
+ apr_redis_conn_t *conn = (apr_redis_conn_t *) conn_;
+ struct iovec vec[3];
+ apr_size_t written;
+
+ /* send a quit message to the Redis server to be nice about it. */
+
+ /*
+ * RESP Command:
+ * *1
+ * $4
+ * QUIT
+ */
+ vec[0].iov_base = RC_RESP_1;
+ vec[0].iov_len = RC_RESP_1_LEN;
+
+ vec[1].iov_base = RC_QUIT_SIZE;
+ vec[1].iov_len = RC_QUIT_SIZE_LEN;
+
+ vec[2].iov_base = RC_QUIT;
+ vec[2].iov_len = RC_QUIT_LEN;
+
+ /* Return values not checked, since we just want to make it go away. */
+ apr_socket_sendv(conn->sock, vec, 3, &written);
+ apr_socket_close(conn->sock);
+
+ apr_pool_destroy(conn->p);
+
+ return APR_SUCCESS;
+}
+#endif
+
+APU_DECLARE(apr_status_t) apr_redis_server_create(apr_pool_t *p,
+ const char *host,
+ apr_port_t port,
+ apr_uint32_t min,
+ apr_uint32_t smax,
+ apr_uint32_t max,
+ apr_uint32_t ttl,
+ apr_uint32_t rwto,
+ apr_redis_server_t **rs)
+{
+ apr_status_t rv = APR_SUCCESS;
+ apr_redis_server_t *server;
+ apr_pool_t *np;
+
+ rv = apr_pool_create(&np, p);
+
+ server = apr_palloc(np, sizeof(apr_redis_server_t));
+
+ server->p = np;
+ server->host = apr_pstrdup(np, host);
+ server->port = port;
+ server->status = APR_RC_SERVER_DEAD;
+ server->rwto = rwto;
+ server->version.major = 0;
+ server->version.minor = 0;
+ server->version.patch = 0;
+
+#if APR_HAS_THREADS
+ rv = apr_thread_mutex_create(&server->lock, APR_THREAD_MUTEX_DEFAULT, np);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_reslist_create(&server->conns,
+ min, /* hard minimum */
+ smax, /* soft maximum */
+ max, /* hard maximum */
+ ttl, /* Time to live */
+ rc_conn_construct, /* Make a New Connection */
+ rc_conn_destruct, /* Kill Old Connection */
+ server, np);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ apr_reslist_cleanup_order_set(server->conns, APR_RESLIST_CLEANUP_FIRST);
+#else
+ rv = rc_conn_construct((void **) &(server->conn), server, np);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+#endif
+
+ *rs = server;
+
+ return rv;
+}
+
+APU_DECLARE(apr_status_t) apr_redis_create(apr_pool_t *p,
+ apr_uint16_t max_servers,
+ apr_uint32_t flags,
+ apr_redis_t **redis)
+{
+ apr_status_t rv = APR_SUCCESS;
+ apr_redis_t *rc;
+
+ rc = apr_palloc(p, sizeof(apr_redis_t));
+ rc->p = p;
+ rc->nalloc = max_servers;
+ rc->ntotal = 0;
+ rc->live_servers =
+ apr_palloc(p, rc->nalloc * sizeof(struct apr_redis_server_t *));
+ rc->hash_func = NULL;
+ rc->hash_baton = NULL;
+ rc->server_func = NULL;
+ rc->server_baton = NULL;
+ *redis = rc;
+ return rv;
+}
+
+
+/* The crc32 functions and data was originally written by Spencer
+ * Garrett <srg@quick.com> and was gleaned from the PostgreSQL source
+ * tree via the files contrib/ltree/crc32.[ch] and from FreeBSD at
+ * src/usr.bin/cksum/crc32.c.
+ */
+
+static const apr_uint32_t crc32tab[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+APU_DECLARE(apr_uint32_t) apr_redis_hash_crc32(void *baton,
+ const char *data,
+ const apr_size_t data_len)
+{
+ apr_uint32_t i;
+ apr_uint32_t crc;
+ crc = ~0;
+
+ for (i = 0; i < data_len; i++)
+ crc = (crc >> 8) ^ crc32tab[(crc ^ (data[i])) & 0xff];
+
+ return ~crc;
+}
+
+APU_DECLARE(apr_uint32_t) apr_redis_hash_default(void *baton,
+ const char *data,
+ const apr_size_t data_len)
+{
+ /* The default Perl Client doesn't actually use just crc32 -- it shifts it again
+ * like this....
+ */
+ return ((apr_redis_hash_crc32(baton, data, data_len) >> 16) & 0x7fff);
+}
+
+APU_DECLARE(apr_uint32_t) apr_redis_hash(apr_redis_t *rc,
+ const char *data,
+ const apr_size_t data_len)
+{
+ if (rc->hash_func) {
+ return rc->hash_func(rc->hash_baton, data, data_len);
+ }
+ else {
+ return apr_redis_hash_default(NULL, data, data_len);
+ }
+}
+
+static apr_status_t get_server_line(apr_redis_conn_t *conn)
+{
+ apr_size_t bsize = BUFFER_SIZE;
+ apr_status_t rv = APR_SUCCESS;
+
+ rv = apr_brigade_split_line(conn->tb, conn->bb, APR_BLOCK_READ,
+ BUFFER_SIZE);
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_brigade_flatten(conn->tb, conn->buffer, &bsize);
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ conn->blen = bsize;
+ conn->buffer[bsize] = '\0';
+
+ return apr_brigade_cleanup(conn->tb);
+}
+
+APU_DECLARE(apr_status_t) apr_redis_set(apr_redis_t *rc,
+ const char *key,
+ char *data,
+ const apr_size_t data_size,
+ apr_uint16_t flags)
+{
+ apr_uint32_t hash;
+ apr_redis_server_t *rs;
+ apr_redis_conn_t *conn;
+ apr_status_t rv;
+ apr_size_t written;
+ struct iovec vec[9];
+ char keysize_str[LILBUFF_SIZE];
+ char datasize_str[LILBUFF_SIZE];
+ apr_size_t len, klen;
+
+ klen = strlen(key);
+ hash = apr_redis_hash(rc, key, klen);
+
+ rs = apr_redis_find_server_hash(rc, hash);
+
+ if (rs == NULL)
+ return APR_NOTFOUND;
+
+ rv = rs_find_conn(rs, &conn);
+
+ if (rv != APR_SUCCESS) {
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ /*
+ * RESP Command:
+ * *3
+ * $3
+ * SET
+ * $<keylen>
+ * key
+ * $<datalen>
+ * data
+ */
+
+ vec[0].iov_base = RC_RESP_3;
+ vec[0].iov_len = RC_RESP_3_LEN;
+
+ vec[1].iov_base = RC_SET_SIZE;
+ vec[1].iov_len = RC_SET_SIZE_LEN;
+
+ vec[2].iov_base = RC_SET;
+ vec[2].iov_len = RC_SET_LEN;
+
+ len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n", klen);
+ vec[3].iov_base = keysize_str;
+ vec[3].iov_len = len;
+
+ vec[4].iov_base = (void *) key;
+ vec[4].iov_len = klen;
+
+ vec[5].iov_base = RC_EOL;
+ vec[5].iov_len = RC_EOL_LEN;
+
+ len = apr_snprintf(datasize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+ data_size);
+ vec[6].iov_base = datasize_str;
+ vec[6].iov_len = len;
+
+ vec[7].iov_base = data;
+ vec[7].iov_len = data_size;
+
+ vec[8].iov_base = RC_EOL;
+ vec[8].iov_len = RC_EOL_LEN;
+
+ rv = apr_socket_sendv(conn->sock, vec, 9, &written);
+
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ rv = get_server_line(conn);
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ if (strcmp(conn->buffer, RS_STORED RC_EOL) == 0) {
+ rv = APR_SUCCESS;
+ }
+ else if (strcmp(conn->buffer, RS_NOT_STORED RC_EOL) == 0) {
+ rv = APR_EEXIST;
+ }
+ else {
+ rv = APR_EGENERAL;
+ }
+
+ rs_release_conn(rs, conn);
+ return rv;
+}
+
+APU_DECLARE(apr_status_t) apr_redis_setex(apr_redis_t *rc,
+ const char *key,
+ char *data,
+ const apr_size_t data_size,
+ apr_uint32_t timeout,
+ apr_uint16_t flags)
+{
+ apr_uint32_t hash;
+ apr_redis_server_t *rs;
+ apr_redis_conn_t *conn;
+ apr_status_t rv;
+ apr_size_t written;
+ struct iovec vec[11];
+ char keysize_str[LILBUFF_SIZE];
+ char expire_str[LILBUFF_SIZE];
+ char expiresize_str[LILBUFF_SIZE];
+ char datasize_str[LILBUFF_SIZE];
+ apr_size_t len, klen, expire_len;
+
+
+ klen = strlen(key);
+ hash = apr_redis_hash(rc, key, klen);
+
+ rs = apr_redis_find_server_hash(rc, hash);
+
+ if (rs == NULL)
+ return APR_NOTFOUND;
+
+ rv = rs_find_conn(rs, &conn);
+
+ if (rv != APR_SUCCESS) {
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ /*
+ * RESP Command:
+ * *4
+ * $5
+ * SETEX
+ * $<keylen>
+ * key
+ * $<expirelen>
+ * expirey
+ * $<datalen>
+ * data
+ */
+
+ vec[0].iov_base = RC_RESP_4;
+ vec[0].iov_len = RC_RESP_4_LEN;
+
+ vec[1].iov_base = RC_SETEX_SIZE;
+ vec[1].iov_len = RC_SETEX_SIZE_LEN;
+
+ vec[2].iov_base = RC_SETEX;
+ vec[2].iov_len = RC_SETEX_LEN;
+
+ len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n", klen);
+ vec[3].iov_base = keysize_str;
+ vec[3].iov_len = len;
+
+ vec[4].iov_base = (void *) key;
+ vec[4].iov_len = klen;
+
+ vec[5].iov_base = RC_EOL;
+ vec[5].iov_len = RC_EOL_LEN;
+
+ expire_len = apr_snprintf(expire_str, LILBUFF_SIZE, "%u\r\n", timeout);
+ len = apr_snprintf(expiresize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+ expire_len - 2);
+ vec[6].iov_base = (void *) expiresize_str;
+ vec[6].iov_len = len;
+
+ vec[7].iov_base = (void *) expire_str;
+ vec[7].iov_len = expire_len;
+
+ len = apr_snprintf(datasize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+ data_size);
+ vec[8].iov_base = datasize_str;
+ vec[8].iov_len = len;
+
+ vec[9].iov_base = data;
+ vec[9].iov_len = data_size;
+
+ vec[10].iov_base = RC_EOL;
+ vec[10].iov_len = RC_EOL_LEN;
+
+ rv = apr_socket_sendv(conn->sock, vec, 11, &written);
+
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ rv = get_server_line(conn);
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ if (strcmp(conn->buffer, RS_STORED RC_EOL) == 0) {
+ rv = APR_SUCCESS;
+ }
+ else if (strcmp(conn->buffer, RS_NOT_STORED RC_EOL) == 0) {
+ rv = APR_EEXIST;
+ }
+ else {
+ rv = APR_EGENERAL;
+ }
+
+ rs_release_conn(rs, conn);
+ return rv;
+}
+
+static apr_status_t grab_bulk_resp(apr_redis_server_t *rs, apr_redis_t *rc,
+ apr_redis_conn_t *conn, apr_pool_t *p,
+ char **baton, apr_size_t *new_length)
+{
+ char *length;
+ char *last;
+ apr_status_t rv;
+ apr_size_t len = 0;
+ *new_length = 0;
+
+ length = apr_strtok(conn->buffer + 1, " ", &last);
+ if (length) {
+ len = strtol(length, (char **) NULL, 10);
+ }
+
+ if (len == 0) {
+ *new_length = 0;
+ *baton = NULL;
+ }
+ else {
+ apr_bucket_brigade *bbb;
+ apr_bucket *e;
+
+ /* eat the trailing \r\n */
+ rv = apr_brigade_partition(conn->bb, len + 2, &e);
+
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ if (rc)
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ bbb = apr_brigade_split(conn->bb, e);
+
+ rv = apr_brigade_pflatten(conn->bb, baton, &len, p);
+
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ if (rc)
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ rv = apr_brigade_destroy(conn->bb);
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ if (rc)
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ conn->bb = bbb;
+
+ *new_length = len - 2;
+ (*baton)[*new_length] = '\0';
+ }
+ return APR_SUCCESS;
+
+}
+
+APU_DECLARE(apr_status_t) apr_redis_getp(apr_redis_t *rc,
+ apr_pool_t *p,
+ const char *key,
+ char **baton,
+ apr_size_t *new_length,
+ apr_uint16_t *flags)
+{
+ apr_status_t rv;
+ apr_redis_server_t *rs;
+ apr_redis_conn_t *conn;
+ apr_uint32_t hash;
+ apr_size_t written;
+ apr_size_t len, klen;
+ struct iovec vec[6];
+ char keysize_str[LILBUFF_SIZE];
+
+ klen = strlen(key);
+ hash = apr_redis_hash(rc, key, klen);
+ rs = apr_redis_find_server_hash(rc, hash);
+
+ if (rs == NULL)
+ return APR_NOTFOUND;
+
+ rv = rs_find_conn(rs, &conn);
+
+ if (rv != APR_SUCCESS) {
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ /*
+ * RESP Command:
+ * *2
+ * $3
+ * GET
+ * $<keylen>
+ * key
+ */
+ vec[0].iov_base = RC_RESP_2;
+ vec[0].iov_len = RC_RESP_2_LEN;
+
+ vec[1].iov_base = RC_GET_SIZE;
+ vec[1].iov_len = RC_GET_SIZE_LEN;
+
+ vec[2].iov_base = RC_GET;
+ vec[2].iov_len = RC_GET_LEN;
+
+ len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+ klen);
+ vec[3].iov_base = keysize_str;
+ vec[3].iov_len = len;
+
+ vec[4].iov_base = (void *) key;
+ vec[4].iov_len = klen;
+
+ vec[5].iov_base = RC_EOL;
+ vec[5].iov_len = RC_EOL_LEN;
+
+ rv = apr_socket_sendv(conn->sock, vec, 6, &written);
+
+
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ rv = get_server_line(conn);
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+ if (strncmp(RS_NOT_FOUND_GET, conn->buffer, RS_NOT_FOUND_GET_LEN) == 0) {
+ rv = APR_NOTFOUND;
+ }
+ else if (strncmp(RS_TYPE_STRING, conn->buffer, RS_TYPE_STRING_LEN) == 0) {
+ rv = grab_bulk_resp(rs, rc, conn, p, baton, new_length);
+ }
+ else {
+ rv = APR_EGENERAL;
+ }
+
+ rs_release_conn(rs, conn);
+ return rv;
+}
+
+APU_DECLARE(apr_status_t)
+ apr_redis_delete(apr_redis_t *rc, const char *key, apr_uint32_t timeout)
+{
+ apr_status_t rv;
+ apr_redis_server_t *rs;
+ apr_redis_conn_t *conn;
+ apr_uint32_t hash;
+ apr_size_t written;
+ struct iovec vec[6];
+ apr_size_t len, klen;
+ char keysize_str[LILBUFF_SIZE];
+
+ klen = strlen(key);
+ hash = apr_redis_hash(rc, key, klen);
+ rs = apr_redis_find_server_hash(rc, hash);
+ if (rs == NULL)
+ return APR_NOTFOUND;
+
+ rv = rs_find_conn(rs, &conn);
+
+ if (rv != APR_SUCCESS) {
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ /*
+ * RESP Command:
+ * *2
+ * $3
+ * DEL
+ * $<keylen>
+ * key
+ */
+ vec[0].iov_base = RC_RESP_2;
+ vec[0].iov_len = RC_RESP_2_LEN;
+
+ vec[1].iov_base = RC_DEL_SIZE;
+ vec[1].iov_len = RC_DEL_SIZE_LEN;
+
+ vec[2].iov_base = RC_DEL;
+ vec[2].iov_len = RC_DEL_LEN;
+
+ len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+ klen);
+ vec[3].iov_base = keysize_str;
+ vec[3].iov_len = len;
+
+ vec[4].iov_base = (void *) key;
+ vec[4].iov_len = klen;
+
+ vec[5].iov_base = RC_EOL;
+ vec[5].iov_len = RC_EOL_LEN;
+
+ rv = apr_socket_sendv(conn->sock, vec, 6, &written);
+
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ rv = get_server_line(conn);
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ if (strncmp(RS_DELETED, conn->buffer, RS_DELETED_LEN) == 0) {
+ rv = APR_SUCCESS;
+ }
+ else if (strncmp(RS_NOT_FOUND_DEL, conn->buffer, RS_NOT_FOUND_DEL_LEN) == 0) {
+ rv = APR_NOTFOUND;
+ }
+ else {
+ rv = APR_EGENERAL;
+ }
+
+ rs_release_conn(rs, conn);
+ return rv;
+}
+
+APU_DECLARE(apr_status_t)
+apr_redis_ping(apr_redis_server_t *rs)
+{
+ apr_status_t rv;
+ apr_size_t written;
+ struct iovec vec[3];
+ apr_redis_conn_t *conn;
+
+ rv = rs_find_conn(rs, &conn);
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ /*
+ * RESP Command:
+ * *1
+ * $4
+ * PING
+ */
+ vec[0].iov_base = RC_RESP_1;
+ vec[0].iov_len = RC_RESP_1_LEN;
+
+ vec[1].iov_base = RC_PING_SIZE;
+ vec[1].iov_len = RC_PING_SIZE_LEN;
+
+ vec[2].iov_base = RC_PING;
+ vec[2].iov_len = RC_PING_LEN;
+
+ rv = apr_socket_sendv(conn->sock, vec, 3, &written);
+
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ return rv;
+ }
+
+ rv = get_server_line(conn);
+ if (rv == APR_SUCCESS) {
+ /* we got *something*. Was it Redis? */
+ if (strncmp(conn->buffer, "+PONG", sizeof("+PONG")-1) != 0) {
+ rv = APR_EGENERAL;
+ }
+ }
+ rs_release_conn(rs, conn);
+ return rv;
+}
+
+APU_DECLARE(apr_status_t)
+apr_redis_info(apr_redis_server_t *rs, apr_pool_t *p, char **baton)
+{
+ apr_status_t rv;
+ apr_redis_conn_t *conn;
+ apr_size_t written;
+ struct iovec vec[3];
+
+ rv = rs_find_conn(rs, &conn);
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ /*
+ * RESP Command:
+ * *1
+ * $4
+ * INFO
+ */
+ vec[0].iov_base = RC_RESP_1;
+ vec[0].iov_len = RC_RESP_1_LEN;
+
+ vec[1].iov_base = RC_INFO_SIZE;
+ vec[1].iov_len = RC_INFO_SIZE_LEN;
+
+ vec[2].iov_base = RC_INFO;
+ vec[2].iov_len = RC_INFO_LEN;
+
+ rv = apr_socket_sendv(conn->sock, vec, 3, &written);
+
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ return rv;
+ }
+
+ rv = get_server_line(conn);
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ return rv;
+ }
+
+ if (strncmp(RS_TYPE_STRING, conn->buffer, RS_TYPE_STRING_LEN) == 0) {
+ apr_size_t nl;
+ rv = grab_bulk_resp(rs, NULL, conn, p, baton, &nl);
+ } else {
+ rs_bad_conn(rs, conn);
+ rv = APR_EGENERAL;
+ }
+
+ rs_release_conn(rs, conn);
+ return rv;
+}
+
+#define RV_FIELD "redis_version:"
+APU_DECLARE(apr_status_t)
+apr_redis_version(apr_redis_server_t *rs, apr_pool_t *p, char **baton)
+{
+ apr_status_t rv;
+ char *ptr, *eptr;
+ apr_pool_t *subpool;
+
+ /* Have we already obtained the version number? */
+ if (rs->version.minor != 0) {
+ if (baton)
+ *baton = apr_pstrdup(p, rs->version.number);
+ return APR_SUCCESS;
+ }
+ if (apr_pool_create(&subpool, p) != APR_SUCCESS) {
+ /* well, we tried */
+ subpool = p;
+ }
+ rv = apr_redis_info(rs, subpool, baton);
+
+ if (rv != APR_SUCCESS) {
+ if (subpool != p) {
+ apr_pool_destroy(subpool);
+ }
+ return rv;
+ }
+
+ ptr = strstr(*baton, RV_FIELD);
+ if (ptr) {
+ rs->version.major = strtol(ptr + sizeof(RV_FIELD) - 1, &eptr, 10);
+ ptr = eptr + 1;
+ rs->version.minor = strtol(ptr, &eptr, 10);
+ ptr = eptr + 1;
+ rs->version.patch = strtol(ptr, &eptr, 10);
+ rs->version.number = apr_psprintf(rs->p, "%d.%d.%d",
+ rs->version.major, rs->version.minor,
+ rs->version.patch);
+ }
+ if (baton)
+ *baton = apr_pstrdup(p, rs->version.number);
+ if (subpool != p) {
+ apr_pool_destroy(subpool);
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t plus_minus(apr_redis_t *rc,
+ int incr,
+ const char *key,
+ apr_int32_t inc,
+ apr_uint32_t *new_value)
+{
+ apr_status_t rv;
+ apr_redis_server_t *rs;
+ apr_redis_conn_t *conn;
+ apr_uint32_t hash;
+ apr_size_t written;
+ apr_size_t len, klen;
+ struct iovec vec[12];
+ char keysize_str[LILBUFF_SIZE];
+ char inc_str[LILBUFF_SIZE];
+ char inc_str_len[LILBUFF_SIZE];
+ int i = 0;
+
+ klen = strlen(key);
+ hash = apr_redis_hash(rc, key, klen);
+ rs = apr_redis_find_server_hash(rc, hash);
+ if (rs == NULL)
+ return APR_NOTFOUND;
+
+ rv = rs_find_conn(rs, &conn);
+
+ if (rv != APR_SUCCESS) {
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ /*
+ * RESP Command:
+ * *2|*3
+ * $4|$6
+ * INCR/DECR|INCRBY/DECRBY
+ * $<keylen>
+ * key
+ * <:inc>
+ */
+ if (inc == 1) {
+ vec[i].iov_base = RC_RESP_2;
+ vec[i].iov_len = RC_RESP_2_LEN;
+ i++;
+
+ vec[i].iov_base = "$4\r\n";
+ vec[i].iov_len = sizeof("$4\r\n")-1;
+ i++;
+
+ if (incr)
+ vec[i].iov_base = "INCR\r\n";
+ else
+ vec[i].iov_base = "DECR\r\n";
+ vec[i].iov_len = sizeof("INCR\r\n")-1;
+ i++;
+ }
+ else {
+ vec[i].iov_base = RC_RESP_3;
+ vec[i].iov_len = RC_RESP_3_LEN;
+ i++;
+
+ vec[i].iov_base = "$6\r\n";
+ vec[i].iov_len = sizeof("$6\r\n")-1;
+ i++;
+
+ if (incr)
+ vec[i].iov_base = "INCRBY\r\n";
+ else
+ vec[i].iov_base = "DECRBY\r\n";
+ vec[i].iov_len = sizeof("INCRBY\r\n")-1;
+ i++;
+ }
+
+ len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+ klen);
+ vec[i].iov_base = keysize_str;
+ vec[i].iov_len = len;
+ i++;
+
+ vec[i].iov_base = (void *) key;
+ vec[i].iov_len = klen;
+ i++;
+
+ vec[i].iov_base = RC_EOL;
+ vec[i].iov_len = RC_EOL_LEN;
+ i++;
+
+ if (inc != 1) {
+ len = apr_snprintf(inc_str, LILBUFF_SIZE, "%d\r\n", inc);
+ klen = apr_snprintf(inc_str_len, LILBUFF_SIZE, "$%d\r\n", (int)(len-2));
+ vec[i].iov_base = inc_str_len;
+ vec[i].iov_len = klen;
+ i++;
+
+ vec[i].iov_base = inc_str;
+ vec[i].iov_len = len;
+ i++;
+
+ vec[i].iov_base = RC_EOL;
+ vec[i].iov_len = RC_EOL_LEN;
+ i++;
+ }
+
+ rv = apr_socket_sendv(conn->sock, vec, i, &written);
+
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+
+ rv = get_server_line(conn);
+ if (rv != APR_SUCCESS) {
+ rs_bad_conn(rs, conn);
+ apr_redis_disable_server(rc, rs);
+ return rv;
+ }
+ if (strncmp(RS_NOT_FOUND_GET, conn->buffer, RS_NOT_FOUND_GET_LEN) == 0) {
+ rv = APR_NOTFOUND;
+ }
+ else if (*conn->buffer == ':') {
+ *new_value = atoi((const char *)(conn->buffer + 1));
+ rv = APR_SUCCESS;
+ }
+ else {
+ rv = APR_EGENERAL;
+ }
+ rs_release_conn(rs, conn);
+ return rv;
+}
+
+APU_DECLARE(apr_status_t)
+apr_redis_incr(apr_redis_t *rc, const char *key, apr_int32_t inc, apr_uint32_t *new_value)
+{
+ return plus_minus(rc, 1, key, inc, new_value);
+}
+
+APU_DECLARE(apr_status_t)
+apr_redis_decr(apr_redis_t *rc, const char *key, apr_int32_t inc, apr_uint32_t *new_value)
+{
+ return plus_minus(rc, 0, key, inc, new_value);
+}
+
+APU_DECLARE(apr_status_t)
+apr_redis_multgetp(apr_redis_t *rc,
+ apr_pool_t *temp_pool,
+ apr_pool_t *data_pool,
+ apr_hash_t *values)
+{
+ return APR_ENOTIMPL;
+}
+
+/**
+ * Define all of the strings for stats
+ */
+
+#define STAT_process_id "process_id:"
+#define STAT_process_id_LEN (sizeof(STAT_process_id)-1)
+
+#define STAT_uptime_in_seconds "uptime_in_seconds:"
+#define STAT_uptime_in_seconds_LEN (sizeof(STAT_uptime_in_seconds)-1)
+
+#define STAT_arch_bits "arch_bits:"
+#define STAT_arch_bits_LEN (sizeof(STAT_arch_bits)-1)
+
+#define STAT_connected_clients "connected_clients:"
+#define STAT_connected_clients_LEN (sizeof(STAT_connected_clients)-1)
+
+#define STAT_blocked_clients "blocked_clients:"
+#define STAT_blocked_clients_LEN (sizeof(STAT_blocked_clients)-1)
+
+#define STAT_maxmemory "maxmemory:"
+#define STAT_maxmemory_LEN (sizeof(STAT_maxmemory)-1)
+
+#define STAT_used_memory "used_memory:"
+#define STAT_used_memory_LEN (sizeof(STAT_used_memory)-1)
+
+#define STAT_total_system_memory "total_system_memory:"
+#define STAT_total_system_memory_LEN (sizeof(STAT_total_system_memory)-1)
+
+#define STAT_total_connections_received "total_connections_received:"
+#define STAT_total_connections_received_LEN (sizeof(STAT_total_connections_received)-1)
+
+#define STAT_total_commands_processed "total_commands_processed:"
+#define STAT_total_commands_processed_LEN (sizeof(STAT_total_commands_processed)-1)
+
+#define STAT_rejected_connections "rejected_connections:"
+#define STAT_rejected_connections_LEN (sizeof(STAT_rejected_connections)-1)
+
+#define STAT_total_net_input_bytes "total_net_input_bytes:"
+#define STAT_total_net_input_bytes_LEN (sizeof(STAT_total_net_input_bytes)-1)
+
+#define STAT_total_net_output_bytes "total_net_output_bytes:"
+#define STAT_total_net_output_bytes_LEN (sizeof(STAT_total_net_output_bytes)-1)
+
+#define STAT_keyspace_hits "keyspace_hits:"
+#define STAT_keyspace_hits_LEN (sizeof(STAT_keyspace_hits)-1)
+
+#define STAT_keyspace_misses "keyspace_misses:"
+#define STAT_keyspace_misses_LEN (sizeof(STAT_keyspace_misses)-1)
+
+#define STAT_connected_slaves "connected_slaves:"
+#define STAT_connected_slaves_LEN (sizeof(STAT_connected_slaves)-1)
+
+#define STAT_used_cpu_sys "used_cpu_sys:"
+#define STAT_used_cpu_sys_LEN (sizeof(STAT_used_cpu_sys)-1)
+
+#define STAT_used_cpu_user "used_cpu_user:"
+#define STAT_used_cpu_user_LEN (sizeof(STAT_used_cpu_user)-1)
+
+#define STAT_cluster_enabled "cluster_enabled:"
+#define STAT_cluster_enabled_LEN (sizeof(STAT_cluster_enabled)-1)
+
+static apr_uint32_t stat_read_uint32( char *buf)
+{
+ return atoi(buf);
+}
+
+static apr_uint64_t stat_read_uint64(char *buf)
+{
+ return apr_atoi64(buf);
+}
+
+#define rc_do_stat(name, type) \
+ if ((ptr = strstr(info , STAT_ ## name )) != NULL ) { \
+ char *str = ptr + (STAT_ ## name ## _LEN ); \
+ stats-> name = stat_read_ ## type (str); \
+ }
+
+static void update_stats(char *info, apr_redis_stats_t *stats)
+{
+ char *ptr;
+
+ rc_do_stat(process_id, uint32);
+ rc_do_stat(uptime_in_seconds, uint32);
+ rc_do_stat(arch_bits, uint32);
+ rc_do_stat(connected_clients, uint32);
+ rc_do_stat(blocked_clients, uint32);
+ rc_do_stat(maxmemory, uint64);
+ rc_do_stat(used_memory, uint64);
+ rc_do_stat(total_system_memory, uint64);
+ rc_do_stat(total_connections_received, uint64);
+ rc_do_stat(total_commands_processed, uint64);
+ rc_do_stat(rejected_connections, uint64);
+ rc_do_stat(total_net_input_bytes, uint64);
+ rc_do_stat(total_net_output_bytes, uint64);
+ rc_do_stat(keyspace_hits, uint64);
+ rc_do_stat(keyspace_misses, uint64);
+ rc_do_stat(connected_slaves, uint32);
+ rc_do_stat(used_cpu_sys, uint32);
+ rc_do_stat(used_cpu_user, uint32);
+ rc_do_stat(cluster_enabled, uint32);
+}
+
+APU_DECLARE(apr_status_t)
+apr_redis_stats(apr_redis_server_t *rs,
+ apr_pool_t *p,
+ apr_redis_stats_t **stats)
+{
+ apr_status_t rv;
+ char *info;
+ apr_pool_t *subpool;
+ apr_redis_stats_t *ret;
+ char *ptr;
+
+ if (apr_pool_create(&subpool, p) != APR_SUCCESS) {
+ /* well, we tried */
+ subpool = p;
+ }
+ rv = apr_redis_info(rs, subpool, &info);
+
+ if (rv != APR_SUCCESS) {
+ if (subpool != p) {
+ apr_pool_destroy(subpool);
+ }
+ return rv;
+ }
+ ret = apr_pcalloc(p, sizeof(apr_redis_stats_t));
+ /* Get the bulk of the stats */
+ update_stats(info, ret);
+
+ /* Now the version number */
+ if (rs->version.major != 0) {
+ ret->major = rs->version.major;
+ ret->minor = rs->version.minor;
+ ret->patch = rs->version.patch;
+ }
+ else {
+ char *eptr;
+ ptr = strstr(info, RV_FIELD);
+ if (ptr) {
+ ret->major = rs->version.major = strtol(ptr + sizeof(RV_FIELD) - 1, &eptr, 10);
+ ptr = eptr + 1;
+ ret->minor = rs->version.minor = strtol(ptr, &eptr, 10);
+ ptr = eptr + 1;
+ ret->patch = rs->version.patch = strtol(ptr, &eptr, 10);
+ }
+ }
+
+ /* Finally, the role */
+ ptr = strstr(info, "role:");
+ if (!ptr) {
+ ret->role = APR_RS_SERVER_UNKNOWN;
+ }
+ else if (!strncmp("master", ptr + sizeof("role:") - 1, sizeof("master")-1)) {
+ ret->role = APR_RS_SERVER_MASTER;
+ }
+ else {
+ ret->role = APR_RS_SERVER_SLAVE;
+ }
+ if (stats) {
+ *stats = ret;
+ }
+
+ return APR_SUCCESS;
+}
diff --git a/test/Makefile.in b/test/Makefile.in
index 5f4cf91b9b13..e1b4d7c20333 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -17,7 +17,7 @@ STDTEST_PORTABLE = dbd testall
TESTS = teststrmatch.lo testuri.lo testuuid.lo testbuckets.lo testpass.lo \
testmd4.lo testmd5.lo testldap.lo testdate.lo testdbm.lo testdbd.lo \
testxml.lo testrmm.lo testreslist.lo testqueue.lo testxlate.lo \
- testmemcache.lo testcrypto.lo
+ testmemcache.lo testcrypto.lo testsiphash.lo testredis.lo
PROGRAMS = $(STDTEST_PORTABLE)
diff --git a/test/Makefile.win b/test/Makefile.win
index a30f39e2b520..fa3d2eba5c2f 100644
--- a/test/Makefile.win
+++ b/test/Makefile.win
@@ -62,6 +62,7 @@ ALL_TESTS = $(INTDIR)\teststrmatch.obj $(INTDIR)\testuri.obj \
$(INTDIR)\testxml.obj $(INTDIR)\testqueue.obj \
$(INTDIR)\testrmm.obj $(INTDIR)\testxlate.obj \
$(INTDIR)\testdate.obj $(INTDIR)\testmemcache.obj \
+ $(INTDIR)\testredis.obj $(INTDIR)\testsiphash.obj \
$(INTDIR)\testcrypto.obj
CLEAN_DATA = manyfile.bin testfile.txt data\sqlite*.db
@@ -89,10 +90,9 @@ APROUTDIR=$(OUTDIR)
PROGRAM_DEPENDENCIES = \
$(APR_PATH)\$(APROUTDIR)\apr-1.lib \
$(API_PATH)\$(OUTDIR)\apriconv-1.lib \
- ..\xml\expat\lib\$(OUTDIR)\xml.lib \
..\$(OUTDIR)\aprutil-1.lib
STATIC_CFLAGS = /D APR_DECLARE_STATIC /D APU_DECLARE_STATIC
-STATIC_LIBS = odbc32.lib odbccp32.lib wldap32.lib
+STATIC_LIBS = libexpatMT.lib odbc32.lib odbccp32.lib wldap32.lib
!ELSE
PROGRAM_DEPENDENCIES = \
$(APR_PATH)\$(APROUTDIR)\libapr-1.lib \
diff --git a/test/NWGNUaputest b/test/NWGNUaputest
index 6b710ad84d53..caf3cd49f6f5 100644
--- a/test/NWGNUaputest
+++ b/test/NWGNUaputest
@@ -185,6 +185,7 @@ FILES_nlm_objs = \
$(OBJDIR)/testqueue.o \
$(OBJDIR)/testreslist.o \
$(OBJDIR)/testrmm.o \
+ $(OBJDIR)/testsiphash.o \
$(OBJDIR)/teststrmatch.o \
$(OBJDIR)/testuri.o \
$(OBJDIR)/testutil.o \
diff --git a/test/abts_tests.h b/test/abts_tests.h
index b612d31b8fa5..cb4e113fe8b6 100644
--- a/test/abts_tests.h
+++ b/test/abts_tests.h
@@ -35,12 +35,14 @@ const struct testlist {
{testdbd},
{testdate},
{testmemcache},
+ {testredis},
{testxml},
{testxlate},
{testrmm},
{testdbm},
{testqueue},
- {testreslist}
+ {testreslist},
+ {testsiphash}
};
#endif /* APR_TEST_INCLUDES */
diff --git a/test/testall.dsw b/test/testall.dsw
index 0a640c8be296..7fde202c2b07 100644
--- a/test/testall.dsw
+++ b/test/testall.dsw
@@ -28,23 +28,6 @@ Package=<4>
End Project Dependency
}}}
-###############################################################################
-
-Project: "apr_dbd_freetds"="..\dbd\apr_dbd_freetds.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name libapr
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name libaprutil
- End Project Dependency
-}}}
###############################################################################
diff --git a/test/testcrypto.c b/test/testcrypto.c
index 335c3ae65d77..865cffc6d5ed 100644
--- a/test/testcrypto.c
+++ b/test/testcrypto.c
@@ -33,22 +33,32 @@ static const apr_crypto_driver_t *get_driver(abts_case *tc, apr_pool_t *pool,
{
const apr_crypto_driver_t *driver = NULL;
- const apu_err_t *err = NULL;
+ const apu_err_t *result = NULL;
apr_status_t rv;
rv = apr_crypto_init(pool);
ABTS_ASSERT(tc, "failed to init apr_crypto", rv == APR_SUCCESS);
- rv = apr_crypto_get_driver(&driver, name, params, &err, pool);
- if (APR_SUCCESS != rv && err) {
- ABTS_NOT_IMPL(tc, err->msg);
+ rv = apr_crypto_get_driver(&driver, name, params, &result, pool);
+ if (APR_ENOTIMPL == rv) {
+ ABTS_NOT_IMPL(tc,
+ apr_psprintf(pool, "Crypto driver '%s' not implemented", (char *)name));
return NULL;
}
- if (APR_ENOTIMPL == rv) {
- ABTS_NOT_IMPL(tc, (char *)driver);
+ if (APR_EDSOOPEN == rv) {
+ ABTS_NOT_IMPL(tc,
+ apr_psprintf(pool, "Crypto driver '%s' DSO could not be opened", (char *)name));
return NULL;
}
- ABTS_ASSERT(tc, "failed to apr_crypto_get_driver", rv == APR_SUCCESS);
+ if (APR_SUCCESS != rv && result) {
+ char err[1024];
+ apr_strerror(rv, err, sizeof(err) - 1);
+ fprintf(stderr, "get_driver error %d: %s: '%s' native error %d: %s (%s),",
+ rv, err, name, result->rc, result->reason ? result->reason : "",
+ result->msg ? result->msg : "");
+ }
+ ABTS_ASSERT(tc, apr_psprintf(pool, "failed to apr_crypto_get_driver for '%s' with %d",
+ name, rv), rv == APR_SUCCESS);
ABTS_ASSERT(tc, "apr_crypto_get_driver returned NULL", driver != NULL);
if (!driver || rv) {
return NULL;
@@ -63,7 +73,7 @@ static const apr_crypto_driver_t *get_nss_driver(abts_case *tc,
{
/* initialise NSS */
- return get_driver(tc, pool, "nss", "dir=data");
+ return get_driver(tc, pool, "nss", "");
}
@@ -75,6 +85,14 @@ static const apr_crypto_driver_t *get_openssl_driver(abts_case *tc,
}
+static const apr_crypto_driver_t *get_commoncrypto_driver(abts_case *tc,
+ apr_pool_t *pool)
+{
+
+ return get_driver(tc, pool, "commoncrypto", NULL);
+
+}
+
static apr_crypto_t *make(abts_case *tc, apr_pool_t *pool,
const apr_crypto_driver_t *driver)
{
@@ -93,6 +111,59 @@ static apr_crypto_t *make(abts_case *tc, apr_pool_t *pool,
}
+static const apr_crypto_key_t *keysecret(abts_case *tc, apr_pool_t *pool,
+ const apr_crypto_driver_t *driver, const apr_crypto_t *f,
+ apr_crypto_block_key_type_e type, apr_crypto_block_key_mode_e mode,
+ int doPad, apr_size_t secretLen, const char *description)
+{
+ apr_crypto_key_t *key = NULL;
+ const apu_err_t *result = NULL;
+ apr_crypto_key_rec_t *rec = apr_pcalloc(pool, sizeof(apr_crypto_key_rec_t));
+ apr_status_t rv;
+
+ if (!f) {
+ return NULL;
+ }
+
+ rec->ktype = APR_CRYPTO_KTYPE_SECRET;
+ rec->type = type;
+ rec->mode = mode;
+ rec->pad = doPad;
+ rec->k.secret.secret = apr_pcalloc(pool, secretLen);
+ rec->k.secret.secretLen = secretLen;
+
+ /* init the passphrase */
+ rv = apr_crypto_key(&key, rec, f, pool);
+ if (APR_ENOCIPHER == rv) {
+ apr_crypto_error(&result, f);
+ ABTS_NOT_IMPL(tc,
+ apr_psprintf(pool, "skipped: %s %s key return APR_ENOCIPHER: error %d: %s (%s)\n", description, apr_crypto_driver_name(driver), result->rc, result->reason ? result->reason : "", result->msg ? result->msg : ""));
+ return NULL;
+ }
+ else {
+ if (APR_SUCCESS != rv) {
+ apr_crypto_error(&result, f);
+ fprintf(stderr, "key: %s %s apr error %d / native error %d: %s (%s)\n",
+ description, apr_crypto_driver_name(driver), rv, result->rc,
+ result->reason ? result->reason : "",
+ result->msg ? result->msg : "");
+ }
+ ABTS_ASSERT(tc, "apr_crypto_key returned APR_EKEYLENGTH", rv != APR_EKEYLENGTH);
+ ABTS_ASSERT(tc, "apr_crypto_key returned APR_ENOKEY", rv != APR_ENOKEY);
+ ABTS_ASSERT(tc, "apr_crypto_key returned APR_EPADDING",
+ rv != APR_EPADDING);
+ ABTS_ASSERT(tc, "apr_crypto_key returned APR_EKEYTYPE",
+ rv != APR_EKEYTYPE);
+ ABTS_ASSERT(tc, "failed to apr_crypto_key", rv == APR_SUCCESS);
+ ABTS_ASSERT(tc, "apr_crypto_key returned NULL context", key != NULL);
+ }
+ if (rv) {
+ return NULL;
+ }
+ return key;
+
+}
+
static const apr_crypto_key_t *passphrase(abts_case *tc, apr_pool_t *pool,
const apr_crypto_driver_t *driver, const apr_crypto_t *f,
apr_crypto_block_key_type_e type, apr_crypto_block_key_mode_e mode,
@@ -124,8 +195,8 @@ static const apr_crypto_key_t *passphrase(abts_case *tc, apr_pool_t *pool,
else {
if (APR_SUCCESS != rv) {
apr_crypto_error(&result, f);
- fprintf(stderr, "passphrase: %s %s native error %d: %s (%s)\n",
- description, apr_crypto_driver_name(driver), result->rc,
+ fprintf(stderr, "passphrase: %s %s apr error %d / native error %d: %s (%s)\n",
+ description, apr_crypto_driver_name(driver), rv, result->rc,
result->reason ? result->reason : "",
result->msg ? result->msg : "");
}
@@ -142,6 +213,64 @@ static const apr_crypto_key_t *passphrase(abts_case *tc, apr_pool_t *pool,
}
+static const apr_crypto_key_t *keypassphrase(abts_case *tc, apr_pool_t *pool,
+ const apr_crypto_driver_t *driver, const apr_crypto_t *f,
+ apr_crypto_block_key_type_e type, apr_crypto_block_key_mode_e mode,
+ int doPad, const char *description)
+{
+
+ apr_crypto_key_t *key = NULL;
+ const apu_err_t *result = NULL;
+ const char *pass = "secret";
+ const char *salt = "salt";
+ apr_crypto_key_rec_t *rec = apr_pcalloc(pool, sizeof(apr_crypto_key_rec_t));
+ apr_status_t rv;
+
+ if (!f) {
+ return NULL;
+ }
+
+ rec->ktype = APR_CRYPTO_KTYPE_PASSPHRASE;
+ rec->type = type;
+ rec->mode = mode;
+ rec->pad = doPad;
+ rec->k.passphrase.pass = pass;
+ rec->k.passphrase.passLen = strlen(pass);
+ rec->k.passphrase.salt = (unsigned char *)salt;
+ rec->k.passphrase.saltLen = strlen(salt);
+ rec->k.passphrase.iterations = 4096;
+
+ /* init the passphrase */
+ rv = apr_crypto_key(&key, rec, f, pool);
+ if (APR_ENOCIPHER == rv) {
+ apr_crypto_error(&result, f);
+ ABTS_NOT_IMPL(tc, apr_psprintf(pool,
+ "skipped: %s %s key passphrase return APR_ENOCIPHER: error %d: %s (%s)\n",
+ description, apr_crypto_driver_name(driver), result->rc,
+ result->reason ? result->reason : "", result->msg ? result->msg : ""));
+ return NULL;
+ }
+ else {
+ if (APR_SUCCESS != rv) {
+ apr_crypto_error(&result, f);
+ fprintf(stderr, "key passphrase: %s %s apr error %d / native error %d: %s (%s)\n",
+ description, apr_crypto_driver_name(driver), rv, result->rc,
+ result->reason ? result->reason : "",
+ result->msg ? result->msg : "");
+ }
+ ABTS_ASSERT(tc, "apr_crypto_key returned APR_ENOKEY", rv != APR_ENOKEY);
+ ABTS_ASSERT(tc, "apr_crypto_key returned APR_EPADDING", rv != APR_EPADDING);
+ ABTS_ASSERT(tc, "apr_crypto_key returned APR_EKEYTYPE", rv != APR_EKEYTYPE);
+ ABTS_ASSERT(tc, "failed to apr_crypto_key", rv == APR_SUCCESS);
+ ABTS_ASSERT(tc, "apr_crypto_key returned NULL context", key != NULL);
+ }
+ if (rv) {
+ return NULL;
+ }
+ return key;
+
+}
+
static unsigned char *encrypt_block(abts_case *tc, apr_pool_t *pool,
const apr_crypto_driver_t *driver, const apr_crypto_t *f,
const apr_crypto_key_t *key, const unsigned char *in,
@@ -167,17 +296,27 @@ static unsigned char *encrypt_block(abts_case *tc, apr_pool_t *pool,
else {
if (APR_SUCCESS != rv) {
apr_crypto_error(&result, f);
- fprintf(stderr, "encrypt_init: %s %s native error %d: %s (%s)\n",
- description, apr_crypto_driver_name(driver), result->rc,
+ fprintf(stderr,
+ "encrypt_init: %s %s (APR %d) native error %d: %s (%s)\n",
+ description, apr_crypto_driver_name(driver), rv, result->rc,
result->reason ? result->reason : "",
result->msg ? result->msg : "");
}
- ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_ENOKEY", rv != APR_ENOKEY);
- ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_ENOIV", rv != APR_ENOIV);
- ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_EKEYTYPE", rv != APR_EKEYTYPE);
- ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_EKEYLENGTH", rv != APR_EKEYLENGTH);
- ABTS_ASSERT(tc, "failed to apr_crypto_block_encrypt_init", rv == APR_SUCCESS);
- ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned NULL context", block != NULL);
+ ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_ENOKEY",
+ rv != APR_ENOKEY);
+ ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_ENOIV",
+ rv != APR_ENOIV);
+ ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_EKEYTYPE",
+ rv != APR_EKEYTYPE);
+ ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_EKEYLENGTH",
+ rv != APR_EKEYLENGTH);
+ ABTS_ASSERT(tc,
+ "apr_crypto_block_encrypt_init returned APR_ENOTENOUGHENTROPY",
+ rv != APR_ENOTENOUGHENTROPY);
+ ABTS_ASSERT(tc, "failed to apr_crypto_block_encrypt_init",
+ rv == APR_SUCCESS);
+ ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned NULL context",
+ block != NULL);
}
if (!block || rv) {
return NULL;
@@ -187,10 +326,10 @@ static unsigned char *encrypt_block(abts_case *tc, apr_pool_t *pool,
rv = apr_crypto_block_encrypt(cipherText, cipherTextLen, in, inlen, block);
if (APR_SUCCESS != rv) {
apr_crypto_error(&result, f);
- fprintf(stderr, "encrypt: %s %s native error %d: %s (%s)\n",
- description, apr_crypto_driver_name(driver), result->rc,
- result->reason ? result->reason : "", result->msg ? result->msg
- : "");
+ fprintf(stderr, "encrypt: %s %s (APR %d) native error %d: %s (%s)\n",
+ description, apr_crypto_driver_name(driver), rv, result->rc,
+ result->reason ? result->reason : "",
+ result->msg ? result->msg : "");
}
ABTS_ASSERT(tc, "apr_crypto_block_encrypt returned APR_ECRYPT", rv != APR_ECRYPT);
ABTS_ASSERT(tc, "failed to apr_crypto_block_encrypt", rv == APR_SUCCESS);
@@ -204,13 +343,15 @@ static unsigned char *encrypt_block(abts_case *tc, apr_pool_t *pool,
block);
if (APR_SUCCESS != rv) {
apr_crypto_error(&result, f);
- fprintf(stderr, "encrypt_finish: %s %s native error %d: %s (%s)\n",
- description, apr_crypto_driver_name(driver), result->rc,
- result->reason ? result->reason : "", result->msg ? result->msg
- : "");
+ fprintf(stderr,
+ "encrypt_finish: %s %s (APR %d) native error %d: %s (%s)\n",
+ description, apr_crypto_driver_name(driver), rv, result->rc,
+ result->reason ? result->reason : "",
+ result->msg ? result->msg : "");
}
ABTS_ASSERT(tc, "apr_crypto_block_encrypt_finish returned APR_ECRYPT", rv != APR_ECRYPT);
ABTS_ASSERT(tc, "apr_crypto_block_encrypt_finish returned APR_EPADDING", rv != APR_EPADDING);
+ ABTS_ASSERT(tc, "apr_crypto_block_encrypt_finish returned APR_ENOSPACE", rv != APR_ENOSPACE);
ABTS_ASSERT(tc, "failed to apr_crypto_block_encrypt_finish", rv == APR_SUCCESS);
*cipherTextLen += len;
apr_crypto_block_cleanup(block);
@@ -247,8 +388,9 @@ static unsigned char *decrypt_block(abts_case *tc, apr_pool_t *pool,
else {
if (APR_SUCCESS != rv) {
apr_crypto_error(&result, f);
- fprintf(stderr, "decrypt_init: %s %s native error %d: %s (%s)\n",
- description, apr_crypto_driver_name(driver), result->rc,
+ fprintf(stderr,
+ "decrypt_init: %s %s (APR %d) native error %d: %s (%s)\n",
+ description, apr_crypto_driver_name(driver), rv, result->rc,
result->reason ? result->reason : "",
result->msg ? result->msg : "");
}
@@ -268,10 +410,10 @@ static unsigned char *decrypt_block(abts_case *tc, apr_pool_t *pool,
cipherTextLen, block);
if (APR_SUCCESS != rv) {
apr_crypto_error(&result, f);
- fprintf(stderr, "decrypt: %s %s native error %d: %s (%s)\n",
- description, apr_crypto_driver_name(driver), result->rc,
- result->reason ? result->reason : "", result->msg ? result->msg
- : "");
+ fprintf(stderr, "decrypt: %s %s (APR %d) native error %d: %s (%s)\n",
+ description, apr_crypto_driver_name(driver), rv, result->rc,
+ result->reason ? result->reason : "",
+ result->msg ? result->msg : "");
}
ABTS_ASSERT(tc, "apr_crypto_block_decrypt returned APR_ECRYPT", rv != APR_ECRYPT);
ABTS_ASSERT(tc, "failed to apr_crypto_block_decrypt", rv == APR_SUCCESS);
@@ -285,13 +427,15 @@ static unsigned char *decrypt_block(abts_case *tc, apr_pool_t *pool,
block);
if (APR_SUCCESS != rv) {
apr_crypto_error(&result, f);
- fprintf(stderr, "decrypt_finish: %s %s native error %d: %s (%s)\n",
- description, apr_crypto_driver_name(driver), result->rc,
- result->reason ? result->reason : "", result->msg ? result->msg
- : "");
+ fprintf(stderr,
+ "decrypt_finish: %s %s (APR %d) native error %d: %s (%s)\n",
+ description, apr_crypto_driver_name(driver), rv, result->rc,
+ result->reason ? result->reason : "",
+ result->msg ? result->msg : "");
}
ABTS_ASSERT(tc, "apr_crypto_block_decrypt_finish returned APR_ECRYPT", rv != APR_ECRYPT);
ABTS_ASSERT(tc, "apr_crypto_block_decrypt_finish returned APR_EPADDING", rv != APR_EPADDING);
+ ABTS_ASSERT(tc, "apr_crypto_block_decrypt_finish returned APR_ENOSPACE", rv != APR_ENOSPACE);
ABTS_ASSERT(tc, "failed to apr_crypto_block_decrypt_finish", rv == APR_SUCCESS);
if (rv) {
return NULL;
@@ -316,7 +460,8 @@ static void crypto_block_cross(abts_case *tc, apr_pool_t *pool,
const apr_crypto_driver_t **drivers,
const apr_crypto_block_key_type_e type,
const apr_crypto_block_key_mode_e mode, int doPad,
- const unsigned char *in, apr_size_t inlen, const char *description)
+ const unsigned char *in, apr_size_t inlen, apr_size_t secretLen,
+ const char *description)
{
const apr_crypto_driver_t *driver1 = drivers[0];
const apr_crypto_driver_t *driver2 = drivers[1];
@@ -324,6 +469,10 @@ static void crypto_block_cross(abts_case *tc, apr_pool_t *pool,
apr_crypto_t *f2 = NULL;
const apr_crypto_key_t *key1 = NULL;
const apr_crypto_key_t *key2 = NULL;
+ const apr_crypto_key_t *key3 = NULL;
+ const apr_crypto_key_t *key4 = NULL;
+ const apr_crypto_key_t *key5 = NULL;
+ const apr_crypto_key_t *key6 = NULL;
unsigned char *cipherText = NULL;
apr_size_t cipherTextLen = 0;
@@ -345,7 +494,51 @@ static void crypto_block_cross(abts_case *tc, apr_pool_t *pool,
if (cipherText && plainText) {
if (memcmp(in, plainText, inlen)) {
- fprintf(stderr, "cross mismatch: %s %s/%s\n", description,
+ fprintf(stderr, "passphrase cross mismatch: %s %s/%s\n", description,
+ apr_crypto_driver_name(driver1), apr_crypto_driver_name(
+ driver2));
+ }
+ ABTS_STR_EQUAL(tc, (char *)in, (char *)plainText);
+ }
+
+ key3 = keysecret(tc, pool, driver1, f1, type, mode, doPad, secretLen, description);
+ key4 = keysecret(tc, pool, driver2, f2, type, mode, doPad, secretLen, description);
+
+ iv = NULL;
+ blockSize = 0;
+ cipherText = NULL;
+ plainText = NULL;
+ cipherText = encrypt_block(tc, pool, driver1, f1, key3, in, inlen,
+ &cipherText, &cipherTextLen, &iv, &blockSize, description);
+ plainText = decrypt_block(tc, pool, driver2, f2, key4, cipherText,
+ cipherTextLen, &plainText, &plainTextLen, iv, &blockSize,
+ description);
+
+ if (cipherText && plainText) {
+ if (memcmp(in, plainText, inlen)) {
+ fprintf(stderr, "key secret cross mismatch: %s %s/%s\n", description,
+ apr_crypto_driver_name(driver1), apr_crypto_driver_name(
+ driver2));
+ }
+ ABTS_STR_EQUAL(tc, (char *)in, (char *)plainText);
+ }
+
+ key5 = keypassphrase(tc, pool, driver1, f1, type, mode, doPad, description);
+ key6 = keypassphrase(tc, pool, driver2, f2, type, mode, doPad, description);
+
+ iv = NULL;
+ blockSize = 0;
+ cipherText = NULL;
+ plainText = NULL;
+ cipherText = encrypt_block(tc, pool, driver1, f1, key5, in, inlen,
+ &cipherText, &cipherTextLen, &iv, &blockSize, description);
+ plainText = decrypt_block(tc, pool, driver2, f2, key6, cipherText,
+ cipherTextLen, &plainText, &plainTextLen, iv, &blockSize,
+ description);
+
+ if (cipherText && plainText) {
+ if (memcmp(in, plainText, inlen)) {
+ fprintf(stderr, "key passphrase cross mismatch: %s %s/%s\n", description,
apr_crypto_driver_name(driver1), apr_crypto_driver_name(
driver2));
}
@@ -372,6 +565,63 @@ static void test_crypto_init(abts_case *tc, void *data)
}
/**
+ * Simple test of OpenSSL key.
+ */
+static void test_crypto_key_openssl(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *driver;
+ apr_crypto_t *f = NULL;
+
+ apr_pool_create(&pool, NULL);
+ driver = get_openssl_driver(tc, pool);
+
+ f = make(tc, pool, driver);
+ keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32,
+ "KEY_AES_256/MODE_CBC");
+ apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of NSS key.
+ */
+static void test_crypto_key_nss(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *driver;
+ apr_crypto_t *f = NULL;
+
+ apr_pool_create(&pool, NULL);
+ driver = get_nss_driver(tc, pool);
+
+ f = make(tc, pool, driver);
+ keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32,
+ "KEY_AES_256/MODE_CBC");
+ apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of CommonCrypto key.
+ */
+static void test_crypto_key_commoncrypto(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *driver;
+ apr_crypto_t *f = NULL;
+
+ apr_pool_create(&pool, NULL);
+ driver = get_commoncrypto_driver(tc, pool);
+
+ f = make(tc, pool, driver);
+ keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32,
+ "KEY_AES_256/MODE_CBC");
+ apr_pool_destroy(pool);
+
+}
+
+/**
* Simple test of OpenSSL block crypt.
*/
static void test_crypto_block_openssl(abts_case *tc, void *data)
@@ -386,21 +636,21 @@ static void test_crypto_block_openssl(abts_case *tc, void *data)
drivers[0] = get_openssl_driver(tc, pool);
drivers[1] = get_openssl_driver(tc, pool);
crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
- in, inlen, "KEY_3DES_192/MODE_CBC");
+ in, inlen, 24, "KEY_3DES_192/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0,
- in, inlen, "KEY_3DES_192/MODE_ECB");
+ in, inlen, 24, "KEY_3DES_192/MODE_ECB");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
- inlen, "KEY_AES_256/MODE_CBC");
+ inlen, 32, "KEY_AES_256/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
- inlen, "KEY_AES_256/MODE_ECB");
+ inlen, 32, "KEY_AES_256/MODE_ECB");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
- inlen, "KEY_AES_192/MODE_CBC");
+ inlen, 24, "KEY_AES_192/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
- inlen, "KEY_AES_192/MODE_ECB");
+ inlen, 24, "KEY_AES_192/MODE_ECB");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
- inlen, "KEY_AES_128/MODE_CBC");
+ inlen, 16, "KEY_AES_128/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
- inlen, "KEY_AES_128/MODE_ECB");
+ inlen, 16, "KEY_AES_128/MODE_ECB");
apr_pool_destroy(pool);
}
@@ -420,21 +670,55 @@ static void test_crypto_block_nss(abts_case *tc, void *data)
drivers[0] = get_nss_driver(tc, pool);
drivers[1] = get_nss_driver(tc, pool);
crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
- in, inlen, "KEY_3DES_192/MODE_CBC");
+ in, inlen, 24, "KEY_3DES_192/MODE_CBC");
/* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
/* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, "KEY_3DES_192/MODE_ECB"); */
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
- inlen, "KEY_AES_256/MODE_CBC");
+ inlen, 32, "KEY_AES_256/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
+ inlen, 32, "KEY_AES_256/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+ inlen, 24, "KEY_AES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+ inlen, 24, "KEY_AES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+ inlen, 16, "KEY_AES_128/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+ inlen, 16, "KEY_AES_128/MODE_ECB");
+ apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of Common Crypto block crypt.
+ */
+static void test_crypto_block_commoncrypto(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+ const unsigned char *in = (const unsigned char *) ALIGNED_STRING;
+ apr_size_t inlen = sizeof(ALIGNED_STRING);
+
+ apr_pool_create(&pool, NULL);
+ drivers[0] = get_commoncrypto_driver(tc, pool);
+ drivers[1] = get_commoncrypto_driver(tc, pool);
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
+ in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0,
+ in, inlen, 24, "KEY_3DES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
+ inlen, 32, "KEY_AES_256/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
- inlen, "KEY_AES_256/MODE_ECB");
+ inlen, 32, "KEY_AES_256/MODE_ECB");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
- inlen, "KEY_AES_192/MODE_CBC");
+ inlen, 24, "KEY_AES_192/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
- inlen, "KEY_AES_192/MODE_ECB");
+ inlen, 24, "KEY_AES_192/MODE_ECB");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
- inlen, "KEY_AES_128/MODE_CBC");
+ inlen, 16, "KEY_AES_128/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
- inlen, "KEY_AES_128/MODE_ECB");
+ inlen, 16, "KEY_AES_128/MODE_ECB");
apr_pool_destroy(pool);
}
@@ -455,25 +739,22 @@ static void test_crypto_block_nss_openssl(abts_case *tc, void *data)
drivers[1] = get_openssl_driver(tc, pool);
crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
- in, inlen, "KEY_3DES_192/MODE_CBC");
+ in, inlen, 24, "KEY_3DES_192/MODE_CBC");
/* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
- /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+ /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
- inlen, "KEY_AES_256/MODE_CBC");
+ inlen, 32, "KEY_AES_256/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
- inlen, "KEY_AES_256/MODE_ECB");
-
- /* all 4 of these tests fail to interoperate - a clue from the xml-security code is that
- * NSS cannot distinguish between the 128 and 192 bit versions of AES. Will need to be
- * investigated.
- */
- /*
- crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_CBC, 0, in, inlen, "KEY_AES_192/MODE_CBC");
- crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_ECB, 0, in, inlen, "KEY_AES_192/MODE_ECB");
- crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_CBC, 0, in, inlen, "KEY_AES_128/MODE_CBC");
- crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_ECB, 0, in, inlen, "KEY_AES_128/MODE_ECB");
- */
+ inlen, 32, "KEY_AES_256/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+ inlen, 24, "KEY_AES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+ inlen, 24, "KEY_AES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+ inlen, 16, "KEY_AES_128/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+ inlen, 16, "KEY_AES_128/MODE_ECB");
apr_pool_destroy(pool);
}
@@ -493,26 +774,95 @@ static void test_crypto_block_openssl_nss(abts_case *tc, void *data)
drivers[0] = get_openssl_driver(tc, pool);
drivers[1] = get_nss_driver(tc, pool);
crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
- in, inlen, "KEY_3DES_192/MODE_CBC");
+ in, inlen, 24, "KEY_3DES_192/MODE_CBC");
/* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
- /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+ /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
- inlen, "KEY_AES_256/MODE_CBC");
+ inlen, 32, "KEY_AES_256/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
- inlen, "KEY_AES_256/MODE_ECB");
+ inlen, 32, "KEY_AES_256/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+ inlen, 24, "KEY_AES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+ inlen, 24, "KEY_AES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+ inlen, 16, "KEY_AES_128/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+ inlen, 16, "KEY_AES_128/MODE_ECB");
+ apr_pool_destroy(pool);
- /* all 4 of these tests fail to interoperate - a clue from the xml-security code is that
- * NSS cannot distinguish between the 128 and 192 bit versions of AES. Will need to be
- * investigated.
- */
- /*
- crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_CBC, 0, in, inlen, "KEY_AES_192/MODE_CBC");
- crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_ECB, 0, in, inlen, "KEY_AES_192/MODE_ECB");
- crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_CBC, 0, in, inlen, "KEY_AES_128/MODE_CBC");
- crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_ECB, 0, in, inlen, "KEY_AES_128/MODE_ECB");
- */
+}
+
+/**
+ * Encrypt OpenSSL, decrypt CommonCrypto.
+ */
+static void test_crypto_block_openssl_commoncrypto(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *drivers[] =
+ { NULL, NULL };
+
+ const unsigned char *in = (const unsigned char *) ALIGNED_STRING;
+ apr_size_t inlen = sizeof(ALIGNED_STRING);
+
+ apr_pool_create(&pool, NULL);
+ drivers[0] = get_openssl_driver(tc, pool);
+ drivers[1] = get_commoncrypto_driver(tc, pool);
+
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0, in,
+ inlen, 24, "KEY_3DES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0, in,
+ inlen, 24, "KEY_3DES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
+ inlen, 32, "KEY_AES_256/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
+ inlen, 32, "KEY_AES_256/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+ inlen, 24, "KEY_AES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+ inlen, 24, "KEY_AES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+ inlen, 16, "KEY_AES_128/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+ inlen, 16, "KEY_AES_128/MODE_ECB");
+ apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt OpenSSL, decrypt CommonCrypto.
+ */
+static void test_crypto_block_commoncrypto_openssl(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *drivers[] =
+ { NULL, NULL };
+
+ const unsigned char *in = (const unsigned char *) ALIGNED_STRING;
+ apr_size_t inlen = sizeof(ALIGNED_STRING);
+
+ apr_pool_create(&pool, NULL);
+ drivers[0] = get_commoncrypto_driver(tc, pool);
+ drivers[1] = get_openssl_driver(tc, pool);
+
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0, in,
+ inlen, 24, "KEY_3DES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0, in,
+ inlen, 24, "KEY_3DES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
+ inlen, 32, "KEY_AES_256/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
+ inlen, 32, "KEY_AES_256/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+ inlen, 24, "KEY_AES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+ inlen, 24, "KEY_AES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+ inlen, 16, "KEY_AES_128/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+ inlen, 16, "KEY_AES_128/MODE_ECB");
apr_pool_destroy(pool);
}
@@ -533,21 +883,21 @@ static void test_crypto_block_openssl_pad(abts_case *tc, void *data)
drivers[1] = get_openssl_driver(tc, pool);
crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
- in, inlen, "KEY_3DES_192/MODE_CBC");
+ in, inlen, 24, "KEY_3DES_192/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1,
- in, inlen, "KEY_3DES_192/MODE_ECB");
+ in, inlen, 24, "KEY_3DES_192/MODE_ECB");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
- inlen, "KEY_AES_256/MODE_CBC");
+ inlen, 32, "KEY_AES_256/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
- inlen, "KEY_AES_256/MODE_ECB");
+ inlen, 32, "KEY_AES_256/MODE_ECB");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
- inlen, "KEY_AES_192/MODE_CBC");
+ inlen, 24, "KEY_AES_192/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
- inlen, "KEY_AES_192/MODE_ECB");
+ inlen, 24, "KEY_AES_192/MODE_ECB");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
- inlen, "KEY_AES_128/MODE_CBC");
+ inlen, 16, "KEY_AES_128/MODE_CBC");
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
- inlen, "KEY_AES_128/MODE_ECB");
+ inlen, 16, "KEY_AES_128/MODE_ECB");
apr_pool_destroy(pool);
@@ -570,27 +920,63 @@ static void test_crypto_block_nss_pad(abts_case *tc, void *data)
drivers[1] = get_nss_driver(tc, pool);
crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
- in, inlen, "KEY_3DES_192/MODE_CBC");
+ in, inlen, 24, "KEY_3DES_192/MODE_CBC");
/* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
- /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+ /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
- inlen, "KEY_AES_256/MODE_CBC");
+ inlen, 32, "KEY_AES_256/MODE_CBC");
/* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
- /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, "KEY_AES_256/MODE_ECB");*/
+ /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, 32, "KEY_AES_256/MODE_ECB");*/
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
- inlen, "KEY_AES_192/MODE_CBC");
+ inlen, 24, "KEY_AES_192/MODE_CBC");
/* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
- /*crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_ECB, 1, in, inlen, "KEY_AES_192/MODE_ECB");*/
+ /*crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_ECB, 1, in, inlen, 24, "KEY_AES_192/MODE_ECB");*/
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
- inlen, "KEY_AES_128/MODE_CBC");
+ inlen, 16, "KEY_AES_128/MODE_CBC");
/* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
- /*crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_ECB, 1, in, inlen, "KEY_AES_128/MODE_ECB");*/
+ /*crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_ECB, 1, in, inlen, 16, "KEY_AES_128/MODE_ECB");*/
+
+ apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of Common Crypto block crypt.
+ */
+static void test_crypto_block_commoncrypto_pad(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+ const unsigned char *in = (const unsigned char *) TEST_STRING;
+ apr_size_t inlen = sizeof(TEST_STRING);
+
+ apr_pool_create(&pool, NULL);
+ drivers[0] = get_commoncrypto_driver(tc, pool);
+ drivers[1] = get_commoncrypto_driver(tc, pool);
+
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
+ in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1,
+ in, inlen, 24, "KEY_3DES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
+ inlen, 32, "KEY_AES_256/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
+ inlen, 32, "KEY_AES_256/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
+ inlen, 24, "KEY_AES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
+ inlen, 24, "KEY_AES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
+ inlen, 16, "KEY_AES_128/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
+ inlen, 16, "KEY_AES_128/MODE_ECB");
apr_pool_destroy(pool);
@@ -612,27 +998,31 @@ static void test_crypto_block_nss_openssl_pad(abts_case *tc, void *data)
drivers[1] = get_openssl_driver(tc, pool);
crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
- in, inlen, "KEY_3DES_192/MODE_CBC");
+ in, inlen, 24, "KEY_3DES_192/MODE_CBC");
/* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
- /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+ /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
- inlen, "KEY_AES_256/MODE_CBC");
+ inlen, 32, "KEY_AES_256/MODE_CBC");
/* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
- /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, "KEY_AES_256/MODE_ECB");*/
+ /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, 32, "KEY_AES_256/MODE_ECB");*/
+
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
+ inlen, 24, "KEY_AES_192/MODE_CBC");
+
+ /* KEY_AES_192 / MODE_ECB doesn't support padding on NSS */
+ /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
+ inlen, 24, "KEY_AES_192/MODE_ECB");*/
+
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
+ inlen, 16, "KEY_AES_128/MODE_CBC");
+
+ /* KEY_AES_192 / MODE_ECB doesn't support padding on NSS */
+ /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
+ inlen, 16, "KEY_AES_128/MODE_ECB");*/
- /* all 4 of these tests fail to interoperate - a clue from the xml-security code is that
- * NSS cannot distinguish between the 128 and 192 bit versions of AES. Will need to be
- * investigated.
- */
- /*
- crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_CBC, 1, in, inlen, "KEY_AES_192/MODE_CBC");
- crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_ECB, 1, in, inlen, "KEY_AES_192/MODE_ECB");
- crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_CBC, 1, in, inlen, "KEY_AES_128/MODE_CBC");
- crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_ECB, 1, in, inlen, "KEY_AES_128/MODE_ECB");
- */
apr_pool_destroy(pool);
}
@@ -652,27 +1042,107 @@ static void test_crypto_block_openssl_nss_pad(abts_case *tc, void *data)
drivers[0] = get_openssl_driver(tc, pool);
drivers[1] = get_nss_driver(tc, pool);
crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
- in, inlen, "KEY_3DES_192/MODE_CBC");
+ in, inlen, 24, "KEY_3DES_192/MODE_CBC");
/* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
- /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+ /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
- inlen, "KEY_AES_256/MODE_CBC");
+ inlen, 32, "KEY_AES_256/MODE_CBC");
/* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
- /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, "KEY_AES_256/MODE_ECB");*/
+ /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, 32, "KEY_AES_256/MODE_ECB");*/
+
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in, inlen,
+ 24, "KEY_AES_192/MODE_CBC");
+
+ /* KEY_AES_192 / MODE_ECB doesn't support padding on NSS */
+ /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in, inlen,
+ 24, "KEY_AES_192/MODE_ECB");*/
+
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in, inlen,
+ 16, "KEY_AES_128/MODE_CBC");
+
+ /* KEY_AES_128 / MODE_ECB doesn't support padding on NSS */
+ /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in, inlen,
+ 16, "KEY_AES_128/MODE_ECB");*/
+
+ apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt CommonCrypto, decrypt OpenSSL.
+ */
+static void test_crypto_block_commoncrypto_openssl_pad(abts_case *tc,
+ void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *drivers[] =
+ { NULL, NULL };
+
+ const unsigned char *in = (const unsigned char *) TEST_STRING;
+ apr_size_t inlen = sizeof(TEST_STRING);
+
+ apr_pool_create(&pool, NULL);
+ drivers[0] = get_commoncrypto_driver(tc, pool);
+ drivers[1] = get_openssl_driver(tc, pool);
+
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1, in,
+ inlen, 24, "KEY_3DES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1, in,
+ inlen, 24, "KEY_3DES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
+ inlen, 32, "KEY_AES_256/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
+ inlen, 32, "KEY_AES_256/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
+ inlen, 24, "KEY_AES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
+ inlen, 24, "KEY_AES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
+ inlen, 16, "KEY_AES_128/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
+ inlen, 16, "KEY_AES_128/MODE_ECB");
+
+ apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt OpenSSL, decrypt CommonCrypto.
+ */
+static void test_crypto_block_openssl_commoncrypto_pad(abts_case *tc,
+ void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *drivers[] =
+ { NULL, NULL };
+
+ const unsigned char *in = (const unsigned char *) TEST_STRING;
+ apr_size_t inlen = sizeof(TEST_STRING);
+
+ apr_pool_create(&pool, NULL);
+ drivers[0] = get_openssl_driver(tc, pool);
+ drivers[1] = get_commoncrypto_driver(tc, pool);
+
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1, in,
+ inlen, 24, "KEY_3DES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1, in,
+ inlen, 24, "KEY_3DES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
+ inlen, 32, "KEY_AES_256/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
+ inlen, 32, "KEY_AES_256/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
+ inlen, 24, "KEY_AES_192/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
+ inlen, 24, "KEY_AES_192/MODE_ECB");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
+ inlen, 16, "KEY_AES_128/MODE_CBC");
+ crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
+ inlen, 16, "KEY_AES_128/MODE_ECB");
- /* all 4 of these tests fail to interoperate - a clue from the xml-security code is that
- * NSS cannot distinguish between the 128 and 192 bit versions of AES. Will need to be
- * investigated.
- */
- /*
- crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_CBC, 1, in, inlen, "KEY_AES_192/MODE_CBC");
- crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_ECB, 1, in, inlen, "KEY_AES_192/MODE_ECB");
- crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_CBC, 1, in, inlen, "KEY_AES_128/MODE_CBC");
- crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_ECB, 1, in, inlen, "KEY_AES_128/MODE_ECB");
- */
apr_pool_destroy(pool);
}
@@ -764,6 +1234,49 @@ static void test_crypto_get_block_key_types_nss(abts_case *tc, void *data)
}
/**
+ * Get Types, Common Crypto.
+ */
+static void test_crypto_get_block_key_types_commoncrypto(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *driver;
+ apr_crypto_t *f;
+ apr_hash_t *types;
+ int *key_3des_192;
+ int *key_aes_128;
+ int *key_aes_192;
+ int *key_aes_256;
+
+ apr_pool_create(&pool, NULL);
+ driver = get_commoncrypto_driver(tc, pool);
+ if (driver) {
+
+ f = make(tc, pool, driver);
+ apr_crypto_get_block_key_types(&types, f);
+
+ key_3des_192 = apr_hash_get(types, "3des192", APR_HASH_KEY_STRING);
+ ABTS_PTR_NOTNULL(tc, key_3des_192);
+ ABTS_INT_EQUAL(tc, *key_3des_192, APR_KEY_3DES_192);
+
+ key_aes_128 = apr_hash_get(types, "aes128", APR_HASH_KEY_STRING);
+ ABTS_PTR_NOTNULL(tc, key_aes_128);
+ ABTS_INT_EQUAL(tc, *key_aes_128, APR_KEY_AES_128);
+
+ key_aes_192 = apr_hash_get(types, "aes192", APR_HASH_KEY_STRING);
+ ABTS_PTR_NOTNULL(tc, key_aes_192);
+ ABTS_INT_EQUAL(tc, *key_aes_192, APR_KEY_AES_192);
+
+ key_aes_256 = apr_hash_get(types, "aes256", APR_HASH_KEY_STRING);
+ ABTS_PTR_NOTNULL(tc, key_aes_256);
+ ABTS_INT_EQUAL(tc, *key_aes_256, APR_KEY_AES_256);
+
+ }
+
+ apr_pool_destroy(pool);
+
+}
+
+/**
* Get Modes, OpenSSL.
*/
static void test_crypto_get_block_key_modes_openssl(abts_case *tc, void *data)
@@ -829,6 +1342,114 @@ static void test_crypto_get_block_key_modes_nss(abts_case *tc, void *data)
}
+/**
+ * Get Modes, Common Crypto.
+ */
+static void test_crypto_get_block_key_modes_commoncrypto(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = NULL;
+ const apr_crypto_driver_t *driver;
+ apr_crypto_t *f;
+ apr_hash_t *modes;
+ int *mode_ecb;
+ int *mode_cbc;
+
+ apr_pool_create(&pool, NULL);
+ driver = get_commoncrypto_driver(tc, pool);
+ if (driver) {
+
+ f = make(tc, pool, driver);
+ apr_crypto_get_block_key_modes(&modes, f);
+
+ mode_ecb = apr_hash_get(modes, "ecb", APR_HASH_KEY_STRING);
+ ABTS_PTR_NOTNULL(tc, mode_ecb);
+ ABTS_INT_EQUAL(tc, *mode_ecb, APR_MODE_ECB);
+
+ mode_cbc = apr_hash_get(modes, "cbc", APR_HASH_KEY_STRING);
+ ABTS_PTR_NOTNULL(tc, mode_cbc);
+ ABTS_INT_EQUAL(tc, *mode_cbc, APR_MODE_CBC);
+
+ }
+
+ apr_pool_destroy(pool);
+
+}
+
+static void test_crypto_memzero(abts_case *tc, void *data)
+{
+ /* Aligned message */
+ struct {
+ char buf[7 * sizeof(int)];
+ int untouched;
+ } msg;
+ /* A bit of type punning such that 'msg' might look unused
+ * after the call to apr_crypto_memzero().
+ */
+ int *ptr = (int *)&msg;
+ int i;
+
+ /* Fill buf with non-zeros (odds) */
+ for (i = 1; i < 2 * sizeof(msg.buf); i += 2) {
+ msg.buf[i / 2] = (char)i;
+ ABTS_ASSERT(tc, "test_crypto_memzero() barrier", msg.buf[i / 2] != 0);
+ }
+
+ /* Zero out the whole, and check it */
+ apr_crypto_memzero(&msg, sizeof msg);
+ for (i = 0; i < sizeof(msg) / sizeof(*ptr); ++i) {
+ ABTS_ASSERT(tc, "test_crypto_memzero() optimized out", ptr[i] == 0);
+ }
+}
+
+static void test_crypto_equals(abts_case *tc, void *data)
+{
+ /* Buffers of each type of scalar */
+ union {
+ char c;
+ short s;
+ int i;
+ long l;
+ float f;
+ double d;
+ void *p;
+ } buf0[7], buf1[7], buf[7];
+ char *ptr = (char *)buf;
+ int i;
+
+#define TEST_SCALAR_MATCH(i, x, r) \
+ ABTS_ASSERT(tc, "test_crypto_equals(" APR_STRINGIFY(x) ")" \
+ " != " APR_STRINGIFY(r), \
+ apr_crypto_equals(&buf##r[i].x, &buf[i].x, \
+ sizeof(buf[i].x)) == r)
+
+ /* Fill buf with non-zeros (odds) */
+ for (i = 1; i < 2 * sizeof(buf); i += 2) {
+ ptr[i / 2] = (char)i;
+ }
+ /* Set buf1 = buf */
+ memcpy(buf1, buf, sizeof buf);
+ /* Set buf0 = {0} */
+ memset(buf0, 0, sizeof buf0);
+
+ /* Check that buf1 == buf for each scalar */
+ TEST_SCALAR_MATCH(0, c, 1);
+ TEST_SCALAR_MATCH(1, s, 1);
+ TEST_SCALAR_MATCH(2, i, 1);
+ TEST_SCALAR_MATCH(3, l, 1);
+ TEST_SCALAR_MATCH(4, f, 1);
+ TEST_SCALAR_MATCH(5, d, 1);
+ TEST_SCALAR_MATCH(6, p, 1);
+
+ /* Check that buf0 != buf for each scalar */
+ TEST_SCALAR_MATCH(0, c, 0);
+ TEST_SCALAR_MATCH(1, s, 0);
+ TEST_SCALAR_MATCH(2, i, 0);
+ TEST_SCALAR_MATCH(3, l, 0);
+ TEST_SCALAR_MATCH(4, f, 0);
+ TEST_SCALAR_MATCH(5, d, 0);
+ TEST_SCALAR_MATCH(6, p, 0);
+}
+
abts_suite *testcrypto(abts_suite *suite)
{
suite = ADD_SUITE(suite);
@@ -836,6 +1457,15 @@ abts_suite *testcrypto(abts_suite *suite)
/* test simple init and shutdown */
abts_run_test(suite, test_crypto_init, NULL);
+ /* test key parsing - openssl */
+ abts_run_test(suite, test_crypto_key_openssl, NULL);
+
+ /* test key parsing - nss */
+ abts_run_test(suite, test_crypto_key_nss, NULL);
+
+ /* test key parsing - commoncrypto */
+ abts_run_test(suite, test_crypto_key_commoncrypto, NULL);
+
/* test a simple encrypt / decrypt operation - openssl */
abts_run_test(suite, test_crypto_block_openssl, NULL);
@@ -848,6 +1478,12 @@ abts_suite *testcrypto(abts_suite *suite)
/* test a padded encrypt / decrypt operation - nss */
abts_run_test(suite, test_crypto_block_nss_pad, NULL);
+ /* test a simple encrypt / decrypt operation - commoncrypto */
+ abts_run_test(suite, test_crypto_block_commoncrypto, NULL);
+
+ /* test a padded encrypt / decrypt operation - commoncrypto */
+ abts_run_test(suite, test_crypto_block_commoncrypto_pad, NULL);
+
/* test encrypt nss / decrypt openssl */
abts_run_test(suite, test_crypto_block_nss_openssl, NULL);
@@ -860,18 +1496,39 @@ abts_suite *testcrypto(abts_suite *suite)
/* test padded encrypt openssl / decrypt nss */
abts_run_test(suite, test_crypto_block_openssl_nss_pad, NULL);
+ /* test encrypt openssl / decrypt commoncrypto */
+ abts_run_test(suite, test_crypto_block_openssl_commoncrypto, NULL);
+
+ /* test padded encrypt openssl / decrypt commoncrypto */
+ abts_run_test(suite, test_crypto_block_openssl_commoncrypto_pad, NULL);
+
+ /* test encrypt commoncrypto / decrypt openssl */
+ abts_run_test(suite, test_crypto_block_commoncrypto_openssl, NULL);
+
+ /* test padded encrypt commoncrypto / decrypt openssl */
+ abts_run_test(suite, test_crypto_block_commoncrypto_openssl_pad, NULL);
+
/* test block key types openssl */
abts_run_test(suite, test_crypto_get_block_key_types_openssl, NULL);
/* test block key types nss */
abts_run_test(suite, test_crypto_get_block_key_types_nss, NULL);
+ /* test block key types commoncrypto */
+ abts_run_test(suite, test_crypto_get_block_key_types_commoncrypto, NULL);
+
/* test block key modes openssl */
abts_run_test(suite, test_crypto_get_block_key_modes_openssl, NULL);
/* test block key modes nss */
abts_run_test(suite, test_crypto_get_block_key_modes_nss, NULL);
+ /* test block key modes commoncrypto */
+ abts_run_test(suite, test_crypto_get_block_key_modes_commoncrypto, NULL);
+
+ abts_run_test(suite, test_crypto_memzero, NULL);
+ abts_run_test(suite, test_crypto_equals, NULL);
+
return suite;
}
diff --git a/test/testredis.c b/test/testredis.c
new file mode 100644
index 000000000000..4b654322f54e
--- /dev/null
+++ b/test/testredis.c
@@ -0,0 +1,552 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "testutil.h"
+#include "apr.h"
+#include "apu.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+#include "apr_redis.h"
+#include "apr_network_io.h"
+
+#include <stdio.h>
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for exit() */
+#endif
+
+#define HOST "localhost"
+#define PORT 6379
+
+/* the total number of items to use for set/get testing */
+#define TDATA_SIZE 3000
+
+/* some smaller subset of TDATA_SIZE used for multiget testing */
+#define TDATA_SET 100
+
+/* our custom hash function just returns this all the time */
+#define HASH_FUNC_RESULT 510
+
+/* all keys will be prefixed with this */
+static const char prefix[] = "testredis";
+
+/* text for values we store */
+static const char txt[] =
+"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis at"
+"lacus in ligula hendrerit consectetuer. Vestibulum tristique odio"
+"iaculis leo. In massa arcu, ultricies a, laoreet nec, hendrerit non,"
+"neque. Nulla sagittis sapien ac risus. Morbi ligula dolor, vestibulum"
+"nec, viverra id, placerat dapibus, arcu. Curabitur egestas feugiat"
+"tellus. Donec dignissim. Nunc ante. Curabitur id lorem. In mollis"
+"tortor sit amet eros auctor dapibus. Proin nulla sem, tristique in,"
+"convallis id, iaculis feugiat cras amet.";
+
+/*
+ * this datatype is for our custom server determination function. this might
+ * be useful if you don't want to rely on simply hashing keys to determine
+ * where a key belongs, but instead want to write something fancy, or use some
+ * other kind of configuration data, i.e. a hash plus some data about a
+ * namespace, or whatever. see my_server_func, and test_redis_user_funcs
+ * for the examples.
+ */
+typedef struct {
+ const char *someval;
+ apr_uint32_t which_server;
+} my_hash_server_baton;
+
+
+/* this could do something fancy and return some hash result.
+ * for simplicity, just return the same value, so we can test it later on.
+ * if you wanted to use some external hashing library or functions for
+ * consistent hashing, for example, this would be a good place to do it.
+ */
+static apr_uint32_t my_hash_func(void *baton, const char *data,
+ apr_size_t data_len)
+{
+
+ return HASH_FUNC_RESULT;
+}
+
+/*
+ * a fancy function to determine which server to use given some kind of data
+ * and a hash value. this example actually ignores the hash value itself
+ * and pulls some number from the *baton, which is a struct that has some
+ * kind of meaningful stuff in it.
+ */
+static apr_redis_server_t *my_server_func(void *baton,
+ apr_redis_t *mc,
+ const apr_uint32_t hash)
+{
+ apr_redis_server_t *ms = NULL;
+ my_hash_server_baton *mhsb = (my_hash_server_baton *)baton;
+
+ if(mc->ntotal == 0) {
+ return NULL;
+ }
+
+ if(mc->ntotal < mhsb->which_server) {
+ return NULL;
+ }
+
+ ms = mc->live_servers[mhsb->which_server - 1];
+
+ return ms;
+}
+
+static apr_uint16_t firsttime = 0;
+static int randval(apr_uint32_t high)
+{
+ apr_uint32_t i = 0;
+ double d = 0;
+
+ if (firsttime == 0) {
+ srand((unsigned) (getpid()));
+ firsttime = 1;
+ }
+
+ d = (double) rand() / ((double) RAND_MAX + 1);
+ i = (int) (d * (high - 0 + 1));
+
+ return i > 0 ? i : 1;
+}
+
+/*
+ * general test to make sure we can create the redis struct and add
+ * some servers, but not more than we tell it we can add
+ */
+
+static void test_redis_create(abts_case * tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_redis_t *redis;
+ apr_redis_server_t *server, *s;
+ apr_uint32_t max_servers = 10;
+ apr_uint32_t i;
+ apr_uint32_t hash;
+
+ rv = apr_redis_create(pool, max_servers, 0, &redis);
+ ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+ for (i = 1; i <= max_servers; i++) {
+ apr_port_t port;
+
+ port = PORT + i;
+ rv =
+ apr_redis_server_create(pool, HOST, PORT + i, 0, 1, 1, 60, 60, &server);
+ ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_add_server(redis, server);
+ ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+ s = apr_redis_find_server(redis, HOST, port);
+ ABTS_PTR_EQUAL(tc, server, s);
+
+ rv = apr_redis_disable_server(redis, s);
+ ABTS_ASSERT(tc, "server disable failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_enable_server(redis, s);
+ ABTS_ASSERT(tc, "server enable failed", rv == APR_SUCCESS);
+
+ hash = apr_redis_hash(redis, prefix, strlen(prefix));
+ ABTS_ASSERT(tc, "hash failed", hash > 0);
+
+ s = apr_redis_find_server_hash(redis, hash);
+ ABTS_PTR_NOTNULL(tc, s);
+ }
+
+ rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 60, &server);
+ ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_add_server(redis, server);
+ ABTS_ASSERT(tc, "server add should have failed", rv != APR_SUCCESS);
+
+}
+
+/* install our own custom hashing and server selection routines. */
+
+static int create_test_hash(apr_pool_t *p, apr_hash_t *h)
+{
+ int i;
+
+ for (i = 0; i < TDATA_SIZE; i++) {
+ char *k, *v;
+
+ k = apr_pstrcat(p, prefix, apr_itoa(p, i), NULL);
+ v = apr_pstrndup(p, txt, randval((apr_uint32_t)strlen(txt)));
+
+ apr_hash_set(h, k, APR_HASH_KEY_STRING, v);
+ }
+
+ return i;
+}
+
+static void test_redis_user_funcs(abts_case * tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_redis_t *redis;
+ apr_redis_server_t *found;
+ apr_uint32_t max_servers = 10;
+ apr_uint32_t hres;
+ apr_uint32_t i;
+ my_hash_server_baton *baton =
+ apr_pcalloc(pool, sizeof(my_hash_server_baton));
+
+ rv = apr_redis_create(pool, max_servers, 0, &redis);
+ ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+ /* as noted above, install our custom hash function, and call
+ * apr_redis_hash. the return value should be our predefined number,
+ * and our function just ignores the other args, for simplicity.
+ */
+ redis->hash_func = my_hash_func;
+
+ hres = apr_redis_hash(redis, "whatever", sizeof("whatever") - 1);
+ ABTS_INT_EQUAL(tc, HASH_FUNC_RESULT, hres);
+
+ /* add some servers */
+ for(i = 1; i <= 10; i++) {
+ apr_redis_server_t *ms;
+
+ rv = apr_redis_server_create(pool, HOST, i, 0, 1, 1, 60, 60, &ms);
+ ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_add_server(redis, ms);
+ ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+ }
+
+ /*
+ * set 'which_server' in our server_baton to find the third server
+ * which should have the same port.
+ */
+ baton->which_server = 3;
+ redis->server_func = my_server_func;
+ redis->server_baton = baton;
+ found = apr_redis_find_server_hash(redis, 0);
+ ABTS_ASSERT(tc, "wrong server found", found->port == baton->which_server);
+}
+
+/* test non data related commands like stats and version */
+static void test_redis_meta(abts_case * tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_redis_t *redis;
+ apr_redis_server_t *server;
+ apr_redis_stats_t *stats;
+ char *result;
+ apr_status_t rv;
+
+ rv = apr_redis_create(pool, 1, 0, &redis);
+ ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 60, &server);
+ ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_add_server(redis, server);
+ ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_version(server, pool, &result);
+ ABTS_PTR_NOTNULL(tc, result);
+
+ rv = apr_redis_stats(server, p, &stats);
+ ABTS_PTR_NOTNULL(tc, stats);
+
+ /*
+ * no way to know exactly what will be in most of these, so
+ * just make sure there is something.
+ */
+ ABTS_ASSERT(tc, "major", stats->major >= 1);
+ ABTS_ASSERT(tc, "minor", stats->minor >= 0);
+ ABTS_ASSERT(tc, "patch", stats->patch >= 0);
+ ABTS_ASSERT(tc, "process_id", stats->process_id >= 0);
+ ABTS_ASSERT(tc, "uptime_in_seconds", stats->uptime_in_seconds >= 0);
+ ABTS_ASSERT(tc, "arch_bits", stats->arch_bits >= 0);
+ ABTS_ASSERT(tc, "connected_clients", stats->connected_clients >= 0);
+ ABTS_ASSERT(tc, "blocked_clients", stats->blocked_clients >= 0);
+ ABTS_ASSERT(tc, "maxmemory", stats->maxmemory >= 0);
+ ABTS_ASSERT(tc, "used_memory", stats->used_memory >= 0);
+ ABTS_ASSERT(tc, "total_system_memory", stats->total_system_memory >= 0);
+ ABTS_ASSERT(tc, "total_connections_received", stats->total_connections_received >= 0);
+ ABTS_ASSERT(tc, "total_commands_processed", stats->total_commands_processed >= 0);
+ ABTS_ASSERT(tc, "total_net_input_bytes", stats->total_net_input_bytes >= 0);
+ ABTS_ASSERT(tc, "total_net_output_bytes", stats->total_net_output_bytes >= 0);
+ ABTS_ASSERT(tc, "keyspace_hits", stats->keyspace_hits >= 0);
+ ABTS_ASSERT(tc, "keyspace_misses", stats->keyspace_misses >= 0);
+ ABTS_ASSERT(tc, "role", stats->role >= 0);
+ ABTS_ASSERT(tc, "connected_slaves", stats->connected_slaves >= 0);
+ ABTS_ASSERT(tc, "used_cpu_sys", stats->used_cpu_sys >= 0);
+ ABTS_ASSERT(tc, "used_cpu_user", stats->used_cpu_user >= 0);
+ ABTS_ASSERT(tc, "cluster_enabled", stats->cluster_enabled >= 0);
+}
+
+
+/* basic tests of the increment and decrement commands */
+static void test_redis_incrdecr(abts_case * tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_redis_t *redis;
+ apr_redis_server_t *server;
+ apr_uint32_t new;
+ char *result;
+ apr_size_t len;
+ apr_uint32_t i;
+
+ rv = apr_redis_create(pool, 1, 0, &redis);
+ ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 60, &server);
+ ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_add_server(redis, server);
+ ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_set(redis, prefix, "271", sizeof("271") - 1, 27);
+ ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+
+ for( i = 1; i <= TDATA_SIZE; i++) {
+ apr_uint32_t expect;
+
+ rv = apr_redis_getp(redis, pool, prefix, &result, &len, NULL);
+ ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+
+ expect = i + atoi(result);
+
+ rv = apr_redis_incr(redis, prefix, i, &new);
+ ABTS_ASSERT(tc, "incr failed", rv == APR_SUCCESS);
+
+ ABTS_INT_EQUAL(tc, expect, new);
+
+ rv = apr_redis_decr(redis, prefix, i, &new);
+ ABTS_ASSERT(tc, "decr failed", rv == APR_SUCCESS);
+
+ ABTS_INT_EQUAL(tc, atoi(result), new);
+
+ }
+
+ rv = apr_redis_getp(redis, pool, prefix, &result, &len, NULL);
+ ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+
+ ABTS_INT_EQUAL(tc, 271, atoi(result));
+
+ rv = apr_redis_delete(redis, prefix, 0);
+ ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+}
+
+
+/* test setting and getting */
+
+static void test_redis_setget(abts_case * tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_redis_t *redis;
+ apr_redis_server_t *server;
+ apr_hash_t *tdata;
+ apr_hash_index_t *hi;
+ char *result;
+ apr_size_t len;
+
+ rv = apr_redis_create(pool, 1, 0, &redis);
+ ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 60, &server);
+ ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_add_server(redis, server);
+ ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+ tdata = apr_hash_make(pool);
+
+ create_test_hash(pool, tdata);
+
+ for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+ const void *k;
+ void *v;
+ const char *key;
+
+ apr_hash_this(hi, &k, NULL, &v);
+ key = k;
+
+ rv = apr_redis_set(redis, key, v, strlen(v), 27);
+ ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+ rv = apr_redis_getp(redis, pool, key, &result, &len, NULL);
+ ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+ }
+
+ rv = apr_redis_getp(redis, pool, "nothere3423", &result, &len, NULL);
+
+ ABTS_ASSERT(tc, "get should have failed", rv != APR_SUCCESS);
+
+ for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+ const void *k;
+ const char *key;
+
+ apr_hash_this(hi, &k, NULL, NULL);
+ key = k;
+
+ rv = apr_redis_delete(redis, key, 0);
+ ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+ }
+}
+
+/* test setting and getting */
+
+static void test_redis_setexget(abts_case * tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_redis_t *redis;
+ apr_redis_server_t *server;
+ apr_hash_t *tdata;
+ apr_hash_index_t *hi;
+ char *result;
+ apr_size_t len;
+
+ rv = apr_redis_create(pool, 1, 0, &redis);
+ ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 60, &server);
+ ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+ rv = apr_redis_add_server(redis, server);
+ ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+ tdata = apr_hash_make(pool);
+
+ create_test_hash(pool, tdata);
+
+ for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+ const void *k;
+ void *v;
+ const char *key;
+
+ apr_hash_this(hi, &k, NULL, &v);
+ key = k;
+
+ rv = apr_redis_ping(server);
+ ABTS_ASSERT(tc, "ping failed", rv == APR_SUCCESS);
+ rv = apr_redis_setex(redis, key, v, strlen(v), 10, 27);
+ ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+ rv = apr_redis_getp(redis, pool, key, &result, &len, NULL);
+ ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+ }
+
+ rv = apr_redis_getp(redis, pool, "nothere3423", &result, &len, NULL);
+
+ ABTS_ASSERT(tc, "get should have failed", rv != APR_SUCCESS);
+
+ for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+ const void *k;
+ const char *key;
+
+ apr_hash_this(hi, &k, NULL, NULL);
+ key = k;
+
+ rv = apr_redis_delete(redis, key, 0);
+ ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+ }
+}
+
+/* use apr_socket stuff to see if there is in fact a Redis server
+ * running on PORT.
+ */
+static apr_status_t check_redis(void)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_socket_t *sock = NULL;
+ apr_sockaddr_t *sa;
+ struct iovec vec[2];
+ apr_size_t written;
+ char buf[128];
+ apr_size_t len;
+
+ rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, 0, pool);
+ if(rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_sockaddr_info_get(&sa, HOST, APR_INET, PORT, 0, pool);
+ if(rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_socket_timeout_set(sock, 1 * APR_USEC_PER_SEC);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_socket_connect(sock, sa);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_socket_timeout_set(sock, -1);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ vec[0].iov_base = "PING";
+ vec[0].iov_len = sizeof("PING") - 1;
+
+ vec[1].iov_base = "\r\n";
+ vec[1].iov_len = sizeof("\r\n") -1;
+
+ rv = apr_socket_sendv(sock, vec, 2, &written);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ len = sizeof(buf);
+ rv = apr_socket_recv(sock, buf, &len);
+ if(rv != APR_SUCCESS) {
+ return rv;
+ }
+ if(strncmp(buf, "+PONG", sizeof("+PONG")-1) != 0) {
+ rv = APR_EGENERAL;
+ }
+
+ apr_socket_close(sock);
+ return rv;
+}
+
+abts_suite *testredis(abts_suite * suite)
+{
+ apr_status_t rv;
+ suite = ADD_SUITE(suite);
+ /* check for a running redis on the typical port before
+ * trying to run the tests. succeed if we don't find one.
+ */
+ rv = check_redis();
+ if (rv == APR_SUCCESS) {
+ abts_run_test(suite, test_redis_create, NULL);
+ abts_run_test(suite, test_redis_user_funcs, NULL);
+ abts_run_test(suite, test_redis_meta, NULL);
+ abts_run_test(suite, test_redis_setget, NULL);
+ abts_run_test(suite, test_redis_setexget, NULL);
+ /* abts_run_test(suite, test_redis_multiget, NULL); */
+ abts_run_test(suite, test_redis_incrdecr, NULL);
+ }
+ else {
+ abts_log_message("Error %d occurred attempting to reach Redis "
+ "on %s:%d. Skipping apr_redis tests...",
+ rv, HOST, PORT);
+ }
+
+ return suite;
+}
diff --git a/test/testsiphash.c b/test/testsiphash.c
new file mode 100644
index 000000000000..58321adebd85
--- /dev/null
+++ b/test/testsiphash.c
@@ -0,0 +1,148 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_siphash.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+/*
+ * Wrapped test vectors from the authors, see
+ * https://131002.net/siphash/siphash24.c
+ */
+typedef unsigned char u8;
+#define crypto_auth apr_siphash24_auth
+
+#define MAXLEN 64
+
+/*
+ SipHash-2-4 output with
+ k = 00 01 02 ...
+ and
+ in = (empty string)
+ in = 00 (1 byte)
+ in = 00 01 (2 bytes)
+ in = 00 01 02 (3 bytes)
+ ...
+ in = 00 01 02 ... 3e (63 bytes)
+*/
+static const u8 vectors[MAXLEN][8] =
+{
+ { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
+ { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
+ { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
+ { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
+ { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
+ { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
+ { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
+ { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
+ { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
+ { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
+ { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
+ { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
+ { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
+ { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
+ { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
+ { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
+ { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
+ { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
+ { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
+ { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
+ { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
+ { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
+ { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
+ { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
+ { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
+ { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
+ { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
+ { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
+ { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
+ { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
+ { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
+ { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
+ { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
+ { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
+ { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
+ { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
+ { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
+ { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
+ { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
+ { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
+ { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
+ { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
+ { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
+ { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
+ { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
+ { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
+ { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
+ { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
+ { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
+ { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
+ { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
+ { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
+ { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
+ { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
+ { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
+ { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
+ { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
+ { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
+ { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
+ { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
+ { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
+ { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
+ { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
+ { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
+};
+
+static int test_vectors(void)
+{
+ u8 in[MAXLEN], out[8], k[16];
+ int i;
+ int ok = 1;
+
+ for( i = 0; i < 16; ++i ) k[i] = i;
+
+ for( i = 0; i < MAXLEN; ++i )
+ {
+ in[i] = i;
+ crypto_auth( out, in, i, k );
+
+ if ( memcmp( out, vectors[i], 8 ) )
+ {
+ printf( "test vector failed for %d bytes\n", i );
+ ok = 0;
+ }
+ }
+
+ return ok;
+}
+
+static void test_siphash_vectors(abts_case *tc, void *data)
+{
+ ABTS_ASSERT(tc, "SipHash-2-4 test vectors", test_vectors());
+}
+
+abts_suite *testsiphash(abts_suite *suite)
+{
+ suite = ADD_SUITE(suite);
+
+ abts_run_test(suite, test_siphash_vectors, NULL);
+
+ return suite;
+}
diff --git a/test/testutil.h b/test/testutil.h
index c471af40a4a6..eaa7e7590572 100644
--- a/test/testutil.h
+++ b/test/testutil.h
@@ -61,11 +61,13 @@ abts_suite *testldap(abts_suite *suite);
abts_suite *testdbd(abts_suite *suite);
abts_suite *testdate(abts_suite *suite);
abts_suite *testmemcache(abts_suite *suite);
+abts_suite *testredis(abts_suite *suite);
abts_suite *testreslist(abts_suite *suite);
abts_suite *testqueue(abts_suite *suite);
abts_suite *testxml(abts_suite *suite);
abts_suite *testxlate(abts_suite *suite);
abts_suite *testrmm(abts_suite *suite);
abts_suite *testdbm(abts_suite *suite);
+abts_suite *testsiphash(abts_suite *suite);
#endif /* APR_TEST_INCLUDES */
diff --git a/xml/apr_xml.c b/xml/apr_xml.c
index b3ec875781e2..ec3bea749761 100644
--- a/xml/apr_xml.c
+++ b/xml/apr_xml.c
@@ -86,7 +86,7 @@ static int find_prefix(apr_xml_parser *parser, const char *prefix)
** prefix.
*/
for (; elem; elem = elem->parent) {
- apr_xml_ns_scope *ns_scope = elem->ns_scope;
+ apr_xml_ns_scope *ns_scope;
for (ns_scope = elem->ns_scope; ns_scope; ns_scope = ns_scope->next) {
if (strcmp(prefix, ns_scope->prefix) == 0) {
@@ -120,6 +120,26 @@ static int find_prefix(apr_xml_parser *parser, const char *prefix)
return APR_XML_NS_ERROR_UNKNOWN_PREFIX;
}
+/* return original prefix given ns index */
+static const char * find_prefix_name(const apr_xml_elem *elem, int ns, int parent)
+{
+ /*
+ ** Walk up the tree, looking for a namespace scope that defines this
+ ** prefix.
+ */
+ for (; elem; elem = parent ? elem->parent : NULL) {
+ apr_xml_ns_scope *ns_scope = elem->ns_scope;
+
+ for (; ns_scope; ns_scope = ns_scope->next) {
+ if (ns_scope->ns == ns)
+ return ns_scope->prefix;
+ }
+ }
+ /* not found */
+ return "";
+}
+
+
static void start_handler(void *userdata, const char *name, const char **attrs)
{
apr_xml_parser *parser = userdata;
@@ -646,7 +666,8 @@ static apr_size_t elem_size(const apr_xml_elem *elem, int style,
{
apr_size_t size;
- if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) {
+ if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG ||
+ style == APR_XML_X2T_PARSED) {
const apr_xml_attr *attr;
size = 0;
@@ -670,11 +691,29 @@ static apr_size_t elem_size(const apr_xml_elem *elem, int style,
size += 11 + strlen(elem->lang) + 1;
}
}
+ else if (style == APR_XML_X2T_PARSED) {
+ apr_xml_ns_scope *ns_scope = elem->ns_scope;
+
+ /* compute size of: ' xmlns:%s="%s"' */
+ for (; ns_scope; ns_scope = ns_scope->next) {
+ size += 10 + strlen(find_prefix_name(elem, ns_scope->ns, 0)) +
+ strlen(APR_XML_GET_URI_ITEM(namespaces, ns_scope->ns));
+ }
+
+ if (elem->lang != NULL) {
+ /* compute size of: ' xml:lang="%s"' */
+ size += 11 + strlen(elem->lang) + 1;
+ }
+ }
if (elem->ns == APR_XML_NS_NONE) {
/* compute size of: <%s> */
size += 1 + strlen(elem->name) + 1;
}
+ else if (style == APR_XML_X2T_PARSED) {
+ /* compute size of: <%s:%s> */
+ size += 3 + strlen(find_prefix_name(elem, elem->ns, 1)) + strlen(elem->name);
+ }
else {
int ns = ns_map ? ns_map[elem->ns] : elem->ns;
@@ -700,6 +739,10 @@ static apr_size_t elem_size(const apr_xml_elem *elem, int style,
/* compute size of: ' %s="%s"' */
size += 1 + strlen(attr->name) + 2 + strlen(attr->value) + 1;
}
+ else if (style == APR_XML_X2T_PARSED) {
+ /* compute size of: ' %s:%s="%s"' */
+ size += 5 + strlen(find_prefix_name(elem, attr->ns, 1)) + strlen(attr->name) + strlen(attr->value);
+ }
else {
/* compute size of: ' ns%d:%s="%s"' */
int ns = ns_map ? ns_map[attr->ns] : attr->ns;
@@ -733,7 +776,7 @@ static apr_size_t elem_size(const apr_xml_elem *elem, int style,
for (elem = elem->first_child; elem; elem = elem->next) {
/* the size of the child element plus the CDATA that follows it */
- size += (elem_size(elem, APR_XML_X2T_FULL, NULL, ns_map) +
+ size += (elem_size(elem, style == APR_XML_X2T_PARSED ? APR_XML_X2T_PARSED : APR_XML_X2T_FULL, NULL, ns_map) +
text_size(elem->following_cdata.first));
}
@@ -757,13 +800,15 @@ static char *write_elem(char *s, const apr_xml_elem *elem, int style,
apr_size_t len;
int ns;
- if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) {
+ if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG ||
+ style == APR_XML_X2T_PARSED) {
int empty = APR_XML_ELEM_IS_EMPTY(elem);
const apr_xml_attr *attr;
- if (elem->ns == APR_XML_NS_NONE) {
+ if (elem->ns == APR_XML_NS_NONE)
len = sprintf(s, "<%s", elem->name);
- }
+ else if (style == APR_XML_X2T_PARSED)
+ len = sprintf(s, "<%s:%s", find_prefix_name(elem, elem->ns, 1), elem->name);
else {
ns = ns_map ? ns_map[elem->ns] : elem->ns;
len = sprintf(s, "<ns%d:%s", ns, elem->name);
@@ -773,10 +818,13 @@ static char *write_elem(char *s, const apr_xml_elem *elem, int style,
for (attr = elem->attr; attr; attr = attr->next) {
if (attr->ns == APR_XML_NS_NONE)
len = sprintf(s, " %s=\"%s\"", attr->name, attr->value);
- else {
- ns = ns_map ? ns_map[attr->ns] : attr->ns;
- len = sprintf(s, " ns%d:%s=\"%s\"", ns, attr->name, attr->value);
- }
+ else if (style == APR_XML_X2T_PARSED)
+ len = sprintf(s, " %s:%s=\"%s\"",
+ find_prefix_name(elem, attr->ns, 1), attr->name, attr->value);
+ else {
+ ns = ns_map ? ns_map[attr->ns] : attr->ns;
+ len = sprintf(s, " ns%d:%s=\"%s\"", ns, attr->name, attr->value);
+ }
s += len;
}
@@ -799,6 +847,18 @@ static char *write_elem(char *s, const apr_xml_elem *elem, int style,
s += len;
}
}
+ else if (style == APR_XML_X2T_PARSED) {
+ apr_xml_ns_scope *ns_scope = elem->ns_scope;
+
+ for (; ns_scope; ns_scope = ns_scope->next) {
+ const char *prefix = find_prefix_name(elem, ns_scope->ns, 0);
+
+ len = sprintf(s, " xmlns%s%s=\"%s\"",
+ *prefix ? ":" : "", *prefix ? prefix : "",
+ APR_XML_GET_URI_ITEM(namespaces, ns_scope->ns));
+ s += len;
+ }
+ }
/* no more to do. close it up and go. */
if (empty) {
@@ -823,14 +883,17 @@ static char *write_elem(char *s, const apr_xml_elem *elem, int style,
s = write_text(s, elem->first_cdata.first);
for (child = elem->first_child; child; child = child->next) {
- s = write_elem(s, child, APR_XML_X2T_FULL, NULL, ns_map);
+ s = write_elem(s, child,
+ style == APR_XML_X2T_PARSED ? APR_XML_X2T_PARSED : APR_XML_X2T_FULL,
+ NULL, ns_map);
s = write_text(s, child->following_cdata.first);
}
- if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) {
- if (elem->ns == APR_XML_NS_NONE) {
+ if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG || style == APR_XML_X2T_PARSED) {
+ if (elem->ns == APR_XML_NS_NONE)
len = sprintf(s, "</%s>", elem->name);
- }
+ else if (style == APR_XML_X2T_PARSED)
+ len = sprintf(s, "</%s:%s>", find_prefix_name(elem, elem->ns, 1), elem->name);
else {
ns = ns_map ? ns_map[elem->ns] : elem->ns;
len = sprintf(s, "</ns%d:%s>", ns, elem->name);