30#define LOG_PREFIX "tls"
33#include <freeradius-devel/unlang/function.h>
34#include <freeradius-devel/unlang/interpret.h>
38#include "connection.h"
54static void tls_connection_request_wake(fr_tls_connection_t *conn)
56 if (!conn->idle)
return;
69static void tls_connection_check(fr_tls_connection_t *conn)
71 fr_tls_session_t *tls_session = conn->tls_session;
78 if (conn->state != TLS_CONNECTION_HANDSHAKE)
return;
80 if (tls_session->result == FR_TLS_RESULT_ERROR) {
81 fr_tls_log(conn->request,
"TLS handshake failed");
90 if (!fr_tls_session_is_init_finished(tls_session))
return;
93 INFO(
"TLS handshake completed");
94 INFO(
" version : %s", SSL_get_version(tls_session->ssl));
95 INFO(
" cipher : %s", SSL_get_cipher(tls_session->ssl));
96 INFO(
" resumed : %s", SSL_session_reused(tls_session->ssl) ?
"yes" :
"no");
110 conn->state = TLS_CONNECTION_COMPLETE;
111 tls_connection_request_wake(conn);
124static void tls_connection_finished(fr_tls_connection_t *conn)
129 conn->finished(conn->uctx, conn);
147static void tls_connection_failed(fr_tls_connection_t *conn)
156 if (conn->state != TLS_CONNECTION_HANDSHAKE) {
157 tls_connection_finished(conn);
161 conn->state = TLS_CONNECTION_COMPLETE;
162 tls_connection_request_wake(conn);
201 ua = fr_tls_session_fail_session(request, conn->tls_session);
217 tls_connection_finished(conn);
221#define TLS_CONNECTION_ERROR_RETURN \
223 if (ua == UNLANG_ACTION_PUSHED_CHILD) return ua; \
224 if (ua == UNLANG_ACTION_FAIL) return tls_connection_error(request, conn); \
227#define TLS_CONNECTION_REPEAT(_func) \
229 if (unlang_function_repeat_set(request, _func) < 0) { \
230 return tls_connection_error(request, conn); \
239 fr_tls_connection_t *conn = talloc_get_type_abort(uctx, fr_tls_connection_t);
250 fr_assert(!fr_tls_cache_pending(conn->tls_session->cache));
252 conn->finished(conn->uctx, conn);
264 fr_tls_connection_t *conn = talloc_get_type_abort(uctx, fr_tls_connection_t);
272 TLS_CONNECTION_REPEAT(tls_connection_application_data);
275 ua = fr_tls_session_fail_session(request, conn->tls_session);
277 ua = fr_tls_cache_store_session(request, conn->tls_session);
279 TLS_CONNECTION_ERROR_RETURN;
281 return tls_connection_application_data(request, conn);
295 fr_tls_connection_t *conn = talloc_get_type_abort(uctx, fr_tls_connection_t);
306 if (conn->state == TLS_CONNECTION_COMPLETE)
return tls_connection_init_finished(request, conn);
311 TLS_CONNECTION_REPEAT(tls_connection_handshake);
317 if (!conn->pending) {
322 conn->pending =
false;
330 ua = fr_tls_session_async_handshake_push(request, conn->tls_session);
333 fr_tls_log(conn->request,
"Failed pushing a TLS handshake round");
334 return tls_connection_error(request, conn);
342 fr_tls_connection_t *conn = talloc_get_type_abort(uctx, fr_tls_connection_t);
352 conn->state = TLS_CONNECTION_HANDSHAKE;
354 if (conn->tls_conf->new_session) {
355 fr_assert(conn->tls_conf->virtual_server);
357 TLS_CONNECTION_REPEAT(tls_connection_handshake);
359 ua = fr_tls_new_session_push(request, conn->tls_conf);
360 TLS_CONNECTION_ERROR_RETURN;
363 return tls_connection_handshake(request, conn);
378int fr_tls_connection_push(fr_tls_connection_t *conn)
381 tls_connection_new_session,
382 tls_connection_new_session,
395void fr_tls_connection_wake(fr_tls_connection_t *conn)
397 conn->pending =
true;
399 tls_connection_request_wake(conn);
428void fr_tls_connection_recv(fr_tls_connection_t *conn,
uint8_t const *
data,
size_t data_len)
430 fr_tls_session_t *tls_session = conn->tls_session;
433 RDEBUG3(
"Read %zu bytes from the connection", data_len);
436 RERROR(
"Failed buffering %zu bytes of TLS record data", data_len);
438 tls_connection_failed(conn);
447 if (fr_tls_session_is_init_finished(tls_session)) {
448 RERROR(
"Received %zu bytes of application data, which is not supported", data_len);
456 fr_tls_connection_wake(conn);
468void fr_tls_connection_process(fr_tls_connection_t *conn)
470 if (conn->write(conn->uctx, conn) < 0) {
471 tls_connection_failed(conn);
475 tls_connection_check(conn);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
@ UNLANG_ACTION_YIELD
Temporarily pause execution until an event occurs.
#define IGNORE(_expr, _type)
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
#define fr_dbuff_in_memcpy_partial(_out, _in, _inlen)
Copy at most _inlen bytes into the dbuff.
int unlang_function_clear(request_t *request)
Clear pending repeat function calls, and remove the signal handler.
#define unlang_function_repeat_set(_request, _repeat)
Set a new repeat function for an existing function frame.
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.