Skip to content

Commit 78114c0

Browse files
ssl: Factor out SSL code from libevent-newsql
Code to accept, connect, read, write over SSL will be reused for replication. Signed-off-by: Akshat Sikarwar <asikarwar1@bloomberg.net>
1 parent 51e0892 commit 78114c0

File tree

5 files changed

+230
-87
lines changed

5 files changed

+230
-87
lines changed

net/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
add_library(net
22
sqlwriter.c
33
net_evbuffer.c
4+
ssl_evbuffer.c
45
info.c
56
net.c
67
trace.c

net/sqlwriter.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <logmsg.h>
2929
#include <net_appsock.h>
3030
#include <sqlwriter.h>
31+
#include <ssl_evbuffer.h>
3132

3233
//send heartbeat if no data every (seconds)
3334
#define min_hb_time 1
@@ -129,14 +130,9 @@ void sql_disable_timeout(struct sqlwriter *writer)
129130
run_on_base(writer->timer_base, do_sql_disable_timeout, writer);
130131
}
131132

132-
static int wr_evbuffer_ssl(struct sqlwriter *writer, int fd)
133+
static int wr_evbuffer_ciphertext(struct sqlwriter *writer, int fd)
133134
{
134-
int len = evbuffer_get_length(writer->wr_buf);
135-
if (len > KB(16)) len = KB(16);
136-
const void *buf = evbuffer_pullup(writer->wr_buf, len);
137-
int rc = SSL_write(writer->ssl, buf, len);
138-
if (rc > 0) evbuffer_drain(writer->wr_buf, rc);
139-
return rc;
135+
return wr_evbuffer_ssl(writer->ssl, writer->wr_buf);
140136
}
141137

142138
static int wr_evbuffer_plaintext(struct sqlwriter *writer, int fd)
@@ -498,7 +494,7 @@ struct sqlwriter *sqlwriter_new(struct sqlwriter_arg *arg)
498494
void sql_enable_ssl(struct sqlwriter *writer, SSL *ssl)
499495
{
500496
writer->ssl = ssl;
501-
writer->wr_evbuffer_fn = wr_evbuffer_ssl;
497+
writer->wr_evbuffer_fn = wr_evbuffer_ciphertext;
502498
}
503499

504500
void sql_disable_ssl(struct sqlwriter *writer)

