44#include <openssl/bio.h>
45#include <openssl/pem.h>
46#include <openssl/ssl.h>
47#include <openssl/x509.h>
50#define MSG "nonblock-client->server"
52#define REPLY "nonblock-server->client"
61 static const char garbage[] =
"not a certificate";
62 BIO* b = BIO_new_mem_buf(garbage, (
int)(
sizeof(garbage) - 1));
64 X509* x = PEM_read_bio_X509(b, NULL, NULL, NULL);
80 while ((opt = getopt(argc, argv,
"hvV:")) != EOF) {
83 if (!strncmp(
"LOG_NULL", optarg, 8))
85 else if (!strncmp(
"LOG_NOTICE", optarg, 10))
87 else if (!strncmp(
"LOG_INFO", optarg, 8))
89 else if (!strncmp(
"LOG_ERR", optarg, 7))
91 else if (!strncmp(
"LOG_DEBUG", optarg, 9))
94 fprintf(stderr,
"Unknown log level %s\n", optarg);
99 fprintf(stderr,
"ex_network_ssl_nonblock\n");
103 fprintf(stderr,
"usage: %s [-V LOG_LEVEL]\n", argv[0]);
118#if N_OSSL_HAVE_PROTO_VERSION_SETTERS
119 SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());
125 SSL_CTX* ctx = SSL_CTX_new(TLSv1_2_server_method());
129 SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
131 BIO* cb = BIO_new_mem_buf(cert_pem->
data, (
int)cert_pem->
written);
132 BIO* kb = BIO_new_mem_buf(key_pem->
data, (
int)key_pem->
written);
133 X509* x = cb ? PEM_read_bio_X509(cb, NULL, NULL, NULL) : NULL;
134 EVP_PKEY* pk = kb ? PEM_read_bio_PrivateKey(kb, NULL, NULL, NULL) : NULL;
135 int ok = x && pk && SSL_CTX_use_certificate(ctx, x) == 1 &&
136 SSL_CTX_use_PrivateKey(ctx, pk) == 1;
161 fd_set rset, wset, eset;
173 tv.tv_sec = timeout_ms / 1000;
174 tv.tv_usec = (timeout_ms % 1000) * 1000;
176 return select((
int)fd + 1, want_write ? NULL : &rset,
177 want_write ? &wset : NULL, want_write ? &eset : NULL, &tv);
181 p.events = (short)(want_write ? POLLOUT : POLLIN);
183 return poll(&p, 1, timeout_ms);
190 for (guard = 0; guard < 10000; guard++) {
213 for (guard = 0; guard < 10000; guard++) {
231 for (guard = 0; guard < 100000 &&
done < n; guard++) {
250 return done == n ? TRUE : FALSE;
259 for (guard = 0; guard < 10000 && !c; guard++) {
283 for (p = 18500; p < 18600; p++) {
286 snprintf(ps,
sizeof(ps),
"%d", p);
288 snprintf(port_out, port_out_len,
"%s", ps);
297int main(
int argc,
char** argv) {
300 SSL_CTX* sctx = NULL;
344 pthread_create(&th, NULL,
server_fn, &srv);
381 n_log(
LOG_ERR,
"stale error queue: idle recv returned %zd, not WANT_READ", idle);
402 pthread_join(th, NULL);
void process_args(int argc, char **argv)
NETWORK * netw
Network for server mode, accepting incomming.
static void * server_fn(void *p)
static NETWORK * bind_free(char *port_out, size_t port_out_len)
#define MSG_LEN
fixed exchange message length (both messages are 17 chars + NUL)
volatile sig_atomic_t done
#define MSG
client->server probe (both messages share this fixed length)
SSL_CTX * ctx
shared server ctx (owned by main)
static SSL_CTX * make_server_ctx(const N_STR *cert_pem, const N_STR *key_pem)
static int io_full(NETWORK *netw, char *buf, uint32_t n, int is_send)
static int poll_fd(SOCKET fd, int want_write, int timeout_ms)
static int drive_handshake(NETWORK *netw, int is_server, SSL_CTX *sctx)
NETWORK * listen
the listening socket
#define REPLY
server->client probe
static int drive_connect(NETWORK *netw)
int ok
set to 1 once the server completed the exchange
static void leave_stale_openssl_error(void)
leave a genuine error on this thread's OpenSSL queue (portable: a failed PEM parse,...
volatile char key[227]
TRUE while the key is held.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
#define LOG_NOTICE
normal but significant condition
#define LOG_NULL
no log output
#define LOG_INFO
informational
size_t written
number of meaningful bytes in data, excluding the null terminator; the size including the null termin...
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
A box including a string and his lenght.
int n_x509_generate_ca(const char *cn, int days, N_STR **ca_cert_pem, N_STR **ca_key_pem)
Generate a self-signed certificate authority (CA) keypair and cert.
N_SOCKET link
networking socket
SOCKET sock
a normal socket
ssize_t send_ssl_data_once(void *netw, char *buf, uint32_t n)
single-attempt TLS send for non-blocking sockets (reactor use).
#define NETW_IO_WANT_READ
single-attempt I/O (send_data_once / recv_data_once): the operation cannot progress until the socket ...
ssize_t recv_ssl_data_once(void *netw, char *buf, uint32_t n)
single-attempt TLS recv for non-blocking sockets (reactor use).
int netw_ssl_set_verify(NETWORK *netw, int enable)
enable or disable SSL peer certificate verification
NETWORK * netw_accept_nonblock_from(NETWORK *from, int blocking)
make a normal blocking 'accept' .
int netw_ssl_server_handshake_once(NETWORK *netw, SSL_CTX *ctx)
non-blocking, resumable TLS server handshake against a shared ctx
int netw_connect_nonblock(NETWORK **netw, char *host, char *port, int ip_version)
begin a non-blocking TCP connect without waiting for it to complete
int netw_ssl_handshake_once(NETWORK *netw, const char *sni_hostname)
non-blocking, resumable TLS client handshake
int netw_init_openssl(void)
Do not directly use, internal api.
#define NETW_TLS_MAX_VERSION
highest TLS version the linked TLS library can negotiate, as a TLS*_VERSION constant.
int netw_make_listening(NETWORK **netw, char *addr, char *port, int nbpending, int ip_version)
Make a NETWORK be a Listening network.
int netw_unload_openssl(void)
Do not directly use, internal api.
#define NETWORK_IPALL
Flag for auto detection by OS of ip version to use.
int SOCKET
default socket declaration
int netw_connect_check(NETWORK *netw)
advance a non-blocking connect started by netw_connect_nonblock()
#define NETW_IO_WANT_WRITE
single-attempt I/O: the operation cannot progress until the socket is WRITABLE.
int netw_close(NETWORK **netw)
Closing a specified Network, destroy queues, free the structure.
int netw_ssl_start_client(NETWORK *netw)
Set up a client SSL_CTX on an already-connected NETWORK.
int netw_ssl_set_versions(NETWORK *netw, int min_version, int max_version)
set the minimum (and optionally maximum) TLS protocol version on a connection's SSL context
Common headers and low-level functions & define.
N_STR and string function declaration.
X.509 helpers: self-signed CA generation and per-host leaf minting.