Skip to content

Commit 31dda00

Browse files
committed
add basics for OpenSSL err handling
Add the basic structure required for properly handling the error queue. Otherwise SSL_get_error() can return junk.
1 parent 84a2db0 commit 31dda00

File tree

3 files changed

+62
-9
lines changed

3 files changed

+62
-9
lines changed

proxy_network.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,7 @@ static void proxy_beconn_tls_handler(const int fd, const short which, void *arg)
11811181
if (_proxy_beconn_checkconnect(be) == -1) {
11821182
return;
11831183
}
1184+
// TODO: check return code.
11841185
mcp_tls_connect(be);
11851186
// fall through to handshake attempt.
11861187
}
@@ -1193,9 +1194,11 @@ static void proxy_beconn_tls_handler(const int fd, const short which, void *arg)
11931194
_set_main_event(be, be->event_thread->base, EV_READ, &tmp_time, proxy_beconn_tls_handler);
11941195
return;
11951196
} else if (ret == 1) {
1196-
// complete.
1197-
// TODO: handle errors.
1198-
mcp_tls_send_validate(be);
1197+
// handshake complete.
1198+
if (mcp_tls_send_validate(be) != 1) {
1199+
_reset_bad_backend(be, P_BE_FAIL_BADVALIDATE);
1200+
return;
1201+
}
11991202

12001203
// switch to another handler for the final stage.
12011204
_set_main_event(be, be->event_thread->base, EV_READ, &tmp_time, proxy_bevalidate_tls_handler);

proxy_tls.c

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,22 @@
33
#include "proxy.h"
44
#include "proxy_tls.h"
55
#include <openssl/ssl.h>
6+
#include <openssl/err.h>
7+
8+
/* Notes on ERR_clear_error() and friends:
9+
* - Errors from SSL calls leave errors on a thread-local "error stack"
10+
* - If an error is received from an SSL call, the stack needs to be inspected
11+
* and cleared.
12+
* - The error stack _must_ be clear before any SSL_get_error() calls, as it
13+
* may return garbage.
14+
* - There may be _multiple_ errors queued after one SSL call, so just
15+
* checking the top level does not clear it.
16+
* - ERR_clear_error() is not "free", so we would prefer to avoid calling it
17+
* before hotpath calls. Thus, we should ensure it's called _after_ any
18+
* hotpath call that receives any kind of error.
19+
* - We should also call it _before_ any non-hotpath SSL calls (such as
20+
* SSL_connect()) for defense against bugs in our code or OpenSSL.
21+
*/
622

723
int mcp_tls_init(proxy_ctx_t *ctx) {
824
if (ctx->tls_ctx) {
@@ -47,8 +63,23 @@ int mcp_tls_connect(struct mcp_backendconn_s *be) {
4763
// TODO: check return code. can fail if BIO fails to alloc.
4864
SSL_set_fd(be->ssl, mcmc_fd(be->client));
4965

50-
// TODO: care about the error code.
51-
int ret = SSL_connect(be->ssl);
66+
ERR_clear_error();
67+
int n = SSL_connect(be->ssl);
68+
int ret = 1;
69+
// TODO: complete error handling.
70+
if (n == 1) {
71+
// Successfully established and handshake complete.
72+
} else if (n == 0) {
73+
// Not successsful, but shut down normally.
74+
ERR_clear_error();
75+
ret = -1;
76+
} else if (n < 0) {
77+
// Not successful. Check for temporary error.
78+
79+
// clear all errors in case of other junk.
80+
ERR_clear_error();
81+
ret = -1;
82+
}
5283

5384
return ret;
5485
}
@@ -58,6 +89,8 @@ int mcp_tls_handshake(struct mcp_backendconn_s *be) {
5889
return 1;
5990
}
6091

92+
// Non hot path, so clear errors before running.
93+
ERR_clear_error();
6194
int n = SSL_do_handshake(be->ssl);
6295
if (n == 1) {
6396
return 1;
@@ -69,20 +102,32 @@ int mcp_tls_handshake(struct mcp_backendconn_s *be) {
69102
// leaving this note just in case.
70103
if (err == SSL_ERROR_WANT_READ ||
71104
err == SSL_ERROR_WANT_WRITE) {
105+
// So far as I can tell there would be an error on the queue here.
106+
ERR_clear_error();
72107
return 0;
73108
} else {
74109
// TODO: can get the full error message and give to the caller to log
75110
// to proxyevents?
111+
ERR_clear_error();
76112
return -1;
77113
}
78114
}
79115

80-
// TODO: error processing.
81-
void mcp_tls_send_validate(struct mcp_backendconn_s *be) {
116+
int mcp_tls_send_validate(struct mcp_backendconn_s *be) {
82117
const char *str = "version\r\n";
83118
const size_t len = strlen(str);
84119

85-
SSL_write(be->ssl, str, len);
120+
// Non hot path, clear errors.
121+
ERR_clear_error();
122+
int n = SSL_write(be->ssl, str, len);
123+
124+
// TODO: more detailed error checking.
125+
if (n < 0 || n != len) {
126+
ERR_clear_error();
127+
return -1;
128+
}
129+
130+
return 1;
86131
}
87132

88133
int mcp_tls_read(struct mcp_backendconn_s *be) {
@@ -92,8 +137,11 @@ int mcp_tls_read(struct mcp_backendconn_s *be) {
92137
int err = SSL_get_error(be->ssl, n);
93138
if (err == SSL_ERROR_WANT_WRITE ||
94139
err == SSL_ERROR_WANT_READ) {
140+
ERR_clear_error();
95141
return -1;
96142
} else {
143+
// TODO: log detailed error.
144+
ERR_clear_error();
97145
return -2;
98146
}
99147
} else {
@@ -142,8 +190,10 @@ int mcp_tls_writev(struct mcp_backendconn_s *be, int iovcnt) {
142190
int err = SSL_get_error(be->ssl, n);
143191
if (err == SSL_ERROR_WANT_WRITE ||
144192
err == SSL_ERROR_WANT_READ) {
193+
ERR_clear_error();
145194
return -1;
146195
}
196+
ERR_clear_error();
147197
return -2;
148198
}
149199

proxy_tls.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ int mcp_tls_init(proxy_ctx_t *ctx);
55
int mcp_tls_backend_init(proxy_ctx_t *ctx, struct mcp_backendconn_s *be);
66
int mcp_tls_connect(struct mcp_backendconn_s *be);
77
int mcp_tls_handshake(struct mcp_backendconn_s *be);
8-
void mcp_tls_send_validate(struct mcp_backendconn_s *be);
8+
int mcp_tls_send_validate(struct mcp_backendconn_s *be);
99
int mcp_tls_read(struct mcp_backendconn_s *be);
1010
int mcp_tls_writev(struct mcp_backendconn_s *be, int iovcnt);
1111

0 commit comments

Comments
 (0)