aboutsummaryrefslogtreecommitdiff
path: root/src/tls
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls')
-rw-r--r--src/tls/Makefile.in69
-rw-r--r--src/tls/Makefile.win3238
-rw-r--r--src/tls/sha_drv.c120
-rwxr-xr-xsrc/tls/stdint.h232
-rw-r--r--src/tls/tls.erl386
-rw-r--r--src/tls/tls_drv.c653
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;
-}
-
-