diff --git a/examples/server/server.c b/examples/server/server.c index 326f3b28d..bceeca1db 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1410,6 +1410,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef HAVE_SUPPORTED_CURVES {"onlyPskDheKe", 2, 264}, #endif /* HAVE_SUPPORTED_CURVES */ +#ifdef HAVE_CRL + {"crl-dir", 1, 265}, +#endif { 0, 0, 0 } }; #endif @@ -1531,6 +1534,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) int useDtlsCID = 0; char dtlsCID[DTLS_CID_BUFFER_SIZE] = { 0 }; #endif /* WOLFSSL_DTLS_CID */ +#ifdef HAVE_CRL + char* crlDir = NULL; +#endif #ifdef WOLFSSL_STATIC_MEMORY /* Note: Actual memory used is much less, this is the entire buffer buckets, @@ -2279,6 +2285,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef WOLFSSL_TLS13 onlyPskDheKe = 1; #endif +#endif + break; + case 265: +#ifdef HAVE_CRL + crlDir = myoptarg; #endif break; @@ -3029,8 +3040,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif if (wolfSSL_EnableCRL(ssl, 0) != WOLFSSL_SUCCESS) err_sys_ex(runWithErrors, "unable to enable CRL"); - if (wolfSSL_LoadCRL(ssl, crlPemDir, WOLFSSL_FILETYPE_PEM, crlFlags) - != WOLFSSL_SUCCESS) + if (wolfSSL_LoadCRL(ssl, crlDir != NULL ? crlDir : crlPemDir, + WOLFSSL_FILETYPE_PEM, crlFlags) != WOLFSSL_SUCCESS) err_sys_ex(runWithErrors, "unable to load CRL"); if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != WOLFSSL_SUCCESS) err_sys_ex(runWithErrors, "unable to set CRL callback url"); diff --git a/src/crl.c b/src/crl.c index c7c210ebd..02a347360 100644 --- a/src/crl.c +++ b/src/crl.c @@ -1343,7 +1343,7 @@ static int StopMonitor(wolfSSL_CRL_mfd_t mfd) /* windows monitoring * Tested initially by hand by running - * .\server.exe -A certs/ca-cert.pem + * .\server.exe -A certs/ca-cert.pem -i -x * and connecting to with * .\client.exe -C -c certs/server-cert.pem -k certs/server-key.pem * This connection succeeds by default. By deleting all files from certs/crl diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 25dd8f0f1..910e19730 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -57,6 +57,7 @@ static THREAD_RETURN simple_test(func_args *args); static void simple_test(func_args *args); #endif static int test_tls(func_args* server_args); +static int test_crl_monitor(void); static void show_ciphers(void); static void cleanup_output(void); static int validate_cleanup_output(void); @@ -214,6 +215,15 @@ int testsuite_test(int argc, char** argv) cleanup_output(); return server_args.return_code; } + +#ifdef HAVE_CRL_MONITOR + ret = test_crl_monitor(); + if (ret != 0) { + cleanup_output(); + return ret; + } +#endif + #endif /* !NETOS */ show_ciphers(); @@ -246,6 +256,109 @@ int testsuite_test(int argc, char** argv) return EXIT_SUCCESS; } +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \ + defined(HAVE_CRL_MONITOR) +#define CRL_MONITOR_TEST_ROUNDS 6 + +static int test_crl_monitor(void) +{ + func_args server_args; + func_args client_args; + THREAD_TYPE serverThread; + tcp_ready ready; + char buf[128]; + char tmpDir[16]; + char rounds[4]; + char* serverArgv[] = { + "testsuite", + "-A", "certs/ca-cert.pem", + "--crl-dir", tmpDir, + "-C", rounds, + "-x" + }; + char* clientArgv[] = { + "testsuite", + "-C", + "-c", "certs/server-cert.pem", + "-k", "certs/server-key.pem", + "-H", "exitWithRet" + }; + int ret = -1; + int i; + + sprintf(rounds, "%d", CRL_MONITOR_TEST_ROUNDS); + + XMEMSET(&server_args, 0, sizeof(func_args)); + XMEMSET(&client_args, 0, sizeof(func_args)); + + /* Create temp dir */ + if (create_tmp_dir(tmpDir, sizeof(tmpDir) - 1) == NULL) { + fprintf(stderr, "Failed to create tmp dir"); + goto cleanup; + } + + server_args.argv = serverArgv; + server_args.argc = sizeof(serverArgv) / sizeof(*serverArgv); + client_args.signal = server_args.signal = &ready; + client_args.argv = clientArgv; + client_args.argc = sizeof(clientArgv) / sizeof(*clientArgv); + + InitTcpReady(&ready); + start_thread(server_test, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + for (i = 0; i < CRL_MONITOR_TEST_ROUNDS; i++) { + int expectFail; + if (i % 2 == 0) { + /* succeed on even rounds */ + sprintf(buf, "%s/%s", tmpDir, "crl.pem"); + copy_file("certs/crl/crl.pem", buf); + sprintf(buf, "%s/%s", tmpDir, "crl.revoked"); + /* The monitor can be holding the file handle and this will cause + * the remove call to fail. Let's give the monitor a second to + * finish up. */ + XSLEEP_MS(1000); + rem_file(buf); + expectFail = 0; + } + else { + /* fail on odd rounds */ + sprintf(buf, "%s/%s", tmpDir, "crl.revoked"); + copy_file("certs/crl/crl.revoked", buf); + sprintf(buf, "%s/%s", tmpDir, "crl.pem"); + /* The monitor can be holding the file handle and this will cause + * the remove call to fail. Let's give the monitor a second to + * finish up. */ + XSLEEP_MS(1000); + rem_file(buf); + expectFail = 1; + } + + client_args.return_code = 0; + client_test(&client_args); + + if (!expectFail) { + if (client_args.return_code != 0) + goto cleanup; + } + else { + if (client_args.return_code == 0) + goto cleanup; + } + } + + join_thread(serverThread); + ret = 0; +cleanup: + sprintf(buf, "%s/%s", tmpDir, "crl.pem"); + rem_file(buf); + sprintf(buf, "%s/%s", tmpDir, "crl.revoked"); + rem_file(buf); + (void)rem_dir(tmpDir); + return ret; +} +#endif + #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \ (!defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)) /* Perform a basic TLS handshake. @@ -562,6 +675,74 @@ void join_thread(THREAD_TYPE thread) #endif } +#include + +#define TMP_DIR_PREFIX "tmpDir-" +/* len is length of tmpDir name, assuming + * len does not include null terminating character */ +char* create_tmp_dir(char *tmpDir, int len) +{ + if (len < XSTR_SIZEOF(TMP_DIR_PREFIX)) + return NULL; + + XMEMCPY(tmpDir, TMP_DIR_PREFIX, XSTR_SIZEOF(TMP_DIR_PREFIX)); + + if (mymktemp(tmpDir, len, len - XSTR_SIZEOF(TMP_DIR_PREFIX)) == NULL) + return NULL; + + if (_mkdir(tmpDir) != 0) + return NULL; + + return tmpDir; +} + +int rem_dir(const char* dirName) +{ + if (_rmdir(dirName) != 0) + return -1; + return 0; +} + +int rem_file(const char* fileName) +{ + if (_unlink(fileName) != 0) + return -1; + return 0; +} + +int copy_file(const char* in, const char* out) +{ + byte buf[2500]; + XFILE inFile = XBADFILE; + XFILE outFile = XBADFILE; + size_t sz; + int ret = -1; + + inFile = XFOPEN(in, "rb"); + if (inFile == XBADFILE) + goto cleanup; + + outFile = XFOPEN(out, "wb"); + if (outFile == XBADFILE) + goto cleanup; + + sz = XFREAD(buf, 1, sizeof(buf), inFile); + /* 2500 bytes should be more than enough to read the entire files. + * Error out if we can't read the file all at once. */ + if (sz == sizeof(buf) || sz == 0) + goto cleanup; + + if (XFWRITE(buf, 1, sz, outFile) != sz) + goto cleanup; + + ret = 0; +cleanup: + if (inFile != XBADFILE) + XFCLOSE(inFile); + if (outFile != XBADFILE) + XFCLOSE(outFile); + return ret; +} #ifndef NO_SHA256 /* Create SHA-256 hash of the file based on filename. diff --git a/wolfssl/test.h b/wolfssl/test.h index 63dfb97c9..c15aa09ac 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -643,6 +643,17 @@ void test_wolfSSL_client_server_nofail_ex(callback_functions* client_cb, void test_wolfSSL_client_server_nofail(callback_functions* client_cb, callback_functions* server_cb); +/* Return + * tmpDir on success + * NULL on failure */ +char* create_tmp_dir(char* tmpDir, int len); +/* Remaining functions return + * 0 on success + * -1 on failure */ +int rem_dir(const char* dirName); +int rem_file(const char* fileName); +int copy_file(const char* in, const char* out); + /* wolfSSL */ #ifndef TEST_IPV6 static const char* const wolfSSLIP = "127.0.0.1";