diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index ccdd2be3e..fb87141f8 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -2245,6 +2245,9 @@ WOLFSSL_API int wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY *); \return SSL_FAILURE will be returned on failure. This could be caused by the session cache being disabled, or if the session has timed out. + \return When OPENSSL_EXTRA and WOLFSSL_ERROR_CODE_OPENSSL are defined, + SSL_SUCCESS will be returned even if the session has timed out. + \param ssl pointer to the SSL object, created with wolfSSL_new(). \param session pointer to the WOLFSSL_SESSION used to set the session for ssl. @@ -5780,7 +5783,8 @@ WOLFSSL_API int wolfSSL_set_timeout(WOLFSSL*, unsigned int); \brief This function sets the timeout value for SSL sessions, in seconds, for the specified SSL context. - \return SSL_SUCCESS will be returned upon success. + \return the previous timeout value, if WOLFSSL_ERROR_CODE_OPENSSL is + \return defined on success. If not defined, SSL_SUCCESS will be returned. \return BAD_FUNC_ARG will be returned when the input context (ctx) is null. \param ctx pointer to the SSL context, created with wolfSSL_CTX_new(). diff --git a/src/ssl.c b/src/ssl.c index 1037bc304..93d525704 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -11108,7 +11108,24 @@ WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) return NULL; } - +/* + * Sets the session object to use when establishing a TLS/SSL session using + * the ssl object. Therefore, this function must be called before + * wolfSSL_connect. The session object to use can be obtained in a previous + * TLS/SSL connection using wolfSSL_get_session. + * + * This function rejects the session if it has been expired when this function + * is called. Note that this expiration check is wolfSSL specific and differs + * from OpenSSL return code behavior. + * + * By default, wolfSSL_set_session returns WOLFSSL_SUCCESS on successfully + * setting the session, WOLFSSL_FAILURE on failure due to the session cache + * being disabled, or the session has expired. + * + * To match OpenSSL return code behavior when session is expired, define + * OPENSSL_EXTRA and WOLFSSL_ERROR_CODE_OPENSSL. This behavior will return + * WOLFSSL_SUCCESS even when the session is expired and rejected. + */ WOLFSSL_ABI int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session) { @@ -13663,18 +13680,65 @@ int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to) } -/* set ctx session timeout in seconds */ +/** + * Sets ctx session timeout in seconds. + * The timeout value set here should be reflected in the + * "session ticket lifetime hint" if this API works in the openssl compat-layer. + * Therefore wolfSSL_CTX_set_TicketHint is called internally. + * Arguments: + * - ctx WOLFSSL_CTX object which the timeout is set to + * - to timeout value in second + * Returns: + * WOLFSSL_SUCCESS on success, BAD_FUNC_ARG on failure. + * When WOLFSSL_ERROR_CODE_OPENSSL is defined, returns previous timeout value + * on success, BAD_FUNC_ARG on failure. + */ WOLFSSL_ABI int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to) { + #if defined(WOLFSSL_ERROR_CODE_OPENSSL) + word32 prev_timeout; + #endif + + int ret = WOLFSSL_SUCCESS; + (void)ret; + if (ctx == NULL) - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; - if (to == 0) - to = WOLFSSL_SESSION_TIMEOUT; - ctx->timeout = to; + if (ret == WOLFSSL_SUCCESS) { + #if defined(WOLFSSL_ERROR_CODE_OPENSSL) + prev_timeout = ctx->timeout; + #endif + if (to == 0) { + ctx->timeout = WOLFSSL_SESSION_TIMEOUT; + } + else { + ctx->timeout = to; + } + } +#if defined(OPENSSL_EXTRA) && defined(HAVE_SESSION_TICKET) && \ + !defined(NO_WOLFSSL_SERVER) + if (ret == WOLFSSL_SUCCESS) { + if (to == 0) { + ret = wolfSSL_CTX_set_TicketHint(ctx, SESSION_TICKET_HINT_DEFAULT); + } + else { + ret = wolfSSL_CTX_set_TicketHint(ctx, to); + } + } +#endif /* OPENSSL_EXTRA && HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER */ - return WOLFSSL_SUCCESS; +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + if (ret == WOLFSSL_SUCCESS) { + return prev_timeout; + } + else { + return ret; + } +#else + return ret; +#endif /* WOLFSSL_ERROR_CODE_OPENSSL */ } @@ -14048,7 +14112,14 @@ int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) return ret; } - return WOLFSSL_FAILURE; /* session timed out */ + else { +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) + WOLFSSL_MSG("Session is expired but return success for \ + OpenSSL compatibility"); + return WOLFSSL_SUCCESS; +#endif /* OPENSSL_EXTRA && WOLFSSL_ERROR_CODE_OPENSSL */ + return WOLFSSL_FAILURE; /* session timed out */ + } } diff --git a/tests/api.c b/tests/api.c index 550209680..d986738a8 100644 --- a/tests/api.c +++ b/tests/api.c @@ -35048,6 +35048,22 @@ static void test_wolfSSL_SESSION(void) #endif #ifdef OPENSSL_EXTRA + + /* session timeout case */ + /* make the session to be expired */ + AssertIntEQ(SSL_SESSION_set_timeout(sess,1), SSL_SUCCESS); + XSLEEP_MS(1200); + + /* SSL_set_session should reject specified session but return success + * if WOLFSSL_ERROR_CODE_OPENSSL macro is defined for OpenSSL compatibility. + */ +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + AssertIntEQ(wolfSSL_set_session(ssl,sess), SSL_SUCCESS); +#else + AssertIntEQ(wolfSSL_set_session(ssl,sess), SSL_FAILURE); +#endif + AssertIntEQ(wolfSSL_SSL_SESSION_set_timeout(sess, 500), SSL_SUCCESS); + /* fail case with miss match session context IDs (use compatibility API) */ AssertIntEQ(SSL_set_session_id_context(ssl, context, contextSz), SSL_SUCCESS); @@ -45029,6 +45045,39 @@ static void test_wolfSSL_EC_curve(void) #endif } +static void test_wolfSSL_CTX_set_timeout(void) +{ +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_SESSION_CACHE) + int timeout; + (void)timeout; + printf(testingFmt, "test_wolfSSL_CTX_set_timeout()"); + + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); + AssertNotNull(ctx); + +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + /* in WOLFSSL_ERROR_CODE_OPENSSL macro guard, + * wolfSSL_CTX_set_timeout returns previous timeout value on success. + */ + AssertIntEQ(wolfSSL_CTX_set_timeout(NULL, 0), BAD_FUNC_ARG); + /* giving 0 as timeout value sets default timeout */ + timeout = wolfSSL_CTX_set_timeout(ctx, 0); + AssertIntEQ(wolfSSL_CTX_set_timeout(ctx, 20), timeout); + AssertIntEQ(wolfSSL_CTX_set_timeout(ctx, 30), 20); + +#else + + AssertIntEQ(wolfSSL_CTX_set_timeout(NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_set_timeout(ctx, 100), 1); + AssertIntEQ(wolfSSL_CTX_set_timeout(ctx, 0), 1); + +#endif + wolfSSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif /* !NO_WOLFSSL_SERVER && !NO_SESSION_CACHE*/ +} + static void test_wolfSSL_OpenSSL_version(void) { #if defined(OPENSSL_EXTRA) @@ -45871,6 +45920,7 @@ void ApiTest(void) test_wolfSSL_security_level(); test_wolfSSL_SSL_in_init(); test_wolfSSL_EC_curve(); + test_wolfSSL_CTX_set_timeout(); test_wolfSSL_OpenSSL_version(); test_wolfSSL_set_psk_use_session_callback();