diff options
Diffstat (limited to 'src/tls')
-rw-r--r-- | src/tls/Makefile.in | 69 | ||||
-rw-r--r-- | src/tls/Makefile.win32 | 38 | ||||
-rw-r--r-- | src/tls/sha_drv.c | 120 | ||||
-rwxr-xr-x | src/tls/stdint.h | 232 | ||||
-rw-r--r-- | src/tls/tls.erl | 386 | ||||
-rw-r--r-- | src/tls/tls_drv.c | 653 |
6 files changed, 0 insertions, 1498 deletions
diff --git a/src/tls/Makefile.in b/src/tls/Makefile.in deleted file mode 100644 index ab5e32dfe..000000000 --- a/src/tls/Makefile.in +++ /dev/null @@ -1,69 +0,0 @@ -# $Id$ - -CC = @CC@ -CFLAGS = @CFLAGS@ -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ - -SSL_CFLAGS = @SSL_CFLAGS@ -SSL_LIBS = @SSL_LIBS@ - -ERLANG_CFLAGS = @ERLANG_CFLAGS@ -ERLANG_LIBS = @ERLANG_LIBS@ - -# Assume Linux-style dynamic library flags -DYNAMIC_LIB_CFLAGS = -fpic -shared -ifeq ($(shell uname),Darwin) - DYNAMIC_LIB_CFLAGS = -fPIC -bundle -flat_namespace -undefined suppress -endif -ifeq ($(shell uname),SunOs) - DYNAMIC_LIB_CFLAGS = -KPIC -G -z text -endif - -EFLAGS += -I .. -EFLAGS += -pz .. - -# make debug=true to compile Erlang module with debug informations. -ifdef debug - EFLAGS+=+debug_info -endif - -ifeq (@md2@, true) - EFLAGS+=-DHAVE_MD2 - ERLANG_CFLAGS += -DHAVE_MD2 -endif - -ERLSHLIBS = ../tls_drv.so ../sha_drv.so -OUTDIR = .. -SOURCES = $(wildcard *.erl) -BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam)) - - -all: $(BEAMS) $(ERLSHLIBS) - -$(OUTDIR)/%.beam: %.erl - @ERLC@ -W $(EFLAGS) -o $(OUTDIR) $< - -#all: $(ERLSHLIBS) -# erl -s make all report "{outdir, \"..\"}" -noinput -s erlang halt - -$(ERLSHLIBS): ../%.so: %.c - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) \ - $(subst ../,,$(subst .so,.c,$@)) \ - $(LIBS) \ - $(SSL_LIBS) \ - $(SSL_CFLAGS) \ - $(ERLANG_LIBS) \ - $(ERLANG_CFLAGS) \ - -o $@ \ - $(DYNAMIC_LIB_CFLAGS) - -clean: - rm -f $(BEAMS) $(ERLSHLIBS) - -distclean: clean - rm -f Makefile - -TAGS: - etags *.erl diff --git a/src/tls/Makefile.win32 b/src/tls/Makefile.win32 deleted file mode 100644 index f5a3dba05..000000000 --- a/src/tls/Makefile.win32 +++ /dev/null @@ -1,38 +0,0 @@ - -include ..\Makefile.inc - -EFLAGS = -I .. -pz .. - -OUTDIR = .. -BEAMS = ..\tls.beam - -SOURCE = tls_drv.c sha_drv.c -OBJECT = tls_drv.o sha_drv.o -DLL = $(OUTDIR)\tls_drv.dll $(OUTPUT)\sha_drv.dll - -ALL : $(DLL) $(BEAMS) - -CLEAN : - -@erase $(DLL) - -@erase $(OUTDIR)\tls_drv.exp - -@erase $(OUTDIR)\tls_drv.lib - -@erase $(OUTDIR)\sha_drv.exp - -@erase $(OUTDIR)\sha_drv.lib - -@erase $(OBJECT) - -@erase $(BEAMS) - -$(OUTDIR)\tls.beam : tls.erl - erlc -W $(EFLAGS) -o $(OUTDIR) tls.erl - -CC=cl.exe -CC_FLAGS=-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT -MD -Ox -I"$(ERLANG_DIR)\usr\include" -I"$(EI_DIR)\include" -I"$(OPENSSL_DIR)\include" -I"." - -LD=link.exe -LD_FLAGS=-release -nologo -incremental:no -dll "$(EI_DIR)\lib\ei_md.lib" "$(EI_DIR)\lib\erl_interface_md.lib" "$(OPENSSL_DIR)\lib\VC\ssleay32MD.lib" "$(OPENSSL_DIR)\lib\VC\libeay32MD.lib" MSVCRT.LIB kernel32.lib advapi32.lib gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib - -$(DLL) : $(OBJECT) - $(LD) $(LD_FLAGS) -out:$@ $< - -$(OBJECT) : $(SOURCE) - $(CC) $(CC_FLAGS) -c -Fo$@ $< - diff --git a/src/tls/sha_drv.c b/src/tls/sha_drv.c deleted file mode 100644 index 3558f790a..000000000 --- a/src/tls/sha_drv.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * ejabberd, Copyright (C) 2002-2013 ProcessOne - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 USA - * - */ - -#include <erl_driver.h> -#include <openssl/sha.h> -#ifdef HAVE_MD2 -#include <openssl/md2.h> -#endif - -/* - * R15B changed several driver callbacks to use ErlDrvSizeT and - * ErlDrvSSizeT typedefs instead of int. - * This provides missing typedefs on older OTP versions. - */ -#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2 -typedef int ErlDrvSizeT; -typedef int ErlDrvSSizeT; -#endif - -static ErlDrvData sha_drv_start(ErlDrvPort port, char *buf) -{ - set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY); - return NULL; -} - -static ErlDrvSSizeT sha_drv_control(ErlDrvData handle, - unsigned int command, - char *buf, ErlDrvSizeT len, - char **rbuf, ErlDrvSizeT rlen) -{ - ErlDrvBinary *b = NULL; - - switch (command) { -#ifdef HAVE_MD2 - case 2: - rlen = MD2_DIGEST_LENGTH; - b = driver_alloc_binary(rlen); - if (b) MD2((unsigned char*)buf, len, (unsigned char*)b->orig_bytes); - break; -#endif - case 224: - rlen = SHA224_DIGEST_LENGTH; - b = driver_alloc_binary(rlen); - if (b) SHA224((unsigned char*)buf, len, (unsigned char*)b->orig_bytes); - break; - case 256: - rlen = SHA256_DIGEST_LENGTH; - b = driver_alloc_binary(rlen); - if (b) SHA256((unsigned char*)buf, len, (unsigned char*)b->orig_bytes); - break; - case 384: - rlen = SHA384_DIGEST_LENGTH; - b = driver_alloc_binary(rlen); - if (b) SHA384((unsigned char*)buf, len, (unsigned char*)b->orig_bytes); - break; - case 512: - rlen = SHA512_DIGEST_LENGTH; - b = driver_alloc_binary(rlen); - if (b) SHA512((unsigned char*)buf, len, (unsigned char*)b->orig_bytes); - break; - }; - - if (b) { - *rbuf = (char *)b; - } else { - *rbuf = NULL; - rlen = 0; - }; - - return rlen; -} - -ErlDrvEntry sha_driver_entry = { - NULL, /* F_PTR init, N/A */ - sha_drv_start, /* L_PTR start, called when port is opened */ - NULL, /* F_PTR stop, called when port is closed */ - NULL, /* F_PTR output, called when erlang has sent */ - NULL, /* F_PTR ready_input, called when input descriptor ready */ - NULL, /* F_PTR ready_output, called when output descriptor ready */ - "sha_drv", /* char *driver_name, the argument to open_port */ - NULL, /* F_PTR finish, called when unloaded */ - NULL, /* handle */ - sha_drv_control, /* F_PTR control, port_command callback */ - NULL, /* F_PTR timeout, reserved */ - NULL, /* F_PTR outputv, reserved */ - /* Added in Erlang/OTP R15B: */ - NULL, /* ready_async */ - NULL, /* flush */ - NULL, /* call */ - NULL, /* event */ - ERL_DRV_EXTENDED_MARKER, /* extended_marker */ - ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */ - ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */ - 0, /* driver_flags */ - NULL, /* handle2 */ - NULL, /* process_exit */ - NULL /* stop_select */ -}; - -DRIVER_INIT(sha_drv) /* must match name in driver_entry */ -{ - return &sha_driver_entry; -} diff --git a/src/tls/stdint.h b/src/tls/stdint.h deleted file mode 100755 index e032ff160..000000000 --- a/src/tls/stdint.h +++ /dev/null @@ -1,232 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2008 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include <limits.h> - -// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#if (_MSC_VER < 1300) && defined(__cplusplus) - extern "C++" { -#endif -# include <wchar.h> -#if (_MSC_VER < 1300) && defined(__cplusplus) - } -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] diff --git a/src/tls/tls.erl b/src/tls/tls.erl deleted file mode 100644 index 74a62709b..000000000 --- a/src/tls/tls.erl +++ /dev/null @@ -1,386 +0,0 @@ -%%%---------------------------------------------------------------------- -%%% File : tls.erl -%%% Author : Alexey Shchepin <alexey@process-one.net> -%%% Purpose : Interface to openssl -%%% Created : 24 Jul 2004 by Alexey Shchepin <alexey@process-one.net> -%%% -%%% -%%% ejabberd, Copyright (C) 2002-2013 ProcessOne -%%% -%%% This program is free software; you can redistribute it and/or -%%% modify it under the terms of the GNU General Public License as -%%% published by the Free Software Foundation; either version 2 of the -%%% License, or (at your option) any later version. -%%% -%%% This program is distributed in the hope that it will be useful, -%%% but WITHOUT ANY WARRANTY; without even the implied warranty of -%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%%% General Public License for more details. -%%% -%%% You should have received a copy of the GNU General Public License -%%% along with this program; if not, write to the Free Software -%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -%%% 02111-1307 USA -%%% -%%%---------------------------------------------------------------------- - --module(tls). - --author('alexey@process-one.net'). - --behaviour(gen_server). - --export([start/0, start_link/0, tcp_to_tls/2, - tls_to_tcp/1, send/2, recv/2, recv/3, recv_data/2, - setopts/2, sockname/1, peername/1, - controlling_process/2, close/1, get_peer_certificate/1, - get_verify_result/1, get_cert_verify_string/2, test/0]). - -%% Internal exports, call-back functions. --export([init/1, handle_call/3, handle_cast/2, - handle_info/2, code_change/3, terminate/2]). - --include("ejabberd.hrl"). - --define(SET_CERTIFICATE_FILE_ACCEPT, 1). - --define(SET_CERTIFICATE_FILE_CONNECT, 2). - --define(SET_ENCRYPTED_INPUT, 3). - --define(SET_DECRYPTED_OUTPUT, 4). - --define(GET_ENCRYPTED_OUTPUT, 5). - --define(GET_DECRYPTED_INPUT, 6). - --define(GET_PEER_CERTIFICATE, 7). - --define(GET_VERIFY_RESULT, 8). - --define(VERIFY_NONE, 65536). - --record(tlssock, {tcpsock :: inet:socket(), - tlsport :: port()}). - --type tls_socket() :: #tlssock{}. - --type cert() :: any(). %% TODO - --export_type([tls_socket/0]). - -start() -> - gen_server:start({local, ?MODULE}, ?MODULE, [], []). - -start_link() -> - gen_server:start_link({local, ?MODULE}, ?MODULE, [], - []). - -init([]) -> - case erl_ddll:load_driver(ejabberd:get_so_path(), - tls_drv) - of - ok -> ok; - {error, already_loaded} -> ok - end, - Port = open_port({spawn, "tls_drv"}, [binary]), - Res = port_control(Port, ?SET_CERTIFICATE_FILE_ACCEPT, - <<"./ssl.pem", 0>>), - case Res of - <<0>> -> {ok, Port}; - <<1, Error/binary>> -> {error, (Error)} - end. - -%%% -------------------------------------------------------- -%%% The call-back functions. -%%% -------------------------------------------------------- - -handle_call(_, _, State) -> {noreply, State}. - -handle_cast(_, State) -> {noreply, State}. - -handle_info({'EXIT', Port, Reason}, Port) -> - {stop, {port_died, Reason}, Port}; -handle_info({'EXIT', _Pid, _Reason}, Port) -> - {noreply, Port}; -handle_info(_, State) -> {noreply, State}. - -code_change(_OldVsn, State, _Extra) -> {ok, State}. - -terminate(_Reason, Port) -> Port ! {self, close}, ok. - --spec tcp_to_tls(inet:socket(), - [{atom(), any()}]) -> {'error','no_certfile' | binary()} | - {ok, tls_socket()}. - -tcp_to_tls(TCPSocket, Options) -> - case lists:keysearch(certfile, 1, Options) of - {value, {certfile, CertFile}} -> - case erl_ddll:load_driver(ejabberd:get_so_path(), - tls_drv) - of - ok -> ok; - {error, already_loaded} -> ok - end, - Port = open_port({spawn, "tls_drv"}, [binary]), - Flags = case lists:member(verify_none, Options) of - true -> ?VERIFY_NONE; - false -> 0 - end, - Command = case lists:member(connect, Options) of - true -> ?SET_CERTIFICATE_FILE_CONNECT; - false -> ?SET_CERTIFICATE_FILE_ACCEPT - end, - CertFile1 = iolist_to_binary(CertFile), - case port_control(Port, Command bor Flags, - <<CertFile1/binary, 0>>) - of - <<0>> -> - {ok, #tlssock{tcpsock = TCPSocket, tlsport = Port}}; - <<1, Error/binary>> -> {error, (Error)} - end; - false -> {error, no_certfile} - end. - --spec tls_to_tcp(tls_socket()) -> inet:socket(). - -tls_to_tcp(#tlssock{tcpsock = TCPSocket, - tlsport = Port}) -> - port_close(Port), TCPSocket. - -recv(Socket, Length) -> recv(Socket, Length, infinity). - --spec recv(tls_socket(), non_neg_integer(), - timeout()) -> {error, inet:posix()} | - {error, binary()} | - {ok, binary()}. - -recv(#tlssock{tcpsock = TCPSocket, tlsport = Port} = - TLSSock, - Length, Timeout) -> - case port_control(Port, ?GET_DECRYPTED_INPUT, - <<Length:32>>) - of - <<0>> -> - case gen_tcp:recv(TCPSocket, 0, Timeout) of - {ok, Packet} -> recv_data(TLSSock, Packet, Length); - {error, _Reason} = Error -> Error - end; - <<0, In/binary>> -> {ok, In}; - <<1, Error/binary>> -> {error, (Error)} - end. - -recv_data(TLSSock, Packet) -> - recv_data(TLSSock, Packet, 0). - --spec recv_data(tls_socket(), binary(), - non_neg_integer()) -> {error, inet:posix() | binary()} | - {ok, binary()}. - -recv_data(TLSSock, Packet, Length) -> - case catch recv_data1(TLSSock, Packet, Length) of - {'EXIT', Reason} -> {error, Reason}; - Res -> Res - end. - -recv_data1(#tlssock{tcpsock = TCPSocket, - tlsport = Port}, - Packet, Length) -> - case port_control(Port, ?SET_ENCRYPTED_INPUT, Packet) of - <<0>> -> - case port_control(Port, ?GET_DECRYPTED_INPUT, - <<Length:32>>) - of - <<0, In/binary>> -> - case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of - <<0, Out/binary>> -> - case gen_tcp:send(TCPSocket, Out) of - ok -> {ok, In}; - Error -> Error - end; - <<1, Error/binary>> -> {error, (Error)} - end; - <<1, Error/binary>> -> {error, (Error)} - end; - <<1, Error/binary>> -> {error, (Error)} - end. - --spec send(tls_socket(), binary()) -> ok | {error, inet:posix() | - binary() | timeout}. - -send(#tlssock{tcpsock = TCPSocket, tlsport = Port} = - TLSSock, - Packet) -> - case port_control(Port, ?SET_DECRYPTED_OUTPUT, Packet) - of - <<0>> -> - case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of - <<0, Out/binary>> -> gen_tcp:send(TCPSocket, Out); - <<1, Error/binary>> -> {error, (Error)} - end; - <<1, Error/binary>> -> {error, (Error)}; - <<2>> -> % Dirty hack - receive - {timeout, _Timer, _} -> {error, timeout} - after 100 -> send(TLSSock, Packet) - end - end. - --spec setopts(tls_socket(), list()) -> ok | {error, inet:posix()}. - -setopts(#tlssock{tcpsock = TCPSocket}, Opts) -> - inet:setopts(TCPSocket, Opts). - --spec sockname(tls_socket()) -> {ok, {inet:ip_address(), inet:port_number()}} | - {error, inet:posix()}. - -sockname(#tlssock{tcpsock = TCPSocket}) -> - inet:sockname(TCPSocket). - -peername(#tlssock{tcpsock = TCPSocket}) -> - inet:peername(TCPSocket). - -controlling_process(#tlssock{tcpsock = TCPSocket}, - Pid) -> - gen_tcp:controlling_process(TCPSocket, Pid). - -close(#tlssock{tcpsock = TCPSocket, tlsport = Port}) -> - gen_tcp:close(TCPSocket), port_close(Port). - --spec get_peer_certificate(tls_socket()) -> error | {ok, cert()}. - -get_peer_certificate(#tlssock{tlsport = Port}) -> - case port_control(Port, ?GET_PEER_CERTIFICATE, []) of - <<0, BCert/binary>> -> - case catch public_key:pkix_decode_cert(BCert, plain) - of - {ok, Cert} -> {ok, Cert}; - {'Certificate', _, _, _} = Cert -> {ok, Cert}; - _ -> error - end; - <<1>> -> error - end. - --spec get_verify_result(tls_socket()) -> byte(). - -get_verify_result(#tlssock{tlsport = Port}) -> - <<Res>> = port_control(Port, ?GET_VERIFY_RESULT, []), - Res. - -test() -> - case erl_ddll:load_driver(ejabberd:get_so_path(), - tls_drv) - of - ok -> ok; - {error, already_loaded} -> ok - end, - Port = open_port({spawn, "tls_drv"}, [binary]), - ?PRINT("open_port: ~p~n", [Port]), - PCRes = port_control(Port, ?SET_CERTIFICATE_FILE_ACCEPT, - <<"./ssl.pem", 0>>), - ?PRINT("port_control: ~p~n", [PCRes]), - {ok, ListenSocket} = gen_tcp:listen(1234, - [binary, {packet, 0}, {active, true}, - {reuseaddr, true}, {nodelay, true}]), - ?PRINT("listen: ~p~n", [ListenSocket]), - {ok, Socket} = gen_tcp:accept(ListenSocket), - ?PRINT("accept: ~p~n", [Socket]), - loop(Port, Socket). - -loop(Port, Socket) -> - receive - {tcp, Socket, Data} -> - Res = port_control(Port, ?SET_ENCRYPTED_INPUT, Data), - ?PRINT("SET_ENCRYPTED_INPUT: ~p~n", [Res]), - DIRes = port_control(Port, ?GET_DECRYPTED_INPUT, Data), - ?PRINT("GET_DECRYPTED_INPUT: ~p~n", [DIRes]), - case DIRes of - <<0, In/binary>> -> ?PRINT("input: ~s~n", [(In)]); - <<1, DIError/binary>> -> - ?PRINT("GET_DECRYPTED_INPUT error: ~p~n", [(DIError)]) - end, - EORes = port_control(Port, ?GET_ENCRYPTED_OUTPUT, Data), - ?PRINT("GET_ENCRYPTED_OUTPUT: ~p~n", [EORes]), - case EORes of - <<0, Out/binary>> -> gen_tcp:send(Socket, Out); - <<1, EOError/binary>> -> - ?PRINT("GET_ENCRYPTED_OUTPUT error: ~p~n", [(EOError)]) - end, - loop(Port, Socket); - Msg -> - ?PRINT("receive: ~p~n", [Msg]), loop(Port, Socket) - end. - --spec get_cert_verify_string(number(), cert()) -> binary(). - -get_cert_verify_string(CertVerifyRes, Cert) -> - BCert = public_key:pkix_encode('Certificate', Cert, - plain), - IsSelfsigned = public_key:pkix_is_self_signed(BCert), - case {CertVerifyRes, IsSelfsigned} of - {21, true} -> <<"self-signed certificate">>; - _ -> cert_verify_code(CertVerifyRes) - end. - -%% http://www.openssl.org/docs/apps/verify.html -cert_verify_code(0) -> <<"ok">>; -cert_verify_code(2) -> - <<"unable to get issuer certificate">>; -cert_verify_code(3) -> - <<"unable to get certificate CRL">>; -cert_verify_code(4) -> - <<"unable to decrypt certificate's signature">>; -cert_verify_code(5) -> - <<"unable to decrypt CRL's signature">>; -cert_verify_code(6) -> - <<"unable to decode issuer public key">>; -cert_verify_code(7) -> - <<"certificate signature failure">>; -cert_verify_code(8) -> <<"CRL signature failure">>; -cert_verify_code(9) -> - <<"certificate is not yet valid">>; -cert_verify_code(10) -> <<"certificate has expired">>; -cert_verify_code(11) -> <<"CRL is not yet valid">>; -cert_verify_code(12) -> <<"CRL has expired">>; -cert_verify_code(13) -> - <<"format error in certificate's notBefore " - "field">>; -cert_verify_code(14) -> - <<"format error in certificate's notAfter " - "field">>; -cert_verify_code(15) -> - <<"format error in CRL's lastUpdate field">>; -cert_verify_code(16) -> - <<"format error in CRL's nextUpdate field">>; -cert_verify_code(17) -> <<"out of memory">>; -cert_verify_code(18) -> <<"self signed certificate">>; -cert_verify_code(19) -> - <<"self signed certificate in certificate " - "chain">>; -cert_verify_code(20) -> - <<"unable to get local issuer certificate">>; -cert_verify_code(21) -> - <<"unable to verify the first certificate">>; -cert_verify_code(22) -> - <<"certificate chain too long">>; -cert_verify_code(23) -> <<"certificate revoked">>; -cert_verify_code(24) -> <<"invalid CA certificate">>; -cert_verify_code(25) -> - <<"path length constraint exceeded">>; -cert_verify_code(26) -> - <<"unsupported certificate purpose">>; -cert_verify_code(27) -> <<"certificate not trusted">>; -cert_verify_code(28) -> <<"certificate rejected">>; -cert_verify_code(29) -> <<"subject issuer mismatch">>; -cert_verify_code(30) -> - <<"authority and subject key identifier " - "mismatch">>; -cert_verify_code(31) -> - <<"authority and issuer serial number mismatch">>; -cert_verify_code(32) -> - <<"key usage does not include certificate " - "signing">>; -cert_verify_code(50) -> - <<"application verification failure">>; -cert_verify_code(X) -> - <<"Unknown OpenSSL error code: ", (jlib:integer_to_binary(X))/binary>>. diff --git a/src/tls/tls_drv.c b/src/tls/tls_drv.c deleted file mode 100644 index c35f3f0c5..000000000 --- a/src/tls/tls_drv.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * ejabberd, Copyright (C) 2002-2013 ProcessOne - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 USA - * - */ - -#include <stdio.h> -#include <string.h> -#include <erl_driver.h> -#include <openssl/ssl.h> -#include <openssl/err.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <stdint.h> - -#define BUF_SIZE 1024 - -typedef struct { - ErlDrvPort port; - BIO *bio_read; - BIO *bio_write; - SSL *ssl; -} tls_data; - -#ifdef _WIN32 -typedef unsigned __int32 uint32_t; -#endif - -#ifndef SSL_OP_NO_TICKET -#define SSL_OP_NO_TICKET 0 -#endif - -#define CIPHERS "DEFAULT:!EXPORT:!LOW:!SSLv2" - -/* - * R15B changed several driver callbacks to use ErlDrvSizeT and - * ErlDrvSSizeT typedefs instead of int. - * This provides missing typedefs on older OTP versions. - */ -#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2 -typedef int ErlDrvSizeT; -typedef int ErlDrvSSizeT; -#endif - -/* - * str_hash is based on the public domain code from - * http://www.burtleburtle.net/bob/hash/doobs.html - */ -static uint32_t str_hash(char *s) -{ - unsigned char *key = (unsigned char *)s; - uint32_t hash = 0; - size_t i; - - for (i = 0; key[i] != 0; i++) { - hash += key[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - return hash; -} - -/* Linear hashing */ - -#define MIN_LEVEL 8 -#define MAX_LEVEL 20 - -struct bucket { - uint32_t hash; - char *key_file; - time_t mtime; - SSL_CTX *ssl_ctx; - struct bucket *next; -}; - -struct hash_table { - int split; - int level; - struct bucket **buckets; - int size; -}; - -struct hash_table ht; - -static void init_hash_table() -{ - size_t size = 1 << (MIN_LEVEL + 1); - size_t i; - ht.buckets = (struct bucket **)driver_alloc(sizeof(struct bucket *) * size); - ht.split = 0; - ht.level = MIN_LEVEL; - for (i = 0; i < size; i++) - ht.buckets[i] = NULL; - -} - -static void hash_table_insert(char *key_file, time_t mtime, - SSL_CTX *ssl_ctx) -{ - int level, split; - uint32_t hash = str_hash(key_file); - size_t bucket; - int do_split = 0; - struct bucket *el; - struct bucket *new_bucket_el; - - split = ht.split; - level = ht.level; - - bucket = hash & ((1 << level) - 1); - if (bucket < split) - bucket = hash & ((1 << (level + 1)) - 1); - - el = ht.buckets[bucket]; - while (el != NULL) { - if (el->hash == hash && strcmp(el->key_file, key_file) == 0) { - el->mtime = mtime; - if (el->ssl_ctx != NULL) - SSL_CTX_free(el->ssl_ctx); - el->ssl_ctx = ssl_ctx; - break; - } - el = el->next; - } - - if (el == NULL) { - if (ht.buckets[bucket] != NULL) - do_split = !0; - - new_bucket_el = (struct bucket *)driver_alloc(sizeof(struct bucket)); - new_bucket_el->hash = hash; - new_bucket_el->key_file = (char *)driver_alloc(strlen(key_file) + 1); - strcpy(new_bucket_el->key_file, key_file); - new_bucket_el->mtime = mtime; - new_bucket_el->ssl_ctx = ssl_ctx; - new_bucket_el->next = ht.buckets[bucket]; - ht.buckets[bucket] = new_bucket_el; - } - - if (do_split) { - struct bucket **el_ptr = &ht.buckets[split]; - size_t new_bucket = split + (1 << level); - while (*el_ptr != NULL) { - uint32_t hash = (*el_ptr)->hash; - if ((hash & ((1 << (level + 1)) - 1)) == new_bucket) { - struct bucket *moved_el = *el_ptr; - *el_ptr = (*el_ptr)->next; - moved_el->next = ht.buckets[new_bucket]; - ht.buckets[new_bucket] = moved_el; - } else - el_ptr = &(*el_ptr)->next; - } - split++; - if (split == 1 << level) { - size_t size; - size_t i; - split = 0; - level++; - size = 1 << (level + 1); - ht.split = split; - ht.level = level; - ht.buckets = (struct bucket **) - driver_realloc(ht.buckets, sizeof(struct bucket *) * size); - for (i = 1 << level; i < size; i++) - ht.buckets[i] = NULL; - } else - ht.split = split; - } -} - -static SSL_CTX *hash_table_lookup(char *key_file, time_t *pmtime) -{ - int level, split; - uint32_t hash = str_hash(key_file); - size_t bucket; - struct bucket *el; - - split = ht.split; - level = ht.level; - - bucket = hash & ((1 << level) - 1); - if (bucket < split) - bucket = hash & ((1 << (level + 1)) - 1); - - el = ht.buckets[bucket]; - while (el != NULL) { - if (el->hash == hash && strcmp(el->key_file, key_file) == 0) { - *pmtime = el->mtime; - return el->ssl_ctx; - } - el = el->next; - } - - return NULL; -} - - -static ErlDrvData tls_drv_start(ErlDrvPort port, char *buff) -{ - tls_data *d = (tls_data *)driver_alloc(sizeof(tls_data)); - d->port = port; - d->bio_read = NULL; - d->bio_write = NULL; - d->ssl = NULL; - - set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY); - - return (ErlDrvData)d; -} - -static void tls_drv_stop(ErlDrvData handle) -{ - tls_data *d = (tls_data *)handle; - - if (d->ssl != NULL) - SSL_free(d->ssl); - - driver_free((char *)handle); -} - -static void tls_drv_finish() -{ - int level; - struct bucket *el; - int i; - - level = ht.level; - for (i = 0; i < 1 << (level + 1); i++) { - el = ht.buckets[i]; - while (el != NULL) { - if (el->ssl_ctx != NULL) - SSL_CTX_free(el->ssl_ctx); - driver_free(el->key_file); - el = el->next; - } - } - - driver_free(ht.buckets); -} - -static int is_key_file_modified(char *file, time_t *key_file_mtime) -{ - struct stat file_stat; - - if (stat(file, &file_stat)) - { - *key_file_mtime = 0; - return 1; - } else { - if (*key_file_mtime != file_stat.st_mtime) - { - *key_file_mtime = file_stat.st_mtime; - return 1; - } else - return 0; - } -} - -static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) -{ - return 1; -} - -/* - * ECDHE is enabled only on OpenSSL 1.0.0e and later. - * See http://www.openssl.org/news/secadv_20110906.txt - * for details. - */ -#ifndef OPENSSL_NO_ECDH -static void setup_ecdh(SSL_CTX *ctx) -{ - EC_KEY *ecdh; - - if (SSLeay() < 0x1000005fL) { - return; - } - - ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); - SSL_CTX_set_tmp_ecdh(ctx, ecdh); - - EC_KEY_free(ecdh); -} -#endif - -#ifndef OPENSSL_NO_DH -/* -1024-bit MODP Group with 160-bit prime order subgroup (RFC5114) ------BEGIN DH PARAMETERS----- -MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y -mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4 -+qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV -w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0 -sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR -jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA= ------END DH PARAMETERS----- - */ -static unsigned char dh1024_p[] = { - 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E, - 0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6, - 0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86, - 0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0, - 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C, - 0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70, - 0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA, - 0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0, - 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF, - 0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08, - 0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71, -}; -static unsigned char dh1024_g[] = { - 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42, - 0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F, - 0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E, - 0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13, - 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F, - 0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1, - 0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08, - 0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A, - 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59, - 0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24, - 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5, -}; - -static void setup_dh(SSL_CTX *ctx) -{ - DH *dh; - - dh = DH_new(); - if (dh == NULL) { - return; - } - - dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); - dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); - if (dh->p == NULL || dh->g == NULL) { - DH_free(dh); - return; - } - - SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); - SSL_CTX_set_tmp_dh(ctx, dh); - - DH_free(dh); -} -#endif - -#define SET_CERTIFICATE_FILE_ACCEPT 1 -#define SET_CERTIFICATE_FILE_CONNECT 2 -#define SET_ENCRYPTED_INPUT 3 -#define SET_DECRYPTED_OUTPUT 4 -#define GET_ENCRYPTED_OUTPUT 5 -#define GET_DECRYPTED_INPUT 6 -#define GET_PEER_CERTIFICATE 7 -#define GET_VERIFY_RESULT 8 -#define VERIFY_NONE 0x10000 - - -#define die_unless(cond, errstr) \ - if (!(cond)) \ - { \ - int errstrlen = strlen(errstr); \ - unsigned long error_code = ERR_get_error(); \ - char *error_string = error_code ? \ - ERR_error_string(error_code, NULL) : \ - NULL; \ - int error_string_length = error_string ? \ - strlen(error_string) : 0; \ - if (error_code) \ - rlen = errstrlen + error_string_length + 3; \ - else \ - rlen = errstrlen + 1; \ - b = driver_alloc_binary(rlen); \ - b->orig_bytes[0] = 1; \ - strncpy(b->orig_bytes + 1, errstr, errstrlen); \ - if (error_code) { \ - strncpy(b->orig_bytes + 1 + errstrlen, \ - ": ", 2); \ - strncpy(b->orig_bytes + 3 + errstrlen, \ - error_string, error_string_length); \ - } \ - *rbuf = (char *)b; \ - return rlen; \ - } - - -static ErlDrvSSizeT tls_drv_control(ErlDrvData handle, - unsigned int command, - char *buf, ErlDrvSizeT len, - char **rbuf, ErlDrvSizeT rlen) -{ - tls_data *d = (tls_data *)handle; - int res; - int size; - ErlDrvBinary *b; - X509 *cert; - unsigned int flags = command; - - command &= 0xffff; - - ERR_clear_error(); - switch (command) - { - case SET_CERTIFICATE_FILE_ACCEPT: - case SET_CERTIFICATE_FILE_CONNECT: { - time_t mtime = 0; - SSL_CTX *ssl_ctx = hash_table_lookup(buf, &mtime); - if (is_key_file_modified(buf, &mtime) || ssl_ctx == NULL) - { - SSL_CTX *ctx; - - hash_table_insert(buf, mtime, NULL); - - ctx = SSL_CTX_new(SSLv23_method()); - die_unless(ctx, "SSL_CTX_new failed"); - - res = SSL_CTX_use_certificate_chain_file(ctx, buf); - die_unless(res > 0, "SSL_CTX_use_certificate_file failed"); - - res = SSL_CTX_use_PrivateKey_file(ctx, buf, SSL_FILETYPE_PEM); - die_unless(res > 0, "SSL_CTX_use_PrivateKey_file failed"); - - res = SSL_CTX_check_private_key(ctx); - die_unless(res > 0, "SSL_CTX_check_private_key failed"); - - SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET); - - SSL_CTX_set_cipher_list(ctx, CIPHERS); - -#ifndef OPENSSL_NO_ECDH - if (command == SET_CERTIFICATE_FILE_ACCEPT) { - setup_ecdh(ctx); - } -#endif -#ifndef OPENSSL_NO_DH - if (command == SET_CERTIFICATE_FILE_ACCEPT) { - setup_dh(ctx); - } -#endif - - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); - SSL_CTX_set_default_verify_paths(ctx); -#ifdef SSL_MODE_RELEASE_BUFFERS - SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); -#endif - /* SSL_CTX_load_verify_locations(ctx, "/etc/ejabberd/ca_certificates.pem", NULL); */ - /* SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ejabberd/ca_certs/"); */ - - /* This IF is commented to allow verification in all cases: */ - /* if (command == SET_CERTIFICATE_FILE_ACCEPT) */ - /* { */ - SSL_CTX_set_verify(ctx, - SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, - verify_callback); - /* } */ - - ssl_ctx = ctx; - hash_table_insert(buf, mtime, ssl_ctx); - } - - d->ssl = SSL_new(ssl_ctx); - die_unless(d->ssl, "SSL_new failed"); - - if (flags & VERIFY_NONE) - SSL_set_verify(d->ssl, SSL_VERIFY_NONE, verify_callback); - - d->bio_read = BIO_new(BIO_s_mem()); - d->bio_write = BIO_new(BIO_s_mem()); - - SSL_set_bio(d->ssl, d->bio_read, d->bio_write); - - if (command == SET_CERTIFICATE_FILE_ACCEPT) { - SSL_set_accept_state(d->ssl); - } else { - SSL_set_connect_state(d->ssl); - } - break; - } - case SET_ENCRYPTED_INPUT: - die_unless(d->ssl, "SSL not initialized"); - BIO_write(d->bio_read, buf, len); - break; - case SET_DECRYPTED_OUTPUT: - die_unless(d->ssl, "SSL not initialized"); - res = SSL_write(d->ssl, buf, len); - if (res <= 0) - { - res = SSL_get_error(d->ssl, res); - if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE) - { - b = driver_alloc_binary(1); - b->orig_bytes[0] = 2; - *rbuf = (char *)b; - return 1; - } else { - die_unless(0, "SSL_write failed"); - } - } - break; - case GET_ENCRYPTED_OUTPUT: - die_unless(d->ssl, "SSL not initialized"); - size = BIO_ctrl_pending(d->bio_write) + 1; - b = driver_alloc_binary(size); - b->orig_bytes[0] = 0; - BIO_read(d->bio_write, b->orig_bytes + 1, size - 1); - *rbuf = (char *)b; - return size; - case GET_DECRYPTED_INPUT: - if (!SSL_is_init_finished(d->ssl)) - { - res = SSL_do_handshake(d->ssl); - if (res <= 0) - die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ, - "SSL_do_handshake failed"); - } - if (SSL_is_init_finished(d->ssl)) { - size_t req_size = 0; - if (len == 4) - { - unsigned char *b = (unsigned char *)buf; - req_size = - (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; - } - size = BUF_SIZE + 1; - rlen = 1; - b = driver_alloc_binary(size); - b->orig_bytes[0] = 0; - - res = 0; - - while ((req_size == 0 || rlen < req_size + 1) && - (res = SSL_read(d->ssl, - b->orig_bytes + rlen, - (req_size == 0 || req_size + 1 >= size) ? - size - rlen : req_size + 1 - rlen)) > 0) - { - //printf("%d bytes of decrypted data read from state machine\r\n",res); - rlen += res; - if (size - rlen < BUF_SIZE) { - size *= 2; - b = driver_realloc_binary(b, size); - } - } - - if (res < 0) - { - int err = SSL_get_error(d->ssl, res); - - if (err == SSL_ERROR_WANT_READ) - { - //printf("SSL_read wants more data\r\n"); - //return 0; - } - // TODO - } - b = driver_realloc_binary(b, rlen); - *rbuf = (char *)b; - return rlen; - } - break; - case GET_PEER_CERTIFICATE: - cert = SSL_get_peer_certificate(d->ssl); - if (cert == NULL) - { - b = driver_alloc_binary(1); - b->orig_bytes[0] = 1; - *rbuf = (char *)b; - return 1; - } else { - unsigned char *tmp_buf; - rlen = i2d_X509(cert, NULL); - if (rlen >= 0) - { - rlen++; - b = driver_alloc_binary(rlen); - b->orig_bytes[0] = 0; - tmp_buf = (unsigned char *)&b->orig_bytes[1]; - i2d_X509(cert, &tmp_buf); - X509_free(cert); - *rbuf = (char *)b; - return rlen; - } else - X509_free(cert); - } - break; - case GET_VERIFY_RESULT: - b = driver_alloc_binary(1); - b->orig_bytes[0] = SSL_get_verify_result(d->ssl); - *rbuf = (char *)b; - return 1; - break; - } - - b = driver_alloc_binary(1); - b->orig_bytes[0] = 0; - *rbuf = (char *)b; - return 1; -} - - -ErlDrvEntry tls_driver_entry = { - NULL, /* F_PTR init, N/A */ - tls_drv_start, /* L_PTR start, called when port is opened */ - tls_drv_stop, /* F_PTR stop, called when port is closed */ - NULL, /* F_PTR output, called when erlang has sent */ - NULL, /* F_PTR ready_input, called when input descriptor ready */ - NULL, /* F_PTR ready_output, called when output descriptor ready */ - "tls_drv", /* char *driver_name, the argument to open_port */ - tls_drv_finish, /* F_PTR finish, called when unloaded */ - NULL, /* handle */ - tls_drv_control, /* F_PTR control, port_command callback */ - NULL, /* F_PTR timeout, reserved */ - NULL, /* F_PTR outputv, reserved */ - /* Added in Erlang/OTP R15B: */ - NULL, /* ready_async */ - NULL, /* flush */ - NULL, /* call */ - NULL, /* event */ - ERL_DRV_EXTENDED_MARKER, /* extended_marker */ - ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */ - ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */ - 0, /* driver_flags */ - NULL, /* handle2 */ - NULL, /* process_exit */ - NULL /* stop_select */ -}; - -DRIVER_INIT(tls_drv) /* must match name in driver_entry */ -{ - OpenSSL_add_ssl_algorithms(); - SSL_load_error_strings(); - init_hash_table(); - return &tls_driver_entry; -} - - |