cleanup: Remove OpenSSL and consequently https support. Run behind a reverse proxy if you need https.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
This commit is contained in:
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -19,10 +19,6 @@
|
|||||||
[submodule "deps/picohttpparser"]
|
[submodule "deps/picohttpparser"]
|
||||||
path = deps/picohttpparser
|
path = deps/picohttpparser
|
||||||
url = https://github.com/h2o/picohttpparser.git
|
url = https://github.com/h2o/picohttpparser.git
|
||||||
[submodule "deps/openssl_src"]
|
|
||||||
path = deps/openssl_src
|
|
||||||
url = https://github.com/openssl/openssl.git
|
|
||||||
shallow = true
|
|
||||||
[submodule "deps/c-ares"]
|
[submodule "deps/c-ares"]
|
||||||
path = deps/c-ares
|
path = deps/c-ares
|
||||||
url = https://github.com/c-ares/c-ares.git
|
url = https://github.com/c-ares/c-ares.git
|
||||||
|
137
GNUmakefile
137
GNUmakefile
@@ -38,7 +38,6 @@ BUNDLETOOL = out/bundletool.jar
|
|||||||
|
|
||||||
HAVE_WIN :=
|
HAVE_WIN :=
|
||||||
HAVE_CROSS_AARCH64 :=
|
HAVE_CROSS_AARCH64 :=
|
||||||
USE_SYSTEM_SSL :=
|
|
||||||
|
|
||||||
export SOURCE_DATE_EPOCH=1
|
export SOURCE_DATE_EPOCH=1
|
||||||
export TZ=UTC
|
export TZ=UTC
|
||||||
@@ -65,7 +64,6 @@ LDFLAGS += \
|
|||||||
-lbsd \
|
-lbsd \
|
||||||
-lnetwork \
|
-lnetwork \
|
||||||
-Wno-stringop-overflow
|
-Wno-stringop-overflow
|
||||||
USE_SYSTEM_SSL := 1
|
|
||||||
HAVE_ANDROID = 0
|
HAVE_ANDROID = 0
|
||||||
HAVE_LINUX_IOS = 0
|
HAVE_LINUX_IOS = 0
|
||||||
HAVE_LINUX_MACOS = 0
|
HAVE_LINUX_MACOS = 0
|
||||||
@@ -80,13 +78,12 @@ LDFLAGS += \
|
|||||||
HAVE_ANDROID :=
|
HAVE_ANDROID :=
|
||||||
HAVE_LINUX_IOS :=
|
HAVE_LINUX_IOS :=
|
||||||
HAVE_LINUX_MACOS :=
|
HAVE_LINUX_MACOS :=
|
||||||
USE_SYSTEM_SSL := 1
|
|
||||||
else
|
else
|
||||||
$(error Unexpected host platform $(UNAME_S).)
|
$(error Unexpected host platform $(UNAME_S).)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Everything is set above.
|
# Everything is set above.
|
||||||
$(info Building Tilde Friends $(VERSION_NUMBER) android=$(if $(HAVE_ANDROID),1,0) win=$(if $(HAVE_WIN),1,0) cross_aarch64=$(if $(HAVE_CROSS_AARCH64),1,0) cross_ios=$(if $(HAVE_LINUX_IOS),1,0) cross_macos=$(if $(HAVE_LINUX_MACOS),1,0) system_ssl=$(if $(USE_SYSTEM_SSL),1,0))
|
$(info Building Tilde Friends $(VERSION_NUMBER) android=$(if $(HAVE_ANDROID),1,0) win=$(if $(HAVE_WIN),1,0) cross_aarch64=$(if $(HAVE_CROSS_AARCH64),1,0) cross_ios=$(if $(HAVE_LINUX_IOS),1,0) cross_macos=$(if $(HAVE_LINUX_MACOS),1,0))
|
||||||
|
|
||||||
CFLAGS += \
|
CFLAGS += \
|
||||||
-std=gnu11 \
|
-std=gnu11 \
|
||||||
@@ -270,16 +267,12 @@ $(WINDOWS_TARGETS): AS = $(CC)
|
|||||||
$(WINDOWS_TARGETS): CFLAGS += \
|
$(WINDOWS_TARGETS): CFLAGS += \
|
||||||
-D_WIN32_WINNT=0x0A00 \
|
-D_WIN32_WINNT=0x0A00 \
|
||||||
-DWINVER=0x0A00 \
|
-DWINVER=0x0A00 \
|
||||||
-DNTDDI_VERSION=NTDDI_WIN10 \
|
-DNTDDI_VERSION=NTDDI_WIN10
|
||||||
-Iout/openssl/$(UNAME_S)/mingw64/usr/local/include
|
|
||||||
$(WINDOWS_TARGETS): LDFLAGS += \
|
$(WINDOWS_TARGETS): LDFLAGS += \
|
||||||
-static \
|
-static \
|
||||||
-lm \
|
-lm
|
||||||
-Lout/openssl/$(UNAME_S)/mingw64/usr/local/lib
|
|
||||||
$(AARCH64_TARGETS): CC = aarch64-linux-gnu-gcc
|
$(AARCH64_TARGETS): CC = aarch64-linux-gnu-gcc
|
||||||
$(AARCH64_TARGETS): AS = $(CC)
|
$(AARCH64_TARGETS): AS = $(CC)
|
||||||
$(AARCH64_TARGETS): CFLAGS += -Iout/openssl/Linux/aarch64/usr/local/include
|
|
||||||
$(AARCH64_TARGETS): LDFLAGS += -Lout/openssl/Linux/aarch64/usr/local/lib
|
|
||||||
ifeq ($(UNAME_S),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
$(HOST_TARGETS): CC = xcrun clang
|
$(HOST_TARGETS): CC = xcrun clang
|
||||||
$(IOS_TARGETS): IOS_SYSROOT := $(shell xcrun --sdk iphoneos --show-sdk-path)
|
$(IOS_TARGETS): IOS_SYSROOT := $(shell xcrun --sdk iphoneos --show-sdk-path)
|
||||||
@@ -304,39 +297,12 @@ $(ANDROID_TARGETS): AS = $(CC)
|
|||||||
$(ANDROID_TARGETS): CFLAGS += \
|
$(ANDROID_TARGETS): CFLAGS += \
|
||||||
-target $(ANDROID_NDK_TARGET_TRIPLE)$(ANDROID_MIN_SDK_VERSION) \
|
-target $(ANDROID_NDK_TARGET_TRIPLE)$(ANDROID_MIN_SDK_VERSION) \
|
||||||
-Wno-unknown-warning-option
|
-Wno-unknown-warning-option
|
||||||
$(ANDROID_ARMV7A_TARGETS): CFLAGS += -Iout/openssl/android/armeabi-v7a/usr/local/include
|
|
||||||
$(ANDROID_ARMV7A_TARGETS): LDFLAGS += -Lout/openssl/android/armeabi-v7a/usr/local/lib
|
|
||||||
$(ANDROID_ARM64_TARGETS): CFLAGS += -Iout/openssl/android/arm64-v8a/usr/local/include
|
|
||||||
$(ANDROID_ARM64_TARGETS): LDFLAGS += -Lout/openssl/android/arm64-v8a/usr/local/lib
|
|
||||||
$(ANDROID_X86_TARGETS): CFLAGS += -Iout/openssl/android/x86/usr/local/include
|
|
||||||
$(ANDROID_X86_TARGETS): CFLAGS += -Wno-atomic-alignment
|
$(ANDROID_X86_TARGETS): CFLAGS += -Wno-atomic-alignment
|
||||||
$(ANDROID_X86_TARGETS): LDFLAGS += -Lout/openssl/android/x86/usr/local/lib
|
|
||||||
$(ANDROID_X86_64_TARGETS): CFLAGS += -Iout/openssl/android/x86_64/usr/local/include
|
|
||||||
$(ANDROID_X86_64_TARGETS): LDFLAGS += -Lout/openssl/android/x86_64/usr/local/lib
|
|
||||||
$(NONMACOS_TARGETS): CFLAGS += -Wno-cast-function-type
|
$(NONMACOS_TARGETS): CFLAGS += -Wno-cast-function-type
|
||||||
$(MACOS_TARGETS): LDFLAGS += -Wl,-dead_strip
|
$(MACOS_TARGETS): LDFLAGS += -Wl,-dead_strip
|
||||||
$(NONMACOS_TARGETS): LDFLAGS += -Wl,--gc-sections -Wl,--as-needed
|
$(NONMACOS_TARGETS): LDFLAGS += -Wl,--gc-sections -Wl,--as-needed
|
||||||
$(IOS_TARGETS): CFLAGS += -miphoneos-version-min=$(IPHONEOS_VERSION_MIN)
|
$(IOS_TARGETS): CFLAGS += -miphoneos-version-min=$(IPHONEOS_VERSION_MIN)
|
||||||
$(IOS_TARGETS): LDFLAGS += -miphoneos-version-min=$(IPHONEOS_VERSION_MIN)
|
$(IOS_TARGETS): LDFLAGS += -miphoneos-version-min=$(IPHONEOS_VERSION_MIN)
|
||||||
ifeq ($(UNAME_S),Darwin)
|
|
||||||
$(IOS_TARGETS): CFLAGS += -Iout/openssl/ios/ios64-xcrun/usr/local/include
|
|
||||||
$(IOS_TARGETS): LDFLAGS += -Lout/openssl/ios/ios64-xcrun/usr/local/lib
|
|
||||||
else
|
|
||||||
$(IOS_TARGETS): CFLAGS += -Iout/openssl/$(UNAME_S)/ios64-cross/usr/local/include
|
|
||||||
$(IOS_TARGETS): LDFLAGS += -Lout/openssl/$(UNAME_S)/ios64-cross/usr/local/lib
|
|
||||||
$(filter $(BUILD_DIR)/macosdebug-x86_64/%,$(ALL_TARGETS)): CFLAGS += -Iout/openssl/$(UNAME_S)/macos-x86_64/usr/local/include
|
|
||||||
$(filter $(BUILD_DIR)/macosdebug-arm/%,$(ALL_TARGETS)): CFLAGS += -Iout/openssl/$(UNAME_S)/macos-arm/usr/local/include
|
|
||||||
$(filter $(BUILD_DIR)/macosdebug-x86_64/%,$(ALL_TARGETS)): LDFLAGS += -Lout/openssl/$(UNAME_S)/macos-x86_64/usr/local/lib
|
|
||||||
$(filter $(BUILD_DIR)/macosdebug-arm/%,$(ALL_TARGETS)): LDFLAGS += -Lout/openssl/$(UNAME_S)/macos-arm/usr/local/lib
|
|
||||||
$(filter $(BUILD_DIR)/macosrelease-x86_64/%,$(ALL_TARGETS)): CFLAGS += -Iout/openssl/$(UNAME_S)/macos-x86_64/usr/local/include
|
|
||||||
$(filter $(BUILD_DIR)/macosrelease-arm/%,$(ALL_TARGETS)): CFLAGS += -Iout/openssl/$(UNAME_S)/macos-arm/usr/local/include
|
|
||||||
$(filter $(BUILD_DIR)/macosrelease-x86_64/%,$(ALL_TARGETS)): LDFLAGS += -Lout/openssl/$(UNAME_S)/macos-x86_64/usr/local/lib
|
|
||||||
$(filter $(BUILD_DIR)/macosrelease-arm/%,$(ALL_TARGETS)): LDFLAGS += -Lout/openssl/$(UNAME_S)/macos-arm/usr/local/lib
|
|
||||||
endif
|
|
||||||
$(IOSSIM_TARGETS): CFLAGS += -Iout/openssl/ios/iossimulator-xcrun/usr/local/include
|
|
||||||
$(IOSSIM_TARGETS): LDFLAGS += -Lout/openssl/ios/iossimulator-xcrun/usr/local/lib
|
|
||||||
$(HOST_TARGETS): CFLAGS += -Iout/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/include
|
|
||||||
$(HOST_TARGETS): LDFLAGS += -Lout/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib
|
|
||||||
|
|
||||||
ifeq ($(UNAME_M),x86_64)
|
ifeq ($(UNAME_M),x86_64)
|
||||||
ifeq ($(UNAME_S),Linux)
|
ifeq ($(UNAME_S),Linux)
|
||||||
@@ -824,9 +790,6 @@ $(MINIUNZIP_OBJS): CFLAGS += \
|
|||||||
LDFLAGS += \
|
LDFLAGS += \
|
||||||
-pthread \
|
-pthread \
|
||||||
-lm
|
-lm
|
||||||
$(HOST_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS) $(AARCH64_TARGETS) $(filter-out $(HOST_TARGETS),$(MACOS_TARGETS)): LDFLAGS += \
|
|
||||||
-lssl \
|
|
||||||
-lcrypto
|
|
||||||
ifneq ($(UNAME_S),Haiku)
|
ifneq ($(UNAME_S),Haiku)
|
||||||
ifneq ($(UNAME_S),OpenBSD)
|
ifneq ($(UNAME_S),OpenBSD)
|
||||||
$(HOST_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \
|
$(HOST_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \
|
||||||
@@ -834,8 +797,6 @@ $(HOST_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
$(WINDOWS_TARGETS): LDFLAGS += \
|
$(WINDOWS_TARGETS): LDFLAGS += \
|
||||||
-lssl \
|
|
||||||
-lcrypto \
|
|
||||||
-lcrypt32 \
|
-lcrypt32 \
|
||||||
-ldbghelp \
|
-ldbghelp \
|
||||||
-liphlpapi \
|
-liphlpapi \
|
||||||
@@ -848,9 +809,7 @@ $(WINDOWS_TARGETS): LDFLAGS += \
|
|||||||
$(ANDROID_TARGETS): LDFLAGS += \
|
$(ANDROID_TARGETS): LDFLAGS += \
|
||||||
-target $(ANDROID_NDK_TARGET_TRIPLE)$(ANDROID_MIN_SDK_VERSION) \
|
-target $(ANDROID_NDK_TARGET_TRIPLE)$(ANDROID_MIN_SDK_VERSION) \
|
||||||
-ldl \
|
-ldl \
|
||||||
-llog \
|
-llog
|
||||||
-lssl \
|
|
||||||
-lcrypto
|
|
||||||
$(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS): CFLAGS += \
|
$(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS): CFLAGS += \
|
||||||
-Wno-unknown-warning-option
|
-Wno-unknown-warning-option
|
||||||
$(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \
|
$(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \
|
||||||
@@ -1225,94 +1184,6 @@ iossimdebuggo: out/tildefriends-iossimdebug.app/tildefriends ## Build, install,
|
|||||||
xcrun simctl launch booted com.unprompted.tildefriends
|
xcrun simctl launch booted com.unprompted.tildefriends
|
||||||
.PHONY: iossimdebuggo
|
.PHONY: iossimdebuggo
|
||||||
|
|
||||||
ANDROID_DEPS := out/openssl/android/arm64-v8a/usr/local/lib/libssl.a
|
|
||||||
$(ANDROID_DEPS):
|
|
||||||
+@export ANDROID_NDK_ROOT=$(ANDROID_NDK)
|
|
||||||
+@export BUILD_PLATFORM=android
|
|
||||||
+@export TOOLCHAIN=$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64
|
|
||||||
+@PATH="$$TOOLCHAIN/x86_64-linux-android/bin:$$TOOLCHAIN/bin:$$PATH" BUILD_TARGET=x86_64 SSL_TARGET=android-x86_64 OPTIONS="-D__ANDROID_API__=$(ANDROID_MIN_SDK_VERSION) -Wno-macro-redefined" tools/ssl-local
|
|
||||||
+@PATH="$$TOOLCHAIN/i686-linux-android/bin:$$TOOLCHAIN/bin:$$PATH" BUILD_TARGET=x86 SSL_TARGET=android-x86 OPTIONS="-D__ANDROID_API__=$(ANDROID_MIN_SDK_VERSION) -Wno-macro-redefined" tools/ssl-local
|
|
||||||
+@PATH="$$TOOLCHAIN/arm-linux-androideabi/bin:$$TOOLCHAIN/bin:$$PATH" BUILD_TARGET=armeabi-v7a SSL_TARGET=android-arm OPTIONS="--target=armv7a-linux-androideabi -Wl,--fix-cortex-a8 -D__ANDROID_API__=$(ANDROID_MIN_SDK_VERSION) -Wno-macro-redefined" tools/ssl-local
|
|
||||||
+@PATH="$$TOOLCHAIN/aarch64-linux-android/bin:$$TOOLCHAIN/bin:$$PATH" BUILD_TARGET=arm64-v8a SSL_TARGET=android-arm64 OPTIONS="-D__ANDROID_API__=$(ANDROID_MIN_SDK_VERSION) -Wno-macro-redefined" tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/android%,$(APP_OBJS)): | $(ANDROID_DEPS)
|
|
||||||
|
|
||||||
ifeq ($(UNAME_S),Linux)
|
|
||||||
ifneq ($(USE_SYSTEM_SSL),1)
|
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
|
|
||||||
$(LOCAL_DEPS):
|
|
||||||
+@tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/debug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/release/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(HAVE_CROSS_AARCH64),1)
|
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/aarch64/usr/local/lib/libssl.a
|
|
||||||
$(LOCAL_DEPS):
|
|
||||||
+@OPTIONS="--cross-compile-prefix=aarch64-linux-gnu-" BUILD_TARGET=aarch64 SSL_TARGET=linux-aarch64 tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/armdebug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/armrelease/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(HAVE_LINUX_IOS),1)
|
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/ios64-cross/usr/local/lib/libssl.a
|
|
||||||
$(LOCAL_DEPS):
|
|
||||||
+@PATH=deps/ios_toolchain/target/bin:$$PATH \
|
|
||||||
BUILD_TARGET=ios64-cross \
|
|
||||||
SSL_TARGET=ios64-cross \
|
|
||||||
CROSS_COMPILE=../../deps/ios_toolchain/target/bin/arm-apple-darwin11- \
|
|
||||||
CROSS_TOP=../../deps/ios_toolchain/target \
|
|
||||||
CROSS_SDK=iPhoneOS18.2.sdk \
|
|
||||||
CC=clang \
|
|
||||||
OPTIONS=-miphoneos-version-min=$(IPHONEOS_VERSION_MIN) \
|
|
||||||
tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/ios%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(HAVE_LINUX_MACOS),1)
|
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/macos-arm/usr/local/lib/libssl.a
|
|
||||||
$(LOCAL_DEPS):
|
|
||||||
+@PATH=../../deps/macos_toolchain/bin:$$PATH \
|
|
||||||
BUILD_TARGET=macos-arm \
|
|
||||||
SSL_TARGET=darwin64-arm64 \
|
|
||||||
CC=../../deps/macos_toolchain/bin/oa64-clang \
|
|
||||||
RANLIB=../../deps/macos_toolchain/bin/x86_64-apple-darwin24-ranlib \
|
|
||||||
AR=../../deps/macos_toolchain/bin/arm64-apple-darwin24-ar \
|
|
||||||
tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/macosrelease-arm/% $(BUILD_DIR)/macosdebug-arm/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
|
||||||
|
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/macos-x86_64/usr/local/lib/libssl.a
|
|
||||||
$(LOCAL_DEPS):
|
|
||||||
+@PATH=../../deps/macos_toolchain/bin:$$PATH \
|
|
||||||
BUILD_TARGET=macos-x86_64 \
|
|
||||||
SSL_TARGET=darwin64-x86_64 \
|
|
||||||
CC=../../deps/macos_toolchain/bin/o64-clang \
|
|
||||||
RANLIB=../../deps/macos_toolchain/bin/x86_64-apple-darwin24-ranlib \
|
|
||||||
AR=../../deps/macos_toolchain/bin/x86_64-apple-darwin24-ar \
|
|
||||||
tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/macosrelease-x86_64/% $(BUILD_DIR)/macosdebug-x86_64/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(UNAME_S),Darwin)
|
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
|
|
||||||
$(LOCAL_DEPS):
|
|
||||||
+@tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/debug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/release/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(HAVE_WIN),1)
|
|
||||||
WINDOWS_DEPS := out/openssl/$(UNAME_S)/mingw64/usr/local/lib/libssl.a
|
|
||||||
$(WINDOWS_DEPS):
|
|
||||||
+@BUILD_TARGET=mingw64 SSL_TARGET=mingw64 OPTIONS="--cross-compile-prefix=x86_64-w64-mingw32-" tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/win%,$(APP_OBJS)): | $(WINDOWS_DEPS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(UNAME_S),Darwin)
|
|
||||||
IOS_DEPS := out/openssl/ios/ios64-xcrun/usr/local/lib/libssl.a
|
|
||||||
$(IOS_DEPS):
|
|
||||||
+@BUILD_PLATFORM=ios BUILD_TARGET=ios64-xcrun SSL_TARGET=ios64-xcrun OPTIONS="-fPIC -Wno-macro-redefined -miphoneos-version-min=$(IPHONEOS_VERSION_MIN)" tools/ssl-local
|
|
||||||
+@BUILD_PLATFORM=ios BUILD_TARGET=iossimulator-xcrun SSL_TARGET=iossimulator-xcrun OPTIONS="-fPIC -Wno-macro-redefined" tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/ios%,$(APP_OBJS)): | $(IOS_DEPS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
out/macos%/tildefriends: out/macos%-arm/tildefriends out/macos%-x86_64/tildefriends
|
out/macos%/tildefriends: out/macos%-arm/tildefriends out/macos%-x86_64/tildefriends
|
||||||
@echo [lipo] $@
|
@echo [lipo] $@
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
|
@@ -38,8 +38,6 @@ dependencies in the right places.
|
|||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
System OpenSSL libraries are assumed to be available on Haiku and OpenBSD.
|
|
||||||
|
|
||||||
On MacOS, Xcode's command-line tools are expected to be available.
|
On MacOS, Xcode's command-line tools are expected to be available.
|
||||||
|
|
||||||
### Build Commands
|
### Build Commands
|
||||||
|
1
deps/openssl_src
vendored
1
deps/openssl_src
vendored
Submodule deps/openssl_src deleted from 7b371d80d9
108
src/http.c
108
src/http.c
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "tls.h"
|
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "util.js.h"
|
#include "util.js.h"
|
||||||
|
|
||||||
@@ -26,7 +25,6 @@ int s_http_instance_count;
|
|||||||
typedef struct _tf_http_connection_t
|
typedef struct _tf_http_connection_t
|
||||||
{
|
{
|
||||||
tf_http_t* http;
|
tf_http_t* http;
|
||||||
tf_tls_session_t* tls;
|
|
||||||
uv_tcp_t tcp;
|
uv_tcp_t tcp;
|
||||||
uv_shutdown_t shutdown;
|
uv_shutdown_t shutdown;
|
||||||
uv_timer_t timeout;
|
uv_timer_t timeout;
|
||||||
@@ -78,7 +76,6 @@ typedef struct _tf_http_handler_t
|
|||||||
typedef struct _tf_http_listener_t
|
typedef struct _tf_http_listener_t
|
||||||
{
|
{
|
||||||
tf_http_t* http;
|
tf_http_t* http;
|
||||||
tf_tls_context_t* tls;
|
|
||||||
uv_tcp_t tcp;
|
uv_tcp_t tcp;
|
||||||
tf_http_cleanup_t* cleanup;
|
tf_http_cleanup_t* cleanup;
|
||||||
void* user_data;
|
void* user_data;
|
||||||
@@ -109,7 +106,6 @@ typedef struct _tf_http_t
|
|||||||
static const char* _http_connection_get_header(const tf_http_connection_t* connection, const char* name);
|
static const char* _http_connection_get_header(const tf_http_connection_t* connection, const char* name);
|
||||||
static void _http_connection_destroy(tf_http_connection_t* connection, const char* reason);
|
static void _http_connection_destroy(tf_http_connection_t* connection, const char* reason);
|
||||||
static void _http_timer_reset(tf_http_connection_t* connection);
|
static void _http_timer_reset(tf_http_connection_t* connection);
|
||||||
static void _http_tls_update(tf_http_connection_t* connection);
|
|
||||||
static void _http_builtin_404_handler(tf_http_request_t* request);
|
static void _http_builtin_404_handler(tf_http_request_t* request);
|
||||||
|
|
||||||
tf_http_t* tf_http_create(uv_loop_t* loop)
|
tf_http_t* tf_http_create(uv_loop_t* loop)
|
||||||
@@ -260,11 +256,6 @@ static void _http_connection_destroy(tf_http_connection_t* connection, const cha
|
|||||||
{
|
{
|
||||||
uv_close((uv_handle_t*)&connection->timeout, _http_connection_on_close);
|
uv_close((uv_handle_t*)&connection->timeout, _http_connection_on_close);
|
||||||
}
|
}
|
||||||
if (connection->tls)
|
|
||||||
{
|
|
||||||
tf_tls_session_destroy(connection->tls);
|
|
||||||
connection->tls = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connection->ref_count == 0 && !connection->tcp.data && !connection->shutdown.data && !connection->timeout.data)
|
if (connection->ref_count == 0 && !connection->tcp.data && !connection->shutdown.data && !connection->timeout.data)
|
||||||
{
|
{
|
||||||
@@ -446,7 +437,6 @@ static void _http_add_body_bytes(tf_http_connection_t* connection, const void* d
|
|||||||
*request = (tf_http_request_t) {
|
*request = (tf_http_request_t) {
|
||||||
.http = connection->http,
|
.http = connection->http,
|
||||||
.connection = connection,
|
.connection = connection,
|
||||||
.is_tls = connection->tls != NULL,
|
|
||||||
.method = connection->method,
|
.method = connection->method,
|
||||||
.path = connection->path,
|
.path = connection->path,
|
||||||
.query = connection->query,
|
.query = connection->query,
|
||||||
@@ -587,21 +577,7 @@ static void _http_on_read(uv_stream_t* stream, ssize_t read_size, const uv_buf_t
|
|||||||
_http_timer_reset(connection);
|
_http_timer_reset(connection);
|
||||||
if (read_size > 0)
|
if (read_size > 0)
|
||||||
{
|
{
|
||||||
if (connection->tls)
|
_http_on_read_plain(connection, buffer->base, read_size);
|
||||||
{
|
|
||||||
if (tf_tls_session_write_encrypted(connection->tls, buffer->base, read_size) < 0)
|
|
||||||
{
|
|
||||||
_http_connection_destroy(connection, "tf_tls_session_write_encrypted");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_http_tls_update(connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_http_on_read_plain(connection, buffer->base, read_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (read_size < 0)
|
else if (read_size < 0)
|
||||||
{
|
{
|
||||||
@@ -643,17 +619,6 @@ static void _http_on_connection(uv_stream_t* stream, int status)
|
|||||||
|
|
||||||
tf_http_connection_t* connection = tf_malloc(sizeof(tf_http_connection_t));
|
tf_http_connection_t* connection = tf_malloc(sizeof(tf_http_connection_t));
|
||||||
*connection = (tf_http_connection_t) { .http = http, .tcp = { .data = connection }, .is_receiving_headers = true };
|
*connection = (tf_http_connection_t) { .http = http, .tcp = { .data = connection }, .is_receiving_headers = true };
|
||||||
if (listener->tls)
|
|
||||||
{
|
|
||||||
connection->tls = tf_tls_context_create_session(listener->tls);
|
|
||||||
if (!connection->tls)
|
|
||||||
{
|
|
||||||
_http_connection_destroy(connection, "tf_tls_context_create_session");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tf_tls_session_start_accept(connection->tls);
|
|
||||||
connection->is_handshaking = true;
|
|
||||||
}
|
|
||||||
int r = uv_tcp_init(connection->http->loop, &connection->tcp);
|
int r = uv_tcp_init(connection->http->loop, &connection->tcp);
|
||||||
if (r)
|
if (r)
|
||||||
{
|
{
|
||||||
@@ -694,21 +659,15 @@ static void _http_on_connection(uv_stream_t* stream, int status)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection->tls)
|
|
||||||
{
|
|
||||||
_http_tls_update(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
http->connections = tf_resize_vec(http->connections, sizeof(tf_http_connection_t*) * (http->connections_count + 1));
|
http->connections = tf_resize_vec(http->connections, sizeof(tf_http_connection_t*) * (http->connections_count + 1));
|
||||||
http->connections[http->connections_count++] = connection;
|
http->connections[http->connections_count++] = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tf_http_listen(tf_http_t* http, int port, bool local_only, tf_tls_context_t* tls, tf_http_cleanup_t* cleanup, void* user_data)
|
int tf_http_listen(tf_http_t* http, int port, bool local_only, tf_http_cleanup_t* cleanup, void* user_data)
|
||||||
{
|
{
|
||||||
tf_http_listener_t* listener = tf_malloc(sizeof(tf_http_listener_t));
|
tf_http_listener_t* listener = tf_malloc(sizeof(tf_http_listener_t));
|
||||||
*listener = (tf_http_listener_t) {
|
*listener = (tf_http_listener_t) {
|
||||||
.http = http,
|
.http = http,
|
||||||
.tls = tls,
|
|
||||||
.tcp = { .data = listener },
|
.tcp = { .data = listener },
|
||||||
.cleanup = cleanup,
|
.cleanup = cleanup,
|
||||||
.user_data = user_data,
|
.user_data = user_data,
|
||||||
@@ -948,71 +907,10 @@ static void _http_write_internal(tf_http_connection_t* connection, const void* d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _http_tls_update(tf_http_connection_t* connection)
|
|
||||||
{
|
|
||||||
bool again = true;
|
|
||||||
while (again)
|
|
||||||
{
|
|
||||||
again = false;
|
|
||||||
|
|
||||||
if (connection->is_handshaking && connection->tls)
|
|
||||||
{
|
|
||||||
switch (tf_tls_session_handshake(connection->tls))
|
|
||||||
{
|
|
||||||
case k_tls_handshake_done:
|
|
||||||
connection->is_handshaking = false;
|
|
||||||
break;
|
|
||||||
case k_tls_handshake_more:
|
|
||||||
break;
|
|
||||||
case k_tls_handshake_failed:
|
|
||||||
_http_connection_destroy(connection, "tf_tls_session_handshake");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Maybe we became disconnected and cleaned up our TLS session. */
|
|
||||||
if (connection->tls)
|
|
||||||
{
|
|
||||||
char buffer[8192];
|
|
||||||
int r = tf_tls_session_read_encrypted(connection->tls, buffer, sizeof(buffer));
|
|
||||||
if (r > 0)
|
|
||||||
{
|
|
||||||
_http_write_internal(connection, buffer, r);
|
|
||||||
again = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connection->tls)
|
|
||||||
{
|
|
||||||
char buffer[8192];
|
|
||||||
int r = tf_tls_session_read_plain(connection->tls, buffer, sizeof(buffer));
|
|
||||||
if (r > 0)
|
|
||||||
{
|
|
||||||
_http_on_read_plain(connection, buffer, r);
|
|
||||||
again = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _http_write(tf_http_connection_t* connection, const void* data, size_t size)
|
static void _http_write(tf_http_connection_t* connection, const void* data, size_t size)
|
||||||
{
|
{
|
||||||
_http_timer_reset(connection);
|
_http_timer_reset(connection);
|
||||||
if (connection->tls)
|
_http_write_internal(connection, data, size);
|
||||||
{
|
|
||||||
int r = tf_tls_session_write_plain(connection->tls, data, size);
|
|
||||||
if (r < (ssize_t)size)
|
|
||||||
{
|
|
||||||
char buffer[8192];
|
|
||||||
tf_tls_session_get_error(connection->tls, buffer, sizeof(buffer));
|
|
||||||
tf_printf("tf_tls_session_write_plain: %s\n", buffer);
|
|
||||||
}
|
|
||||||
_http_tls_update(connection);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_http_write_internal(connection, data, size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tf_http_request_websocket_send(tf_http_request_t* request, int op_code, const void* data, size_t size)
|
void tf_http_request_websocket_send(tf_http_request_t* request, int op_code, const void* data, size_t size)
|
||||||
|
@@ -23,9 +23,6 @@ typedef struct _tf_http_request_t tf_http_request_t;
|
|||||||
/** An HTTP instance. */
|
/** An HTTP instance. */
|
||||||
typedef struct _tf_http_t tf_http_t;
|
typedef struct _tf_http_t tf_http_t;
|
||||||
|
|
||||||
/** A TLS context. */
|
|
||||||
typedef struct _tf_tls_context_t tf_tls_context_t;
|
|
||||||
|
|
||||||
/** A trace instance. */
|
/** A trace instance. */
|
||||||
typedef struct _tf_trace_t tf_trace_t;
|
typedef struct _tf_trace_t tf_trace_t;
|
||||||
|
|
||||||
@@ -68,8 +65,6 @@ typedef struct _tf_http_request_t
|
|||||||
tf_http_t* http;
|
tf_http_t* http;
|
||||||
/** The HTTP connection associated with this request. */
|
/** The HTTP connection associated with this request. */
|
||||||
tf_http_connection_t* connection;
|
tf_http_connection_t* connection;
|
||||||
/** True if this is an HTTPS session. */
|
|
||||||
bool is_tls;
|
|
||||||
/** The HTTP method of the request (GET/POST/...). */
|
/** The HTTP method of the request (GET/POST/...). */
|
||||||
const char* method;
|
const char* method;
|
||||||
/** The HTTP request path. */
|
/** The HTTP request path. */
|
||||||
@@ -117,12 +112,11 @@ void tf_http_set_trace(tf_http_t* http, tf_trace_t* trace);
|
|||||||
** @param http The HTTP instance.
|
** @param http The HTTP instance.
|
||||||
** @param port The port on which to listen, or 0 to assign a free port.
|
** @param port The port on which to listen, or 0 to assign a free port.
|
||||||
** @param local_only Only access connections on localhost, otherwise any address.
|
** @param local_only Only access connections on localhost, otherwise any address.
|
||||||
** @param tls An optional TLS context to use for HTTPS requests.
|
|
||||||
** @param cleanup A function called when the HTTP instance is being cleaned up.
|
** @param cleanup A function called when the HTTP instance is being cleaned up.
|
||||||
** @param user_data User data passed to the cleanup callback.
|
** @param user_data User data passed to the cleanup callback.
|
||||||
** @return The port number on which the HTTP instance is now listening.
|
** @return The port number on which the HTTP instance is now listening.
|
||||||
*/
|
*/
|
||||||
int tf_http_listen(tf_http_t* http, int port, bool local_only, tf_tls_context_t* tls, tf_http_cleanup_t* cleanup, void* user_data);
|
int tf_http_listen(tf_http_t* http, int port, bool local_only, tf_http_cleanup_t* cleanup, void* user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Add an HTTP request handler.
|
** Add an HTTP request handler.
|
||||||
|
@@ -7,7 +7,6 @@
|
|||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
#include "ssb.db.h"
|
#include "ssb.db.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "tls.h"
|
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "util.js.h"
|
#include "util.js.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@@ -257,11 +256,6 @@ JSValue tf_httpd_make_response_object(JSContext* context, tf_http_request_t* req
|
|||||||
|
|
||||||
bool tf_httpd_redirect(tf_http_request_t* request)
|
bool tf_httpd_redirect(tf_http_request_t* request)
|
||||||
{
|
{
|
||||||
if (request->is_tls)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
http_user_data_t* user_data = tf_http_get_user_data(request->http);
|
http_user_data_t* user_data = tf_http_get_user_data(request->http);
|
||||||
if (!user_data || !*user_data->redirect)
|
if (!user_data || !*user_data->redirect)
|
||||||
{
|
{
|
||||||
@@ -276,16 +270,12 @@ bool tf_httpd_redirect(tf_http_request_t* request)
|
|||||||
|
|
||||||
typedef struct _httpd_listener_t
|
typedef struct _httpd_listener_t
|
||||||
{
|
{
|
||||||
tf_tls_context_t* tls;
|
int padding;
|
||||||
} httpd_listener_t;
|
} httpd_listener_t;
|
||||||
|
|
||||||
static void _httpd_listener_cleanup(void* user_data)
|
static void _httpd_listener_cleanup(void* user_data)
|
||||||
{
|
{
|
||||||
httpd_listener_t* listener = user_data;
|
httpd_listener_t* listener = user_data;
|
||||||
if (listener->tls)
|
|
||||||
{
|
|
||||||
tf_tls_context_destroy(listener->tls);
|
|
||||||
}
|
|
||||||
tf_free(listener);
|
tf_free(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,7 +564,7 @@ static void _httpd_endpoint_add_slash(tf_http_request_t* request)
|
|||||||
host = tf_http_request_get_header(request, "host");
|
host = tf_http_request_get_header(request, "host");
|
||||||
}
|
}
|
||||||
char url[1024];
|
char url[1024];
|
||||||
snprintf(url, sizeof(url), "%s%s%s/", request->is_tls ? "https://" : "http://", host, request->path);
|
snprintf(url, sizeof(url), "%s%s%s/", "http://", host, request->path);
|
||||||
const char* headers[] = {
|
const char* headers[] = {
|
||||||
"Location",
|
"Location",
|
||||||
url,
|
url,
|
||||||
@@ -860,31 +850,6 @@ bool tf_httpd_is_name_valid(const char* name)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _httpd_free_user_data(void* user_data)
|
|
||||||
{
|
|
||||||
tf_free(user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* _httpd_read_file(tf_task_t* task, const char* path)
|
|
||||||
{
|
|
||||||
const char* actual = tf_task_get_path_with_root(task, path);
|
|
||||||
const size_t k_max_read = 8 * 1024 * 1024;
|
|
||||||
char* result = NULL;
|
|
||||||
char* buffer = tf_malloc(k_max_read);
|
|
||||||
FILE* file = fopen(actual, "rb");
|
|
||||||
if (file)
|
|
||||||
{
|
|
||||||
size_t size = fread(buffer, 1, k_max_read, file);
|
|
||||||
result = tf_malloc(size + 1);
|
|
||||||
memcpy(result, buffer, size);
|
|
||||||
result[size] = '\0';
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
tf_free(buffer);
|
|
||||||
tf_free((char*)actual);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_httpd_register(JSContext* context)
|
void tf_httpd_register(JSContext* context)
|
||||||
{
|
{
|
||||||
JS_NewClassID(&_httpd_request_class_id);
|
JS_NewClassID(&_httpd_request_class_id);
|
||||||
@@ -913,36 +878,14 @@ tf_http_t* tf_httpd_create(JSContext* context)
|
|||||||
tf_http_set_trace(http, tf_task_get_trace(task));
|
tf_http_set_trace(http, tf_task_get_trace(task));
|
||||||
|
|
||||||
int64_t http_port = 0;
|
int64_t http_port = 0;
|
||||||
int64_t https_port = 0;
|
|
||||||
char out_http_port_file[512] = "";
|
char out_http_port_file[512] = "";
|
||||||
bool local_only = false;
|
bool local_only = false;
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
tf_ssb_db_get_global_setting_int64(db, "http_port", &http_port);
|
tf_ssb_db_get_global_setting_int64(db, "http_port", &http_port);
|
||||||
tf_ssb_db_get_global_setting_int64(db, "https_port", &https_port);
|
|
||||||
tf_ssb_db_get_global_setting_string(db, "out_http_port_file", out_http_port_file, sizeof(out_http_port_file));
|
tf_ssb_db_get_global_setting_string(db, "out_http_port_file", out_http_port_file, sizeof(out_http_port_file));
|
||||||
tf_ssb_db_get_global_setting_bool(db, "http_local_only", &local_only);
|
tf_ssb_db_get_global_setting_bool(db, "http_local_only", &local_only);
|
||||||
tf_ssb_release_db_reader(ssb, db);
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
|
|
||||||
if (https_port)
|
|
||||||
{
|
|
||||||
http_user_data_t* user_data = tf_http_get_user_data(http);
|
|
||||||
if (!user_data)
|
|
||||||
{
|
|
||||||
user_data = tf_malloc(sizeof(http_user_data_t));
|
|
||||||
memset(user_data, 0, sizeof(http_user_data_t));
|
|
||||||
tf_http_set_user_data(http, user_data, _httpd_free_user_data);
|
|
||||||
}
|
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
|
||||||
tf_ssb_db_get_global_setting_string(db, "http_redirect", user_data->redirect, sizeof(user_data->redirect));
|
|
||||||
tf_ssb_release_db_reader(ssb, db);
|
|
||||||
|
|
||||||
/* Workaround. */
|
|
||||||
if (strcmp(user_data->redirect, "0") == 0)
|
|
||||||
{
|
|
||||||
*user_data->redirect = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tf_http_add_handler(http, "/", _httpd_endpoint_root, NULL, task);
|
tf_http_add_handler(http, "/", _httpd_endpoint_root, NULL, task);
|
||||||
tf_http_add_handler(http, "/codemirror/*", tf_httpd_endpoint_static, NULL, task);
|
tf_http_add_handler(http, "/codemirror/*", tf_httpd_endpoint_static, NULL, task);
|
||||||
tf_http_add_handler(http, "/lit/*", tf_httpd_endpoint_static, NULL, task);
|
tf_http_add_handler(http, "/lit/*", tf_httpd_endpoint_static, NULL, task);
|
||||||
@@ -977,7 +920,7 @@ tf_http_t* tf_httpd_create(JSContext* context)
|
|||||||
{
|
{
|
||||||
httpd_listener_t* listener = tf_malloc(sizeof(httpd_listener_t));
|
httpd_listener_t* listener = tf_malloc(sizeof(httpd_listener_t));
|
||||||
*listener = (httpd_listener_t) { 0 };
|
*listener = (httpd_listener_t) { 0 };
|
||||||
int assigned_port = tf_http_listen(http, http_port, local_only, NULL, _httpd_listener_cleanup, listener);
|
int assigned_port = tf_http_listen(http, http_port, local_only, _httpd_listener_cleanup, listener);
|
||||||
tf_printf(CYAN "~😎 Tilde Friends" RESET " " YELLOW VERSION_NUMBER RESET " is now up at " MAGENTA "http://127.0.0.1:%d/" RESET ".\n", assigned_port);
|
tf_printf(CYAN "~😎 Tilde Friends" RESET " " YELLOW VERSION_NUMBER RESET " is now up at " MAGENTA "http://127.0.0.1:%d/" RESET ".\n", assigned_port);
|
||||||
|
|
||||||
if (*out_http_port_file)
|
if (*out_http_port_file)
|
||||||
@@ -996,26 +939,6 @@ tf_http_t* tf_httpd_create(JSContext* context)
|
|||||||
}
|
}
|
||||||
tf_free((char*)actual_http_port_file);
|
tf_free((char*)actual_http_port_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (https_port)
|
|
||||||
{
|
|
||||||
const char* k_certificate = "data/httpd/certificate.pem";
|
|
||||||
const char* k_private_key = "data/httpd/privatekey.pem";
|
|
||||||
const char* certificate = _httpd_read_file(task, k_certificate);
|
|
||||||
const char* private_key = _httpd_read_file(task, k_private_key);
|
|
||||||
if (certificate && private_key)
|
|
||||||
{
|
|
||||||
tf_tls_context_t* tls = tf_tls_context_create();
|
|
||||||
tf_tls_context_set_certificate(tls, certificate);
|
|
||||||
tf_tls_context_set_private_key(tls, private_key);
|
|
||||||
httpd_listener_t* listener = tf_malloc(sizeof(httpd_listener_t));
|
|
||||||
*listener = (httpd_listener_t) { .tls = tls };
|
|
||||||
int assigned_port = tf_http_listen(http, https_port, local_only, tls, _httpd_listener_cleanup, listener);
|
|
||||||
tf_printf(CYAN "~😎 Tilde Friends" RESET " " YELLOW VERSION_NUMBER RESET " is now up at " MAGENTA "https://127.0.0.1:%d/" RESET ".\n", assigned_port);
|
|
||||||
}
|
|
||||||
tf_free((char*)certificate);
|
|
||||||
tf_free((char*)private_key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return http;
|
return http;
|
||||||
}
|
}
|
||||||
|
@@ -37,11 +37,11 @@ typedef struct _login_request_t
|
|||||||
const char* tf_httpd_make_set_session_cookie_header(tf_http_request_t* request, const char* session_cookie)
|
const char* tf_httpd_make_set_session_cookie_header(tf_http_request_t* request, const char* session_cookie)
|
||||||
{
|
{
|
||||||
const char* k_pattern = "session=%s; path=/; Max-Age=%" PRId64 "; %sSameSite=Strict; HttpOnly";
|
const char* k_pattern = "session=%s; path=/; Max-Age=%" PRId64 "; %sSameSite=Strict; HttpOnly";
|
||||||
int length = session_cookie ? snprintf(NULL, 0, k_pattern, session_cookie, k_httpd_auth_refresh_interval, request->is_tls ? "Secure; " : "") : 0;
|
int length = session_cookie ? snprintf(NULL, 0, k_pattern, session_cookie, k_httpd_auth_refresh_interval, "") : 0;
|
||||||
char* cookie = length ? tf_malloc(length + 1) : NULL;
|
char* cookie = length ? tf_malloc(length + 1) : NULL;
|
||||||
if (cookie)
|
if (cookie)
|
||||||
{
|
{
|
||||||
snprintf(cookie, length + 1, k_pattern, session_cookie, k_httpd_auth_refresh_interval, request->is_tls ? "Secure; " : "");
|
snprintf(cookie, length + 1, k_pattern, session_cookie, k_httpd_auth_refresh_interval, "");
|
||||||
}
|
}
|
||||||
return cookie;
|
return cookie;
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@ static void _httpd_endpoint_login_work(tf_ssb_t* ssb, void* user_data)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(login->location_header, sizeof(login->location_header), "%s%s/", request->is_tls ? "https://" : "http://", tf_http_request_get_header(request, "host"));
|
snprintf(login->location_header, sizeof(login->location_header), "%s%s/", "http://", tf_http_request_get_header(request, "host"));
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@@ -332,7 +332,7 @@ static void _httpd_endpoint_login_work(tf_ssb_t* ssb, void* user_data)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(login->location_header, sizeof(login->location_header), "%s%s/", request->is_tls ? "https://" : "http://", tf_http_request_get_header(request, "host"));
|
snprintf(login->location_header, sizeof(login->location_header), "%s%s/", "http://", tf_http_request_get_header(request, "host"));
|
||||||
}
|
}
|
||||||
login->set_cookie_header = tf_httpd_make_set_session_cookie_header(request, send_session);
|
login->set_cookie_header = tf_httpd_make_set_session_cookie_header(request, send_session);
|
||||||
tf_free((void*)send_session);
|
tf_free((void*)send_session);
|
||||||
@@ -416,8 +416,7 @@ void tf_httpd_endpoint_login(tf_http_request_t* request)
|
|||||||
|
|
||||||
void tf_httpd_endpoint_logout(tf_http_request_t* request)
|
void tf_httpd_endpoint_logout(tf_http_request_t* request)
|
||||||
{
|
{
|
||||||
const char* k_set_cookie = request->is_tls ? "session=; path=/; Secure; SameSite=Strict; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly"
|
const char* k_set_cookie = "session=; path=/; SameSite=Strict; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly";
|
||||||
: "session=; path=/; SameSite=Strict; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly";
|
|
||||||
const char* k_location_format = "/login%s%s";
|
const char* k_location_format = "/login%s%s";
|
||||||
int length = snprintf(NULL, 0, k_location_format, request->query ? "?" : "", request->query);
|
int length = snprintf(NULL, 0, k_location_format, request->query ? "?" : "", request->query);
|
||||||
char* location = alloca(length + 1);
|
char* location = alloca(length + 1);
|
||||||
|
@@ -1502,13 +1502,11 @@ static int _tf_run_task(const tf_run_args_t* args, int index)
|
|||||||
tf_ssb_t* ssb = tf_task_get_ssb(task);
|
tf_ssb_t* ssb = tf_task_get_ssb(task);
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
int64_t http_port = 0;
|
int64_t http_port = 0;
|
||||||
int64_t https_port = 0;
|
|
||||||
char out_http_port_file[512] = "";
|
char out_http_port_file[512] = "";
|
||||||
tf_ssb_db_get_global_setting_int64(db, "http_port", &http_port);
|
tf_ssb_db_get_global_setting_int64(db, "http_port", &http_port);
|
||||||
tf_ssb_db_get_global_setting_int64(db, "https_port", &https_port);
|
|
||||||
tf_ssb_db_get_global_setting_string(db, "out_http_port_file", out_http_port_file, sizeof(out_http_port_file));
|
tf_ssb_db_get_global_setting_string(db, "out_http_port_file", out_http_port_file, sizeof(out_http_port_file));
|
||||||
tf_ssb_release_db_reader(ssb, db);
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
if (http_port || https_port || *out_http_port_file)
|
if (http_port || *out_http_port_file)
|
||||||
{
|
{
|
||||||
if (args->zip)
|
if (args->zip)
|
||||||
{
|
{
|
||||||
@@ -1869,7 +1867,6 @@ static void _startup(int argc, char* argv[])
|
|||||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||||
#endif
|
#endif
|
||||||
tf_mem_replace_uv_allocator();
|
tf_mem_replace_uv_allocator();
|
||||||
tf_mem_replace_tls_allocator();
|
|
||||||
tf_mem_replace_sqlite_allocator();
|
tf_mem_replace_sqlite_allocator();
|
||||||
uv_setup_args(argc, argv);
|
uv_setup_args(argc, argv);
|
||||||
tf_taskstub_startup();
|
tf_taskstub_startup();
|
||||||
|
28
src/mem.c
28
src/mem.c
@@ -7,8 +7,6 @@
|
|||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
|
|
||||||
#include <openssl/crypto.h>
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -19,7 +17,6 @@ static bool s_mem_tracking;
|
|||||||
static tf_mem_node_t* s_mem_tracked;
|
static tf_mem_node_t* s_mem_tracked;
|
||||||
static int64_t s_tf_malloc_size;
|
static int64_t s_tf_malloc_size;
|
||||||
static int64_t s_uv_malloc_size;
|
static int64_t s_uv_malloc_size;
|
||||||
static int64_t s_tls_malloc_size;
|
|
||||||
static int64_t s_js_malloc_size;
|
static int64_t s_js_malloc_size;
|
||||||
static int64_t s_sqlite_malloc_size;
|
static int64_t s_sqlite_malloc_size;
|
||||||
|
|
||||||
@@ -387,31 +384,6 @@ size_t tf_mem_get_uv_malloc_size()
|
|||||||
return s_uv_malloc_size;
|
return s_uv_malloc_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* _tf_tls_alloc(size_t size, const char* file, int line)
|
|
||||||
{
|
|
||||||
return _tf_alloc(&s_tls_malloc_size, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* _tf_tls_realloc(void* ptr, size_t size, const char* file, int line)
|
|
||||||
{
|
|
||||||
return _tf_realloc(&s_tls_malloc_size, ptr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _tf_tls_free(void* ptr, const char* file, int line)
|
|
||||||
{
|
|
||||||
_tf_free(&s_tls_malloc_size, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_mem_replace_tls_allocator()
|
|
||||||
{
|
|
||||||
CRYPTO_set_mem_functions(_tf_tls_alloc, _tf_tls_realloc, _tf_tls_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t tf_mem_get_tls_malloc_size()
|
|
||||||
{
|
|
||||||
return s_tls_malloc_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* tf_malloc(size_t size)
|
void* tf_malloc(size_t size)
|
||||||
{
|
{
|
||||||
return _tf_alloc(&s_tf_malloc_size, size);
|
return _tf_alloc(&s_tf_malloc_size, size);
|
||||||
|
13
src/mem.h
13
src/mem.h
@@ -3,7 +3,7 @@
|
|||||||
/**
|
/**
|
||||||
** \defgroup mem Memory management
|
** \defgroup mem Memory management
|
||||||
** tf_malloc() and friends use malloc() behind the scenes but optionally
|
** tf_malloc() and friends use malloc() behind the scenes but optionally
|
||||||
** track memory per system (OpenSSL, sqlite, libuv, ...) and store callstacks
|
** track memory per system (sqlite, libuv, ...) and store callstacks
|
||||||
** to help debug leaks.
|
** to help debug leaks.
|
||||||
** @{
|
** @{
|
||||||
*/
|
*/
|
||||||
@@ -38,17 +38,6 @@ void tf_mem_replace_uv_allocator();
|
|||||||
*/
|
*/
|
||||||
size_t tf_mem_get_uv_malloc_size();
|
size_t tf_mem_get_uv_malloc_size();
|
||||||
|
|
||||||
/**
|
|
||||||
** Register a custom allocator with OpenSSL.
|
|
||||||
*/
|
|
||||||
void tf_mem_replace_tls_allocator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Get the number of bytes currently allocated by OpenSSL.
|
|
||||||
** @return The allocated size in bytes.
|
|
||||||
*/
|
|
||||||
size_t tf_mem_get_tls_malloc_size();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Register a custom allocator with SQLite.
|
** Register a custom allocator with SQLite.
|
||||||
*/
|
*/
|
||||||
|
@@ -923,7 +923,7 @@ static void _write_file(const char* path, const char* contents)
|
|||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_ARGS " --args=ssb_port=0,http_port=0,https_port=0"
|
#define TEST_ARGS " --args=ssb_port=0,http_port=0"
|
||||||
|
|
||||||
void tf_ssb_test_encrypt(const tf_test_options_t* options)
|
void tf_ssb_test_encrypt(const tf_test_options_t* options)
|
||||||
{
|
{
|
||||||
|
@@ -26,8 +26,6 @@
|
|||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
|
||||||
#include <openssl/crypto.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -707,11 +705,6 @@ static JSValue _tf_task_version(JSContext* context, JSValueConst this_val, int a
|
|||||||
JS_SetPropertyStr(context, version, "name", JS_NewString(context, VERSION_NAME));
|
JS_SetPropertyStr(context, version, "name", JS_NewString(context, VERSION_NAME));
|
||||||
JS_SetPropertyStr(context, version, "libuv", JS_NewString(context, uv_version_string()));
|
JS_SetPropertyStr(context, version, "libuv", JS_NewString(context, uv_version_string()));
|
||||||
JS_SetPropertyStr(context, version, "sqlite", JS_NewString(context, sqlite3_libversion()));
|
JS_SetPropertyStr(context, version, "sqlite", JS_NewString(context, sqlite3_libversion()));
|
||||||
#if defined(OPENSSL_VERSION_STRING)
|
|
||||||
JS_SetPropertyStr(context, version, "openssl", JS_NewString(context, OpenSSL_version(OPENSSL_VERSION_STRING)));
|
|
||||||
#else
|
|
||||||
JS_SetPropertyStr(context, version, "openssl", JS_NewString(context, OpenSSL_version(OPENSSL_VERSION)));
|
|
||||||
#endif
|
|
||||||
const char* sodium_version_string();
|
const char* sodium_version_string();
|
||||||
JS_SetPropertyStr(context, version, "c-ares", JS_NewString(context, ares_version(NULL)));
|
JS_SetPropertyStr(context, version, "c-ares", JS_NewString(context, ares_version(NULL)));
|
||||||
JS_SetPropertyStr(context, version, "libsodium", JS_NewString(context, sodium_version_string()));
|
JS_SetPropertyStr(context, version, "libsodium", JS_NewString(context, sodium_version_string()));
|
||||||
@@ -822,7 +815,6 @@ static JSValue _tf_task_getStats(JSContext* context, JSValueConst this_val, int
|
|||||||
JS_SetPropertyStr(context, result, "sqlite3_memory_percent", JS_NewFloat64(context, 100.0 * tf_mem_get_sqlite_malloc_size() / total_memory));
|
JS_SetPropertyStr(context, result, "sqlite3_memory_percent", JS_NewFloat64(context, 100.0 * tf_mem_get_sqlite_malloc_size() / total_memory));
|
||||||
JS_SetPropertyStr(context, result, "js_malloc_percent", JS_NewFloat64(context, 100.0 * tf_mem_get_js_malloc_size() / total_memory));
|
JS_SetPropertyStr(context, result, "js_malloc_percent", JS_NewFloat64(context, 100.0 * tf_mem_get_js_malloc_size() / total_memory));
|
||||||
JS_SetPropertyStr(context, result, "uv_malloc_percent", JS_NewFloat64(context, 100.0 * tf_mem_get_uv_malloc_size() / total_memory));
|
JS_SetPropertyStr(context, result, "uv_malloc_percent", JS_NewFloat64(context, 100.0 * tf_mem_get_uv_malloc_size() / total_memory));
|
||||||
JS_SetPropertyStr(context, result, "tls_malloc_percent", JS_NewFloat64(context, 100.0 * tf_mem_get_tls_malloc_size() / total_memory));
|
|
||||||
JS_SetPropertyStr(context, result, "tf_malloc_percent", JS_NewFloat64(context, 100.0 * tf_mem_get_tf_malloc_size() / total_memory));
|
JS_SetPropertyStr(context, result, "tf_malloc_percent", JS_NewFloat64(context, 100.0 * tf_mem_get_tf_malloc_size() / total_memory));
|
||||||
|
|
||||||
if (task->_ssb)
|
if (task->_ssb)
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TEST_ARGS " --args=ssb_port=0,http_port=0,https_port=0"
|
#define TEST_ARGS " --args=ssb_port=0,http_port=0"
|
||||||
|
|
||||||
#if !TARGET_OS_IPHONE
|
#if !TARGET_OS_IPHONE
|
||||||
static void _write_file(const char* path, const char* contents)
|
static void _write_file(const char* path, const char* contents)
|
||||||
@@ -694,7 +694,7 @@ static void _test_http(const tf_test_options_t* options)
|
|||||||
tf_http_t* http = tf_http_create(&loop);
|
tf_http_t* http = tf_http_create(&loop);
|
||||||
tf_http_add_handler(http, "/hello", _test_http_handler, NULL, NULL);
|
tf_http_add_handler(http, "/hello", _test_http_handler, NULL, NULL);
|
||||||
tf_http_add_handler(http, "/post", _test_http_handler_post, NULL, NULL);
|
tf_http_add_handler(http, "/post", _test_http_handler_post, NULL, NULL);
|
||||||
tf_http_listen(http, 23456, true, NULL, NULL, NULL);
|
tf_http_listen(http, 23456, true, NULL, NULL);
|
||||||
|
|
||||||
test_http_t test = { .loop = &loop };
|
test_http_t test = { .loop = &loop };
|
||||||
uv_async_init(&loop, &test.async, _test_http_async);
|
uv_async_init(&loop, &test.async, _test_http_async);
|
||||||
@@ -786,7 +786,7 @@ static void _test_httpd(const tf_test_options_t* options)
|
|||||||
uv_spawn(&loop, &process,
|
uv_spawn(&loop, &process,
|
||||||
&(uv_process_options_t) {
|
&(uv_process_options_t) {
|
||||||
.file = options->exe_path,
|
.file = options->exe_path,
|
||||||
.args = (char*[]) { (char*)options->exe_path, "run", "--db-path=out/test_db0.sqlite", "--args=ssb_port=0,http_port=8080,https_port=0", NULL },
|
.args = (char*[]) { (char*)options->exe_path, "run", "--db-path=out/test_db0.sqlite", "--args=ssb_port=0,http_port=8080", NULL },
|
||||||
.stdio_count = sizeof(stdio) / sizeof(*stdio),
|
.stdio_count = sizeof(stdio) / sizeof(*stdio),
|
||||||
.stdio = stdio,
|
.stdio = stdio,
|
||||||
});
|
});
|
||||||
|
384
src/tls.c
384
src/tls.c
@@ -1,384 +0,0 @@
|
|||||||
#include "tls.h"
|
|
||||||
|
|
||||||
#include "mem.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <openssl/bio.h>
|
|
||||||
#include <openssl/err.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
#include <openssl/x509v3.h>
|
|
||||||
|
|
||||||
typedef enum _direction_t
|
|
||||||
{
|
|
||||||
k_direction_undetermined,
|
|
||||||
k_direction_accept,
|
|
||||||
k_direction_connect,
|
|
||||||
} direction_t;
|
|
||||||
|
|
||||||
typedef struct _tf_tls_context_t
|
|
||||||
{
|
|
||||||
SSL_CTX* context;
|
|
||||||
} tf_tls_context_t;
|
|
||||||
|
|
||||||
typedef struct _tf_tls_session_t
|
|
||||||
{
|
|
||||||
tf_tls_context_t* context;
|
|
||||||
BIO* bio_in;
|
|
||||||
BIO* bio_out;
|
|
||||||
SSL* ssl;
|
|
||||||
const char* hostname;
|
|
||||||
direction_t direction;
|
|
||||||
} tf_tls_session_t;
|
|
||||||
|
|
||||||
tf_tls_context_t* tf_tls_context_create()
|
|
||||||
{
|
|
||||||
tf_tls_context_t* context = tf_malloc(sizeof(tf_tls_context_t));
|
|
||||||
memset(context, 0, sizeof(*context));
|
|
||||||
OPENSSL_init_ssl(0, NULL);
|
|
||||||
context->context = SSL_CTX_new(SSLv23_method());
|
|
||||||
SSL_CTX_set_default_verify_paths(context->context);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tf_tls_context_set_certificate(tf_tls_context_t* context, const char* certificate)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
BIO* bio = BIO_new(BIO_s_mem());
|
|
||||||
BIO_puts(bio, certificate);
|
|
||||||
X509* x509 = PEM_read_bio_X509(bio, 0, 0, 0);
|
|
||||||
result = SSL_CTX_use_certificate(context->context, x509);
|
|
||||||
X509_free(x509);
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
x509 = PEM_read_bio_X509(bio, 0, 0, 0);
|
|
||||||
if (x509)
|
|
||||||
{
|
|
||||||
SSL_CTX_add_extra_chain_cert(context->context, x509);
|
|
||||||
/* Docs say don't x509_free: https://www.openssl.org/docs/man3.2/man3/SSL_CTX_add_extra_chain_cert.html. */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIO_free(bio);
|
|
||||||
return result == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tf_tls_context_set_private_key(tf_tls_context_t* context, const char* private_key)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
BIO* bio = BIO_new(BIO_s_mem());
|
|
||||||
BIO_puts(bio, private_key);
|
|
||||||
EVP_PKEY* key = PEM_read_bio_PrivateKey(bio, 0, 0, 0);
|
|
||||||
result = SSL_CTX_use_PrivateKey(context->context, key);
|
|
||||||
EVP_PKEY_free(key);
|
|
||||||
BIO_free(bio);
|
|
||||||
return result == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tf_tls_context_add_trusted_certificate(tf_tls_context_t* context, const char* certificate)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
BIO* bio = BIO_new_mem_buf(certificate, -1);
|
|
||||||
X509* x509 = PEM_read_bio_X509(bio, 0, 0, 0);
|
|
||||||
BIO_free(bio);
|
|
||||||
|
|
||||||
if (x509)
|
|
||||||
{
|
|
||||||
X509_STORE* store = SSL_CTX_get_cert_store(context->context);
|
|
||||||
if (store && X509_STORE_add_cert(store, x509) == 1)
|
|
||||||
{
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
X509_free(x509);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
tf_tls_session_t* tf_tls_context_create_session(tf_tls_context_t* context)
|
|
||||||
{
|
|
||||||
tf_tls_session_t* session = tf_malloc(sizeof(tf_tls_session_t));
|
|
||||||
memset(session, 0, sizeof(*session));
|
|
||||||
session->context = context;
|
|
||||||
session->bio_in = BIO_new(BIO_s_mem());
|
|
||||||
session->bio_out = BIO_new(BIO_s_mem());
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_tls_context_destroy(tf_tls_context_t* context)
|
|
||||||
{
|
|
||||||
SSL_CTX_free(context->context);
|
|
||||||
OPENSSL_cleanup();
|
|
||||||
tf_free(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_tls_session_destroy(tf_tls_session_t* session)
|
|
||||||
{
|
|
||||||
if (session->ssl)
|
|
||||||
{
|
|
||||||
SSL_free(session->ssl);
|
|
||||||
}
|
|
||||||
if (session->hostname)
|
|
||||||
{
|
|
||||||
tf_free((void*)session->hostname);
|
|
||||||
}
|
|
||||||
tf_free(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_tls_session_set_hostname(tf_tls_session_t* session, const char* hostname)
|
|
||||||
{
|
|
||||||
if (session->hostname)
|
|
||||||
{
|
|
||||||
tf_free((void*)session->hostname);
|
|
||||||
session->hostname = NULL;
|
|
||||||
}
|
|
||||||
if (hostname)
|
|
||||||
{
|
|
||||||
session->hostname = tf_strdup(hostname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_tls_session_start_accept(tf_tls_session_t* session)
|
|
||||||
{
|
|
||||||
session->direction = k_direction_accept;
|
|
||||||
session->ssl = SSL_new(session->context->context);
|
|
||||||
SSL_set_bio(session->ssl, session->bio_in, session->bio_out);
|
|
||||||
SSL_accept(session->ssl);
|
|
||||||
tf_tls_session_handshake(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_tls_session_start_connect(tf_tls_session_t* session)
|
|
||||||
{
|
|
||||||
session->direction = k_direction_connect;
|
|
||||||
session->ssl = SSL_new(session->context->context);
|
|
||||||
X509_VERIFY_PARAM* param = SSL_get0_param(session->ssl);
|
|
||||||
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
|
||||||
X509_VERIFY_PARAM_set1_host(param, session->hostname, 0);
|
|
||||||
SSL_set_tlsext_host_name(session->ssl, session->hostname);
|
|
||||||
SSL_set_bio(session->ssl, session->bio_in, session->bio_out);
|
|
||||||
SSL_connect(session->ssl);
|
|
||||||
tf_tls_session_handshake(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_tls_session_shutdown(tf_tls_session_t* session)
|
|
||||||
{
|
|
||||||
SSL_shutdown(session->ssl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int tf_tls_session_get_peer_certificate(tf_tls_session_t* session, char* buffer, size_t bytes)
|
|
||||||
{
|
|
||||||
int result = -1;
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
|
||||||
X509* certificate = SSL_get_peer_certificate(session->ssl);
|
|
||||||
#else
|
|
||||||
X509* certificate = SSL_get1_peer_certificate(session->ssl);
|
|
||||||
#endif
|
|
||||||
BIO* bio = BIO_new(BIO_s_mem());
|
|
||||||
PEM_write_bio_X509(bio, certificate);
|
|
||||||
X509_free(certificate);
|
|
||||||
BUF_MEM* mem;
|
|
||||||
BIO_get_mem_ptr(bio, &mem);
|
|
||||||
if (mem->length <= bytes)
|
|
||||||
{
|
|
||||||
memcpy(buffer, mem->data, mem->length);
|
|
||||||
result = mem->length;
|
|
||||||
}
|
|
||||||
BIO_free(bio);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
||||||
static bool _tls_session_wildcard_match(const char* pattern, size_t pattern_length, const char* name)
|
|
||||||
{
|
|
||||||
const char* it = pattern;
|
|
||||||
while (it - pattern < pattern_length && *name)
|
|
||||||
{
|
|
||||||
if (*it == '*')
|
|
||||||
{
|
|
||||||
for (const char* p = name; *p; ++p)
|
|
||||||
{
|
|
||||||
if (_tls_session_wildcard_match(it + 1, pattern_length - 1, p))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (tolower(*it) == tolower(*name))
|
|
||||||
{
|
|
||||||
++it;
|
|
||||||
++name;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return it - pattern <= pattern_length && *name == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _tls_session_verify_hostname(X509* certificate, const char* hostname)
|
|
||||||
{
|
|
||||||
bool verified = false;
|
|
||||||
void* names = X509_get_ext_d2i(certificate, NID_subject_alt_name, 0, 0);
|
|
||||||
if (names)
|
|
||||||
{
|
|
||||||
int count = sk_GENERAL_NAME_num(names);
|
|
||||||
for (int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
const GENERAL_NAME* check = sk_GENERAL_NAME_value(names, i);
|
|
||||||
if (!verified)
|
|
||||||
{
|
|
||||||
#if OPENSSL_VERSION_NUMBER <= 0x1000211fL
|
|
||||||
const unsigned char* name = ASN1_STRING_data(check->d.ia5);
|
|
||||||
#else
|
|
||||||
const char* name = ASN1_STRING_get0_data(check->d.ia5);
|
|
||||||
#endif
|
|
||||||
size_t length = ASN1_STRING_length(check->d.ia5);
|
|
||||||
if (_tls_session_wildcard_match((const char*)name, length, hostname))
|
|
||||||
{
|
|
||||||
verified = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sk_GENERAL_NAMES_free(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!verified)
|
|
||||||
{
|
|
||||||
int index = X509_NAME_get_index_by_NID(X509_get_subject_name(certificate), NID_commonName, -1);
|
|
||||||
if (index >= 0)
|
|
||||||
{
|
|
||||||
X509_NAME_ENTRY* entry = X509_NAME_get_entry(X509_get_subject_name(certificate), index);
|
|
||||||
if (entry)
|
|
||||||
{
|
|
||||||
ASN1_STRING* asn1 = X509_NAME_ENTRY_get_data(entry);
|
|
||||||
if (asn1)
|
|
||||||
{
|
|
||||||
#if OPENSSL_VERSION_NUMBER <= 0x1000211fL
|
|
||||||
const unsigned char* commonName = ASN1_STRING_data(asn1);
|
|
||||||
#else
|
|
||||||
const char* commonName = ASN1_STRING_get0_data(asn1);
|
|
||||||
#endif
|
|
||||||
if ((size_t)(ASN1_STRING_length(asn1)) == strlen((const char*)commonName))
|
|
||||||
{
|
|
||||||
verified = _tls_session_wildcard_match((const char*)commonName, ASN1_STRING_length(asn1), hostname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return verified;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool _tls_session_verify_peer_certificate(tf_tls_session_t* session)
|
|
||||||
{
|
|
||||||
bool verified = false;
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
|
||||||
X509* certificate = SSL_get_peer_certificate(session->ssl);
|
|
||||||
#else
|
|
||||||
X509* certificate = SSL_get1_peer_certificate(session->ssl);
|
|
||||||
#endif
|
|
||||||
if (certificate)
|
|
||||||
{
|
|
||||||
if (SSL_get_verify_result(session->ssl) == X509_V_OK)
|
|
||||||
{
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
||||||
if (_tls_session_verify_hostname(certificate, session->hostname))
|
|
||||||
{
|
|
||||||
verified = true;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
verified = true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
X509_free(certificate);
|
|
||||||
}
|
|
||||||
return verified;
|
|
||||||
}
|
|
||||||
|
|
||||||
tf_tls_handshake_t tf_tls_session_handshake(tf_tls_session_t* session)
|
|
||||||
{
|
|
||||||
tf_tls_handshake_t result = k_tls_handshake_done;
|
|
||||||
if (!SSL_is_init_finished(session->ssl))
|
|
||||||
{
|
|
||||||
int value = SSL_do_handshake(session->ssl);
|
|
||||||
if (value <= 0)
|
|
||||||
{
|
|
||||||
int error = SSL_get_error(session->ssl, value);
|
|
||||||
if (error != SSL_ERROR_WANT_READ && error != SSL_ERROR_WANT_WRITE)
|
|
||||||
{
|
|
||||||
result = k_tls_handshake_failed;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = k_tls_handshake_more;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result == k_tls_handshake_done && session->direction == k_direction_connect && !_tls_session_verify_peer_certificate(session))
|
|
||||||
{
|
|
||||||
result = k_tls_handshake_failed;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tf_tls_session_read_plain(tf_tls_session_t* session, char* buffer, size_t bytes)
|
|
||||||
{
|
|
||||||
int result = SSL_read(session->ssl, buffer, bytes);
|
|
||||||
if (result <= 0)
|
|
||||||
{
|
|
||||||
int error = SSL_get_error(session->ssl, result);
|
|
||||||
if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
else if (error == SSL_ERROR_ZERO_RETURN)
|
|
||||||
{
|
|
||||||
if ((SSL_get_shutdown(session->ssl) & SSL_RECEIVED_SHUTDOWN) != 0)
|
|
||||||
{
|
|
||||||
result = k_tls_read_zero;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = k_tls_read_failed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tf_tls_session_write_plain(tf_tls_session_t* session, const char* buffer, size_t bytes)
|
|
||||||
{
|
|
||||||
return SSL_write(session->ssl, buffer, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
int tf_tls_session_read_encrypted(tf_tls_session_t* session, char* buffer, size_t bytes)
|
|
||||||
{
|
|
||||||
return BIO_read(session->bio_out, buffer, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
int tf_tls_session_write_encrypted(tf_tls_session_t* session, const char* buffer, size_t bytes)
|
|
||||||
{
|
|
||||||
return BIO_write(session->bio_in, buffer, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tf_tls_session_get_error(tf_tls_session_t* session, char* buffer, size_t bytes)
|
|
||||||
{
|
|
||||||
unsigned long error = ERR_get_error();
|
|
||||||
if (error != 0)
|
|
||||||
{
|
|
||||||
ERR_error_string_n(error, buffer, bytes);
|
|
||||||
}
|
|
||||||
return error != 0;
|
|
||||||
}
|
|
177
src/tls.h
177
src/tls.h
@@ -1,177 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/**
|
|
||||||
** \defgroup tls TLS
|
|
||||||
** A minimal wrapper around OpenSSL.
|
|
||||||
** @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
** A TLS context. May have many tf_tls_session_t instances.
|
|
||||||
*/
|
|
||||||
typedef struct _tf_tls_context_t tf_tls_context_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
** A TLS session. Belongs to one tf_tls_context_t and represents a single connection.
|
|
||||||
*/
|
|
||||||
typedef struct _tf_tls_session_t tf_tls_session_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
** The state of a TLS handshake.
|
|
||||||
*/
|
|
||||||
typedef enum _tf_tls_handshake_t
|
|
||||||
{
|
|
||||||
k_tls_handshake_done,
|
|
||||||
k_tls_handshake_more,
|
|
||||||
k_tls_handshake_failed,
|
|
||||||
} tf_tls_handshake_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Possible error statuses from tf_tls_session_read_plain.
|
|
||||||
*/
|
|
||||||
typedef enum _tf_tls_read_t
|
|
||||||
{
|
|
||||||
k_tls_read_zero = -1,
|
|
||||||
k_tls_read_failed = -2,
|
|
||||||
} tf_tls_read_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Create a TLS context. Clean up with tf_tls_context_destroy().
|
|
||||||
** @return A new TLS context.
|
|
||||||
*/
|
|
||||||
tf_tls_context_t* tf_tls_context_create();
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Set the TLS context's server certificate.
|
|
||||||
** @param context The TLS context.
|
|
||||||
** @param certificate The certificate in PEM format.
|
|
||||||
** @return true if set successfully.
|
|
||||||
*/
|
|
||||||
bool tf_tls_context_set_certificate(tf_tls_context_t* context, const char* certificate);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Set the TLS context's server certificate's private key.
|
|
||||||
** @param context The TLS context.
|
|
||||||
** @param private_key The private key in PEM format.
|
|
||||||
** @return true if set successfully.
|
|
||||||
*/
|
|
||||||
bool tf_tls_context_set_private_key(tf_tls_context_t* context, const char* private_key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Add a trusted certificate.
|
|
||||||
** @param context The TLS context.
|
|
||||||
** @param certificate The certificate in PEM format.
|
|
||||||
** @return true if the certificate was added to the trusted list successfully.
|
|
||||||
*/
|
|
||||||
bool tf_tls_context_add_trusted_certificate(tf_tls_context_t* context, const char* certificate);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Create a TLS session from a context. Once created, call
|
|
||||||
** tf_tls_session_handshake() until it returns k_tls_handshake_done. Call
|
|
||||||
** tf_tls_session_[read/write]_[plain/encrypted]() as data is available.
|
|
||||||
** @param context The TLS context. Clean up with tf_tls_session_destroy().
|
|
||||||
** @return A new TLS session.
|
|
||||||
*/
|
|
||||||
tf_tls_session_t* tf_tls_context_create_session(tf_tls_context_t* context);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Destroy a TLS context.
|
|
||||||
** @param context The TLS contextx created by tf_tls_context_create().
|
|
||||||
*/
|
|
||||||
void tf_tls_context_destroy(tf_tls_context_t* context);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Destroy a TLS session.
|
|
||||||
** @param session A TLS sesssion created by tf_tls_context_create_session().
|
|
||||||
*/
|
|
||||||
void tf_tls_session_destroy(tf_tls_session_t* session);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Set the remote hostname for a session.
|
|
||||||
** @param session The TLS session.
|
|
||||||
** @param hostname The hostname.
|
|
||||||
*/
|
|
||||||
void tf_tls_session_set_hostname(tf_tls_session_t* session, const char* hostname);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Begin an outgoing TLS session.
|
|
||||||
** @param session The TLS session.
|
|
||||||
*/
|
|
||||||
void tf_tls_session_start_accept(tf_tls_session_t* session);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Begin an incoming TLS session.
|
|
||||||
** @param session The TLS session.
|
|
||||||
*/
|
|
||||||
void tf_tls_session_start_connect(tf_tls_session_t* session);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Begin the clean shutdown process for a TLS session.
|
|
||||||
** @param session The TLS session.
|
|
||||||
*/
|
|
||||||
void tf_tls_session_shutdown(tf_tls_session_t* session);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Get the certificate from the remote end of a TLS session if available.
|
|
||||||
** @param session The TLS session.
|
|
||||||
** @param buffer A buffer to receive the certificate.
|
|
||||||
** @param bytes The size of the buffer.
|
|
||||||
** @return The size of the returned certificate, or -1 on failure.
|
|
||||||
*/
|
|
||||||
int tf_tls_session_get_peer_certificate(tf_tls_session_t* session, char* buffer, size_t bytes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Update the TLS handshake. Call repeatedly as new data is available until it returns done.
|
|
||||||
** @param session The TLS session.
|
|
||||||
** @return The current state of the handshake process.
|
|
||||||
*/
|
|
||||||
tf_tls_handshake_t tf_tls_session_handshake(tf_tls_session_t* session);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Read decrypted data from the TLS session.
|
|
||||||
** @param session The TLS session.
|
|
||||||
** @param buffer A buffer to receive the data.
|
|
||||||
** @param bytes The size of the buffer.
|
|
||||||
** @return The number of bytes returned.
|
|
||||||
*/
|
|
||||||
int tf_tls_session_read_plain(tf_tls_session_t* session, char* buffer, size_t bytes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Write unencrypted data to the TLS session.
|
|
||||||
** @param session The TLS session.
|
|
||||||
** @param buffer The data to encrypt.
|
|
||||||
** @param bytes The size of the data.
|
|
||||||
** @return 1 on success, 0 on failure.
|
|
||||||
*/
|
|
||||||
int tf_tls_session_write_plain(tf_tls_session_t* session, const char* buffer, size_t bytes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Read encrypted data from the TLS session that needs to be sent.
|
|
||||||
** @param session The TLS session.
|
|
||||||
** @param buffer A buffer to receive the data.
|
|
||||||
** @param bytes The size of the buffer.
|
|
||||||
** @return The number of bytes returned.
|
|
||||||
*/
|
|
||||||
int tf_tls_session_read_encrypted(tf_tls_session_t* session, char* buffer, size_t bytes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Write encrypted data to the TLS session.
|
|
||||||
** @param session The TLS session.
|
|
||||||
** @param buffer The encrypted data.
|
|
||||||
** @param bytes The number of bytes written.
|
|
||||||
*/
|
|
||||||
int tf_tls_session_write_encrypted(tf_tls_session_t* session, const char* buffer, size_t bytes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Retrieve the last error from a TLS session.
|
|
||||||
** @param session The TLS session.
|
|
||||||
** @param buffer A buffer to receive the error text.
|
|
||||||
** @param bytes The size of the buffer.
|
|
||||||
** @return true if an error was retrieved.
|
|
||||||
*/
|
|
||||||
bool tf_tls_session_get_error(tf_tls_session_t* session, char* buffer, size_t bytes);
|
|
||||||
|
|
||||||
/** @} */
|
|
@@ -289,7 +289,6 @@ static const setting_t k_settings[] = {
|
|||||||
.description = "Whether to bind http(s) to the loopback address. Otherwise any.",
|
.description = "Whether to bind http(s) to the loopback address. Otherwise any.",
|
||||||
.default_value = { .kind = k_kind_bool, .bool_value = TF_IS_MOBILE ? true : false } },
|
.default_value = { .kind = k_kind_bool, .bool_value = TF_IS_MOBILE ? true : false } },
|
||||||
{ .name = "http_port", .type = "integer", .description = "Port on which to listen for HTTP connections.", .default_value = { .kind = k_kind_int, .int_value = 12345 } },
|
{ .name = "http_port", .type = "integer", .description = "Port on which to listen for HTTP connections.", .default_value = { .kind = k_kind_int, .int_value = 12345 } },
|
||||||
{ .name = "https_port", .type = "integer", .description = "Port on which to listen for secure HTTP connections.", .default_value = { .kind = k_kind_int, .int_value = 0 } },
|
|
||||||
{ .name = "out_http_port_file", .type = "hidden", .description = "File to which to write bound HTTP port.", .default_value = { .kind = k_kind_string, .string_value = NULL } },
|
{ .name = "out_http_port_file", .type = "hidden", .description = "File to which to write bound HTTP port.", .default_value = { .kind = k_kind_string, .string_value = NULL } },
|
||||||
{ .name = "blob_fetch_age_seconds",
|
{ .name = "blob_fetch_age_seconds",
|
||||||
.type = "integer",
|
.type = "integer",
|
||||||
|
Reference in New Issue
Block a user