Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
8fa1b449
Commit
8fa1b449
authored
Oct 29, 2022
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve SSL wrapper API and and add pw handling
parent
b713a845
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
255 additions
and
21 deletions
+255
-21
libcaf_net/CMakeLists.txt
libcaf_net/CMakeLists.txt
+2
-0
libcaf_net/caf/net/ssl/connection.hpp
libcaf_net/caf/net/ssl/connection.hpp
+1
-1
libcaf_net/caf/net/ssl/context.hpp
libcaf_net/caf/net/ssl/context.hpp
+63
-5
libcaf_net/caf/net/ssl/password.hpp
libcaf_net/caf/net/ssl/password.hpp
+47
-0
libcaf_net/caf/net/ssl/verify.hpp
libcaf_net/caf/net/ssl/verify.hpp
+40
-0
libcaf_net/src/net/ssl/acceptor.cpp
libcaf_net/src/net/ssl/acceptor.cpp
+2
-2
libcaf_net/src/net/ssl/context.cpp
libcaf_net/src/net/ssl/context.cpp
+52
-7
libcaf_net/src/net/ssl/password.cpp
libcaf_net/src/net/ssl/password.cpp
+13
-0
libcaf_net/src/net/ssl/startup.cpp
libcaf_net/src/net/ssl/startup.cpp
+6
-0
libcaf_net/src/net/ssl/verify.cpp
libcaf_net/src/net/ssl/verify.cpp
+23
-0
libcaf_net/test/net/ssl/transport.cpp
libcaf_net/test/net/ssl/transport.cpp
+6
-6
No files found.
libcaf_net/CMakeLists.txt
View file @
8fa1b449
...
...
@@ -67,9 +67,11 @@ caf_add_component(
src/net/ssl/context.cpp
src/net/ssl/dtls.cpp
src/net/ssl/format.cpp
src/net/ssl/password.cpp
src/net/ssl/startup.cpp
src/net/ssl/tls.cpp
src/net/ssl/transport.cpp
src/net/ssl/verify.cpp
src/net/stream_oriented.cpp
src/net/stream_socket.cpp
src/net/stream_transport.cpp
...
...
libcaf_net/caf/net/ssl/connection.hpp
View file @
8fa1b449
...
...
@@ -69,7 +69,7 @@ public:
/// from a client.
[[
nodiscard
]]
ptrdiff_t
accept
();
/// Gracefully closes the SSL connection.
/// Gracefully closes the SSL connection
without closing the socket
.
ptrdiff_t
close
();
// -- reading and writing ----------------------------------------------------
...
...
libcaf_net/caf/net/ssl/context.hpp
View file @
8fa1b449
...
...
@@ -8,9 +8,12 @@
#include "caf/net/ssl/dtls.hpp"
#include "caf/net/ssl/format.hpp"
#include "caf/net/ssl/fwd.hpp"
#include "caf/net/ssl/password.hpp"
#include "caf/net/ssl/tls.hpp"
#include "caf/net/ssl/verify.hpp"
#include "caf/net/stream_socket.hpp"
#include <cstring>
#include <string>
namespace
caf
::
net
::
ssl
{
...
...
@@ -27,6 +30,9 @@ public:
/// The opaque implementation type.
struct
impl
;
/// Stores additional data provided by the user.
struct
user_data
;
// -- constructors, destructors, and assignment operators --------------------
context
()
=
delete
;
...
...
@@ -65,6 +71,30 @@ public:
return
pimpl_
==
nullptr
;
}
/// Overrides the verification mode for this context.
/// @note calls @c SSL_CTX_set_verify
void
set_verify_mode
(
verify_t
flags
);
/// Overrides the callback to obtain the password for encrypted PEM files.
/// @note calls @c SSL_CTX_set_default_passwd_cb
template
<
typename
PasswordCallback
>
void
set_password_callback
(
PasswordCallback
callback
)
{
set_password_callback_impl
(
password
::
make_callback
(
std
::
move
(
callback
)));
}
/// Overrides the callback to obtain the password for encrypted PEM files with
/// a function that always returns @p password.
/// @note calls @c SSL_CTX_set_default_passwd_cb
void
set_password
(
std
::
string
password
)
{
auto
cb
=
[
pw
=
std
::
move
(
password
)](
char
*
buf
,
int
len
,
password
::
purpose
)
{
strncpy
(
buf
,
pw
.
c_str
(),
static_cast
<
size_t
>
(
len
));
buf
[
len
-
1
]
=
'\0'
;
return
static_cast
<
int
>
(
pw
.
size
());
};
set_password_callback
(
std
::
move
(
cb
));
}
// -- native handles ---------------------------------------------------------
/// Reinterprets `native_handle` as the native implementation type and takes
...
...
@@ -111,29 +141,57 @@ public:
/// e.g., `9d66eef0.0` and `9d66eef0.1`.
/// @returns `true` on success, `false` otherwise and `last_error` can be used
/// to retrieve a human-readable error representation.
[[
nodiscard
]]
bool
load_verify_dir
(
const
char
*
path
);
/// @note Calls @c SSL_CTX_load_verify_locations
[[
nodiscard
]]
bool
add_verify_path
(
const
char
*
path
);
/// @copydoc add_verify_path
[[
nodiscard
]]
bool
add_verify_path
(
const
std
::
string
&
path
)
{
return
add_verify_path
(
path
.
c_str
());
}
/// Loads a CA certificate file.
/// @param path Null-terminated string with a path to a single PEM file.
/// @returns `true` on success, `false` otherwise and `last_error` can be used
/// to retrieve a human-readable error representation.
/// @note Calls @c SSL_CTX_load_verify_locations
[[
nodiscard
]]
bool
load_verify_file
(
const
char
*
path
);
/// @copydoc load_verify_file
[[
nodiscard
]]
bool
load_verify_file
(
const
std
::
string
&
path
)
{
return
load_verify_file
(
path
.
c_str
());
}
/// Loads the first certificate found in given file.
/// @param path Null-terminated string with a path to a single PEM file.
[[
nodiscard
]]
bool
use_certificate_from_file
(
const
char
*
path
,
format
file_format
);
[[
nodiscard
]]
bool
use_certificate_file
(
const
char
*
path
,
format
file_format
);
/// Loads a certificate chain from a PEM-formatted file.
/// @note calls @c SSL_CTX_use_certificate_chain_file
[[
nodiscard
]]
bool
use_certificate_chain_file
(
const
char
*
path
);
/// @copydoc use_certificate_chain_file
[[
nodiscard
]]
bool
use_certificate_chain_file
(
const
std
::
string
&
path
)
{
return
use_certificate_chain_file
(
path
.
c_str
());
}
/// Loads the first private key found in given file.
[[
nodiscard
]]
bool
use_private_key_from_file
(
const
char
*
path
,
format
file_format
);
[[
nodiscard
]]
bool
use_private_key_file
(
const
char
*
path
,
format
file_format
);
/// @copydoc use_private_key_file
[[
nodiscard
]]
bool
use_private_key_file
(
const
std
::
string
&
path
,
format
file_format
)
{
return
use_private_key_file
(
path
.
c_str
(),
file_format
);
}
private:
constexpr
explicit
context
(
impl
*
ptr
)
:
pimpl_
(
ptr
)
{
// nop
}
void
set_password_callback_impl
(
password
::
callback_ptr
callback
);
impl
*
pimpl_
;
user_data
*
data_
=
nullptr
;
};
}
// namespace caf::net::ssl
libcaf_net/caf/net/ssl/password.hpp
0 → 100644
View file @
8fa1b449
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#include "caf/default_enum_inspect.hpp"
#include "caf/detail/net_export.hpp"
#include "caf/fwd.hpp"
#include <memory>
namespace
caf
::
net
::
ssl
::
password
{
/// Purpose of PEM password.
enum
class
purpose
{
/// SSL asks the password is reading/decryption.
reading
,
/// SSL asks the password is for writing/encryption.
writing
};
class
CAF_NET_EXPORT
callback
{
public:
virtual
~
callback
();
/// Reads the password into the buffer @p buf of size @p len.
/// @returns Written characters on success, -1 otherwise.
virtual
int
operator
()(
char
*
buf
,
int
len
,
purpose
flag
)
=
0
;
};
using
callback_ptr
=
std
::
unique_ptr
<
callback
>
;
template
<
class
PasswordCallback
>
callback_ptr
make_callback
(
PasswordCallback
callback
)
{
struct
impl
:
callback
{
explicit
impl
(
PasswordCallback
&&
cb
)
:
cb_
(
std
::
move
(
cb
))
{
// nop
}
int
operator
()(
char
*
buf
,
int
len
,
purpose
flag
)
override
{
return
cb_
(
buf
,
len
,
flag
);
}
PasswordCallback
cb_
;
};
return
std
::
make_unique
<
impl
>
(
std
::
move
(
callback
));
}
}
// namespace caf::net::ssl::password
libcaf_net/caf/net/ssl/verify.hpp
0 → 100644
View file @
8fa1b449
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#include "caf/default_enum_inspect.hpp"
#include "caf/detail/net_export.hpp"
#include "caf/fwd.hpp"
#include <string>
namespace
caf
::
net
::
ssl
{
/// Bitmask type for the SSL verification mode.
enum
class
verify_t
{};
namespace
verify
{
CAF_NET_EXPORT
extern
const
verify_t
none
;
CAF_NET_EXPORT
extern
const
verify_t
peer
;
CAF_NET_EXPORT
extern
const
verify_t
fail_if_no_peer_cert
;
CAF_NET_EXPORT
extern
const
verify_t
client_once
;
}
// namespace verify
constexpr
int
to_integer
(
verify_t
x
)
{
return
static_cast
<
int
>
(
x
);
}
inline
verify_t
&
operator
|=
(
verify_t
&
x
,
verify_t
y
)
noexcept
{
return
x
=
static_cast
<
verify_t
>
(
to_integer
(
x
)
|
to_integer
(
y
));
}
constexpr
verify_t
operator
|
(
verify_t
x
,
verify_t
y
)
noexcept
{
return
static_cast
<
verify_t
>
(
to_integer
(
x
)
|
to_integer
(
y
));
}
}
// namespace caf::net::ssl
libcaf_net/src/net/ssl/acceptor.cpp
View file @
8fa1b449
...
...
@@ -33,11 +33,11 @@ acceptor::make_with_cert_file(tcp_accept_socket fd, const char* cert_file_path,
if
(
!
ctx
)
{
return
{
make_error
(
sec
::
runtime_error
,
"unable to create SSL context"
)};
}
if
(
!
ctx
->
use_certificate_f
rom_f
ile
(
cert_file_path
,
file_format
))
{
if
(
!
ctx
->
use_certificate_file
(
cert_file_path
,
file_format
))
{
return
{
make_error
(
sec
::
runtime_error
,
"unable to load certificate file"
,
ctx
->
last_error_string
())};
}
if
(
!
ctx
->
use_private_key_f
rom_f
ile
(
key_file_path
,
file_format
))
{
if
(
!
ctx
->
use_private_key_file
(
key_file_path
,
file_format
))
{
return
{
make_error
(
sec
::
runtime_error
,
"unable to load private key file"
,
ctx
->
last_error_string
())};
}
...
...
libcaf_net/src/net/ssl/context.cpp
View file @
8fa1b449
...
...
@@ -23,22 +23,34 @@ auto native(context::impl* ptr) {
}
// namespace
// -- member types -------------------------------------------------------------
struct
context
::
user_data
{
password
::
callback_ptr
pw_callback
;
};
// -- constructors, destructors, and assignment operators ----------------------
context
::
context
(
context
&&
other
)
{
pimpl_
=
other
.
pimpl_
;
other
.
pimpl_
=
nullptr
;
data_
=
other
.
data_
;
other
.
data_
=
nullptr
;
}
context
&
context
::
operator
=
(
context
&&
other
)
{
SSL_CTX_free
(
native
(
pimpl_
));
pimpl_
=
other
.
pimpl_
;
other
.
pimpl_
=
nullptr
;
delete
data_
;
data_
=
other
.
data_
;
other
.
data_
=
nullptr
;
return
*
this
;
}
context
::~
context
()
{
SSL_CTX_free
(
native
(
pimpl_
));
// Already checks for NULL.
delete
data_
;
}
// -- factories ----------------------------------------------------------------
...
...
@@ -147,6 +159,34 @@ expected<context> context::make_client(dtls vmin, dtls vmax) {
return
{
make_error
(
sec
::
logic_error
,
errstr
)};
}
// -- properties ---------------------------------------------------------------
void
context
::
set_verify_mode
(
verify_t
flags
)
{
auto
ptr
=
native
(
pimpl_
);
SSL_CTX_set_verify
(
ptr
,
to_integer
(
flags
),
SSL_CTX_get_verify_callback
(
ptr
));
}
namespace
{
int
c_password_callback
(
char
*
buf
,
int
size
,
int
rwflag
,
void
*
ptr
)
{
if
(
ptr
==
nullptr
)
return
-
1
;
auto
flag
=
static_cast
<
password
::
purpose
>
(
rwflag
);
auto
fn
=
static_cast
<
password
::
callback
*>
(
ptr
);
return
(
*
fn
)(
buf
,
size
,
flag
);
}
}
// namespace
void
context
::
set_password_callback_impl
(
password
::
callback_ptr
callback
)
{
if
(
data_
==
nullptr
)
data_
=
new
user_data
;
auto
ptr
=
native
(
pimpl_
);
data_
->
pw_callback
=
std
::
move
(
callback
);
SSL_CTX_set_default_passwd_cb
(
ptr
,
c_password_callback
);
SSL_CTX_set_default_passwd_cb_userdata
(
ptr
,
data_
->
pw_callback
.
get
());
}
// -- native handles -----------------------------------------------------------
context
context
::
from_native
(
void
*
native_handle
)
{
...
...
@@ -217,7 +257,7 @@ bool context::set_default_verify_paths() {
return
SSL_CTX_set_default_verify_paths
(
native
(
pimpl_
))
==
1
;
}
bool
context
::
load_verify_dir
(
const
char
*
path
)
{
bool
context
::
add_verify_path
(
const
char
*
path
)
{
ERR_clear_error
();
return
SSL_CTX_load_verify_locations
(
native
(
pimpl_
),
nullptr
,
path
)
==
1
;
}
...
...
@@ -227,16 +267,21 @@ bool context::load_verify_file(const char* path) {
return
SSL_CTX_load_verify_locations
(
native
(
pimpl_
),
path
,
nullptr
)
==
1
;
}
bool
context
::
use_certificate_from_file
(
const
char
*
path
,
format
file_format
)
{
bool
context
::
use_certificate_file
(
const
char
*
path
,
format
file_format
)
{
ERR_clear_error
();
auto
nff
=
native
(
file_format
);
return
SSL_CTX_use_certificate_file
(
native
(
pimpl_
),
path
,
nff
)
==
1
;
}
bool
context
::
use_certificate_chain_file
(
const
char
*
path
)
{
ERR_clear_error
();
return
SSL_CTX_use_certificate_file
(
native
(
pimpl_
),
path
,
native
(
file_format
))
==
1
;
return
SSL_CTX_use_certificate_chain_file
(
native
(
pimpl_
),
path
)
==
1
;
}
bool
context
::
use_private_key_f
rom_f
ile
(
const
char
*
path
,
format
file_format
)
{
bool
context
::
use_private_key_file
(
const
char
*
path
,
format
file_format
)
{
ERR_clear_error
();
return
SSL_CTX_use_PrivateKey_file
(
native
(
pimpl_
),
path
,
native
(
file_format
))
==
1
;
auto
nff
=
native
(
file_format
);
return
SSL_CTX_use_PrivateKey_file
(
native
(
pimpl_
),
path
,
nff
)
==
1
;
}
}
// namespace caf::net::ssl
libcaf_net/src/net/ssl/password.cpp
0 → 100644
View file @
8fa1b449
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#include "caf/net/ssl/password.hpp"
namespace
caf
::
net
::
ssl
::
password
{
callback
::~
callback
()
{
// nop
}
}
// namespace caf::net::ssl::password
libcaf_net/src/net/ssl/startup.cpp
View file @
8fa1b449
...
...
@@ -62,6 +62,8 @@ void startup() {
CRYPTO_set_dynlock_create_callback
(
dynlock_create
);
CRYPTO_set_dynlock_lock_callback
(
dynlock_lock
);
CRYPTO_set_dynlock_destroy_callback
(
dynlock_destroy
);
#else
OPENSSL_init_ssl
(
0
,
nullptr
);
#endif
}
...
...
@@ -72,6 +74,10 @@ void cleanup() {
CRYPTO_set_dynlock_lock_callback
(
nullptr
);
CRYPTO_set_dynlock_destroy_callback
(
nullptr
);
mutexes
.
clear
();
#else
ERR_free_strings
();
EVP_cleanup
();
CRYPTO_cleanup_all_ex_data
();
#endif
}
...
...
libcaf_net/src/net/ssl/verify.cpp
0 → 100644
View file @
8fa1b449
#include "caf/net/ssl/verify.hpp"
#include <openssl/ssl.h>
namespace
caf
::
net
::
ssl
::
verify
{
namespace
{
constexpr
verify_t
i2v
(
int
x
)
{
return
static_cast
<
verify_t
>
(
x
);
}
}
// namespace
const
verify_t
none
=
i2v
(
SSL_VERIFY_NONE
);
const
verify_t
peer
=
i2v
(
SSL_VERIFY_PEER
);
const
verify_t
fail_if_no_peer_cert
=
i2v
(
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
);
const
verify_t
client_once
=
i2v
(
SSL_VERIFY_CLIENT_ONCE
);
}
// namespace caf::net::ssl::verify
libcaf_net/test/net/ssl/transport.cpp
View file @
8fa1b449
...
...
@@ -112,12 +112,12 @@ void dummy_tls_server(stream_socket fd, const char* cert_file,
auto
guard
=
detail
::
make_scope_guard
([
fd
]
{
close
(
fd
);
});
// Get and configure our SSL context.
auto
ctx
=
unbox
(
ssl
::
context
::
make_server
(
ssl
::
tls
::
any
));
if
(
!
ctx
.
use_certificate_f
rom_f
ile
(
cert_file
,
ssl
::
format
::
pem
))
{
if
(
!
ctx
.
use_certificate_file
(
cert_file
,
ssl
::
format
::
pem
))
{
std
::
cerr
<<
"*** failed to load certificate_file: "
<<
ctx
.
last_error_string
()
<<
'\n'
;
return
;
}
if
(
!
ctx
.
use_private_key_f
rom_f
ile
(
key_file
,
ssl
::
format
::
pem
))
{
if
(
!
ctx
.
use_private_key_file
(
key_file
,
ssl
::
format
::
pem
))
{
std
::
cerr
<<
"*** failed to load private key file: "
<<
ctx
.
last_error_string
()
<<
'\n'
;
return
;
...
...
@@ -231,10 +231,10 @@ SCENARIO("ssl::transport::make_server performs the server handshake") {
mpx
->
set_thread_id
();
std
::
ignore
=
mpx
->
init
();
auto
ctx
=
unbox
(
ssl
::
context
::
make_server
(
ssl
::
tls
::
any
));
REQUIRE
(
ctx
.
use_certificate_f
rom_f
ile
(
cert_1_pem_path
,
//
ssl
::
format
::
pem
));
REQUIRE
(
ctx
.
use_private_key_f
rom_f
ile
(
key_1_pem_path
,
//
ssl
::
format
::
pem
));
REQUIRE
(
ctx
.
use_certificate_file
(
cert_1_pem_path
,
//
ssl
::
format
::
pem
));
REQUIRE
(
ctx
.
use_private_key_file
(
key_1_pem_path
,
//
ssl
::
format
::
pem
));
auto
conn
=
unbox
(
ctx
.
new_connection
(
server_fd
));
auto
done
=
std
::
make_shared
<
bool
>
(
false
);
auto
buf
=
std
::
make_shared
<
byte_buffer
>
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment