diff --git a/src/OpenSSL.jl b/src/OpenSSL.jl index fee43d6..d433987 100644 --- a/src/OpenSSL.jl +++ b/src/OpenSSL.jl @@ -8,6 +8,9 @@ include("consts.jl") include("evp_md.jl") include("types.jl") export SSLContext, SSLClient + +include("methods.jl") + include("bio.jl") include("context.jl") diff --git a/src/bio.jl b/src/bio.jl index ec5a29f..68696cd 100644 --- a/src/bio.jl +++ b/src/bio.jl @@ -1,5 +1,21 @@ -s_mem() = ccall((:BIO_s_mem, libssl), Ptr{Cvoid}, ()) -bio_new(mem::Ptr{Cvoid}) = ccall((:BIO_new, libssl), Ptr{Cvoid}, (Ptr{Cvoid},), mem) +# BIO_METHOD * BIO_s_mem(void); + +# BIO_set_mem_eof_return(BIO *b,int v) +# long BIO_get_mem_data(BIO *b, char **pp) +# BIO_set_mem_buf(BIO *b,BUF_MEM *bm,int c) +# BIO_get_mem_ptr(BIO *b,BUF_MEM **pp) + +# BIO * BIO_new(const BIO_METHOD *type); +# int BIO_set(BIO *a, const BIO_METHOD *type); +# # int BIO_up_ref(BIO *a); # Don't see a use case +# int BIO_free(BIO *a); +# # void BIO_vfree(BIO *a); # Same as BIO_free +# void BIO_free_all(BIO *a); + +s_mem() = ccall((:BIO_s_mem, libssl), Ptr{BIO_Method}, ()) + +bio_new(mem::Ptr{BIO_Method}) = + ccall((:BIO_new, libssl), Ptr{Cvoid}, (Ptr{BIO_Method},), mem) bio_new() = bio_new(s_mem()) function set_bio!(client::SSLClient, rbio, wbio) diff --git a/src/certs.jl b/src/certs.jl index 7407499..afe2407 100644 --- a/src/certs.jl +++ b/src/certs.jl @@ -18,6 +18,8 @@ end get_peer_certificate(client::SSLClient) = ccall((:SSL_get_peer_certificate, libssl), Ptr{Cvoid}, (Ptr{Cvoid},), client.ssl) +# TODO: add response codes +# https://www.openssl.org/docs/man1.0.2/man1/verify.html verify_certificate(client::SSLClient) = ccall((:SSL_get_verify_result, libssl), Clong, (Ptr{Cvoid},), client.ssl) diff --git a/src/context.jl b/src/context.jl index 8c19006..c4e7f2b 100644 --- a/src/context.jl +++ b/src/context.jl @@ -17,3 +17,8 @@ function set_verify_callback(ctx::SSLContext, callback) ccall((:SSL_CTX_set_cert_verify_callback, libssl), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), ctx.ptr, callback, args) end + +free(ctx::SSLContext) = ccall((:SSL_CTX_free, libssl), Cvoid, (Ptr{Cvoid},), ctx.ptr) + +# TODO: +# SSL_CTX_load_verify_locations diff --git a/src/errors.jl b/src/errors.jl new file mode 100644 index 0000000..5662fb9 --- /dev/null +++ b/src/errors.jl @@ -0,0 +1,7 @@ +# ERR_set_mark() +# ERR_pop_to_mark() + +ERR_pop_to_mark() = ccall((:ERR_pop_to_mark, libssl), Cint, ()) +ERR_set_mark() = ccall((:ERR_set_mark, libssl), Cint, ()) +ERR_print_errors(file_ptr) = + ccall((:ERR_print_errors, libssl), Cvoid, (Ptr{Cvoid},), file_ptr) diff --git a/src/methods.jl b/src/methods.jl new file mode 100644 index 0000000..63407c8 --- /dev/null +++ b/src/methods.jl @@ -0,0 +1,29 @@ +# https://www.openssl.org/docs/man1.1.0/man3/TLS_server_method.html +TLSv1_2_method() = ccall((:TLSv1_2_method, libssl), Ptr{SSL_Method}, ()) +TLSv1_2_server_method() = ccall((:TLSv1_2_server_method, libssl), Ptr{SSL_Method}, ()) +TLSv1_2_client_method() = ccall((:TLSv1_2_client_method, libssl), Ptr{SSL_Method}, ()) +# Not defined in my openssl release +# SSLv3_method() = ccall((:SSLv3_method, libssl), Ptr{SSL_Method}, ()) +# SSLv3_server_method() = ccall((:SSLv3_server_method, libssl), Ptr{SSL_Method}, ()) +# SSLv3_client_method() = ccall((:SSLv3_client_method, libssl), Ptr{SSL_Method}, ()) +TLSv1_method() = ccall((:TLSv1_method, libssl), Ptr{SSL_Method}, ()) +TLSv1_server_method() = ccall((:TLSv1_server_method, libssl), Ptr{SSL_Method}, ()) +TLSv1_client_method() = ccall((:TLSv1_client_method, libssl), Ptr{SSL_Method}, ()) +TLSv1_1_method() = ccall((:TLSv1_1_method, libssl), Ptr{SSL_Method}, ()) +TLSv1_1_server_method() = ccall((:TLSv1_1_server_method, libssl), Ptr{SSL_Method}, ()) +TLSv1_1_client_method() = ccall((:TLSv1_1_client_method, libssl), Ptr{SSL_Method}, ()) +TLS_method() = ccall((:TLS_method, libssl), Ptr{SSL_Method}, ()) +TLS_server_method() = ccall((:TLS_server_method, libssl), Ptr{SSL_Method}, ()) +TLS_client_method() = ccall((:TLS_client_method, libssl), Ptr{SSL_Method}, ()) +SSLv23_method() = ccall((:SSLv23_method, libssl), Ptr{SSL_Method}, ()) +SSLv23_server_method() = ccall((:SSLv23_server_method, libssl), Ptr{SSL_Method}, ()) +SSLv23_client_method() = ccall((:SSLv23_client_method, libssl), Ptr{SSL_Method}, ()) +DTLS_method() = ccall((:DTLS_method, libssl), Ptr{SSL_Method}, ()) +DTLS_server_method() = ccall((:DTLS_server_method, libssl), Ptr{SSL_Method}, ()) +DTLS_client_method() = ccall((:DTLS_client_method, libssl), Ptr{SSL_Method}, ()) +DTLSv1_method() = ccall((:DTLSv1_method, libssl), Ptr{SSL_Method}, ()) +DTLSv1_server_method() = ccall((:DTLSv1_server_method, libssl), Ptr{SSL_Method}, ()) +DTLSv1_client_method() = ccall((:DTLSv1_client_method, libssl), Ptr{SSL_Method}, ()) +DTLSv1_2_method() = ccall((:DTLSv1_2_method, libssl), Ptr{SSL_Method}, ()) +DTLSv1_2_server_method() = ccall((:DTLSv1_2_server_method, libssl), Ptr{SSL_Method}, ()) +DTLSv1_2_client_method() = ccall((:DTLSv1_2_client_method, libssl), Ptr{SSL_Method}, ()) diff --git a/src/ssl.jl b/src/ssl.jl index 23801ab..7bd3a6c 100644 --- a/src/ssl.jl +++ b/src/ssl.jl @@ -7,6 +7,9 @@ SSL_handshake(client::SSLClient) = SSL_new(ctx::SSLContext) = ccall((:SSL_new, libssl), Ptr{Cvoid}, (Ptr{Cvoid},), ctx.ptr) +SSL_CTX_new(method::Ptr{SSL_Method}) = + ccall((:SSL_CTX_new, libssl), Ptr{SSL_Context}, (Ptr{SSL_Method},), method) + SSL_accept_state(client::SSLClient) = ccall((:SSL_set_accept_state, libssl), Ptr{Cvoid}, (Ptr{Cvoid},), client.ssl) @@ -30,5 +33,4 @@ ssl_write(client::SSLClient, buf::Vector{UInt8}) = shutdown(client::SSLClient) = ccall((:SSL_shutdown, libssl), Cint, (Ptr{Cvoid},), client.ssl) -free(client::SSLClient) = - ccall((:SSL_free, libssl), Cint, (Ptr{Cvoid},), client.ssl) +free(client::SSLClient) = ccall((:SSL_free, libssl), Cint, (Ptr{Cvoid},), client.ssl) diff --git a/src/types.jl b/src/types.jl index 07f5e2e..9503c2d 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,13 +1,23 @@ +# Returned from C as Ptr +struct SSL_Method ptr end +struct BIO_Method ptr end +struct SSL_Context ptr end + mutable struct SSLContext <: IO data - ptr::Ptr{Cvoid} + ptr::Ptr{SSL_Context} - function SSLContext() + "Construct the SSLContext object, initializing its relatvie SSL_Context + pointer. + + Might throw ErrorException if the ccall fails" + function SSLContext(; method::Ptr{SSL_Method} = TLS_method()) ssl_context = new() - method = ccall((:TLS_server_method, libssl), Ptr{Cvoid}, ()) - ssl_context.ptr = ccall((:SSL_CTX_new, libssl), Ptr{Cvoid}, (Ptr{Cvoid},), method) - # if ssl_context.ptr == 0 - # end + ssl_context.ptr = SSL_CTX_new(method) + if ssl_context.ptr == C_NULL + # TODO: check error stack and report the right exception + throw(ErrorException("Could not create SSL context")) + end ssl_context end end @@ -32,6 +42,7 @@ mutable struct SSLClient{T} client.write_buf = UInt8[] client.encrypt_buf = UInt8[] client.sock = io + # finalizer(free, client) client end end