diff options
-rw-r--r-- | GNUmakefile | 3 | ||||
-rw-r--r-- | config.h.guess | 881 | ||||
-rw-r--r-- | doc/luaossl.tex | 8 | ||||
-rwxr-xr-x | examples/vrfy.sig | 16 | ||||
-rwxr-xr-x | mk/luapath (renamed from mk/lua.path) | 538 | ||||
-rwxr-xr-x | regress/00-store-verify.lua | 19 | ||||
-rw-r--r-- | regress/53-csr-extensions.lua | 168 | ||||
-rw-r--r-- | regress/regress.lua | 161 | ||||
-rw-r--r-- | src/GNUmakefile | 9 | ||||
-rw-r--r-- | src/openssl.auxlib.lua | 21 | ||||
-rw-r--r-- | src/openssl.c | 1004 | ||||
-rw-r--r-- | src/openssl.x509.altname.lua | 3 | ||||
-rw-r--r-- | src/openssl.x509.name.lua | 3 |
13 files changed, 2462 insertions, 372 deletions
diff --git a/GNUmakefile b/GNUmakefile index 2955d86..c58686c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -133,6 +133,9 @@ endif # include $(d)/src/GNUmakefile +$(d)/config.h: $(d)/config.h.guess + $(CP) $< $@ + # # C L E A N R U L E S diff --git a/config.h.guess b/config.h.guess new file mode 100644 index 0000000..9b5fcdc --- /dev/null +++ b/config.h.guess @@ -0,0 +1,881 @@ +/* ========================================================================== + * config.h.guess - Preprocessor-based feature detection + * -------------------------------------------------------------------------- + * Copyright (c) 2015-2016 William Ahern + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * ========================================================================== + */ +#ifndef CONFIG_H_GUESS +#define CONFIG_H_GUESS + +/* + * A U T O G U E S S V E R S I O N + * + * Change AG_VENDOR if maintaining a fork. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define AG_VENDOR "william+autoguess@25thandClement.com" +#define AG_VERSION 20161019L + + +/* + * C O M P I L E R V E N D O R / V E R S I O N D E T E C T I O N + * + * See http://sourceforge.net/p/predef/wiki/Compilers/ + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define AG_GNUC_2VER(M, m, p) (((M) * 10000) + ((m) * 100) + (p)) +#define AG_GNUC_PREREQ(M, m, p) (__GNUC__ > 0 && AG_GNUC_2VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) >= AG_GNUC_2VER((M), (m), (p))) + +#define AG_MSC_2VER(M, m, p) ((((M) + 6) * 10000000) + ((m) * 1000000) + (p)) +#define AG_MSC_PREREQ(M, m, p) (_MSC_VER_FULL > 0 && _MSC_VER_FULL >= AG_MSC_2VER((M), (m), (p))) + +#define AG_SUNPRO_PREREQ(M, m, p) (__SUNPRO_C > 0 && __SUNPRO_C >= 0x ## M ## m ## p) + + +/* + * C O M P I L E R / L A N G U A G E F E A T U R E D E T E C T I O N + * + * NOTE: The has_ and test_ macros are separate because if the test + * expression uses the preprocessor "defined" operator the operand + * identifier may be replaced before the expression is evaluated. Most tests + * will only use arithmetic operations, but if this is not possible then the + * test must be written inline, for example + * + * #if has_attribute(x) || (!HAVE_C___HAS_ATTRIBUTE && defined FOO) + * #define HAVE___ATTRIBUTE___X + * #endif + * + * NOTE: Solaris Studio 12.4 supports __has_attribute, but we must enclose + * it in parentheses because the expansion results in a token sequence that + * chokes the compiler: __has_attribute(nonnull) becomes + * __has_attribute__ (nonnull), with a literal space between the preprocessor + * identifier and the open parenthesis. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#if defined __has_attribute +#define ag_has_attribute(a) __has_attribute(a) +#define ag_test_attribute(a, E) (ag_has_attribute(a)) +#else +#define ag_has_attribute(a) 0 +#define ag_test_attribute(a, E) (E) +#endif + +#if defined __has_extension +#define ag_has_extension(x) __has_extension(x) +#define ag_test_extension(x, E) (ag_has_extension(x)) +#else +#define ag_has_extension(x) 0 +#define ag_test_extension(x, E) (E) +#endif + +#if defined __has_include +#define ag_has_include(p) __has_include(p) +#define ag_test_include(p, E) (ag_has_include(p)) +#else +#define ag_has_include(p) 0 +#define ag_test_include(p, E) (E) +#endif + +#if defined __has_builtin +#define ag_has_builtin(f) __has_builtin(f) +#define ag_test_builtin(f, E) (ag_has_builtin(f)) +#else +#define ag_has_builtin(f) 0 +#define ag_test_builtin(f, E) (E) +#endif + +#ifndef HAVE_C___ATTRIBUTE__ +#define HAVE_C___ATTRIBUTE__ (__GNUC__ || AG_SUNPRO_PREREQ(5,9,0)) +#endif + +#ifndef HAVE_C___ATTRIBUTE___CONSTRUCTOR +#define HAVE_C___ATTRIBUTE___CONSTRUCTOR ag_test_attribute(constructor, __GNUC__) +#endif + +#ifndef HAVE_C___ATTRIBUTE___NONNULL +#define HAVE_C___ATTRIBUTE___NONNULL ag_test_attribute(nonnull, AG_GNUC_PREREQ(3,3,1)) +#endif + +#ifndef HAVE_C___ATTRIBUTE___UNUSED +#define HAVE_C___ATTRIBUTE___UNUSED ag_test_attribute(unused, __GNUC__) +#endif + +#ifndef HAVE_C___ATTRIBUTE___USED +#define HAVE_C___ATTRIBUTE___USED ag_test_attribute(used, __GNUC__) +#endif + +#ifndef HAVE_C___ATTRIBUTE___VISIBILITY +#define HAVE_C___ATTRIBUTE___VISIBILITY ag_test_attribute(visibility, __GNUC__) +#endif + +#ifndef HAVE_C___HAS_EXTENSION +#define HAVE_C___HAS_EXTENSION (defined __has_extension) +#endif + +#ifndef HAVE_C___HAS_INCLUDE +#define HAVE_C___HAS_INCLUDE (defined __has_include) +#endif + +#ifndef HAVE_C___EXTENSION__ +#define HAVE_C___EXTENSION__ (__GNUC__) +#endif + +#ifndef HAVE_C___TYPEOF +#define HAVE_C___TYPEOF (_MSC_VER || __GNUC__ || AG_SUNPRO_PREREQ(5,9,0)) +#endif + +#ifndef HAVE_C___TYPEOF__ +#define HAVE_C___TYPEOF__ (__GNUC__ || __xlc__ || AG_SUNPRO_PREREQ(5,9,0)) +#endif + +#ifndef HAVE_C__GENERIC +#define HAVE_C__GENERIC ag_test_extension(c_generic_selections, (AG_GNUC_PREREQ(4,9,0) || __STDC_VERSION__ >= 201112L)) +#endif + +#ifndef HAVE_C_STATEMENT_EXPRESSION +#define HAVE_C_STATEMENT_EXPRESSION (__GNUC__ || AG_SUNPRO_PREREQ(5,9,0)) +#endif + +#ifndef HAVE_C_TYPEOF +#define HAVE_C_TYPEOF (__GNUC__ || __xlc__ || AG_SUNPRO_PREREQ(5,9,0)) +#endif + +#ifndef HAVE___ATOMIC_FETCH_ADD +#define HAVE___ATOMIC_FETCH_ADD (defined __ATOMIC_RELAXED) +#endif + +#ifndef HAVE___ATOMIC_FETCH_SUB +#define HAVE___ATOMIC_FETCH_SUB HAVE___ATOMIC_FETCH_ADD +#endif + +#ifndef HAVE___BUILTIN_CHOOSE_EXPR +#define HAVE___BUILTIN_CHOOSE_EXPR (AG_GNUC_PREREQ(3,1,1) || __clang__) +#endif + +#ifndef HAVE___BUILTIN_EXPECT +#define HAVE___BUILTIN_EXPECT ag_test_builtin(__builtin_expect, __GNUC__) +#endif + +#ifndef HAVE___BUILTIN_NAN +#define HAVE___BUILTIN_NAN ag_test_builtin(__builtin_nan, AG_GNUC_PREREQ(3,3,1)) +#endif + +#ifndef HAVE___BUILTIN_TRAP +#define HAVE___BUILTIN_TRAP ag_test_builtin(__builtin_trap, AG_GNUC_PREREQ(3,3,1)) +#endif + +#ifndef HAVE___BUILTIN_TYPES_COMPATIBLE_P +#define HAVE___BUILTIN_TYPES_COMPATIBLE_P (AG_GNUC_PREREQ(3,1,1) || __clang__) +#endif + +#ifndef HAVE___BUILTIN_UNREACHABLE +#define HAVE___BUILTIN_UNREACHABLE ag_test_builtin(__builtin_unreachable, AG_GNUC_PREREQ(4,5,0)) +#endif + +#ifndef HAVE__STATIC_ASSERT +#define HAVE__STATIC_ASSERT ag_test_extension(c_static_assert, (AG_GNUC_PREREQ(4,6,0) || __C11FEATURES__ || __STDC_VERSION__ >= 201112L)) +#endif + + +/* + * S Y S T E M E X T E N S I O N S + * + * We must set these before including any headers for feature detection. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#if AG_USE_SYSTEM_EXTENSIONS + +/* Solaris */ +#ifndef __EXTENSIONS__ +#define __EXTENSIONS__ 1 +#endif + +/* AIX */ +#ifndef _ALL_SOURCE +#define _ALL_SOURCE 1 +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +#ifndef _MINIX +#define _MINIX 1 +#endif + +/* Solaris */ +#ifndef _POSIX_PTHREAD_SEMANTICS +#define _POSIX_PTHREAD_SEMANTICS 1 +#endif + +#endif /* AG_USE_SYSTEM_EXTENSIONS */ + +#if AG_SYS_LARGEFILE + +/* NOTE: BSDs and musl-libc always provide a 64-bit file API */ + +/* Apple */ +#ifndef _DARWIN_USE_64_BIT_INODE +#define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Solaris and glibc (per Large File Summit recommendation) */ +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + +/* AIX */ +#ifndef _LARGE_FILES +#define _LARGE_FILES 1 +#endif + +#endif /* AG_SYS_LARGEFILE */ + + +/* + * S Y S T E M D E T E C T I O N (S T A G E 0) + * + * Define HAVE_FOO macros as arithmetic truth values for any predefined + * system macros which have truth values solely based on whether they're + * defined. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* NOTE: None so far. See stage 3 below. */ + + +/* + * S Y S T E M D E T E C T I O N (S T A G E 1) + * + * Include any headers necessary for minimal libc feature checking, defining + * any prerequisite feature macros. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * NOTE: <limits.h> will indirectly include <features.h>, <standards.h>, + * <sys/cdefs.h>, <sys/feature_tests.h>, <sys/featuretest.h>, and similar + * system headers which define most of what we care about. Among the typical + * feature macros, we also get _DTRACE_VERSION. + */ +#include <limits.h> + +#ifndef AG_MUSL_MAYBE +#define AG_MUSL_MAYBE (__linux__ && !__GLIBC__ && !__BIONIC__) +#endif + +#ifndef HAVE_SYS_PARAM_H +#define HAVE_SYS_PARAM_H ag_test_include(<sys/param.h>, !AG_MUSL_MAYBE) +#endif + +/* + * NOTE: Conditionally load <sys/param.h> so we don't unnecessarily pollute + * the namespace. + */ +#if HAVE_SYS_PARAM_H && !__linux__ && !__sun && !_AIX +#include <sys/param.h> /* __FreeBSD_version __NetBSD_Prereq__ BSD OpenBSD */ +#endif + +#include <fcntl.h> /* F_DUPFD_CLOEXEC */ + + +/* + * S Y S T E M D E T E C T I O N (S T A G E 2) + * + * Macros which determine libc vendor and version. + * + * See http://sourceforge.net/p/predef/wiki/Libraries/ + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define AG_AIX_PREREQ(M, m) (_AIX # M # m) + +#if defined __GLIBC_PREREQ && !defined __UCLIBC__ +#define AG_GLIBC_PREREQ(M, m) (__GLIBC_PREREQ(M, m)) +#else +#define AG_GLIBC_PREREQ(M, m) 0 +#endif + +#define AG_FREEBSD_2VER(M, m, p) (((M) * 100000) + ((m) * 1000) + (p)) +#define AG_FREEBSD_PREREQ(M, m, p) (__FreeBSD__ > 0 && __FreeBSD_version >= AG_FREEBSD_2VER((M), (m), (p))) + +#define AG_IPHONE_2VER(M, m) (((M) * 10000) + ((m) * 100)) +#if defined __IPHONE_OS_VERSION_MIN_REQUIRED +#define AG_IPHONE_PREREQ(M, m) (AG_IPHONE_2VER((M), (m)) <= __IPHONE_OS_VERSION_MIN_REQUIRED) +#else +#define AG_IPHONE_PREREQ(M, m) 0 +#endif + +#if defined __NetBSD_Prereq__ +#define AG_NETBSD_PREREQ(M, m, p) (!__minix && __NetBSD_Prereq__(M, m, p)) +#else +#define AG_NETBSD_PREREQ(M, m, p) 0 +#endif + +#define AG_MACOS_2VER_10_9(M, m, p) (((M) * 100) + ((m) * 10)) +#define AG_MACOS_2VER_10_10(M, m, p) (((M) * 10000) + ((m) * 100) + (p)) +#define AG_MACOS_PREREQ_10_10(M, m, p) (((M) > 10 || ((M) == 10 && (m) >= 10)) && AG_MACOS_2VER_10_10((M), (m), (p)) <= __MAC_OS_X_VERSION_MIN_REQUIRED) +#define AG_MACOS_PREREQ_10_9(M, m, p) (((M) == 10 && (m) < 10) && AG_MACOS_2VER_10_9((M), (m), (p)) <= __MAC_OS_X_VERSION_MIN_REQUIRED) +#if defined __MAC_OS_X_VERSION_MIN_REQUIRED +#define AG_MACOS_PREREQ(M, m, p) (AG_MACOS_PREREQ_10_10((M), (m), (p)) || AG_MACOS_PREREQ_10_9((M), (m), (p))) +#else +#define AG_MACOS_PREREQ(M, m, p) 0 +#endif + +#define AG_OPENBSD_PREREQ_0_0 (__OpenBSD__) +#define AG_OPENBSD_PREREQ_5_5 (OpenBSD >= 201405) +#define AG_OPENBSD_PREREQ_5_7 (OpenBSD >= 201505) +#define AG_OPENBSD_PREREQ(M, m) (AG_OPENBSD_PREREQ_ ## M ## _ ## m) + +#define AG_SUNOS_PREREQ_5_10 (__sun && _DTRACE_VERSION) +#define AG_SUNOS_PREREQ_5_11 (__sun && F_DUPFD_CLOEXEC) +#define AG_SUNOS_PREREQ(M, m) (AG_SUNOS_PREREQ_ ## M ## _ ## m) + +#define AG_UCLIBC_2VER(M, m, p) (((M) * 10000) + ((m) * 100) + (p)) +#if defined __UCLIBC__ +#define AG_UCLIBC_PREREQ(M, m, p) (AG_UCLIBC_2VER(__UCLIBC_MAJOR__, __UCLIBC_MINOR__, __UCLIBC_SUBLEVEL__) >= AG_UCLIBC_2VER((M), (m), (p))) +#else +#define AG_UCLIBC_PREREQ(M, m, p) 0 +#endif + + +/* + * S Y S T E M D E T E C T I O N (S T A G E 3) + * + * Define HAVE_FOO macros as arithmetic truth values for any system macros + * which have a truth value solely based on whether they're defined. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef HAVE___EXTENSIONS__ +#ifdef __EXTENSIONS__ +#define HAVE___EXTENSIONS__ 1 +#endif +#endif + +#ifndef HAVE__ALL_SOURCE +#ifdef _ALL_SOURCE +#define HAVE__ALL_SOURCE 1 +#endif +#endif + +#ifndef HAVE__GNU_SOURCE +#ifdef _GNU_SOURCE +#define HAVE__GNU_SOURCE 1 +#endif +#endif + +#ifndef HAVE__MINIX +#if defined _MINIX || (defined __minix && defined _NETBSD_SOURCE) +#define HAVE__MINIX 1 +#endif +#endif + +#ifndef HAVE__POSIX_PTHREAD_SEMANTICS +#ifdef _POSIX_PTHREAD_SEMANTICS +#define HAVE__POSIX_PTHREAD_SEMANTICS 1 +#endif +#endif + +#ifndef HAVE__REENTRANT +#ifdef _REENTRANT +#define HAVE__REENTRANT 1 +#endif +#endif + + +/* + * H E A D E R D E T E C T I O N + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef HAVE_DLFCN_H +#define HAVE_DLFCN_H ag_test_include(<dlfcn.h>, 1) +#endif + +#ifndef HAVE_IFADDRS_H +#define HAVE_IFADDRS_H_ (!_AIX && (!__sun || AG_SUNOS_PREREQ(5,11))) +#define HAVE_IFADDRS_H ag_test_include(<ifaddrs.h>, HAVE_IFADDRS_H_) +#endif + +#ifndef HAVE_INTTYPES_H +#define HAVE_INTTYPES_H 1 +#endif + +#ifndef HAVE_MACH_CLOCK_H +#define HAVE_MACH_CLOCK_H ag_test_include(<mach/clock.h>, __APPLE__) +#endif + +#ifndef HAVE_MACH_MACH_H +#define HAVE_MACH_MACH_H ag_test_include(<mach/mach.h>, __APPLE__) +#endif + +#ifndef HAVE_MACH_MACH_TIME_H +#define HAVE_MACH_MACH_TIME_H ag_test_include(<mach/mach_time.h>, __APPLE__) +#endif + +#ifndef HAVE_MEMORY_H +#define HAVE_MEMORY_H 1 +#endif + +#ifndef HAVE_PORT_H +#define HAVE_PORT_H ag_test_include(<port.h>, AG_SUNOS_PREREQ(5,10)) +#endif + +/* TODO: Maybe test _POSIX_THREADS from <unistd.h>. */ +#ifndef HAVE_PTHREAD_H +#define HAVE_PTHREAD_H ag_test_include(<pthread.h>, !__minix) +#endif + +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H 1 +#endif + +#ifndef HAVE_STDLIB_H +#define HAVE_STDLIB_H 1 +#endif + +#ifndef HAVE_STRING_H +#define HAVE_STRING_H 1 +#endif + +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 1 +#endif + +#ifndef HAVE_SYS_AUXV_H +#define HAVE_SYS_AUXV_H_ (AG_GLIBC_PREREQ(2,16) || (!AG_GLIBC_PREREQ(0,0) && __linux__) || __sun) +#define HAVE_SYS_AUXV_H ag_test_include(<sys/auxv.h>, HAVE_SYS_AUXV_H_) +#endif + +#ifndef HAVE_SYS_EPOLL_H +#define HAVE_SYS_EPOLL_H ag_test_include(<sys/epoll.h>, __linux__) +#endif + +#ifndef HAVE_SYS_EVENT_H +#define HAVE_SYS_EVENT_H ag_test_include(<sys/event.h>, BSD) +#endif + +#ifndef HAVE_SYS_EVENTFD_H +#define HAVE_SYS_EVENTFD_H_ (AG_GLIBC_PREREQ(2,8) || (!AG_GLIBC_PREREQ(0,0) && __linux__) || defined EFD_CLOEXEC) +#define HAVE_SYS_EVENTFD_H ag_test_include(<sys/eventfd.h>, HAVE_SYS_EVENTFD_H_) +#endif + +#ifndef HAVE_SYS_INOTIFY_H +#define HAVE_SYS_INOTIFY_H ag_test_include(<sys/inotify.h>, __linux__) +#endif + +#ifndef HAVE_SYS_SIGNALFD_H +#define HAVE_SYS_SIGNALFD_H_ (AG_GLIBC_PREREQ(2,8) || (!AG_GLIBC_PREREQ(0,0) && __linux__) || defined SFD_CLOEXEC) +#define HAVE_SYS_SIGNALFD_H ag_test_include(<sys/signalfd.h>, HAVE_SYS_SIGNALFD_H_) +#endif + +#ifndef HAVE_SYS_SOCKIO_H +#define HAVE_SYS_SOCKIO_H ag_test_include(<sys/sockio.h>, (__sun || BSD)) +#endif + +#ifndef HAVE_SYS_STAT_H +#define HAVE_SYS_STAT_H 1 +#endif + +#ifndef HAVE_SYS_SYSCALL_H +#define HAVE_SYS_SYSCALL_H_ (BSD || __linux__ || __sun) +#define HAVE_SYS_SYSCALL_H ag_test_include(<sys/syscall.h>, HAVE_SYS_SYSCALL_H_) +#endif + +#ifndef HAVE_SYS_SYSCTL_H +#define HAVE_SYS_SYSCTL_H ag_test_include(<sys/sysctl.h>, (BSD || __GLIBC__)) +#endif + +#ifndef HAVE_SYS_TIMERFD_H +#define HAVE_SYS_TIMERFD_H_ (AG_GLIBC_PREREQ(2,8) || (!AG_GLIBC_PREREQ(0,0) && __linux__) || defined TFD_CLOEXEC) +#define HAVE_SYS_TIMERFD_H ag_test_include(<sys/timerfd.h>, HAVE_SYS_TIMERFD_H_) +#endif + +#ifndef HAVE_SYS_TYPES_H +#define HAVE_SYS_TYPES_H 1 +#endif + +#ifndef HAVE_UNISTD_H +#define HAVE_UNISTD_H 1 +#endif + + +/* + * T Y P E D E T E C T I O N + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef HAVE_CLOCKID_T +#define HAVE_CLOCKID_T (defined CLOCK_MONOTONIC) +#endif + +#ifndef HAVE_STRUCT_SOCKADDR_SA_LEN +#define HAVE_STRUCT_SOCKADDR_SA_LEN (!__linux__ && !__sun) +#endif + +#ifndef HAVE_STRUCT_STAT_ST_ATIM +#define HAVE_STRUCT_STAT_ST_ATIM (defined st_atime && ((!__APPLE__ && (!__NetBSD__ || AG_NETBSD_PREREQ(7,0,0))) || !HAVE_STRUCT_STAT_ST_ATIMESPEC)) +#endif + +#ifndef HAVE_STRUCT_STAT_ST_CTIM +#define HAVE_STRUCT_STAT_ST_CTIM HAVE_STRUCT_STAT_ST_ATIM +#endif + +#ifndef HAVE_STRUCT_STAT_ST_MTIM +#define HAVE_STRUCT_STAT_ST_MTIM HAVE_STRUCT_STAT_ST_ATIM +#endif + +#ifndef HAVE_STRUCT_STAT_ST_ATIMESPEC +#define HAVE_STRUCT_STAT_ST_ATIMESPEC (__APPLE__ || defined st_atimespec || defined st_atimensec) +#endif + +#ifndef HAVE_STRUCT_STAT_ST_CTIMESPEC +#define HAVE_STRUCT_STAT_ST_CTIMESPEC HAVE_STRUCT_STAT_ST_ATIMESPEC +#endif + +#ifndef HAVE_STRUCT_STAT_ST_MTIMESPEC +#define HAVE_STRUCT_STAT_ST_MTIMESPEC HAVE_STRUCT_STAT_ST_ATIMESPEC +#endif + +#ifndef HAVE_STRUCT_STAT_ST_BLOCKS +#define HAVE_STRUCT_STAT_ST_BLOCKS 1 +#endif + +#ifndef HAVE_STRUCT_STAT_ST_BLKSIZE +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 +#endif + +#ifndef HAVE_STRUCT_STAT_ST_RDEV +#define HAVE_STRUCT_STAT_ST_RDEV 1 +#endif + + +/* + * D E C L A R A T I O N D E T E C T I O N + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef HAVE___DECL_LIBC_ENABLE_SECURE +#define HAVE___DECL_LIBC_ENABLE_SECURE 0 +#endif + +#ifndef HAVE_DECL_CLOCK_GETTIME +#define HAVE_DECL_CLOCK_GETTIME HAVE_DECL_CLOCK_MONOTONIC +#endif + +#ifndef HAVE_DECL_CLOCK_MONOTONIC +#define HAVE_DECL_CLOCK_MONOTONIC (defined CLOCK_MONOTONIC) +#endif + +#ifndef HAVE_DECL_CLOCK_REALTIME +#define HAVE_DECL_CLOCK_REALTIME (defined CLOCK_REALTIME) +#endif + +#ifndef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME +#define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME (__linux__ && HAVE__GNU_SOURCE) +#endif + +#ifndef HAVE_DECL_PTHREAD_MUTEX_ROBUST +#define HAVE_DECL_PTHREAD_MUTEX_ROBUST (defined PTHREAD_MUTEX_ROBUST || AG_GLIBC_PREREQ(2,12)) +#endif + +#ifndef HAVE_DECL_RANDOM_UUID +#define HAVE_DECL_RANDOM_UUID (HAVE_SYS_SYSCTL_H && defined __linux__) /* RANDOM_UUID is an enum, not macro */ +#endif + +#ifndef HAVE_DECL_STRERROR_R +#define HAVE_DECL_STRERROR_R 1 +#endif + +#ifndef HAVE_DECL_SYS_SIGLIST +#define HAVE_DECL_SYS_SIGLIST (!AG_MUSL_MAYBE && !__sun && !_AIX) +#endif + +#ifndef HAVE_DECL_SYS_GETRANDOM +#define HAVE_DECL_SYS_GETRANDOM (defined SYS_getrandom) +#endif + + +/* + * V A R I A B L E D E T E C T I O N + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef HAVE___LIBC_ENABLE_SECURE +#define HAVE___LIBC_ENABLE_SECURE AG_GLIBC_PREREQ(2,1) /* added to glibc between 2.0.98 and 2.0.99 */ +#endif + +#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME +#define HAVE_PROGRAM_INVOCATION_SHORT_NAME (__linux__) +#endif + +#ifndef HAVE_SYS_SIGLIST +#define HAVE_SYS_SIGLIST HAVE_DECL_SYS_SIGLIST +#endif + + +/* + * F U N C T I O N D E T E C T I O N + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef HAVE_ACCEPT4 +#define HAVE_ACCEPT4 (defined SOCK_CLOEXEC && !__NetBSD__) +#endif + +#ifndef HAVE_ARC4RANDOM +#define HAVE_ARC4RANDOM \ + (__APPLE__ || __DragonFly__ || __FreeBSD__ || __NetBSD__ || \ + __OpenBSD__ || __minix) +#endif + +#ifndef HAVE_ARC4RANDOM_ADDRANDOM +#define HAVE_ARC4RANDOM_ADDRANDOM (HAVE_ARC4RANDOM && !AG_OPENBSD_PREREQ(5,5)) +#endif + +#ifndef HAVE_ARC4RANDOM_BUF +#define HAVE_ARC4RANDOM_BUF_APPLE_ (!__APPLE__ || AG_MACOS_PREREQ(10,7,0) || AG_IPHONE_PREREQ(4,3)) +#define HAVE_ARC4RANDOM_BUF_NETBSD_ (!__NetBSD__ || AG_NETBSD_PREREQ(6,0,0)) +#define HAVE_ARC4RANDOM_BUF_IFF_ (HAVE_ARC4RANDOM_BUF_APPLE_ && HAVE_ARC4RANDOM_BUF_NETBSD_) +#define HAVE_ARC4RANDOM_BUF (HAVE_ARC4RANDOM && HAVE_ARC4RANDOM_BUF_IFF_) +#endif + +#ifndef HAVE_ARC4RANDOM_STIR +#define HAVE_ARC4RANDOM_STIR HAVE_ARC4RANDOM_ADDRANDOM +#endif + +#ifndef HAVE_CLOCK_GETTIME +#define HAVE_CLOCK_GETTIME (!__APPLE__ || AG_MACOS_PREREQ(10,12,0)) +#endif + +#ifndef HAVE_DLADDR +#define HAVE_DLADDR (HAVE_DLOPEN && !_AIX && ((!__GLIBC__ && !AG_MUSL_MAYBE) || HAVE__GNU_SOURCE)) +#endif + +#ifndef HAVE_DLOPEN +#define HAVE_DLOPEN HAVE_DLFCN_H +#endif + +#ifndef HAVE_DLSYM +#define HAVE_DLSYM HAVE_DLOPEN +#endif + +#ifndef HAVE_DUP2 +#define HAVE_DUP2 1 +#endif + +#ifndef HAVE_DUP3 +#define HAVE_DUP3 (AG_GLIBC_PREREQ(2,9) || AG_FREEBSD_PREREQ(10,0,0) || AG_NETBSD_PREREQ(6,0,0) || AG_UCLIBC_PREREQ(0,9,34) || AG_MUSL_MAYBE || __BIONIC__ || AG_OPENBSD_PREREQ(5,7)) +#endif + +#ifndef HAVE_FDOPENDIR +#define HAVE_FDOPENDIR ( \ + (!__APPLE__ || AG_MACOS_PREREQ(10,10,0) || AG_IPHONE_PREREQ(8,0)) \ + && (!__NetBSD__ || AG_NETBSD_PREREQ(6,0,0)) \ +) +#endif + +#ifndef HAVE_EPOLL_CREATE +#define HAVE_EPOLL_CREATE HAVE_SYS_EPOLL_H +#endif + +#if HAVE_SYS_EPOLL_H +#include <sys/epoll.h> +#endif + +#ifndef HAVE_EPOLL_CREATE1 +#define HAVE_EPOLL_CREATE1 (HAVE_EPOLL_CREATE && (defined EPOLL_CLOEXEC || AG_GLIBC_PREREQ(2,9))) +#endif + +#ifndef HAVE_EPOLL_CTL +#define HAVE_EPOLL_CTL HAVE_EPOLL_CREATE +#endif + +#ifndef HAVE_EPOLL_PWAIT +#define HAVE_EPOLL_PWAIT (HAVE_EPOLL_WAIT && (AG_GLIBC_PREREQ(2,6) || (!AG_GLIBC_PREREQ(0,0) && defined EPOLL_CLOEXEC))) +#endif + +#ifndef HAVE_EPOLL_WAIT +#define HAVE_EPOLL_WAIT HAVE_EPOLL_CREATE +#endif + +#ifndef HAVE_EVENTFD +#define HAVE_EVENTFD HAVE_SYS_EVENTFD_H +#endif + +#ifndef HAVE_GETAUXVAL +#define HAVE_GETAUXVAL (HAVE_SYS_AUXV_H && !__sun) +#endif + +#ifndef HAVE_GETENV_R +#define HAVE_GETENV_R (AG_NETBSD_PREREQ(4,0,0) || __minix) +#endif + +#ifndef HAVE_GETEXECNAME +#define HAVE_GETEXECNAME (__sun) +#endif + +#ifndef HAVE_GETIFADDRS +#define HAVE_GETIFADDRS (HAVE_IFADDRS_H && !__sun) +#endif + +#ifndef HAVE_GETPROGNAME +#define HAVE_GETPROGNAME (HAVE_ARC4RANDOM || AG_SUNOS_PREREQ(5,11)) +#endif + +#ifndef HAVE_INOTIFY_INIT +#define HAVE_INOTIFY_INIT HAVE_SYS_INOTIFY_H +#endif + +#ifndef HAVE_INOTIFY_INIT1 +#define HAVE_INOTIFY_INIT1 (HAVE_INOTIFY_INIT && defined IN_CLOEXEC) +#endif + +#ifndef HAVE_ISSETUGID +#define HAVE_ISSETUGID ((!__linux__ || (AG_MUSL_MAYBE && HAVE__GNU_SOURCE)) && !_AIX) +#endif + +#if HAVE_SYS_EVENT_H +#include <sys/event.h> +#endif + +#ifndef HAVE_KEVENT +#define HAVE_KEVENT (defined EV_SET) +#endif + +#ifndef HAVE_KQUEUE +#define HAVE_KQUEUE HAVE_KEVENT +#endif + +#ifndef HAVE_KQUEUE1 +#define HAVE_KQUEUE1 (HAVE_KQUEUE && AG_NETBSD_PREREQ(6,0,0)) +#endif + +#ifndef HAVE_OPENAT +#define HAVE_OPENAT \ + ((!__APPLE__ || AG_MACOS_PREREQ(10,10,0) || AG_IPHONE_PREREQ(8,0)) \ + && (!__NetBSD__ || AG_NETBSD_PREREQ(7,0,0))) +#endif + +#ifndef HAVE_PACCEPT +#define HAVE_PACCEPT AG_NETBSD_PREREQ(6,0,0) +#endif + +#ifndef HAVE_PIPE2 +#define HAVE_PIPE2 (AG_GLIBC_PREREQ(2,9) || AG_FREEBSD_PREREQ(10,0,0) || AG_NETBSD_PREREQ(6,0,0) || AG_UCLIBC_PREREQ(0,9,32) || AG_MUSL_MAYBE || __BIONIC__ || AG_OPENBSD_PREREQ(5,7)) +#endif + +#ifndef HAVE_PORT_ALERT +#define HAVE_PORT_ALERT HAVE_PORT_CREATE +#endif + +#ifndef HAVE_PORT_ASSOCIATE +#define HAVE_PORT_ASSOCIATE HAVE_PORT_CREATE +#endif + +#ifndef HAVE_PORT_CREATE +#define HAVE_PORT_CREATE HAVE_PORT_H +#endif + +#ifndef HAVE_PORT_DISSOCIATE +#define HAVE_PORT_DISSOCIATE HAVE_PORT_CREATE +#endif + +#ifndef HAVE_PORT_GET +#define HAVE_PORT_GET HAVE_PORT_CREATE +#endif + +#ifndef HAVE_PORT_GETN +#define HAVE_PORT_GETN HAVE_PORT_CREATE +#endif + +#ifndef HAVE_PORT_SEND +#define HAVE_PORT_SEND HAVE_PORT_CREATE +#endif + +#ifndef HAVE_PORT_SENDN +#define HAVE_PORT_SENDN HAVE_PORT_CREATE +#endif + +#ifndef HAVE_POSIX_FADVISE +#define HAVE_POSIX_FADVISE (defined POSIX_FADV_NORMAL || AG_GLIBC_PREREQ(2,2) || __sun || AG_MUSL_MAYBE || AG_FREEBSD_PREREQ(9,0,0)) +#endif + +#ifndef HAVE_POSIX_FALLOCATE +#define HAVE_POSIX_FALLOCATE (_AIX || AG_FREEBSD_PREREQ(9,0,0) || AG_GLIBC_PREREQ(2,2) || AG_MUSL_MAYBE || AG_NETBSD_PREREQ(7,0,0) || __sun) +#endif + +#ifndef HAVE_SIGNALFD +#define HAVE_SIGNALFD HAVE_SYS_SIGNALFD_H +#endif + +#ifndef HAVE_SIGTIMEDWAIT +#define HAVE_SIGTIMEDWAIT (!__APPLE__ && !__OpenBSD__) +#endif + +#ifndef HAVE_SIGWAIT +#define HAVE_SIGWAIT (!__minix) +#endif + +#ifndef HAVE_STATIC_ASSERT +#if AG_GLIBC_PREREQ(0,0) && !HAVE__STATIC_ASSERT +#define HAVE_STATIC_ASSERT 0 /* glibc doesn't check GCC version */ +#else +#define HAVE_STATIC_ASSERT (defined static_assert) +#endif +#endif + +#ifndef HAVE_STRERROR_R +#define HAVE_STRERROR_R 1 +#endif + +#ifndef HAVE_SYSCALL +#define HAVE_SYSCALL HAVE_SYS_SYSCALL_H +#endif + +#ifndef HAVE_SYSCTL +#define HAVE_SYSCTL HAVE_SYS_SYSCTL_H +#endif + +#ifndef HAVE_TIMERFD_CREATE +#define HAVE_TIMERFD_CREATE HAVE_SYS_TIMERFD_H +#endif + +#ifndef HAVE_TIMERFD_GETTIME +#define HAVE_TIMERFD_GETTIME HAVE_TIMERFD_CREATE +#endif + +#ifndef HAVE_TIMERFD_SETTIME +#define HAVE_TIMERFD_SETTIME HAVE_TIMERFD_CREATE +#endif + +#ifndef STRERROR_R_CHAR_P +#define STRERROR_R_CHAR_P ((AG_GLIBC_PREREQ(0,0) || AG_UCLIBC_PREREQ(0,0,0)) && (HAVE__GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600))) +#endif + + +#endif /* CONFIG_H_GUESS */ diff --git a/doc/luaossl.tex b/doc/luaossl.tex index 433dd03..7db7463 100644 --- a/doc/luaossl.tex +++ b/doc/luaossl.tex @@ -597,6 +597,14 @@ Returns the subject distinguished name as an \module{x509.name} object. Sets the subject distinguished name. $name$ should be an \module{x509.name} object. +\subsubsection[\fn{csr:getSubjectAlt}]{\fn{csr:getSubjectAlt()}} + +Returns the subject alternative name as an \module{x509.altname} object. + +\subsubsection[\fn{csr:setSubjectAlt}]{\fn{csr:setSubjectAlt($name$)}} + +Sets the subject alternative names. $name$ should be an \module{x509.altname} object. + \subsubsection[\fn{csr:getPublicKey}]{\fn{csr:getPublicKey()}} Returns the public key component as an \module{openssl.pkey} object. diff --git a/examples/vrfy.sig b/examples/vrfy.sig index 258490a..84bcfcc 100755 --- a/examples/vrfy.sig +++ b/examples/vrfy.sig @@ -14,15 +14,16 @@ local function genkey(type) type = string.upper(type or (not openssl.NO_EC and "EC") or "RSA") if type == "RSA" then - return pkey.new{ type = "RSA", bits = 1024 }, "sha256" + return pkey.new{ type = "RSA", bits = 1024 } elseif type == "DSA" then - return pkey.new{ type = "DSA", bits = 1024 }, "dss1" + return pkey.new{ type = "DSA", bits = 1024 } else - return pkey.new{ type = "EC", curve = "prime192v1" }, "ecdsa-with-SHA1" + return pkey.new{ type = "EC", curve = "prime192v1" } end end -local key, hash = genkey(keytype) +local key = genkey(keytype) +local hash = key:getDefaultDigestName() -- digest our message using an appropriate digest ("ecdsa-with-SHA1" for EC; -- "dss1" for DSA; and "sha1", "sha256", etc for RSA). @@ -45,6 +46,7 @@ local function tohex(b) return x end -print("okay", pub:verify(sig, data)) -print("type", pub:type()) -print("sig", tohex(sig)) +print("verified", pub:verify(sig, data)) +print("key-type", pub:type()) +print("hash-type", hash) +print("signature", tohex(sig)) @@ -26,10 +26,10 @@ # Changelog: # # * 2013-08-02 - Published. Derived from an earlier script, lua.path, -# written for the cqueues project. +# written for the cqueues project. # # * 2013-08-05 - Redirect stdin from /dev/null when probing so we don't -# freeze if a utility tries to read from stdin. +# freeze if a utility tries to read from stdin. # # chdir to a read-only directory by default to try to prevent creation # of temporary files. These features address the issues of LuaTeX @@ -82,9 +82,55 @@ # hardcode /usr/local/lib/lua/5.1, ordered before the LuaJIT # installation prefix. # +# * 2015-07-14 - Add recursive glob function implemented in shell code +# and use instead of find(1). +# +# * 2016-03-18 - Fix bug in tryluac where a continue statement was used +# instead of return 0. +# +# * 2016-03-25 - Support ${CC} values with trailing flags, which invoke +# the compiler through env(1), or which otherwise are intended to +# expand as multiple words. +# +# OpenBSD 5.8 sh does not suppress strict errors within an eval +# invoked from an if condition compound-list. Workaround by changing +# trylua to return 0 on matching failure, like tryluainclude and +# tryluac do. +# +# Undeprecate ldir and cdir. The names are more intuitive and +# convenient as evidenced by the fact that I keep using them instead +# of package.path and package.cpath. Try to maintain backwards +# compatibility by using a simple heuristic to differentiate lua +# interpreter glob patterns from preferred install directory +# string.match expressions. +# +# * 2016-10-10 - Fix issue with passing empty CPPFLAGS to ${CC}. /usr/bin/cc +# in NetBSD 7.0.1 does not tolerate an empty string argument. This +# exposed a bug in NetBSD's and FreeBSD's /bin/sh, triggered by how we +# pass CPPFLAGS (see evalmacro and runcc routines, below). +# +# Some Ash variants (confirmed /bin/sh in NetBSD 7.0.1 and FreeBSD +# 10.1) will expand unquoted ${UNSET-} and ${UNSET:-} as an empty +# string rather than eliding it during argument processing. That is, +# +# nargs() { printf "%d\n" "$#"; } +# nargs ${UNSET} 2 3 +# nargs ${UNSET-} 2 3 +# +# prints "2" and "3", whereas every other shell tested prints "2" and +# "2" (confirmed dash in Ubuntu Xenial; bash 4.3 in Ubuntu Xenial; +# pdksh in FreeBSD 10.1, NetBSD 7.0, OS X 10.1, OpenBSD 6.0; ksh93 in +# Solaris 11.3 and AIX 7.1; ksh88 in AIX 7.1). +# +# A workaround in set -u mode (where unbound variable expansion aborts +# execution) is to substitute a known empty value. E.g. +# +# EMPTY= +# nargs ${UNSET-$EMPTY} +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# Copyright (C) 2012-2015 William Ahern +# Copyright (C) 2012-2016 William Ahern # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -116,10 +162,11 @@ unset IFS # no field splitting surprises unset LUA_PATH || true # interferes search for module install directory unset LUA_CPATH || true -MYVERSION=20150119 +MYVERSION=20161010 MYVENDOR="william@25thandClement.com" +EMPTY= # empty string for parameter expansion workaround for Ash bug DEVRANDOM=/dev/urandom SANDBOX="${TMPDIR}/${0##*/}-" @@ -129,8 +176,7 @@ LDDIRS= # -L directories from LDFLAGS LIBDIRS= BINDIRS= RECURSE=no -MAXDEPTH= # full command switch, like "-maxdepth 3", if supported -XDEV= # do not cross device boundaries; i.e. "-xdev" +MAXDEPTH=5 # maximum recursion depth SHORTEST= # continue searching until shortest pathname found PKGCONFIG= # path to pkg-config, found by `command -v` when -k option invoked GLOB= # -e GLOB expression for lua, luac, ldir, and cdir @@ -165,6 +211,27 @@ LUA_VER= # +# warn FORMAT [...] +# +# Print message to original stderr. +# +exec 9>&2 +warn() { + printf "%s: %.0s${1}\n" "${0##*/}" "$@" >&9 +} + +# +# panic FORMAT [...] +# +# Print message to original stderr, then exit with failure. +# +panic() { + warn "$@" + exit 1 +} + + +# # parse CPPFLAGS -I or LDFLAGS -L directories # xdirs() { @@ -231,6 +298,46 @@ append() { } # +# glob PATTERN [MAXDEPTH] [EXEC-COMMAND] [INTERNAL:GLOB-COUNT] +# +glob() { + glob_N="${4:-0}" + + IFS= + set +f + for F in ${1}; do + [ -e "${F}" ] || continue + if eval "${3:-printf '%s\\n'} \"\${F}\""; then + glob_N=$((${glob_N} + 1)) + fi + done + set -f + unset IFS + + if [ "${2-0}" -gt 0 ]; then + glob "${1%/*}/*/${1##*/}" "$((${2} - 1))" "${3:-}" "${glob_N}" || : + fi + + [ "${glob_N}" -gt 0 ] +} # glob + + +# +# runcc [...] +# +# Wrapper for invoking ${CC}. Some build system include flags in ${CC}, +# invoke the compiler through env(1), or employ other hacks. +# +# TODO: Optionally handle unescaping of words in a manner similar to how +# ${CC} would be evaluated from a make rule--typically by being passed +# through system(3). +# +runcc() { + (unset IFS; exec ${CC} "$@") +} + + +# # evalmacro PATH MACRO [REGEX] [SUBST] # # PATH Header identifier--#include <PATH> @@ -240,7 +347,7 @@ append() { # evalmacro() { printf "#include <$1>\n[===[$2]===]\n" \ - | "${CC:-cc}" ${CPPFLAGS:-} -E - 2>>/dev/null \ + | runcc ${CPPFLAGS:-${EMPTY}} -E - 2>>/dev/null \ | sed -ne " s/^.*\\[===\\[ *\\(${3:-.*}\\) *\\]===\\].*$/${4:-\\1}/ t Found @@ -267,7 +374,7 @@ testsym() { # and within [A-T]. (nm -Pg ${1} 2>>/dev/null || nm -g 2>>/dev/null) \ | sed -ne '/ [A-T] /p' \ - | grep -qE "${2}" + | grep -q "${2}" } @@ -398,7 +505,9 @@ luapc() { findinstalldir() { V_DIR=$((${LUA_VER} / 100 % 100)).$((${LUA_VER} % 100)) - if [ "${1}" = "package.cpath" ]; then + if [ "${1}" = "package.cpath" -o "${1}" = "cdir" ]; then + ARRAY="package.cpath" + DIR="$(luapc --variable INSTALL_CMOD)" [ -n "${DIR}" ] && set -- "$@" "${DIR}" @@ -418,6 +527,8 @@ findinstalldir() { set -- "$@" "${LUA_PATH}/../../lib/lua/${V_DIR}" set -- "$@" "${LUA_PATH}/../../lib/*/lua/${V_DIR}" # e.g. lib/x86_64-linux-gnu else + ARRAY="package.path" + DIR="$(luapc --variable INSTALL_LMOD)" [ -n "${DIR}" ] && set -- "$@" "${DIR}" @@ -429,7 +540,6 @@ findinstalldir() { set -- "$@" "${LUA_PATH}/../../share/lua/${V_DIR}" fi - ARRAY="${1}" shift if [ $# -eq 0 ]; then @@ -576,13 +686,11 @@ findversion() { if [ $# -gt 0 ]; then for D; do - for F in $(find "${D}" ${MAXDEPTH} ${XDEV} -name lua.h -print 2>>/dev/null); do - tryluainclude "${F}" + glob "${D}/lua.h" "${MAXDEPTH}" tryluainclude || : - if foundversion; then - return 0 - fi - done + if foundversion; then + return 0 + fi done fi @@ -594,13 +702,11 @@ findversion() { if [ $# -gt 0 ]; then for D; do - for F in $(find "${D}/." ${MAXDEPTH} ${XDEV} -name lua.h -print 2>>/dev/null); do - tryluainclude "${F}" + glob "${D}/lua.h" "${MAXDEPTH}" tryluainclude || : - if foundversion; then - return 0 - fi - done + if foundversion; then + return 0 + fi done fi @@ -612,13 +718,11 @@ findversion() { D="${D%/*}/include" if [ -d "${D}" ]; then - for F in $(find "${D}" ${MAXDEPTH} ${XDEV} -name lua.h -print 2>>/dev/null); do - tryluainclude "${F}" + glob "${D}/lua.h" "${MAXDEPTH}" tryluainclude || : - if foundversion; then - return 0 - fi - done + if foundversion; then + return 0 + fi fi fi @@ -631,9 +735,10 @@ findversion() { # compatible. # trylib() { - if ! testsym "${1}" "lua_newstate"; then - return 0 - fi + testsym "${1}" "lua_newstate" || return 1 + + # exclude C++ + [ "${1#*++}" = "${1}" ] || return 1 V=0 J=0 @@ -662,16 +767,20 @@ trylib() { if testsym "${1}" "lua_getfenv"; then V=501 elif testsym "${1}" "lua_yieldk"; then - V=502 + if testsym "${1}" "lua_getctx"; then + V=502 + else + V=503 + fi else - return 0 + return 1 fi - [ "$V" -gt 0 -a "$V" -ge "${LIBLUA_VER:-0}" ] || return 0 + [ "$V" -gt 0 -a "$V" -ge "${LIBLUA_VER:-0}" ] || return 1 - [ "$V" -gt "${LIBLUA_VER:-0}" -o "${#D}" -lt "${#LIBLUA_DIR}" -o \( "${JIT_REQ}" = "yes" -a "${LIBJIT_VER:-0}" -lt "${JIT_MAX}" \) ] || return 0 + [ "$V" -gt "${LIBLUA_VER:-0}" -o "${#D}" -lt "${#LIBLUA_DIR}" -o \( "${JIT_REQ}" = "yes" -a "${LIBJIT_VER:-0}" -lt "${JIT_MAX}" \) ] || return 1 - [ "$V" -ge "${API_MIN}" -a "$V" -le "${API_MAX}" ] || return 0 + [ "$V" -ge "${API_MIN}" -a "$V" -le "${API_MAX}" ] || return 1 if [ -n "${JIT_REQ}" ]; then @@ -681,12 +790,12 @@ trylib() { fi if [ "${JIT_REQ}" = "skip" ]; then - [ "${J}" -eq 0 ] || return 0 + [ "${J}" -eq 0 ] || return 1 elif [ "${JIT_REQ}" = "yes" ]; then - [ "$J" -ge "${LIBJIT_VER:-0}" ] || return 0 - [ "$J" -gt "${LIBJIT_VER:-0}" -o "${#D}" -lt "${#LIBJIT_DIR}" ] || return 0 - [ "$J" -ge ${JIT_MIN} ] || return 0 - [ "$J" -le "${JIT_MAX}" ] || return 0 + [ "$J" -ge "${LIBJIT_VER:-0}" ] || return 1 + [ "$J" -gt "${LIBJIT_VER:-0}" -o "${#D}" -lt "${#LIBJIT_DIR}" ] || return 1 + [ "$J" -ge ${JIT_MIN} ] || return 1 + [ "$J" -le "${JIT_MAX}" ] || return 1 LIBJIT_VER="$J" LIBJIT_DIR="$D" @@ -745,15 +854,17 @@ findlib() { #printf -- "I=$I K=$K $findlib_L/lib$findlib_l*.*\n" - for findlib_R in no ${RECURSE}; do - for findlib_lib in $(findpath "lib${findlib_l}*.*" ${findlib_R} "${findlib_L}"); do - trylib "${findlib_lib}" - done + glob "${findlib_L}/lib${findlib_l}*.*" 0 trylib || : - if foundlib; then - return 0 - fi - done + if foundlib; then + return 0; + fi + + glob "${findlib_L}/lib${findlib_l}*.*" ${MAXDEPTH} trylib || : + + if foundlib; then + return 0; + fi K=$(($K + 1)) done @@ -768,48 +879,73 @@ findlib() { unset IFS for findlib_D; do - for findlib_R in no ${RECURSE}; do - for findlib_lib in $(findpath "liblua*.*" ${findlib_R} "${findlib_D}"); do - trylib "${findlib_lib}" - done + glob "${findlib_D}/liblua*.*" "${MAXDEPTH}" trylib || : + + if foundlib; then + return 0 + fi + done + + # if we can find the lua interpreter, use it as a reference for + # library locations. + if findlua; then + findlib_D="${LUA_PATH%/*}" + findlib_D="${findlib_D%/*}/lib" + + if [ -d "${findlib_D}" ]; then + glob "${findlib_D}/liblua*.*" "${MAXDEPTH}" trylib || : if foundlib; then return 0 fi - done - done + fi + fi +} + + +# check setuid and setgid mode +safeperm() { + [ -f "$1" -a ! -u "$1" -a ! -g "$1" ] } -findpath() { - NAME="$1" - WHERE="$3" +tryluac() { + tryluac_F="${1}" - PRUNE= + [ -x "${tryluac_F}" ] && safeperm "${tryluac_F}" || return 0 - if [ "${2}" = "no" ]; then - PRUNE="-name . -o -type d -prune -o" - fi + tryluac_V="$("${tryluac_F}" -v </dev/null 2>&1 | head -n1 | sed -ne 's/^Lua \([0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')" + : ${tryluac_V:=0} + tryluac_V="$((${tryluac_V%%.*} * 100 + ${tryluac_V##*.} % 100))" - [ ${#WHERE} -gt 0 ] || return 0 + [ "${tryluac_V}" -gt 0 -a "${tryluac_V}" -ge "${LUAC_VER:-0}" ] || return 0 - IFS=: - set -- ${WHERE} - unset IFS + [ "${tryluac_V}" -gt "${LUAC_VER:-0}" -o "${#tryluac_F}" -lt "${#LUAC_PATH}" ] || return 0 - if [ $# -gt 0 ]; then - for findpath_D; do - find "${findpath_D}/." ${MAXDEPTH} ${XDEV} ${PRUNE} -name "${NAME}" -print 2>>/dev/null | sed -e 's/\/\.//' - done - fi -} + [ "${tryluac_V}" -ge "${API_MIN}" -a "${tryluac_V}" -le "${API_MAX}" ] || return 0 + printf "return true" 2>>/dev/null | ${tryluac_F} -p - </dev/null >>/dev/null 2>&1 || return 0 -# check setuid and setgid mode -safeperm() { - [ -f "$1" -a ! -u "$1" -a ! -g "$1" ] + LUAC_PATH="${tryluac_F}" + LUAC_VER="${tryluac_V}" } +# +# foundluac +# +# true if found the best (maximum) possible version, false otherwise +# +foundluac() { + if [ "${LUAC_VER:-0}" -lt "${API_MAX}" ]; then + return 1 + fi + + if [ "${SHORTEST}" = "yes" ]; then + return 1 + fi + + return 0 +} findluac() { if [ $# -eq 0 ]; then @@ -818,36 +954,33 @@ findluac() { unset IFS fi - while [ $# -gt 0 ]; do - for F in $(findpath "${1}" no "${PATH}"; findpath "${1}" "${RECURSE}" "${BINDIRS}"); do - [ -x "$F" ] && safeperm "$F" || continue - - V="$("$F" -v </dev/null 2>&1 | head -n1 | sed -ne 's/^Lua \([0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')" - : ${V:=0} - V="$((${V%%.*} * 100 + ${V##*.} % 100))" - - [ "${V}" -gt 0 -a "${V}" -ge "${LUAC_VER:-0}" ] || continue + for findluac_G; do + IFS=: + for findluac_D in ${PATH}; do + unset IFS - [ "${V}" -gt "${LUAC_VER:-0}" -o "${#F}" -lt "${#LUAC_PATH}" ] || continue + glob "${findluac_D}/${findluac_G}" 0 tryluac || : - [ "${V}" -ge "${API_MIN}" -a "${V}" -le "${API_MAX}" ] || continue + if foundluac; then + return 0 + fi + done - printf "return true" 2>>/dev/null | ${F} -p - </dev/null >>/dev/null 2>&1 || continue + IFS=: + for findluac_D in ${BINDIRS}; do + unset IFS - LUAC_PATH="$F" - LUAC_VER="$V" + glob "${findluac_D}/${findluac_G}" "${MAXDEPTH}" tryluac || : - [ "${SHORTEST}" = "yes" -o "${LUAC_VER}" -lt "${API_MAX}" ] || break 2 + if foundluac; then + return 0 + fi done - shift + unset IFS done - if [ -n "${LUAC_PATH}" -a -n "${LUAC_VER}" ]; then - return 0 - else - return 1 - fi + [ "${LUAC_VER:-0}" -gt 0 ] && [ "${#LUAC_PATH}" -gt 0 ] } @@ -871,7 +1004,7 @@ isinteger() { checkints() { while [ $# -gt 0 ]; do if ! isinteger "${1}"; then - printf -- "${0##*/}: ${1}: not a number\n" >&2 + warn "%s: not a number" "${1}" return 1 fi @@ -946,6 +1079,54 @@ mmp2num() { } +trylua() { + trylua_F="${1}" + [ -x "${trylua_F}" ] && safeperm "${trylua_F}" || return 0 + + trylua_V="$("${trylua_F}" -e 'print(string.match(_VERSION, [[[%d.]+]]))' </dev/null 2>>/dev/null | head -n1 | sed -ne 's/^\([0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')" + : ${trylua_V:=0} + trylua_V="$((${trylua_V%%.*} * 100 + ${trylua_V##*.} % 100))" + + [ "${trylua_V}" -gt 0 -a "${trylua_V}" -ge "${LUA_VER:-0}" ] || return 0 + + [ "${trylua_V}" -gt "${LUA_VER:-0}" -o "${#trylua_F}" -lt "${#LUA_PATH}" ] || return 0 + + [ "${trylua_V}" -ge "${API_MIN}" -a "${trylua_V}" -le "${API_MAX}" ] || return 0 + + if [ -n "${JIT_REQ}" ]; then + J="$("${trylua_F}" -v </dev/null 2>&1 | head -n1 | sed -ne 's/^LuaJIT \([0123456789][0123456789]*\.[0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')" + J="$(jit2num ${J:-0})" + + if [ "${JIT_REQ}" = "skip" ]; then + [ "${J}" -eq 0 ] || return 0 + elif [ "${JIT_REQ}" = "yes" ]; then + [ "${J}" -gt 0 ] || return 0 + [ "${J}" -ge "${JIT_MIN}" ] || return 0 + [ "${J}" -le "${JIT_MAX}" ] || return 0 + fi + fi + + LUA_PATH="${trylua_F}" + LUA_VER="${trylua_V}" +} + +# +# foundlua +# +# true if found the best (maximum) possible version, false otherwise +# +foundlua() { + if [ "${LUA_VER:-0}" -lt "${API_MAX}" ]; then + return 1 + fi + + if [ "${SHORTEST}" = "yes" ]; then + return 1 + fi + + return 0 +} + findlua() { if [ $# -eq 0 ]; then IFS=: @@ -953,52 +1134,38 @@ findlua() { unset IFS fi - while [ $# -gt 0 ]; do - for F in $(findpath "${1}" no "${PATH}"; findpath "${1}" "${RECURSE}" "${BINDIRS}"); do - [ -x "$F" ] && safeperm "$F" || continue - - V="$("$F" -e 'print(string.match(_VERSION, [[[%d.]+]]))' </dev/null 2>>/dev/null | head -n1 | sed -ne 's/^\([0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')" - : ${V:=0} - V="$((${V%%.*} * 100 + ${V##*.} % 100))" + for findlua_G; do + IFS=: + for findlua_D in ${PATH}; do + unset IFS - [ "${V}" -gt 0 -a "${V}" -ge "${LUA_VER:-0}" ] || continue + glob "${findlua_D}/${findlua_G}" 0 trylua || : - [ "${V}" -gt "${LUA_VER:-0}" -o "${#F}" -lt "${#LUA_PATH}" ] || continue + if foundlua; then + return 0 + fi + done - [ "${V}" -ge "${API_MIN}" -a "${V}" -le "${API_MAX}" ] || continue + IFS=: + for findlua_D in ${BINDIRS}; do + unset IFS - if [ -n "${JIT_REQ}" ]; then - J="$("$F" -v </dev/null 2>&1 | head -n1 | sed -ne 's/^LuaJIT \([0123456789][0123456789]*\.[0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')" - J="$(jit2num ${J:-0})" + glob "${findlua_D}/${findlua_G}" "${MAXDEPTH}" trylua || : - if [ "${JIT_REQ}" = "skip" ]; then - [ "${J}" -eq 0 ] || continue - elif [ "${JIT_REQ}" = "yes" ]; then - [ "${J}" -gt 0 ] || continue - [ "${J}" -ge "${JIT_MIN}" ] || continue - [ "${J}" -le "${JIT_MAX}" ] || continue - fi + if foundlua; then + return 0 fi - - LUA_PATH="$F" - LUA_VER="$V" - - [ "${SHORTEST}" = "yes" -o "${LUA_VER}" -lt "${API_MAX}" ] || break 2 done - shift + unset IFS done - if [ -n "${LUA_PATH}" -a -n "${LUA_VER}" ]; then - return 0 - else - return 1 - fi + [ "${LUA_VER:-0}" -gt 0 ] && [ "${#LUA_PATH}" -gt 0 ] } ccname() { - "${CC}" -E - <<-EOF | awk '/sunpro/||/clang/||/gcc/||/other/{ print $1; exit; }' + runcc -E - <<-EOF | awk '/sunpro/||/clang/||/gcc/||/other/{ print $1; exit; }' #if defined __SUNPRO_C sunpro #elif defined __clang__ @@ -1026,8 +1193,7 @@ usage() { -e GLOB glob pattern for finding utilities (lua, luac, etc) -k query pkg-config if available -r recursively search directories - -m MAXDEPTH limit recursion to MAXDEPTH (only for GNU and BSD find) - -x do not cross device mounts when recursing + -m MAXDEPTH limit recursion to MAXDEPTH -s find shortest pathname, otherwise print first best match -v VERSION require specific Lua version or range (e.g. "5.1" or "5.1-5.2") @@ -1038,8 +1204,10 @@ usage() { -h print this usage message cppflags print derived additional CPPFLAGS necessary + version print derived Lua API version from cppflags discovery ldflags print derived additional LDFLAGS necessary (TODO) - version print derived Lua API version + libs print derived additional LIBS necessary (TODO) + libversion print derived Lua API version from ldflags/libs discovery luac print path to luac utility ($(printf "${GLOB_LUA}" | tr ':' ' ')) lua print path to lua interpreter ($(printf "${GLOB_LUAC}" | tr ':' ' ')) package.path print preferred module install path @@ -1114,20 +1282,21 @@ while getopts I:L:P:d:De:krm:xsv:j:JVh OPT; do RECURSE=yes ;; m) - if [ -n "${OPTARG##[0123456789]}" ]; then - printf -- "${0##*/}: ${OPTARG}: invalid maxdepth\n" >&2 - exit 1 - fi - - if find "${TMPDIR:-/tmp}" -maxdepth ${OPTARG} -prune >>/dev/null 2>&1; then - MAXDEPTH="-maxdepth ${OPTARG}" - else - printf -- "${0##*/}: $(command -v find): -maxdepth unsupported\n" >&2 + if [ "${#OPTARG}" -eq 0 -o -n "${OPTARG##[0123456789]}" ]; then + panic "%s: invalid maxdepth" "${OPTARG}" fi + MAXDEPTH="${OPTARG}" ;; x) - XDEV="-xdev" + # + # NOTE: This option was + # + # -x do not cross device mounts when recursing + # + # but is currently unsupported as our built-in glob function + # does not implement this functionality. Previously this + # option caused -xdev to be added to invocations of find(1). ;; s) SHORTEST=yes @@ -1140,8 +1309,7 @@ while getopts I:L:P:d:De:krm:xsv:j:JVh OPT; do API_MAX="$(lua2num ${MAX:-99} 99)" if [ "${API_MIN}" -gt "${API_MAX}" ]; then - printf -- "${0##*/}: ${OPTARG}: invalid version range\n" >&2 - exit 1 + panic "%s: invalid version range" "${OPTARG}" fi ;; @@ -1153,8 +1321,7 @@ while getopts I:L:P:d:De:krm:xsv:j:JVh OPT; do JIT_MAX="$(jit2num ${MAX:-99} 99 99)" if [ "${JIT_MIN}" -gt "${JIT_MAX}" ]; then - printf -- "${0##*/}: ${OPTARG}: invalid version range\n" >&2 - exit 1 + panic "%s: invalid version range" "${OPTARG}" fi JIT_REQ=yes @@ -1180,10 +1347,16 @@ done shift $(($OPTIND - 1)) -for U in "${CC:-cc}" find grep od rm rmdir sed xargs; do - if ! command -v "${U}" >>/dev/null 2>&1; then - printf -- "${0##*/}: ${U}: command not found\n" >&2 - fi +[ "${RECURSE}" = "yes" ] || MAXDEPTH=0 + + +for U in "${CC}" grep od rm rmdir sed xargs; do + ! command -v "${U}" >>/dev/null 2>&1 || continue + + # ${CC} might have trailing flags or invoke the compiler through env + ! command -v "${U%% *}" >>/dev/null 2>&1 || continue + + warn "%s: command not found" "${U}" done @@ -1191,15 +1364,13 @@ if [ -n "${SANDBOX}" ]; then if [ "${SANDBOX}" = "${SANDBOX%/}" ]; then if [ ! -c "${DEVRANDOM}" ]; then # TODO: expand DEVRANDOM into set of different possibilities to check - printf -- "${0##*/}: ${DEVRANDDOM}: no character random device available\n" >&2 - exit 1 + panic "%s: no character random device available" "${DEVRANDOM}" fi TMP="${SANDBOX}$(od -An -N8 -tx1 < ${DEVRANDOM} 2>>/dev/null | tr -d ' ')" if [ ${#TMP} -ne $((${#SANDBOX} + 16)) ]; then - printf -- "${0##*/}: ${SANDBOX}: unable to generate random suffix\n" >&2 - exit 1 + panic "%s: unable to generate random suffix" "${SANDBOX}" fi SANDBOX="${TMP}" @@ -1241,18 +1412,28 @@ cppflags) [ -z "${API_DIR:-}" ] || printf -- "-I${API_DIR}\n" ;; +version) + findversion || exit 1 + + printf "$(((${API_VER} / 100) % 100)).$((($API_VER) % 100))\n" + + ;; ldflags) findlib [ "${LIBLUA_VER:-0}" -gt 0 ] || exit 1 - printf -- "-L${LIBLUA_DIR} -l${LIBLUA_LIB}\n" + if [ "${#LIBLUA_DIR}" -gt 0 ]; then + printf -- "-L%s\n" "${LIBLUA_DIR}" + fi ;; -version) - findversion || exit 1 +libs) + findlib - printf "$(((${API_VER} / 100) % 100)).$((($API_VER) % 100))\n" + [ "${LIBLUA_VER:-0}" -gt 0 ] || exit 1 + + printf -- "-l%s\n" "${LIBLUA_LIB}" ;; libv*) @@ -1288,21 +1469,38 @@ lua) ;; ldir|cdir) - printf -- "${0##*/}: ${1}: deprecated command\n" >&2 - MODE="${1}" - shift + # + # ldir and cdir were deprecated on 2014-12-18. On 2016-03-25 they + # were revived because their names are more intuitive than + # package.path and package.cpath. For now try to support the + # semantics of both by assuming interpreter glob patterns only match + # file names, while preferred install directory string.match + # expressions have directory components. + # + if true; then + MODE="${1}" + + # move command to end; rotates to ${1} after loop + set -- "$@" "${1}" + shift - if [ $# -gt 0 ]; then - append GLOB $* + cdir_I=0 + cdir_N="$(($# - 1))" + while [ "${cdir_I}" -lt "${cdir_N}" ]; do + if [ "${1#*/}" = "${1}" ]; then + append GLOB "${1}" + warn "%s: passing glob patterns to %s is deprecated" "${1}" "${MODE}" + else + set -- "$@" "${1}" + fi + shift + cdir_I=$((${cdir_I} + 1)) + done fi findlua || exit 1 - if [ "${MODE}" = "cdir" ]; then - findinstalldir package.cpath - else - findinstalldir package.path - fi + findinstalldir "$@" || exit 1 ;; package.path|package.cpath) @@ -1333,9 +1531,9 @@ testsym) ;; *) if [ -n "${1:-}" ]; then - printf -- "${0##*/}: ${1}: unknown command\n" >&2 + warn "%s: unknown command" "${1}" else - printf -- "${0##*/}: no command specified\n" >&2 + warn "no command specified" fi exit 1 diff --git a/regress/00-store-verify.lua b/regress/00-store-verify.lua new file mode 100755 index 0000000..f45ad7e --- /dev/null +++ b/regress/00-store-verify.lua @@ -0,0 +1,19 @@ +#!/usr/bin/env lua + +require"regress".export".*" + +local st = store.new() + +local ca_key, ca_crt = genkey() +st:add(ca_crt) + +local key, crt = genkey("RSA", ca_key, ca_crt) + +local ok, proof_or_reason = st:verify(crt) +check(ok, "%s", proof_or_reason) + +--for _,crt in pairs(proof_or_reason) do +-- print(crt:text()) +--end + +say"OK" diff --git a/regress/53-csr-extensions.lua b/regress/53-csr-extensions.lua new file mode 100644 index 0000000..38346da --- /dev/null +++ b/regress/53-csr-extensions.lua @@ -0,0 +1,168 @@ +local auxlib = require"openssl.auxlib" +local pkey = require "openssl.pkey" +local x509_csr = require"_openssl.x509.csr" +local x509_altname = require"openssl.x509.altname" +local x509_name = require"openssl.x509.name" + +local _basename = arg and arg[0] and arg[0]:match"([^/]+)$" or "UNKNOWN" + +local function cluck(fmt, ...) + io.stderr:write(_basename, ": ", string.format(fmt, ...), "\n") +end + +local function croak(fmt, ...) + io.stderr:write(_basename, ": ", string.format(fmt, ...), "\n") + os.exit(1) +end + +local function OK() + cluck("OK") + return true +end + +local _testno = 0 +local function testnames(altnames, expected) + local matched = {} + + _testno = _testno + 1 + + for type,data in auxlib.pairs(altnames) do + local found + + for i,e in ipairs(expected) do + if not matched[i] and e.type == type and e.data == data then + cluck("expected match #%d.%d found (%s=%s)", _testno, i, type,data) + + matched[i] = true + found = true + end + end + + if not found then + return false, string.format("extra name in test #%d (%s=%s)", _testno, type, data) + end + end + + for i,e in ipairs(expected) do + if not matched[i] then + return false, string.format("expected match #%d.%d not found (%s=%s)", _testno, i, e.type, e.data) + end + end + + return true +end + +local function checknames(altnames, expected) + local ok, why = testnames(altnames, expected) + + if not ok then + croak(why or "UNKNOWN") + end + + return true +end + +key = pkey.new({ bits = 4096 }) + +data = [[ +-----BEGIN CERTIFICATE REQUEST----- +MIIFQjCCAyoCAQAwUzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1OMRQwEgYDVQQH +DAtNaW5uZWFwb2xpczEhMB8GA1UECwwYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVk +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4sXzE3GQtpFKiuGe389k +MB0OaGXQxiI/yl6zm9PyYWe5aMpx1THDVhkWXemDVkduEqtLfa8GSNT0ps3BPdTx +qxNwZ3J9xiVfNZZYO5ZSxs1g32M1lw20wIezLpbQ1ggyt01o9VTQDY6kA+D0G87B +4FtIZxVaXM2z5HVaGYyivxAygDukDsO+RU0NC9mYOfAP4rt/u/xp8LsW0b4aIFqx +gPcBZj92B+Wi2B4sKSe1m5kMfmh+e8v981hbY7V8FUMebB63iRGF6GU4kjXiMMW6 +gSoc+usq9li8VxjxPngql9pyLqFIa/2gW0c9sKKB2X9tB0nmudjAUrjZjHZEDlNr +yx15JHhEIT31yP9xGQpy5H+jBldp/shqaV4Alsou9Hn9W71ap7VHOWLrIcaZGKTn +CVSSYPygn4Rm8Cgwbv5mP6G+SqGHAFqirEysAARUFxsjBLlkNaVFOA38l2cufH8n +1NE/B4iOG/ETvQDR/aKrbyKKo2k/hO941h3J9pwJcCikE0NsRcH6WAm8ifJ0Zd/q +u8fqI8g9mYPbMWy11+njnfNOVFVhNOmM1/ZM66ac9zgGYncaHu4UzYnvWw75tDbF +vA+oIJlcxBUtWeTcYRf4xEcRL8IcHEwh1BZq7bgP42Wu+0aBuaa3eYXNBApCNP39 +QmnHlo0iGH2rVeOfcq/wULcCAwEAAaCBqTCBpgYJKoZIhvcNAQkOMYGYMIGVMAkG +A1UdEwQCMAAwCwYDVR0PBAQDAgXgMHsGA1UdEQR0MHKCE3NlcnZlcjEuZXhhbXBs +ZS5jb22CEG1haWwuZXhhbXBsZS5jb22CD3d3dy5leGFtcGxlLmNvbYITd3d3LnN1 +Yi5leGFtcGxlLmNvbYIObXguZXhhbXBsZS5jb22CE3N1cHBvcnQuZXhhbXBsZS5j +b20wDQYJKoZIhvcNAQEFBQADggIBAMiFPtDKVsy4HBhVkHSnbbIl41baaGGFjI/O +MG8fI7P9jplq5rNZcLxSW2zLzMVuYzCoC+q5roRE5zVVyJlB+5dY0A8e2xKaWVOT +AB9WvgepPvXDoGNViMBoX/idj3J2BU3e/cX08QWRPjKigwQWQWvUGsZYitGJv+Yv +/LbIDlxr8Jr+1Txcm1EdXcff6Owlh6Nu59bgCMRdZvABmWfU5ULmUDTJnmc3P9St +onz07v8ku8/XL7wwOfLJWVSVOk7RONySIJiPfVkgrU3YWiT64JaluDbFEIwnEgJS +04xL6Pl66bADXCaeG3pZ8ypCs41+4bqFvCnOYma0Sk8fv8hSCWvJfMQI+nQslPJu +UuGK4C4EEnYvoh/Qs/XEshfrVaNcG0zER3XtsRPAjhZjTPTcRgEjpOI0w3TJAvlN +LSQV4mXN6E2bcU+cRYvNSgqITwJ7c6wpsONwApIQwFryLsFSCHaIdSLpAZbEPNEW +UPa3uWXk5lWrBBPPkxyPbt8D3zpzahY4ycYEFKdz8MLdgA7pDalI2XpwgmoUybkw +AJnsFg7fnFc03R4FsqxCqvbRYj3Bccb8Uhg1zTeXU+7nxjP2yYdT+In16L9SYOsU +4ozEPqnGY9aI11i6C7hBwrUTvHYD6ZSDlylsUXKw/VZXQvS3+C0h6NuRmjBx8jNU +RG1EyxL4 +-----END CERTIFICATE REQUEST----- +]] + +-- baseline +do + local expected = { + { type = "DNS", data = "server1.example.com" }, + { type = "DNS", data = "mail.example.com" }, + { type = "DNS", data = "www.example.com" }, + { type = "DNS", data = "www.sub.example.com" }, + { type = "DNS", data = "mx.example.com" }, + { type = "DNS", data = "support.example.com" }, + } + + checknames((x509_csr.new(data)):getSubjectAlt(), expected) +end + +-- modifying existing altnames +do + local expected = { + { type = "DNS", data = "foo.com" }, + { type = "DNS", data = "*.foo.com" }, + } + + local csr = x509_csr.new(data) + local gn = x509_altname.new() + gn:add("DNS", "foo.com") + gn:add("DNS", "*.foo.com") + csr:setSubjectAlt(gn) + csr:setPublicKey(key) + csr:sign(key) + + -- check modified object + checknames(csr:getSubjectAlt(), expected) + -- check after a round-trip through PEM + checknames(x509_csr.new(tostring(csr)):getSubjectAlt(), expected) +end + +-- adding altnames where none existed +do + local expected = { + name = { + { type = "CN", data = "example.com" }, + }, + altname = { + { type = "DNS", data = "foo.com" }, + { type = "DNS", data = "*.foo.com" }, + }, + } + + local csr = x509_csr.new() + local name = x509_name.new() + name:add("CN", "example.com") + csr:setSubject(name) + local gn = x509_altname.new() + gn:add("DNS", "foo.com") + gn:add("DNS", "*.foo.com") + csr:setSubjectAlt(gn) + csr:setPublicKey(key) + csr:sign(key) + + checknames(csr:getSubject(), expected.name) + checknames(csr:getSubjectAlt(), expected.altname) + + local csr1 = x509_csr.new(tostring(csr)) + checknames(csr1:getSubject(), expected.name) + checknames(csr1:getSubjectAlt(), expected.altname) +end + +return OK() + diff --git a/regress/regress.lua b/regress/regress.lua new file mode 100644 index 0000000..8d955ea --- /dev/null +++ b/regress/regress.lua @@ -0,0 +1,161 @@ +local regress = { + openssl = require"openssl", + pkey = require"openssl.pkey", + x509 = require"openssl.x509", + name = require"openssl.x509.name", + altname = require"openssl.x509.altname", + store = require"openssl.x509.store", + pack = table.pack or function (...) + local t = { ... } + t.n = select("#", ...) + return t + end, + unpack = table.unpack or unpack, +} + +local emit_progname = os.getenv"REGRESS_PROGNAME" or "regress" +local emit_verbose = tonumber(os.getenv"REGRESS_VERBOSE" or 1) +local emit_info = {} +local emit_ll = 0 + +local function emit(fmt, ...) + local msg = string.format(fmt, ...) + + for txt, nl in msg:gmatch("([^\n]*)(\n?)") do + if emit_ll == 0 and #txt > 0 then + io.stderr:write(emit_progname, ": ") + emit_ll = #emit_progname + 2 + end + + io.stderr:write(txt, nl) + + if nl == "\n" then + emit_ll = 0 + else + emit_ll = emit_ll + #txt + end + end +end -- emit + +local function emitln(fmt, ...) + if emit_ll > 0 then + emit"\n" + end + + emit(fmt .. "\n", ...) +end -- emitln + +local function emitinfo() + for _, txt in ipairs(emit_info) do + emitln("%s", txt) + end +end -- emitinfo + +function regress.say(...) + emitln(...) +end -- say + +function regress.panic(...) + emitinfo() + emitln(...) + os.exit(1) +end -- panic + +function regress.info(...) + if emit_verbose > 1 then + emitln(...) + else + emit_info[#emit_info + 1] = string.format(...) + + if emit_verbose > 0 then + if emit_ll > 78 then + emit"\n." + else + emit"." + end + end + end +end -- info + +function regress.check(v, ...) + if v then + return v, ... + else + regress.panic(...) + end +end -- check + +function regress.export(...) + for _, pat in ipairs{ ... } do + for k, v in pairs(regress) do + if string.match(k, pat) then + _G[k] = v + end + end + end + + return regress +end -- export + +local counter = 0 +function regress.genkey(type, ca_key, ca_crt) + local pkey = require"openssl.pkey" + local x509 = require"openssl.x509" + local name = require"openssl.x509.name" + local altname = require"openssl.x509.altname" + local key + + type = string.upper(type or "RSA") + + if type == "EC" then + key = regress.check(pkey.new{ type = "EC", curve = "prime192v1" }) + else + key = regress.check(pkey.new{ type = type, bits = 1024 }) + end + + local dn = name.new() + dn:add("C", "US") + dn:add("ST", "California") + dn:add("L", "San Francisco") + dn:add("O", "Acme, Inc.") + dn:add("CN", string.format("acme%d.inc", counter)) + counter = counter + 1 + + local alt = altname.new() + alt:add("DNS", "acme.inc") + alt:add("DNS", "localhost") + + local crt = x509.new() + crt:setVersion(3) + crt:setSerial(47) + crt:setSubject(dn) + crt:setIssuer((ca_crt or crt):getSubject()) + crt:setSubjectAlt(alt) + + local issued, expires = crt:getLifetime() + crt:setLifetime(issued, expires + 60) + + crt:setBasicConstraints{ CA = true, pathLen = 2 } + crt:setBasicConstraintsCritical(true) + + crt:setPublicKey(key) + crt:sign(ca_key or key) + + return key, crt +end -- regress.genkey + +local function getsubtable(t, name, ...) + name = name or false -- cannot be nil + + if not t[name] then + t[name] = {} + end + + if select('#', ...) > 0 then + return getsubtable(t[name], ...) + else + return t[name] + end +end -- getsubtable + +return regress diff --git a/src/GNUmakefile b/src/GNUmakefile index 3aff30a..e7cb54d 100644 --- a/src/GNUmakefile +++ b/src/GNUmakefile @@ -18,9 +18,9 @@ include $(d)/../GNUmakefile # OS_$(d) = $(shell $(d)/../mk/vendor.os) CC_$(d) = $(shell env CC="$(CC) "$(d)/../mk/vendor.cc) -LUAPATH_$(d) = $(shell env CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" $(<D)/../mk/lua.path -krxm3 -I$(DESTDIR)$(includedir) -I/usr/include -I/usr/local/include -P$(DESTDIR)$(bindir) -P$(bindir) -L$(DESTDIR)$(libdir) -L$(libdir) -v$(1) $(2)) +LUAPATH_$(d) = $(shell env CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" $(<D)/../mk/luapath -krxm3 -I$(DESTDIR)$(includedir) -I/usr/include -I/usr/local/include -P$(DESTDIR)$(bindir) -P$(bindir) -L$(DESTDIR)$(libdir) -L$(libdir) -v$(1) $(2)) -CPPFLAGS_$(d) = $(CPPFLAGS_$(abspath $(@D)/../..)) -DLUA_COMPAT_APIINTCASTS +CPPFLAGS_$(d) = $(CPPFLAGS_$(abspath $(@D)/../..)) -DLUA_COMPAT_APIINTCASTS -DHAVE_CONFIG_H CFLAGS_$(d) = $(CFLAGS_$(abspath $(@D)/../..)) LDFLAGS_$(d) = $(LDFLAGS_$(abspath $(@D)/../..)) SOFLAGS_$(d) = $(SOFLAGS_$(abspath $(@D)/../..)) @@ -41,6 +41,8 @@ endif # # C O M P I L A T I O N R U L E S # +$(d)/config.h: $(abspath $(d)/..)/config.h + $(CP) $< $@ define BUILD_$(d) @@ -49,7 +51,7 @@ define BUILD_$(d) $$(d)/$(1)/openssl.so: $$(d)/$(1)/openssl.o $$(CC) -o $$@ $$^ $$(SOFLAGS_$$(abspath $$(@D)/..)) $$(SOFLAGS) $$(LDFLAGS_$$(abspath $$(@D)/..)) $$(LDFLAGS) -$$(d)/$(1)/openssl.o: $$(d)/openssl.c $$(d)/compat52.h +$$(d)/$(1)/openssl.o: $$(d)/openssl.c $$(d)/compat52.h $$(d)/config.h test "$$(notdir $$(@D))" = "$$(call LUAPATH_$$(<D), $$(notdir $$(@D)), version)" $$(MKDIR) -p $$(@D) $$(CC) $$(CFLAGS_$$(<D)) $$(CFLAGS) $$(call LUAPATH_$$(<D), $$(notdir $$(@D)), cppflags) $$(CPPFLAGS_$$(<D)) $$(CPPFLAGS) -c -o $$@ $$< @@ -88,6 +90,7 @@ LUAC$(1)_$(d) = $$(or $$(call LUAPATH_$(d), $(1), luac), true) MODS$(1)_$(d) = \ $$(DESTDIR)$(2)/_openssl.so \ $$(DESTDIR)$(3)/openssl.lua \ + $$(DESTDIR)$(3)/openssl/auxlib.lua \ $$(DESTDIR)$(3)/openssl/bignum.lua \ $$(DESTDIR)$(3)/openssl/pkey.lua \ $$(DESTDIR)$(3)/openssl/pubkey.lua \ diff --git a/src/openssl.auxlib.lua b/src/openssl.auxlib.lua new file mode 100644 index 0000000..4f00c25 --- /dev/null +++ b/src/openssl.auxlib.lua @@ -0,0 +1,21 @@ +local auxlib = {} + +if _VERSION == "Lua 5.1" then + local _pairs = pairs + + function auxlib.pairs(t) + if type(t) == "userdata" then + local mt = getmetatable(t) + + if mt and mt.__pairs then + return mt.__pairs(t) + else + return _pairs(t) + end + end + end +else + auxlib.pairs = pairs +end + +return auxlib diff --git a/src/openssl.c b/src/openssl.c index 2275d49..ed7222e 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -23,6 +23,10 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. * ========================================================================== */ +#if HAVE_CONFIG_H +#include "config.h" +#endif + #include <limits.h> /* INT_MAX INT_MIN LLONG_MAX LLONG_MIN UCHAR_MAX ULLONG_MAX */ #include <stdint.h> /* uintptr_t */ #include <string.h> /* memset(3) strerror_r(3) */ @@ -79,24 +83,40 @@ #define LIBRESSL_PREREQ(M, m, p) \ (LIBRESSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12))) -#ifndef HAVE_DLADDR -#define HAVE_DLADDR (!defined _AIX) /* TODO: https://root.cern.ch/drupal/content/aix-and-dladdr */ +#ifndef HAVE_ASN1_STRING_GET0_DATA +#define HAVE_ASN1_STRING_GET0_DATA OPENSSL_PREREQ(1,1,0) #endif -#ifndef HAVE_SSL_CTX_SET_ALPN_PROTOS -#define HAVE_SSL_CTX_SET_ALPN_PROTOS OPENSSL_PREREQ(1, 0, 2) +#ifndef HAVE_DH_GET0_KEY +#define HAVE_DH_GET0_KEY OPENSSL_PREREQ(1,1,0) #endif -#ifndef HAVE_SSL_CTX_SET_ALPN_SELECT_CB -#define HAVE_SSL_CTX_SET_ALPN_SELECT_CB HAVE_SSL_CTX_SET_ALPN_PROTOS +#ifndef HAVE_DH_GET0_PQG +#define HAVE_DH_GET0_PQG OPENSSL_PREREQ(1,1,0) #endif -#ifndef HAVE_SSL_SET_ALPN_PROTOS -#define HAVE_SSL_SET_ALPN_PROTOS HAVE_SSL_CTX_SET_ALPN_PROTOS +#ifndef HAVE_DH_SET0_KEY +#define HAVE_DH_SET0_KEY OPENSSL_PREREQ(1,1,0) #endif -#ifndef HAVE_SSL_GET0_ALPN_SELECTED -#define HAVE_SSL_GET0_ALPN_SELECTED HAVE_SSL_CTX_SET_ALPN_PROTOS +#ifndef HAVE_DH_SET0_PQG +#define HAVE_DH_SET0_PQG OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_DSA_GET0_KEY +#define HAVE_DSA_GET0_KEY OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_DSA_GET0_PQG +#define HAVE_DSA_GET0_PQG OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_DSA_SET0_KEY +#define HAVE_DSA_SET0_KEY OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_DSA_SET0_PQG +#define HAVE_DSA_SET0_PQG OPENSSL_PREREQ(1,1,0) #endif #ifndef HAVE_DTLSV1_CLIENT_METHOD @@ -108,7 +128,7 @@ #endif #ifndef HAVE_DTLS_CLIENT_METHOD -#define HAVE_DTLS_CLIENT_METHOD (OPENSSL_PREREQ(1, 0, 2) && !defined OPENSSL_NO_DTLS1) +#define HAVE_DTLS_CLIENT_METHOD (OPENSSL_PREREQ(1,0,2) && !defined OPENSSL_NO_DTLS1) #endif #ifndef HAVE_DTLS_SERVER_METHOD @@ -116,13 +136,133 @@ #endif #ifndef HAVE_DTLSV1_2_CLIENT_METHOD -#define HAVE_DTLSV1_2_CLIENT_METHOD (OPENSSL_PREREQ(1, 0, 2) && !defined OPENSSL_NO_DTLS1) +#define HAVE_DTLSV1_2_CLIENT_METHOD (OPENSSL_PREREQ(1,0,2) && !defined OPENSSL_NO_DTLS1) #endif #ifndef HAVE_DTLSV1_2_SERVER_METHOD #define HAVE_DTLSV1_2_SERVER_METHOD HAVE_DTLSV1_2_CLIENT_METHOD #endif +#ifndef HAVE_EVP_CIPHER_CTX_FREE +#define HAVE_EVP_CIPHER_CTX_FREE OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_EVP_CIPHER_CTX_NEW +#define HAVE_EVP_CIPHER_CTX_NEW OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_EVP_MD_CTX_FREE +#define HAVE_EVP_MD_CTX_FREE OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_EVP_MD_CTX_NEW +#define HAVE_EVP_MD_CTX_NEW OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_EVP_PKEY_GET_DEFAULT_DIGEST_NID +#define HAVE_EVP_PKEY_GET_DEFAULT_DIGEST_NID OPENSSL_PREREQ(0,9,9) +#endif + +#ifndef HAVE_EVP_PKEY_BASE_ID +#define HAVE_EVP_PKEY_BASE_ID OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_EVP_PKEY_GET0 +#define HAVE_EVP_PKEY_GET0 OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_EVP_PKEY_ID +#define HAVE_EVP_PKEY_ID OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_HMAC_CTX_FREE +#define HAVE_HMAC_CTX_FREE OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_HMAC_CTX_NEW +#define HAVE_HMAC_CTX_NEW OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_I2D_RE_X509_REQ_TBS +#define HAVE_I2D_RE_X509_REQ_TBS OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_RSA_GET0_CRT_PARAMS +#define HAVE_RSA_GET0_CRT_PARAMS OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_RSA_GET0_FACTORS +#define HAVE_RSA_GET0_FACTORS OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_RSA_GET0_KEY +#define HAVE_RSA_GET0_KEY OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_RSA_SET0_CRT_PARAMS +#define HAVE_RSA_SET0_CRT_PARAMS OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_RSA_SET0_FACTORS +#define HAVE_RSA_SET0_FACTORS OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_RSA_SET0_KEY +#define HAVE_RSA_SET0_KEY OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_SSL_CLIENT_VERSION +#define HAVE_SSL_CLIENT_VERSION OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_SSL_CTX_SET_ALPN_PROTOS +#define HAVE_SSL_CTX_SET_ALPN_PROTOS (OPENSSL_PREREQ(1,0,2) || LIBRESSL_PREREQ(2,1,3)) +#endif + +#ifndef HAVE_SSL_CTX_SET_ALPN_SELECT_CB +#define HAVE_SSL_CTX_SET_ALPN_SELECT_CB HAVE_SSL_CTX_SET_ALPN_PROTOS +#endif + +#ifndef HAVE_SSL_CTX_SET1_CERT_STORE +#define HAVE_SSL_CTX_SET1_CERT_STORE (HAVE_SSL_CTX_set1_cert_store || 0) /* backwards compatible with old macro name */ +#endif + +#ifndef HAVE_SSL_CTX_CERT_STORE +#define HAVE_SSL_CTX_CERT_STORE (!OPENSSL_PREREQ(1,1,0)) +#endif + +#ifndef HAVE_SSL_SET_ALPN_PROTOS +#define HAVE_SSL_SET_ALPN_PROTOS HAVE_SSL_CTX_SET_ALPN_PROTOS +#endif + +#ifndef HAVE_SSL_GET0_ALPN_SELECTED +#define HAVE_SSL_GET0_ALPN_SELECTED HAVE_SSL_CTX_SET_ALPN_PROTOS +#endif + +#ifndef HAVE_SSL_UP_REF +#define HAVE_SSL_UP_REF OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_SSLV2_CLIENT_METHOD +#define HAVE_SSLV2_CLIENT_METHOD (!OPENSSL_PREREQ(1,1,0) && !defined OPENSSL_NO_SSL2) +#endif + +#ifndef HAVE_SSLV2_SERVER_METHOD +#define HAVE_SSLV2_SERVER_METHOD (!OPENSSL_PREREQ(1,1,0) && !defined OPENSSL_NO_SSL2) +#endif + +#ifndef HAVE_X509_STORE_REFERENCES +#define HAVE_X509_STORE_REFERENCES (!OPENSSL_PREREQ(1,1,0)) +#endif + +#ifndef HAVE_X509_UP_REF +#define HAVE_X509_UP_REF OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HMAC_INIT_EX_INT +#define HMAC_INIT_EX_INT OPENSSL_PREREQ(1,0,0) +#endif + #ifndef STRERROR_R_CHAR_P #define STRERROR_R_CHAR_P (defined __GLIBC__ && (_GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600))) #endif @@ -161,9 +301,9 @@ #define PKCS12_CLASS "PKCS12*" #define SSL_CTX_CLASS "SSL_CTX*" #define SSL_CLASS "SSL*" -#define DIGEST_CLASS "EVP_MD_CTX" /* not a pointer */ -#define HMAC_CLASS "HMAC_CTX" /* not a pointer */ -#define CIPHER_CLASS "EVP_CIPHER_CTX" /* not a pointer */ +#define DIGEST_CLASS "EVP_MD_CTX*" +#define HMAC_CLASS "HMAC_CTX*" +#define CIPHER_CLASS "EVP_CIPHER_CTX*" #if __GNUC__ @@ -488,6 +628,13 @@ static const char *aux_strerror_r(int error, char *dst, size_t lim) { * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +static void auxS_bn_free_and_set0(BIGNUM **dst, BIGNUM *src) { + if (*dst) { + BN_clear_free(*dst); + } + *dst = src; +} /* auxS_bn_free_and_set0() */ + static size_t auxS_nid2sn(void *dst, size_t lim, int nid) { const char *sn; @@ -1021,14 +1168,173 @@ static struct { .X509_STORE_free = &X509_STORE_free, }; +#if !HAVE_ASN1_STRING_GET0_DATA +#define ASN1_STRING_get0_data(s) ASN1_STRING_data((s)) +#endif + +#if !HAVE_DH_GET0_KEY +#define DH_get0_key(...) compat_DH_get0_key(__VA_ARGS__) + +static void compat_DH_get0_key(const DH *d, const BIGNUM **pub_key, const BIGNUM **priv_key) { + if (pub_key) + *pub_key = d->pub_key; + if (priv_key) + *priv_key = d->priv_key; +} /* compat_DH_get0_key() */ +#endif + +#if !HAVE_DH_GET0_PQG +#define DH_get0_pqg(...) compat_DH_get0_pqg(__VA_ARGS__) + +static void compat_DH_get0_pqg(const DH *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { + if (p) + *p = d->p; + if (q) + *q = d->q; + if (g) + *g = d->g; +} /* compat_DH_get0_pqg() */ +#endif + +#if !HAVE_DH_SET0_KEY +#define DH_set0_key(...) compat_DH_set0_key(__VA_ARGS__) + +static void compat_DH_set0_key(DH *d, BIGNUM *pub_key, BIGNUM *priv_key) { + if (pub_key) + auxS_bn_free_and_set0(&d->pub_key, pub_key); + if (priv_key) + auxS_bn_free_and_set0(&d->priv_key, priv_key); +} /* compat_DH_set0_key() */ +#endif + +#if !HAVE_DH_SET0_PQG +#define DH_set0_pqg(...) compat_DH_set0_pqg(__VA_ARGS__) + +static void compat_DH_set0_pqg(DH *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) { + if (p) + auxS_bn_free_and_set0(&d->p, p); + if (q) + auxS_bn_free_and_set0(&d->q, q); + if (g) + auxS_bn_free_and_set0(&d->g, g); +} /* compat_DH_set0_pqg() */ +#endif + +#if !HAVE_DSA_GET0_KEY +#define DSA_get0_key(...) compat_DSA_get0_key(__VA_ARGS__) + +static void compat_DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) { + if (pub_key) + *pub_key = d->pub_key; + if (priv_key) + *priv_key = d->priv_key; +} /* compat_DSA_get0_key() */ +#endif + +#if !HAVE_DSA_GET0_PQG +#define DSA_get0_pqg(...) compat_DSA_get0_pqg(__VA_ARGS__) + +static void compat_DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { + if (p) + *p = d->p; + if (q) + *q = d->q; + if (g) + *g = d->g; +} /* compat_DSA_get0_pqg() */ +#endif + +#if !HAVE_DSA_SET0_KEY +#define DSA_set0_key(...) compat_DSA_set0_key(__VA_ARGS__) + +static void compat_DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) { + if (pub_key) + auxS_bn_free_and_set0(&d->pub_key, pub_key); + if (priv_key) + auxS_bn_free_and_set0(&d->priv_key, priv_key); +} /* compat_DSA_set0_key() */ +#endif + +#if !HAVE_DSA_SET0_PQG +#define DSA_set0_pqg(...) compat_DSA_set0_pqg(__VA_ARGS__) + +static void compat_DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) { + if (p) + auxS_bn_free_and_set0(&d->p, p); + if (q) + auxS_bn_free_and_set0(&d->q, q); + if (g) + auxS_bn_free_and_set0(&d->g, g); +} /* compat_DSA_set0_pqg() */ +#endif + +#if !HAVE_EVP_CIPHER_CTX_FREE +#define EVP_CIPHER_CTX_free(ctx) compat_EVP_CIPHER_CTX_free((ctx)) + +static void compat_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) { + EVP_CIPHER_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} /* compat_EVP_CIPHER_CTX_free() */ +#endif + +#if !HAVE_EVP_CIPHER_CTX_NEW +#define EVP_CIPHER_CTX_new() compat_EVP_CIPHER_CTX_new() + +static EVP_CIPHER_CTX *compat_EVP_CIPHER_CTX_new(void) { + EVP_CIPHER_CTX *ctx; + + if (!(ctx = OPENSSL_malloc(sizeof *ctx))) + return NULL; + memset(ctx, 0, sizeof *ctx); + EVP_CIPHER_CTX_init(ctx); + + return ctx; +} /* compat_EVP_CIPHER_CTX_new() */ +#endif + +#if !HAVE_EVP_MD_CTX_FREE +#define EVP_MD_CTX_free(md) EVP_MD_CTX_destroy((md)) +#endif + +#if !HAVE_EVP_MD_CTX_NEW +#define EVP_MD_CTX_new(md) EVP_MD_CTX_create() +#endif + +#if !HAVE_EVP_PKEY_ID +#define EVP_PKEY_id(key) ((key)->type) +#endif + #if !HAVE_EVP_PKEY_BASE_ID #define EVP_PKEY_base_id(key) compat_EVP_PKEY_base_id((key)) static int compat_EVP_PKEY_base_id(EVP_PKEY *key) { - return EVP_PKEY_type(key->type); + return EVP_PKEY_type(EVP_PKEY_id(key)); } /* compat_EVP_PKEY_base_id() */ #endif +#if !HAVE_EVP_PKEY_GET_DEFAULT_DIGEST_NID +#define EVP_PKEY_get_default_digest_nid(...) \ + compat_EVP_PKEY_get_default_digest_nid(__VA_ARGS__) + +static int compat_EVP_PKEY_get_default_digest_nid(EVP_PKEY *key, int *nid) { + switch (EVP_PKEY_base_id(key)) { + case EVP_PKEY_RSA: + *nid = EVP_MD_nid(EVP_sha1()); + break; + case EVP_PKEY_DSA: + *nid = EVP_MD_nid(EVP_dss1()); + break; + case EVP_PKEY_EC: + *nid = EVP_MD_nid(EVP_ecdsa()); + break; + default: + *nid = EVP_MD_nid(EVP_sha1()); + break; + } + + return 1; +} /* compat_EVP_PKEY_get_default_digest_nid() */ +#endif #if !HAVE_EVP_PKEY_GET0 #define EVP_PKEY_get0(key) compat_EVP_PKEY_get0((key)) @@ -1065,6 +1371,123 @@ static void *compat_EVP_PKEY_get0(EVP_PKEY *key) { } /* compat_EVP_PKEY_get0() */ #endif +#if !HAVE_HMAC_CTX_FREE +#define HMAC_CTX_free(ctx) compat_HMAC_CTX_free((ctx)) + +static void compat_HMAC_CTX_free(HMAC_CTX *ctx) { + HMAC_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} /* compat_HMAC_CTX_free() */ +#endif + +#if !HAVE_HMAC_CTX_NEW +#define HMAC_CTX_new() compat_HMAC_CTX_new() + +static HMAC_CTX *compat_HMAC_CTX_new(void) { + HMAC_CTX *ctx; + + if (!(ctx = OPENSSL_malloc(sizeof *ctx))) + return NULL; + memset(ctx, 0, sizeof *ctx); + + return ctx; +} /* compat_HMAC_CTX_new() */ +#endif + +#if !HAVE_RSA_GET0_CRT_PARAMS +#define RSA_get0_crt_params(...) compat_RSA_get0_crt_params(__VA_ARGS__) + +static void compat_RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp) { + if (dmp1) + *dmp1 = r->dmp1; + if (dmq1) + *dmq1 = r->dmq1; + if (iqmp) + *iqmp = r->iqmp; +} /* compat_RSA_get0_crt_params() */ +#endif + +#if !HAVE_RSA_GET0_FACTORS +#define RSA_get0_factors(...) compat_RSA_get0_factors(__VA_ARGS__) + +static void compat_RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) { + if (p) + *p = r->p; + if (q) + *q = r->q; +} /* compat_RSA_get0_factors() */ +#endif + +#if !HAVE_RSA_GET0_KEY +#define RSA_get0_key(...) compat_RSA_get0_key(__VA_ARGS__) + +static void compat_RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { + if (n) + *n = r->n; + if (e) + *e = r->e; + if (d) + *d = r->d; +} /* compat_RSA_get0_key() */ +#endif + +#if !HAVE_RSA_SET0_CRT_PARAMS +#define RSA_set0_crt_params(...) compat_RSA_set0_crt_params(__VA_ARGS__) + +static void compat_RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) { + if (dmp1) + auxS_bn_free_and_set0(&r->dmp1, dmp1); + if (dmq1) + auxS_bn_free_and_set0(&r->dmq1, dmq1); + if (iqmp) + auxS_bn_free_and_set0(&r->iqmp, iqmp); +} /* compat_RSA_set0_crt_params() */ +#endif + +#if !HAVE_RSA_SET0_FACTORS +#define RSA_set0_factors(...) compat_RSA_set0_factors(__VA_ARGS__) + +static void compat_RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) { + if (p) + auxS_bn_free_and_set0(&r->p, p); + if (q) + auxS_bn_free_and_set0(&r->q, q); +} /* compat_RSA_set0_factors() */ +#endif + +#if !HAVE_RSA_SET0_KEY +#define RSA_set0_key(...) compat_RSA_set0_key(__VA_ARGS__) + +static void compat_RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { + if (n) + auxS_bn_free_and_set0(&r->n, n); + if (e) + auxS_bn_free_and_set0(&r->e, e); + if (d) + auxS_bn_free_and_set0(&r->d, d); +} /* compat_RSA_set0_key() */ +#endif + +#if !HAVE_SSL_CLIENT_VERSION +#define SSL_client_version(...) compat_SSL_client_version(__VA_ARGS__) + +static int compat_SSL_client_version(const SSL *ssl) { + return ssl->client_version; +} /* compat_SSL_client_version() */ +#endif + +#if !HAVE_SSL_UP_REF +#define SSL_up_ref(...) compat_SSL_up_ref(__VA_ARGS__) + +static int compat_SSL_up_ref(SSL *ssl) { + /* our caller should already have had a proper reference */ + if (CRYPTO_add(&ssl->references, 1, CRYPTO_LOCK_SSL) < 2) + return 0; /* fail */ + + return 1; +} /* compat_SSL_up_ref() */ +#endif + #if !HAVE_X509_GET0_EXT #define X509_get0_ext(crt, i) X509_get_ext((crt), (i)) #endif @@ -1081,13 +1504,18 @@ static void *compat_EVP_PKEY_get0(EVP_PKEY *key) { #define X509_EXTENSION_get0_data(ext) X509_EXTENSION_get_data((ext)) #endif +#if HAVE_X509_STORE_REFERENCES /* * X509_STORE_free in OpenSSL versions < 1.0.2 doesn't obey reference count */ #define X509_STORE_free(store) \ (compat.X509_STORE_free)((store)) -static void compat_X509_STORE_free(X509_STORE *store) { +/* to support preprocessor detection below */ +#define compat_X509_STORE_free(store) \ + compat_X509_STORE_free((store)) + +static void (compat_X509_STORE_free)(X509_STORE *store) { int i; i = CRYPTO_add(&store->references, -1, CRYPTO_LOCK_X509_STORE); @@ -1097,12 +1525,21 @@ static void compat_X509_STORE_free(X509_STORE *store) { (X509_STORE_free)(store); } /* compat_X509_STORE_free() */ +#endif -#if !HAVE_SSL_CTX_set1_cert_store +#if !HAVE_SSL_CTX_SET1_CERT_STORE +#if !HAVE_SSL_CTX_CERT_STORE || !HAVE_X509_STORE_REFERENCES #define SSL_CTX_set1_cert_store(ctx, store) \ + SSL_CTX_set_cert_store((ctx), (store)) +#else +#define SSL_CTX_set1_cert_store(ctx, store) \ + compat_SSL_CTX_set1_cert_store((ctx), (store)) + +/* to support preprocessor detection below */ +#define compat_SSL_CTX_set1_cert_store(ctx, store) \ compat_SSL_CTX_set1_cert_store((ctx), (store)) -static void compat_SSL_CTX_set1_cert_store(SSL_CTX *ctx, X509_STORE *store) { +static void (compat_SSL_CTX_set1_cert_store)(SSL_CTX *ctx, X509_STORE *store) { int n; /* @@ -1122,6 +1559,9 @@ static void compat_SSL_CTX_set1_cert_store(SSL_CTX *ctx, X509_STORE *store) { CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE); } /* compat_SSL_CTX_set1_cert_store() */ #endif +#endif + +#if HAVE_SSL_CTX_CERT_STORE static void compat_init_SSL_CTX_onfree(void *_ctx, void *data NOTUSED, CRYPTO_EX_DATA *ad NOTUSED, int idx NOTUSED, long argl NOTUSED, void *argp NOTUSED) { SSL_CTX *ctx = _ctx; @@ -1132,6 +1572,8 @@ static void compat_init_SSL_CTX_onfree(void *_ctx, void *data NOTUSED, CRYPTO_EX } } /* compat_init_SSL_CTX_onfree() */ +#endif + /* helper routine to determine if X509_STORE_free obeys reference count */ static void compat_init_X509_STORE_onfree(void *store, void *data NOTUSED, CRYPTO_EX_DATA *ad NOTUSED, int idx NOTUSED, long argl NOTUSED, void *argp NOTUSED) { /* unfortunately there's no way to remove a handler */ @@ -1142,6 +1584,18 @@ static void compat_init_X509_STORE_onfree(void *store, void *data NOTUSED, CRYPT compat.tmp.store = NULL; } /* compat_init_X509_STORE_onfree() */ +#if !HAVE_X509_UP_REF +#define X509_up_ref(...) compat_X509_up_ref(__VA_ARGS__) + +static int compat_X509_up_ref(X509 *crt) { + /* our caller should already have had a proper reference */ + if (CRYPTO_add(&crt->references, 1, CRYPTO_LOCK_X509) < 2) + return 0; /* fail */ + + return 1; +} /* compat_X509_up_ref() */ +#endif + static int compat_init(void) { static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static int store_index = -1, ssl_ctx_index = -1, done; @@ -1161,6 +1615,7 @@ static int compat_init(void) { if ((error = dl_anchor())) goto epilog; +#if defined compat_X509_STORE_free /* * Test if X509_STORE_free obeys reference counts by installing an * onfree callback. @@ -1210,6 +1665,7 @@ static int compat_init(void) { compat.flags |= COMPAT_X509_STORE_FREE_BUG; } +#endif done = 1; epilog: @@ -1262,7 +1718,13 @@ static struct ex_type { [EX_SSL_CTX_ALPN_SELECT_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data }, }; -static int ex_ondup(CRYPTO_EX_DATA *to NOTUSED, CRYPTO_EX_DATA *from NOTUSED, void *from_d, int idx NOTUSED, long argl NOTUSED, void *argp NOTUSED) { +#if OPENSSL_PREREQ(1,1,0) +typedef const CRYPTO_EX_DATA const_CRYPTO_EX_DATA; +#else +typedef CRYPTO_EX_DATA const_CRYPTO_EX_DATA; +#endif + +static int ex_ondup(CRYPTO_EX_DATA *to NOTUSED, const_CRYPTO_EX_DATA *from NOTUSED, void *from_d, int idx NOTUSED, long argl NOTUSED, void *argp NOTUSED) { struct ex_data **data = from_d; if (*data) @@ -1861,13 +2323,13 @@ static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) { if (hex) { luaL_argcheck(L, len > 2+(size_t)neg, index, "invalid hex string"); for (i = 2+neg; i < len; i++) { - if (!isxdigit(str[i])) + if (!isxdigit((unsigned char)str[i])) luaL_argerror(L, 1, "invalid hex string"); } } else { luaL_argcheck(L, len > neg, index, "invalid decimal string"); for (i = neg; i < len; i++) { - if (!isdigit(str[i])) + if (!isdigit((unsigned char)str[i])) luaL_argerror(L, 1, "invalid decimal string"); } } @@ -2644,7 +3106,7 @@ static int pk_interpose(lua_State *L) { static int pk_type(lua_State *L) { EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS); - int nid = key->type; + int nid = EVP_PKEY_id(key); auxL_pushnid(L, nid); @@ -2718,7 +3180,7 @@ static int pk_setPrivateKey(lua_State *L) { static int pk_sign(lua_State *L) { EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS); - EVP_MD_CTX *md = luaL_checkudata(L, 2, DIGEST_CLASS); + EVP_MD_CTX *md = checksimple(L, 2, DIGEST_CLASS); luaL_Buffer B; unsigned n; @@ -2742,7 +3204,7 @@ static int pk_verify(lua_State *L) { EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS); size_t len; const void *sig = luaL_checklstring(L, 2, &len); - EVP_MD_CTX *md = luaL_checkudata(L, 3, DIGEST_CLASS); + EVP_MD_CTX *md = checksimple(L, 3, DIGEST_CLASS); switch (EVP_VerifyFinal(md, sig, len, key)) { case 0: /* WRONG */ @@ -2806,7 +3268,7 @@ static int pk_toPEM(lua_State *L) { #if 0 case 4: case 5: /* params, Parameters */ /* EVP_PKEY_base_id not in OS X */ - switch (EVP_PKEY_type(key->type)) { + switch (EVP_PKEY_base_id(key)) { case EVP_PKEY_RSA: break; case EVP_PKEY_DSA: { @@ -2849,7 +3311,7 @@ static int pk_toPEM(lua_State *L) { } #endif default: - return luaL_error(L, "%d: unsupported EVP_PKEY base type", EVP_PKEY_type(key->type)); + return luaL_error(L, "%d: unsupported EVP_PKEY base type", EVP_PKEY_base_id(key)); } lua_pushlstring(L, pem, len); @@ -2869,6 +3331,26 @@ static int pk_toPEM(lua_State *L) { } /* pk_toPEM() */ +static int pk_getDefaultDigestName(lua_State *L) { + EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS); + int nid; + char txt[256]; + size_t len; + + if (!(EVP_PKEY_get_default_digest_nid(key, &nid) > 0)) + return auxL_error(L, auxL_EOPENSSL, "pkey:getDefaultDigestName"); + + if (!(len = auxS_nid2txt(txt, sizeof txt, nid))) + return auxL_error(L, auxL_EOPENSSL, "pkey:getDefaultDigestName"); + if (len > sizeof txt) + return auxL_error(L, EOVERFLOW, "pkey:getDefaultDigestName"); + + lua_pushlstring(L, txt, len); + + return 1; +} /* pk_getDefaultDigestName() */ + + enum pk_param { #define PK_RSA_OPTLIST { "n", "e", "d", "p", "q", "dmp1", "dmq1", "iqmp", NULL } #define PK_RSA_OPTOFFSET PK_RSA_N @@ -2965,82 +3447,100 @@ static void pk_pushparam(lua_State *L, void *base_key, enum pk_param which) { EC_KEY *ec; #endif } key = { base_key }; + const BIGNUM *i; switch (which) { case PK_RSA_N: /* RSA public modulus n */ - bn_dup_nil(L, key.rsa->n); + RSA_get0_key(key.rsa, &i, NULL, NULL); + bn_dup_nil(L, i); break; case PK_RSA_E: /* RSA public exponent e */ - bn_dup_nil(L, key.rsa->e); + RSA_get0_key(key.rsa, NULL, &i, NULL); + bn_dup_nil(L, i); break; case PK_RSA_D: /* RSA secret exponent d */ - bn_dup_nil(L, key.rsa->d); + RSA_get0_key(key.rsa, NULL, NULL, &i); + bn_dup_nil(L, i); break; case PK_RSA_P: /* RSA secret prime p */ - bn_dup_nil(L, key.rsa->p); + RSA_get0_factors(key.rsa, &i, NULL); + bn_dup_nil(L, i); break; case PK_RSA_Q: /* RSA secret prime q with p < q */ - bn_dup_nil(L, key.rsa->q); + RSA_get0_factors(key.rsa, NULL, &i); + bn_dup_nil(L, i); break; case PK_RSA_DMP1: /* exponent1 */ - bn_dup_nil(L, key.rsa->dmp1); + RSA_get0_crt_params(key.rsa, &i, NULL, NULL); + bn_dup_nil(L, i); break; case PK_RSA_DMQ1: /* exponent2 */ - bn_dup_nil(L, key.rsa->dmq1); + RSA_get0_crt_params(key.rsa, NULL, &i, NULL); + bn_dup_nil(L, i); break; case PK_RSA_IQMP: /* coefficient */ - bn_dup_nil(L, key.rsa->iqmp); + RSA_get0_crt_params(key.rsa, NULL, NULL, &i); + bn_dup_nil(L, i); break; case PK_DSA_P: - bn_dup_nil(L, key.dsa->p); + DSA_get0_pqg(key.dsa, &i, NULL, NULL); + bn_dup_nil(L, i); break; case PK_DSA_Q: - bn_dup_nil(L, key.dsa->q); + DSA_get0_pqg(key.dsa, NULL, &i, NULL); + bn_dup_nil(L, i); break; case PK_DSA_G: - bn_dup_nil(L, key.dsa->g); + DSA_get0_pqg(key.dsa, NULL, NULL, &i); + bn_dup_nil(L, i); break; case PK_DSA_PUB_KEY: - bn_dup_nil(L, key.dsa->pub_key); + DSA_get0_key(key.dsa, &i, NULL); + bn_dup_nil(L, i); break; case PK_DSA_PRIV_KEY: - bn_dup_nil(L, key.dsa->priv_key); + DSA_get0_key(key.dsa, NULL, &i); + bn_dup_nil(L, i); break; case PK_DH_P: - bn_dup_nil(L, key.dh->p); + DH_get0_pqg(key.dh, &i, NULL, NULL); + bn_dup_nil(L, i); break; case PK_DH_G: - bn_dup_nil(L, key.dh->g); + DH_get0_pqg(key.dh, NULL, NULL, &i); + bn_dup_nil(L, i); break; case PK_DH_PUB_KEY: - bn_dup_nil(L, key.dh->pub_key); + DH_get0_key(key.dh, &i, NULL); + bn_dup_nil(L, i); break; case PK_DH_PRIV_KEY: - bn_dup_nil(L, key.dh->priv_key); + DH_get0_key(key.dh, NULL, &i); + bn_dup_nil(L, i); break; #ifndef OPENSSL_NO_EC @@ -3073,22 +3573,9 @@ static void pk_pushparam(lua_State *L, void *base_key, enum pk_param which) { } /* pk_pushparam() */ -static _Bool pk_bn_set_nothrow(BIGNUM **dst, BIGNUM *src) { - BIGNUM *tmp; - - if (!(tmp = BN_dup(src))) - return 0; - - if (*dst) - BN_clear_free(*dst); - *dst = tmp; - - return 1; -} /* pk_bn_set_nothrow() */ - -#define pk_bn_set(L, dst, index) do { \ - BIGNUM *n = checkbig((L), (index)); \ - if (!pk_bn_set_nothrow((dst), n)) \ +#define pk_setparam_bn_dup(L, index, dst) do { \ + BIGNUM *tmp = checkbig((L), (index)); \ + if (!(*dst = BN_dup(tmp))) \ goto sslerr; \ } while (0) @@ -3101,74 +3588,92 @@ static void pk_setparam(lua_State *L, void *base_key, enum pk_param which, int i EC_KEY *ec; #endif } key = { base_key }; + BIGNUM *i; switch (which) { case PK_RSA_N: - pk_bn_set(L, &key.rsa->n, index); + pk_setparam_bn_dup(L, index, &i); + RSA_set0_key(key.rsa, i, NULL, NULL); break; case PK_RSA_E: - pk_bn_set(L, &key.rsa->e, index); + pk_setparam_bn_dup(L, index, &i); + RSA_set0_key(key.rsa, NULL, i, NULL); break; case PK_RSA_D: - pk_bn_set(L, &key.rsa->d, index); + pk_setparam_bn_dup(L, index, &i); + RSA_set0_key(key.rsa, NULL, NULL, i); break; case PK_RSA_P: - pk_bn_set(L, &key.rsa->p, index); + pk_setparam_bn_dup(L, index, &i); + RSA_set0_factors(key.rsa, i, NULL); break; case PK_RSA_Q: - pk_bn_set(L, &key.rsa->q, index); + pk_setparam_bn_dup(L, index, &i); + RSA_set0_factors(key.rsa, NULL, i); break; case PK_RSA_DMP1: - pk_bn_set(L, &key.rsa->dmp1, index); + pk_setparam_bn_dup(L, index, &i); + RSA_set0_crt_params(key.rsa, i, NULL, NULL); break; case PK_RSA_DMQ1: - pk_bn_set(L, &key.rsa->dmq1, index); + pk_setparam_bn_dup(L, index, &i); + RSA_set0_crt_params(key.rsa, NULL, i, NULL); break; case PK_RSA_IQMP: - pk_bn_set(L, &key.rsa->iqmp, index); + pk_setparam_bn_dup(L, index, &i); + RSA_set0_crt_params(key.rsa, NULL, NULL, i); break; case PK_DSA_P: - pk_bn_set(L, &key.dsa->p, index); + pk_setparam_bn_dup(L, index, &i); + DSA_set0_pqg(key.dsa, i, NULL, NULL); break; case PK_DSA_Q: - pk_bn_set(L, &key.dsa->q, index); + pk_setparam_bn_dup(L, index, &i); + DSA_set0_pqg(key.dsa, NULL, i, NULL); break; case PK_DSA_G: - pk_bn_set(L, &key.dsa->g, index); + pk_setparam_bn_dup(L, index, &i); + DSA_set0_pqg(key.dsa, NULL, NULL, i); break; case PK_DSA_PUB_KEY: - pk_bn_set(L, &key.dsa->pub_key, index); + pk_setparam_bn_dup(L, index, &i); + DSA_set0_key(key.dsa, i, NULL); break; case PK_DSA_PRIV_KEY: - pk_bn_set(L, &key.dsa->priv_key, index); + pk_setparam_bn_dup(L, index, &i); + DSA_set0_key(key.dsa, NULL, i); break; case PK_DH_P: - pk_bn_set(L, &key.dh->p, index); + pk_setparam_bn_dup(L, index, &i); + DH_set0_pqg(key.dh, i, NULL, NULL); break; case PK_DH_G: - pk_bn_set(L, &key.dh->g, index); + pk_setparam_bn_dup(L, index, &i); + DH_set0_pqg(key.dh, NULL, NULL, i); break; case PK_DH_PUB_KEY: - pk_bn_set(L, &key.dh->pub_key, index); + pk_setparam_bn_dup(L, index, &i); + DH_set0_key(key.dh, i, NULL); break; case PK_DH_PRIV_KEY: - pk_bn_set(L, &key.dh->priv_key, index); + pk_setparam_bn_dup(L, index, &i); + DH_set0_key(key.dh, NULL, i); break; #ifndef OPENSSL_NO_EC @@ -3399,6 +3904,7 @@ static const auxL_Reg pk_methods[] = { { "setPrivateKey", &pk_setPrivateKey }, { "sign", &pk_sign }, { "verify", &pk_verify }, + { "getDefaultDigestName", &pk_getDefaultDigestName }, { "toPEM", &pk_toPEM }, { "getParameters", &pk_getParameters }, { "setParameters", &pk_setParameters }, @@ -3474,21 +3980,6 @@ static EC_GROUP *ecg_dup_nil(lua_State *L, const EC_GROUP *src) { return (src)? ecg_dup(L, src) : (lua_pushnil(L), (EC_GROUP *)0); } /* ecg_dup_nil() */ -static EC_GROUP *ecg_new_by_nid(int nid) { - EC_GROUP *group; - - if (!(group = EC_GROUP_new_by_curve_name(nid))) - return NULL; - - /* flag as named for benefit of __tostring */ - EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); - - /* compressed points may be patented */ - EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED); - - return group; -} /* ecg_new_by_nid() */ - static EC_GROUP *ecg_push_by_nid(lua_State *L, int nid) { EC_GROUP **group = prepsimple(L, EC_GROUP_CLASS); @@ -3743,7 +4234,7 @@ static int xn_all(lua_State *L) { lua_setfield(L, -2, "id"); len = ASN1_STRING_length(X509_NAME_ENTRY_get_data(entry)); - lua_pushlstring(L, (char *)ASN1_STRING_data(X509_NAME_ENTRY_get_data(entry)), len); + lua_pushlstring(L, (char *)ASN1_STRING_get0_data(X509_NAME_ENTRY_get_data(entry)), len); lua_setfield(L, -2, "blob"); @@ -3777,7 +4268,7 @@ static int xn__next(lua_State *L) { lua_pushlstring(L, txt, len); len = ASN1_STRING_length(X509_NAME_ENTRY_get_data(entry)); - lua_pushlstring(L, (char *)ASN1_STRING_data(X509_NAME_ENTRY_get_data(entry)), len); + lua_pushlstring(L, (char *)ASN1_STRING_get0_data(X509_NAME_ENTRY_get_data(entry)), len); break; } @@ -3955,7 +4446,7 @@ text: gen->type = type; - if (!(gen->d.ia5 = M_ASN1_IA5STRING_new())) + if (!(gen->d.ia5 = ASN1_STRING_type_new(V_ASN1_IA5STRING))) goto error; if (!ASN1_STRING_set(gen->d.ia5, (unsigned char *)txt, len)) @@ -3976,7 +4467,7 @@ error: #define GN_PUSHSTRING(L, o) \ - lua_pushlstring((L), (char *)M_ASN1_STRING_data((o)), M_ASN1_STRING_length((o))) + lua_pushlstring((L), (char *)ASN1_STRING_get0_data((o)), ASN1_STRING_length((o))) static int gn__next(lua_State *L) { GENERAL_NAMES *gens = checksimple(L, lua_upvalueindex(1), X509_GENS_CLASS); @@ -4013,8 +4504,8 @@ static int gn__next(lua_State *L) { break; case GEN_IPADD: - txt = (char *)M_ASN1_STRING_data(name->d.iPAddress); - len = M_ASN1_STRING_length(name->d.iPAddress); + txt = (char *)ASN1_STRING_get0_data(name->d.iPAddress); + len = ASN1_STRING_length(name->d.iPAddress); switch (len) { case 16: @@ -4259,7 +4750,7 @@ static int xe_getLongName(lua_State *L) { static int xe_getData(lua_State *L) { ASN1_STRING *data = X509_EXTENSION_get0_data(checksimple(L, 1, X509_EXT_CLASS)); - lua_pushlstring(L, (char *)ASN1_STRING_data(data), ASN1_STRING_length(data)); + lua_pushlstring(L, (char *)ASN1_STRING_get0_data(data), ASN1_STRING_length(data)); return 1; } /* xe_getData() */ @@ -4332,6 +4823,7 @@ static const auxL_IntegerReg xe_textopts[] = { { "ERROR_UNKNOWN", X509V3_EXT_ERROR_UNKNOWN }, { "PARSE_UNKNOWN", X509V3_EXT_PARSE_UNKNOWN }, { "DUMP_UNKNOWN", X509V3_EXT_DUMP_UNKNOWN }, + { NULL, 0 }, }; int luaopen__openssl_x509_extension(lua_State *L) { @@ -4588,7 +5080,7 @@ static double timeutc(ASN1_TIME *time) { if (!ASN1_TIME_check(time)) return 0; - cp = strncpy(buf, (const char *)ASN1_STRING_data((ASN1_STRING *)time), sizeof buf - 1); + cp = strncpy(buf, (const char *)ASN1_STRING_get0_data((ASN1_STRING *)time), sizeof buf - 1); if (ASN1_STRING_type(time) == V_ASN1_GENERALIZEDTIME) { if (!scan(&year, &cp, 4, 1)) @@ -4992,7 +5484,7 @@ static int xc_setBasicConstraint(lua_State *L) { if (pathLen >= 0) { ASN1_INTEGER_free(bs->pathlen); - if (!(bs->pathlen = M_ASN1_INTEGER_new())) + if (!(bs->pathlen = ASN1_STRING_type_new(V_ASN1_INTEGER))) goto error; if (!ASN1_INTEGER_set(bs->pathlen, pathLen)) @@ -5179,20 +5671,21 @@ static int xc_getPublicKeyDigest(lua_State *L) { static const EVP_MD *xc_signature(lua_State *L, int index, EVP_PKEY *key) { const char *id; const EVP_MD *md; + int nid; - if ((id = luaL_optstring(L, index, NULL))) - return ((md = EVP_get_digestbyname(id)))? md : EVP_md_null(); - - switch (EVP_PKEY_type(key->type)) { - case EVP_PKEY_RSA: - return EVP_sha1(); - case EVP_PKEY_DSA: - return EVP_dss1(); - case EVP_PKEY_EC: - return EVP_ecdsa(); - default: - return EVP_md_null(); + if ((id = luaL_optstring(L, index, NULL))) { + if (!(md = EVP_get_digestbyname(id))) + goto unknown; + } else { + if (!(EVP_PKEY_get_default_digest_nid(key, &nid) > 0)) + goto unknown; + if (!(md = EVP_get_digestbynid(nid))) + goto unknown; } + + return md; +unknown: + return EVP_sha1(); } /* xc_signature() */ static int xc_sign(lua_State *L) { @@ -5491,6 +5984,103 @@ static int xr_setPublicKey(lua_State *L) { } /* xr_setPublicKey() */ +static int xr_setExtensionByNid(lua_State *L, X509_REQ *csr, int target_nid, void* value) { + STACK_OF(X509_EXTENSION) *sk = NULL; + int has_attrs=0; + + /* + * Replace existing if it's there. Extensions are stored in a CSR in + * an interesting way: + * + * They are stored as a list under either (most likely) the + * "official" NID_ext_req or under NID_ms_ext_req which means + * everything is stored under a list in a single "attribute" so we + * can't use X509_REQ_add1_attr or similar. + * + * Instead we have to get the extensions, find and replace the SAN + * if it's in there, then *replace* the extensions in the list of + * attributes. (If we just try to add it the old ones are found + * first and don't take priority.) + */ + has_attrs = X509_REQ_get_attr_count(csr); + + sk = X509_REQ_get_extensions(csr); + if (!X509V3_add1_i2d(&sk, target_nid, value, 0, X509V3_ADD_REPLACE)) + goto error; + if (X509_REQ_add_extensions(csr, sk) == 0) + goto error; + sk_X509_EXTENSION_pop_free(sk, X509_EXTENSION_free); + sk = NULL; + + /* + * Delete the old extensions attribute, so that the one we just + * added takes priority. + */ + if (has_attrs) { + X509_ATTRIBUTE *attr = NULL; + int idx, *pnid; + + for (pnid = X509_REQ_get_extension_nids(); *pnid != NID_undef; pnid++) { + idx = X509_REQ_get_attr_by_NID(csr, *pnid, -1); + if (idx == -1) + continue; + if (!(attr = X509_REQ_delete_attr(csr, idx))) + goto error; + X509_ATTRIBUTE_free(attr); + break; + } + if (!attr) + goto error; + } + + /* + * We have to mark the encoded form as invalid, otherwise when we + * write it out again it will use the loaded version. + */ +#if HAVE_I2D_RE_X509_REQ_TBS + (void)i2d_re_X509_REQ_tbs(csr, NULL); /* sets csr->req_info->enc.modified */ +#else + csr->req_info->enc.modified = 1; +#endif + + lua_pushboolean(L, 1); + + return 1; +error: + if (sk) + sk_X509_EXTENSION_pop_free(sk, X509_EXTENSION_free); + + return auxL_error(L, auxL_EOPENSSL, "x509.csr.setExtensionByNid"); +} /* xr_setExtensionByNid() */ + + +static int xr_setSubjectAlt(lua_State *L) { + X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); + GENERAL_NAMES *gens = checksimple(L, 2, X509_GENS_CLASS); + + return xr_setExtensionByNid(L, csr, NID_subject_alt_name, gens); +} /* xr_setSubjectAlt */ + + +static int xr_getSubjectAlt(lua_State *L) { + X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); + STACK_OF(X509_EXTENSION) *exts; + GENERAL_NAMES *gens; + + exts = X509_REQ_get_extensions(csr); + gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + if (!gens) goto error; + + gn_dup(L, gens); + + return 1; +error: + return 0; +} /* xr_getSubjectAlt() */ + + + static int xr_sign(lua_State *L) { X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS); @@ -5548,6 +6138,8 @@ static const auxL_Reg xr_methods[] = { { "setSubject", &xr_setSubject }, { "getPublicKey", &xr_getPublicKey }, { "setPublicKey", &xr_setPublicKey }, + { "getSubjectAlt", &xr_getSubjectAlt }, + { "setSubjectAlt", &xr_setSubjectAlt }, { "sign", &xr_sign }, { "tostring", &xr__tostring }, { NULL, NULL }, @@ -6010,7 +6602,7 @@ static void xl_dup(lua_State *L, STACK_OF(X509) *src, _Bool copy) { for (i = 0; i < n; i++) { if (!(crt = sk_X509_value(*dst, i))) continue; - CRYPTO_add(&crt->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(crt); } } @@ -6195,8 +6787,8 @@ static int xs_verify(lua_State *L) { X509_STORE *store = checksimple(L, 1, X509_STORE_CLASS); X509 *crt = checksimple(L, 2, X509_CERT_CLASS); STACK_OF(X509) *chain = NULL, **proof; - X509_STORE_CTX ctx; - int ok, why; + X509_STORE_CTX *ctx = NULL; + int nr = 0, ok, why; /* pre-allocate space for a successful return */ lua_settop(L, 3); @@ -6207,53 +6799,56 @@ static int xs_verify(lua_State *L) { int i, n; if (!(chain = sk_X509_dup(checksimple(L, 3, X509_CHAIN_CLASS)))) - return auxL_error(L, auxL_EOPENSSL, "x509.store:verify"); + goto eossl; n = sk_X509_num(chain); for (i = 0; i < n; i++) { if (!(elm = sk_X509_value(chain, i))) continue; - CRYPTO_add(&elm->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(elm); } } - if (!X509_STORE_CTX_init(&ctx, store, crt, chain)) { + if (!(ctx = X509_STORE_CTX_new()) || !X509_STORE_CTX_init(ctx, store, crt, chain)) { sk_X509_pop_free(chain, X509_free); - return auxL_error(L, auxL_EOPENSSL, "x509.store:verify"); + goto eossl; } ERR_clear_error(); - ok = X509_verify_cert(&ctx); + ok = X509_verify_cert(ctx); switch (ok) { case 1: /* verified */ - *proof = X509_STORE_CTX_get1_chain(&ctx); - - X509_STORE_CTX_cleanup(&ctx); - - if (!*proof) - return auxL_error(L, auxL_EOPENSSL, "x509.store:verify"); + if (!(*proof = X509_STORE_CTX_get1_chain(ctx))) + goto eossl; lua_pushboolean(L, 1); lua_pushvalue(L, -2); + nr = 2; - return 2; + break; case 0: /* not verified */ - why = X509_STORE_CTX_get_error(&ctx); - - X509_STORE_CTX_cleanup(&ctx); + why = X509_STORE_CTX_get_error(ctx); lua_pushboolean(L, 0); lua_pushstring(L, X509_verify_cert_error_string(why)); + nr = 2; - return 2; + break; default: - X509_STORE_CTX_cleanup(&ctx); - - return auxL_error(L, auxL_EOPENSSL, "x509.store:verify"); + goto eossl; } + + X509_STORE_CTX_free(ctx); + + return nr; +eossl: + if (ctx) + X509_STORE_CTX_free(ctx); + + return auxL_error(L, auxL_EOPENSSL, "x509.store:verify"); } /* xs_verify() */ @@ -6529,7 +7124,7 @@ static int sx_new(lua_State *L) { method = (srv)? &SSLv23_server_method : &SSLv23_client_method; options = SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3; break; -#ifndef OPENSSL_NO_SSL2 +#if HAVE_SSLV2_CLIENT_METHOD && HAVE_SSLV2_SERVER_METHOD case 2: /* SSLv2 */ method = (srv)? &SSLv2_server_method : &SSLv2_client_method; break; @@ -7001,7 +7596,7 @@ int luaopen__openssl_ssl_context(lua_State *L) { static SSL *ssl_push(lua_State *L, SSL *ssl) { SSL **ud = prepsimple(L, SSL_CLASS); - CRYPTO_add(&(ssl)->references, 1, CRYPTO_LOCK_SSL); + SSL_up_ref(ssl); *ud = ssl; return *ud; @@ -7152,7 +7747,7 @@ static int ssl_getVersion(lua_State *L) { static int ssl_getClientVersion(lua_State *L) { SSL *ssl = checksimple(L, 1, SSL_CLASS); int format = luaL_checkoption(L, 2, "d", (const char *[]){ "d", ".", "f", NULL }); - int version = ssl->client_version; + int version = SSL_client_version(ssl); int major, minor; switch (format) { @@ -7306,13 +7901,10 @@ static const EVP_MD *md_optdigest(lua_State *L, int index) { static int md_new(lua_State *L) { const EVP_MD *type = md_optdigest(L, 1); - EVP_MD_CTX *ctx; - - ctx = prepudata(L, sizeof *ctx, DIGEST_CLASS, NULL); - - EVP_MD_CTX_init(ctx); + EVP_MD_CTX **ctx; - if (!EVP_DigestInit_ex(ctx, type, NULL)) + ctx = prepsimple(L, DIGEST_CLASS, NULL); + if (!(*ctx = EVP_MD_CTX_new()) || !EVP_DigestInit_ex(*ctx, type, NULL)) return auxL_error(L, auxL_EOPENSSL, "digest.new"); return 1; @@ -7340,7 +7932,7 @@ static void md_update_(lua_State *L, EVP_MD_CTX *ctx, int from, int to) { static int md_update(lua_State *L) { - EVP_MD_CTX *ctx = luaL_checkudata(L, 1, DIGEST_CLASS); + EVP_MD_CTX *ctx = checksimple(L, 1, DIGEST_CLASS); md_update_(L, ctx, 2, lua_gettop(L)); @@ -7351,7 +7943,7 @@ static int md_update(lua_State *L) { static int md_final(lua_State *L) { - EVP_MD_CTX *ctx = luaL_checkudata(L, 1, DIGEST_CLASS); + EVP_MD_CTX *ctx = checksimple(L, 1, DIGEST_CLASS); unsigned char md[EVP_MAX_MD_SIZE]; unsigned len; @@ -7367,9 +7959,10 @@ static int md_final(lua_State *L) { static int md__gc(lua_State *L) { - EVP_MD_CTX *ctx = luaL_checkudata(L, 1, DIGEST_CLASS); + EVP_MD_CTX **ctx = luaL_checkudata(L, 1, DIGEST_CLASS); - EVP_MD_CTX_cleanup(ctx); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; return 0; } /* md__gc() */ @@ -7410,16 +8003,25 @@ static int hmac_new(lua_State *L) { const void *key; size_t len; const EVP_MD *type; - HMAC_CTX *ctx; + HMAC_CTX **ctx; key = luaL_checklstring(L, 1, &len); type = md_optdigest(L, 2); - ctx = prepudata(L, sizeof *ctx, HMAC_CLASS, NULL); + ctx = prepsimple(L, HMAC_CLASS, NULL); + if (!(*ctx = HMAC_CTX_new())) + goto eossl; - HMAC_Init_ex(ctx, key, len, type, NULL); +#if HMAC_INIT_EX_INT + if (!HMAC_Init_ex(*ctx, key, len, type, NULL)) + goto eossl; +#else + HMAC_Init_ex(*ctx, key, len, type, NULL); +#endif return 1; +eossl: + return auxL_error(L, auxL_EOPENSSL, "hmac.new"); } /* hmac_new() */ @@ -7443,7 +8045,7 @@ static void hmac_update_(lua_State *L, HMAC_CTX *ctx, int from, int to) { static int hmac_update(lua_State *L) { - HMAC_CTX *ctx = luaL_checkudata(L, 1, HMAC_CLASS); + HMAC_CTX *ctx = checksimple(L, 1, HMAC_CLASS); hmac_update_(L, ctx, 2, lua_gettop(L)); @@ -7454,7 +8056,7 @@ static int hmac_update(lua_State *L) { static int hmac_final(lua_State *L) { - HMAC_CTX *ctx = luaL_checkudata(L, 1, HMAC_CLASS); + HMAC_CTX *ctx = checksimple(L, 1, HMAC_CLASS); unsigned char hmac[EVP_MAX_MD_SIZE]; unsigned len; @@ -7469,9 +8071,10 @@ static int hmac_final(lua_State *L) { static int hmac__gc(lua_State *L) { - HMAC_CTX *ctx = luaL_checkudata(L, 1, HMAC_CLASS); + HMAC_CTX **ctx = luaL_checkudata(L, 1, HMAC_CLASS); - HMAC_CTX_cleanup(ctx); + HMAC_CTX_free(*ctx); + *ctx = NULL; return 0; } /* hmac__gc() */ @@ -7521,23 +8124,26 @@ static const EVP_CIPHER *cipher_checktype(lua_State *L, int index) { static int cipher_new(lua_State *L) { const EVP_CIPHER *type; - EVP_CIPHER_CTX *ctx; + EVP_CIPHER_CTX **ctx; unsigned char key[EVP_MAX_KEY_LENGTH] = { 0 }; type = cipher_checktype(L, 1); - ctx = prepudata(L, sizeof *ctx, CIPHER_CLASS, NULL); - EVP_CIPHER_CTX_init(ctx); + ctx = prepsimple(L, CIPHER_CLASS, NULL); + if (!(*ctx = EVP_CIPHER_CTX_new())) + goto eossl; /* * NOTE: For some ciphers like AES calling :update or :final without * setting a key causes a SEGV. Set a dummy key here. Same solution * as used by Ruby OSSL. */ - if (!EVP_CipherInit_ex(ctx, type, NULL, key, NULL, -1)) - return auxL_error(L, auxL_EOPENSSL, "cipher.new"); + if (!EVP_CipherInit_ex(*ctx, type, NULL, key, NULL, -1)) + goto eossl; return 1; +eossl: + return auxL_error(L, auxL_EOPENSSL, "cipher.new"); } /* cipher_new() */ @@ -7547,7 +8153,7 @@ static int cipher_interpose(lua_State *L) { static int cipher_init(lua_State *L, _Bool encrypt) { - EVP_CIPHER_CTX *ctx = luaL_checkudata(L, 1, CIPHER_CLASS); + EVP_CIPHER_CTX *ctx = checksimple(L, 1, CIPHER_CLASS); const void *key, *iv; size_t n, m; @@ -7619,7 +8225,7 @@ static _Bool cipher_update_(lua_State *L, EVP_CIPHER_CTX *ctx, luaL_Buffer *B, i static int cipher_update(lua_State *L) { - EVP_CIPHER_CTX *ctx = luaL_checkudata(L, 1, CIPHER_CLASS); + EVP_CIPHER_CTX *ctx = checksimple(L, 1, CIPHER_CLASS); luaL_Buffer B; luaL_buffinit(L, &B); @@ -7639,7 +8245,7 @@ sslerr: static int cipher_final(lua_State *L) { - EVP_CIPHER_CTX *ctx = luaL_checkudata(L, 1, CIPHER_CLASS); + EVP_CIPHER_CTX *ctx = checksimple(L, 1, CIPHER_CLASS); luaL_Buffer B; size_t block; int out; @@ -7670,9 +8276,10 @@ sslerr: static int cipher__gc(lua_State *L) { - EVP_CIPHER_CTX *ctx = luaL_checkudata(L, 1, CIPHER_CLASS); + EVP_CIPHER_CTX **ctx = luaL_checkudata(L, 1, CIPHER_CLASS); - EVP_CIPHER_CTX_cleanup(ctx); + EVP_CIPHER_CTX_free(*ctx); + *ctx = NULL; return 0; } /* cipher__gc() */ @@ -7719,49 +8326,61 @@ static struct randL_state *randL_getstate(lua_State *L) { return lua_touserdata(L, lua_upvalueindex(1)); } /* randL_getstate() */ -#ifndef HAVE_SYS_SYSCTL_H -#define HAVE_SYS_SYSCTL_H (!defined __sun && !defined _AIX) +#if HAVE_SYS_SYSCALL_H +#include <sys/syscall.h> /* SYS_getrandom syscall(2) */ #endif #if HAVE_SYS_SYSCTL_H -#include <sys/sysctl.h> /* CTL_KERN KERN_RANDOM RANDOM_UUID KERN_URND KERN_ARND sysctl(2) */ -#endif - -#ifndef HAVE_RANDOM_UUID -#define HAVE_RANDOM_UUID (defined __linux) /* RANDOM_UUID is an enum, not macro */ -#endif - -#ifndef HAVE_KERN_URND -#define HAVE_KERN_URND (defined KERN_URND) -#endif - -#ifndef HAVE_KERN_ARND -#define HAVE_KERN_ARND (defined KERN_ARND) +#include <sys/sysctl.h> /* CTL_KERN KERN_RANDOM RANDOM_UUID sysctl(2) */ #endif static int randL_stir(struct randL_state *st, unsigned rqstd) { unsigned count = 0; int error; unsigned char data[256]; -#if HAVE_RANDOM_UUID || HAVE_KERN_URND || HAVE_KERN_ARND -#if HAVE_RANDOM_UUID - int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; -#elif HAVE_KERN_URND - int mib[] = { CTL_KERN, KERN_URND }; -#else - int mib[] = { CTL_KERN, KERN_ARND }; + +#if HAVE_ARC4RANDOM_BUF + while (count < rqstd) { + size_t n = MIN(rqstd - count, sizeof data); + + arc4random_buf(data, n); + + RAND_seed(data, n); + + count += n; + } +#endif + +#if HAVE_SYSCALL && HAVE_DECL_SYS_GETRANDOM + while (count < rqstd) { + size_t lim = MIN(rqstd - count, sizeof data); + int n; + + n = syscall(SYS_getrandom, data, lim, 0); + + if (n == -1) { + break; + } + + RAND_seed(data, n); + + count += n; + } #endif +#if HAVE_SYS_SYSCTL_H && HAVE_DECL_RANDOM_UUID while (count < rqstd) { + int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; size_t n = MIN(rqstd - count, sizeof data); if (0 != sysctl(mib, countof(mib), data, &n, (void *)0, 0)) break; - RAND_add(data, n, n); + RAND_seed(data, n); count += n; } + #endif if (count < rqstd) { @@ -7792,7 +8411,7 @@ static int randL_stir(struct randL_state *st, unsigned rqstd) { goto error; default: - RAND_add(data, n, n); + RAND_seed(data, n); count += n; } @@ -7830,7 +8449,12 @@ error:; #elif defined __sun /* * NOTE: Linux requires -lrt for clock_gettime, and in any event - * already has RANDOM_UUID. The BSDs have KERN_URND and KERN_ARND. + * should have RANDOM_UUID or getrandom. (Though, some middle-aged + * kernels might have neither). The BSDs have arc4random which + * should be using KERN_URND, KERN_ARND, and more recently + * getentropy. (Though, again, some older BSD kernels used an + * arc4random implementation that opened /dev/urandom.) + * * Just do this for Solaris to keep things simple. We've already * crossed the line of what can be reasonably accomplished on * unreasonable platforms. diff --git a/src/openssl.x509.altname.lua b/src/openssl.x509.altname.lua index 66f16e7..e8222a0 100644 --- a/src/openssl.x509.altname.lua +++ b/src/openssl.x509.altname.lua @@ -1,9 +1,10 @@ local altname = require"_openssl.x509.altname" +local auxlib = require"openssl.auxlib" altname.interpose("__tostring", function (self) local t = { } - for k, v in pairs(self) do + for k, v in auxlib.pairs(self) do t[#t + 1] = k .. ":" .. v end diff --git a/src/openssl.x509.name.lua b/src/openssl.x509.name.lua index a531502..f33339a 100644 --- a/src/openssl.x509.name.lua +++ b/src/openssl.x509.name.lua @@ -1,9 +1,10 @@ local name = require"_openssl.x509.name" +local auxlib = require"openssl.auxlib" name.interpose("__tostring", function (self) local t = { } - for k, v in pairs(self) do + for k, v in auxlib.pairs(self) do t[#t + 1] = k .. "=" .. v end |