Skip to content

Commit a24437d

Browse files
handle race condition with connect
1 parent 194103a commit a24437d

1 file changed

Lines changed: 68 additions & 28 deletions

File tree

port/posix/posix_transport_tls.c

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343

4444

4545
#ifndef WOLFHSM_CFG_NO_CRYPTO
46+
4647
/* returns 1 (true) if the error passed in is a notice for non blocking
4748
* 0 if the error is a fatal error */
4849
static int NonBlockingError(int err)
@@ -63,40 +64,26 @@ int posixTransportTls_InitConnect(void* context, const void* config,
6364
(posixTransportTlsClientContext*)context;
6465
posixTransportTlsConfig* cfg = (posixTransportTlsConfig*)config;
6566
int rc;
67+
WOLFSSL_CTX* ssl_ctx;
6668

6769
if (!ctx || !cfg) {
6870
return WH_ERROR_BADARGS;
6971
}
7072

73+
/* Save configured WOLFSSL_CTX and clear rest of the context struct */
74+
ssl_ctx = ctx->ssl_ctx;
75+
memset(ctx, 0, sizeof(posixTransportTlsClientContext));
76+
ctx->ssl_ctx = ssl_ctx;
77+
7178
/* Setup underlying TCP transport */
7279
rc = posixTransportTcp_InitConnect((void*)&ctx->tcpCtx, cfg, connectcb,
7380
connectcb_arg);
7481
if (rc != WH_ERROR_OK) {
7582
return rc;
7683
}
7784

78-
/* Create SSL object if not already created */
79-
if (ctx->ssl == NULL) {
80-
if (posixTransportTcp_GetConnectFd(
81-
(void*)&ctx->tcpCtx, &ctx->connect_fd_p1) != WH_ERROR_OK) {
82-
return WH_ERROR_NOTREADY;
83-
}
84-
85-
ctx->ssl = wolfSSL_new(ctx->ssl_ctx);
86-
if (!ctx->ssl) {
87-
posixTransportTcp_CleanupConnect((void*)&ctx->tcpCtx);
88-
return WH_ERROR_ABORTED;
89-
}
90-
91-
/* Set the socket file descriptor */
92-
rc = wolfSSL_set_fd(ctx->ssl, ctx->connect_fd_p1);
93-
if (rc != WOLFSSL_SUCCESS) {
94-
wolfSSL_free(ctx->ssl);
95-
ctx->ssl = NULL;
96-
posixTransportTcp_CleanupConnect((void*)&ctx->tcpCtx);
97-
return WH_ERROR_ABORTED;
98-
}
99-
}
85+
/* At the point of the TCP claiming to be connected, the TLS handshake will
86+
* happen during send/recv calls */
10087
if (ctx->connectcb != NULL) {
10188
ctx->connectcb(ctx->connectcb_arg, WH_COMM_CONNECTED);
10289
}
@@ -119,7 +106,7 @@ int posixTransportTls_SendRequest(void* context, uint16_t size,
119106
posixTransportTlsClientContext* ctx =
120107
(posixTransportTlsClientContext*)context;
121108
int err;
122-
int rc;
109+
int rc = 0;
123110

124111
if (!ctx || !data || size == 0) {
125112
return WH_ERROR_BADARGS;
@@ -131,13 +118,61 @@ int posixTransportTls_SendRequest(void* context, uint16_t size,
131118
return WH_ERROR_NOTREADY;
132119
}
133120

121+
/* Create SSL object if not already created
122+
* (posixTransportTcp_HandleConnect can change the socket used if server
123+
* is not listening yet, thats why we need to wait to set the fd in
124+
* wolfSSL until after the connect() has completed) */
125+
if (ctx->ssl == NULL) {
126+
if (posixTransportTcp_GetConnectFd(
127+
(void*)&ctx->tcpCtx, &ctx->connect_fd_p1) != WH_ERROR_OK) {
128+
return WH_ERROR_NOTREADY;
129+
}
130+
131+
ctx->ssl = wolfSSL_new(ctx->ssl_ctx);
132+
if (!ctx->ssl) {
133+
posixTransportTcp_CleanupConnect((void*)&ctx->tcpCtx);
134+
return WH_ERROR_ABORTED;
135+
}
136+
137+
/* Set the current socket file descriptor */
138+
rc = wolfSSL_set_fd(ctx->ssl, ctx->connect_fd_p1);
139+
if (rc != WOLFSSL_SUCCESS) {
140+
wolfSSL_free(ctx->ssl);
141+
ctx->ssl = NULL;
142+
posixTransportTcp_CleanupConnect((void*)&ctx->tcpCtx);
143+
return WH_ERROR_ABORTED;
144+
}
145+
}
146+
134147
rc = wolfSSL_connect(ctx->ssl);
135148
err = wolfSSL_get_error(ctx->ssl, rc);
136149
if (rc != WOLFSSL_SUCCESS) {
137150
if (NonBlockingError(err)) {
138151
return WH_ERROR_NOTREADY;
139152
}
140153
else {
154+
if (err == SOCKET_ERROR_E) {
155+
/* There is a case where TCP connect() returned successfully
156+
* but the server has not called accept() and the pending
157+
* send was in the TCP backlog waiting on the server. But
158+
* if the server closes down the listen port then RST gets
159+
* returned. Retry the TCP connect() */
160+
wolfSSL_free(ctx->ssl);
161+
ctx->ssl = NULL;
162+
163+
/* Close the failed socket fd and set state for retry */
164+
if (ctx->tcpCtx.connect_fd_p1 != 0) {
165+
close(ctx->tcpCtx.connect_fd_p1 - 1);
166+
ctx->tcpCtx.connect_fd_p1 = 0;
167+
}
168+
ctx->tcpCtx.state = PTT_STATE_UNCONNECTED;
169+
return WH_ERROR_NOTREADY;
170+
171+
}
172+
173+
if (ctx->connectcb != NULL) {
174+
ctx->connectcb(ctx->connectcb_arg, WH_COMM_DISCONNECTED);
175+
}
141176
return WH_ERROR_ABORTED;
142177
}
143178
}
@@ -218,6 +253,8 @@ int posixTransportTls_CleanupConnect(void* context)
218253
wolfSSL_free(ctx->ssl);
219254
}
220255
ctx->ssl = NULL;
256+
ctx->state = PTTLS_STATE_UNCONNECTED;
257+
ctx->connect_fd_p1 = 0;
221258
posixTransportTcp_CleanupConnect((void*)&ctx->tcpCtx);
222259
return WH_ERROR_OK;
223260
#else
@@ -237,28 +274,29 @@ int posixTransportTls_InitListen(void* context, const void* config,
237274
(posixTransportTlsServerContext*)context;
238275
posixTransportTlsConfig* cfg = (posixTransportTlsConfig*)config;
239276
int rc;
277+
WOLFSSL_CTX* ssl_ctx;
240278

241279
if (!ctx || !cfg) {
242280
return WH_ERROR_BADARGS;
243281
}
244282

283+
/* Save configured WOLFSSL_CTX and clear rest of the context struct */
284+
ssl_ctx = ctx->ssl_ctx;
285+
memset(ctx, 0, sizeof(posixTransportTlsServerContext));
286+
ctx->ssl_ctx = ssl_ctx;
287+
245288
/* Initialize TCP server context */
246289
rc = posixTransportTcp_InitListen(&ctx->tcpCtx, cfg, connectcb,
247290
connectcb_arg);
248291
if (rc != WH_ERROR_OK) {
249292
return rc;
250293
}
251294

252-
/* Copy TCP context fields to TLS context for compatibility */
253295
ctx->connectcb = connectcb;
254296
ctx->connectcb_arg = connectcb_arg;
255297
ctx->server_addr = ctx->tcpCtx.server_addr;
256298
ctx->listen_fd_p1 = ctx->tcpCtx.listen_fd_p1;
257299

258-
259-
/* Load private key and certificate */
260-
261-
/* Connecting is handled internally so we need server to call recv */
262300
if (ctx->connectcb != NULL) {
263301
ctx->connectcb(ctx->connectcb_arg, WH_COMM_CONNECTED);
264302
}
@@ -409,6 +447,8 @@ int posixTransportTls_CleanupListen(void* context)
409447
}
410448

411449
if (ctx->ssl) {
450+
/* Give a quick shutdown signal to the client but do not wait for a
451+
* response from the client before tearing down the transport. */
412452
(void)wolfSSL_shutdown(ctx->ssl);
413453
wolfSSL_free(ctx->ssl);
414454
ctx->ssl = NULL;

0 commit comments

Comments
 (0)