net/ssl_evbuffer.c

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
Copyright 2023 Bloomberg Finance L.P.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#include <string.h>
18+
19+
#include <event2/buffer.h>
20+
#include <event2/event.h>
21+
#include <openssl/err.h>
22+
#include <openssl/ssl.h>
23+
24+
#include <comdb2_atomic.h>
25+
#include <logmsg.h>
26+
27+
#include <net_appsock.h>
28+
#include <ssl_evbuffer.h>
29+
30+
extern SSL_CTX *gbl_ssl_ctx;
31+
extern uint64_t gbl_ssl_num_full_handshakes;
32+
extern uint64_t gbl_ssl_num_partial_handshakes;
33+
34+
struct ssl_handshake_arg {
35+
struct event_base *base;
36+
void *data;
37+
ssl_evbuffer_cb *error_cb;
38+
ssl_evbuffer_cb *success_cb;
39+
SSL *ssl;
40+
};
41+
42+
static void ssl_handshake_evbuffer(int fd, short what, void *data)
43+
{
44+
struct ssl_handshake_arg *arg = data;
45+
SSL *ssl = arg->ssl;
46+
ERR_clear_error();
47+
int rc = SSL_do_handshake(ssl);
48+
if (rc == 1) {
49+
if (SSL_session_reused(ssl)) {
50+
ATOMIC_ADD64(gbl_ssl_num_partial_handshakes, 1);
51+
} else {
52+
ATOMIC_ADD64(gbl_ssl_num_full_handshakes, 1);
53+
}
54+
arg->success_cb(arg->data);
55+
free(arg);
56+
return;
57+
}
58+
int err = SSL_get_error(ssl, rc);
59+
switch (err) {
60+
case SSL_ERROR_WANT_READ:
61+
event_base_once(arg->base, fd, EV_READ, ssl_handshake_evbuffer, arg, NULL);
62+
return;
63+
case SSL_ERROR_WANT_WRITE:
64+
event_base_once(arg->base, fd, EV_WRITE, ssl_handshake_evbuffer, arg, NULL);
65+
return;
66+
case SSL_ERROR_SYSCALL:
67+
logmsg(LOGMSG_ERROR, "%s:%d SSL_do_handshake rc:%d err:%d errno:%d [%s]\n",
68+
__func__, __LINE__, rc, err, errno, strerror(errno));
69+
break;
70+
default:
71+
logmsg(LOGMSG_ERROR, "%s:%d SSL_do_handshake rc:%d err:%d error_string:%s]\n",
72+
__func__, __LINE__, rc, err, ERR_error_string(err, NULL));
73+
break;
74+
}
75+
arg->error_cb(arg->data);
76+
free(arg);
77+
}
78+
79+
static struct ssl_handshake_arg *new_ssl_handshake(SSL **ssl, int fd, struct event_base *base, ssl_evbuffer_cb *error_cb, ssl_evbuffer_cb *success_cb, void *data)
80+
{
81+
struct ssl_handshake_arg *arg = malloc(sizeof(*arg));
82+
arg->base = base;
83+
arg->data = data;
84+
arg->error_cb = error_cb;
85+
arg->success_cb = success_cb;
86+
arg->ssl = *ssl = SSL_new(gbl_ssl_ctx);
87+
SSL_set_mode(arg->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
88+
SSL_set_fd(arg->ssl, fd);
89+
return arg;
90+
}
91+
92+
void accept_evbuffer_ssl(SSL **ssl, int fd, struct event_base *base, ssl_evbuffer_cb *error_cb, ssl_evbuffer_cb *success_cb, void *data)
93+
{
94+
struct ssl_handshake_arg *arg = new_ssl_handshake(ssl, fd, base, error_cb, success_cb, data);
95+
SSL_set_accept_state(arg->ssl);
96+
ssl_handshake_evbuffer(fd, EV_READ, arg);
97+
}
98+
99+
void connect_evbuffer_ssl(SSL **ssl, int fd, struct event_base *base, ssl_evbuffer_cb *error_cb, ssl_evbuffer_cb *success_cb, void *data)
100+
{
101+
struct ssl_handshake_arg *arg = new_ssl_handshake(ssl, fd, base, error_cb, success_cb, data);
102+
SSL_set_connect_state(arg->ssl);
103+
ssl_handshake_evbuffer(fd, EV_READ, arg);
104+
}
105+
106+
int rd_evbuffer_ssl(struct evbuffer *rd_buf, SSL *ssl, int *eof)
107+
{
108+
*eof = 0;
109+
int len = KB(16);
110+
struct iovec v = {0};
111+
if (evbuffer_reserve_space(rd_buf, len, &v, 1) == -1) {
112+
return -1;
113+
}
114+
ERR_clear_error();
115+
int rc = SSL_read(ssl, v.iov_base, len);
116+
if (rc > 0) {
117+
v.iov_len = rc;
118+
evbuffer_commit_space(rd_buf, &v, 1);
119+
return rc;
120+
}
121+
int err = SSL_get_error(ssl, rc);
122+
switch (err) {
123+
case SSL_ERROR_ZERO_RETURN: *eof = 1; /* fallthrough */
124+
case SSL_ERROR_WANT_READ: return 1;
125+
case SSL_ERROR_WANT_WRITE:
126+
logmsg(LOGMSG_ERROR, "%s:%d SSL_read rc:%d err:%d SSL_ERROR_WANT_WRITE]\n",
127+
__func__, __LINE__, rc, err);
128+
break;
129+
case SSL_ERROR_SYSCALL:
130+
logmsg(LOGMSG_ERROR, "%s:%d SSL_read rc:%d err:%d errno:%d [%s]\n",
131+
__func__, __LINE__, rc, err, errno, strerror(errno));
132+
break;
133+
default:
134+
logmsg(LOGMSG_ERROR, "%s:%d SSL_read rc:%d err:%d [%s]\n",
135+
__func__, __LINE__, rc, err, ERR_error_string(err, NULL));
136+
break;
137+
}
138+
return rc;
139+
}
140+
141+
int wr_evbuffer_ssl(SSL *ssl, struct evbuffer *wr_buf)
142+
{
143+
int len = evbuffer_get_length(wr_buf);
144+
if (len > KB(16)) len = KB(16);
145+
const void *buf = evbuffer_pullup(wr_buf, len);
146+
ERR_clear_error();
147+
int rc = SSL_write(ssl, buf, len);
148+
if (rc > 0) {
149+
evbuffer_drain(wr_buf, rc);
150+
return rc;
151+
}
152+
int err = SSL_get_error(ssl, rc);
153+
switch (err) {
154+
case SSL_ERROR_WANT_WRITE:
155+
errno = EAGAIN;
156+
break;
157+
case SSL_ERROR_WANT_READ:
158+
logmsg(LOGMSG_ERROR, "%s:%d SSL_write rc:%d err:%d SSL_ERROR_WANT_READ]\n",
159+
__func__, __LINE__, rc, err);
160+
break;
161+
case SSL_ERROR_SYSCALL:
162+
logmsg(LOGMSG_ERROR, "%s:%d SSL_write rc:%d err:%d errno:%d [%s]\n",
163+
__func__, __LINE__, rc, err, errno, strerror(errno));
164+
break;
165+
default:
166+
logmsg(LOGMSG_ERROR, "%s:%d SSL_write rc:%d err:%d [%s]\n",
167+
__func__, __LINE__, rc, err, ERR_error_string(err, NULL));
168+
break;
169+
}
170+
return rc;
171+
}

net/ssl_evbuffer.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2023 Bloomberg Finance L.P.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#ifndef INCLUDED_SSLWRITER_H
18+
#define INCLUDED_SSLWRITER_H
19+
20+
struct ssl_st;
21+
struct evbuffer;
22+
struct event_base;
23+
typedef void (ssl_evbuffer_cb)(void *);
24+
void accept_evbuffer_ssl(struct ssl_st **, int, struct event_base *, ssl_evbuffer_cb *on_error, ssl_evbuffer_cb *on_success, void *);
25+
void connect_evbuffer_ssl(struct ssl_st **, int fd, struct event_base *base, ssl_evbuffer_cb *error_cb, ssl_evbuffer_cb *success_cb, void *data);
26+
int rd_evbuffer_ssl(struct evbuffer *, struct ssl_st *, int *eof);
27+
int wr_evbuffer_ssl(struct ssl_st *, struct evbuffer *);
28+
29+
#endif /* INCLUDED_SSLWRITER_H */

0 commit comments

Comments
 (0)