From a805e21eed21b112488fd1b0e9ad6119f41ea8c2 Mon Sep 17 00:00:00 2001 From: Bill Williams Date: Thu, 19 Apr 2018 10:17:17 -0700 Subject: [PATCH 1/2] tests for jwt expiration --- src/conn_interface.c | 22 ++++++++ src/connection.c | 6 +- src/token.c | 32 ++++++++++- src/token.h | 13 +++++ tests/test_conn_interface.c | 110 ++++++++++++++++++++++++++++++++++-- 5 files changed, 173 insertions(+), 10 deletions(-) diff --git a/src/conn_interface.c b/src/conn_interface.c index 4910d6b0..2b78c77d 100644 --- a/src/conn_interface.c +++ b/src/conn_interface.c @@ -33,6 +33,7 @@ #include "spin_thread.h" #include "service_alive.h" #include "seshat_interface.h" +#include "token.h" #ifdef FEATURE_DNS_QUERY #include #endif @@ -122,6 +123,27 @@ void createSocketConnection(void (* initKeypress)()) } heartBeatTimer = 0; } +#ifdef FEATURE_DNS_QUERY + else if(jwt_has_expired()) + { + if(!close_retry) + { + ParodusError("JWT Expired. Terminating the connection with WebPA server and retrying\n"); + ParodusInfo("Reconnect detected, setting JWT Expired reason for Reconnect\n"); + set_global_reconnect_reason("JWT Expired"); + set_global_reconnect_status(true); + pthread_mutex_lock (&close_mut); + close_retry = true; + pthread_mutex_unlock (&close_mut); + } + else + { + ParodusPrint("JWT Expiration Handler - close_retry set to %d\n", close_retry); + } + heartBeatTimer = 0; + intTimer = 0; + } +#endif else if(intTimer >= 30) { ParodusPrint("heartBeatTimer %d\n",heartBeatTimer); diff --git a/src/connection.c b/src/connection.c index 71d0c511..4b7b36b8 100644 --- a/src/connection.c +++ b/src/connection.c @@ -35,6 +35,8 @@ #define HTTP_CUSTOM_HEADER_COUNT 5 #define INITIAL_CJWT_RETRY -2 +#define Parodus_Print printf + /*----------------------------------------------------------------------------*/ /* File Scoped Variables */ /*----------------------------------------------------------------------------*/ @@ -192,12 +194,12 @@ int createNopollConnection(noPollCtx *ctx) } if(allow_insecure <= 0) { - ParodusPrint("secure true\n"); + Parodus_Print("secure true\n"); connection = nopoll_tls_common_conn(ctx,server_Address, port, extra_headers,&fallback); } else { - ParodusPrint("secure false\n"); + Parodus_Print("secure false\n"); noPollConnOpts * opts; opts = createConnOpts(extra_headers, false); connection = nopoll_conn_new_opts (ctx, opts,server_Address,port,NULL,get_parodus_cfg()->webpa_path_url,NULL,NULL);// WEBPA-787 diff --git a/src/token.c b/src/token.c index 34771644..25789bca 100644 --- a/src/token.c +++ b/src/token.c @@ -73,12 +73,12 @@ /*----------------------------------------------------------------------------*/ /* File Scoped Variables */ /*----------------------------------------------------------------------------*/ -/* none */ +time_t jwt_expiration = (time_t) -1; /*----------------------------------------------------------------------------*/ /* Function Prototypes */ /*----------------------------------------------------------------------------*/ -/* none */ +void init_jwt_expiration (void); /*----------------------------------------------------------------------------*/ /* External Functions */ @@ -92,6 +92,7 @@ extern int __res_nquery(res_state statp, int class, int type, /* class and type of query */ u_char *answer, /* buffer to put answer */ int anslen); /* size of answer buffer */ +#endif /*----------------------------------------------------------------------------*/ /* Internal functions */ @@ -110,6 +111,8 @@ static void show_times (time_t exp_time, time_t cur_time) (int)exp_time, exp_buf+4, (int)cur_time, cur_buf+4); } +#ifdef FEATURE_DNS_QUERY + // returns 1 if insecure, 0 if secure, < 0 if error int analyze_jwt (const cjwt_t *jwt, char *url_buf, int url_buflen, char *port_buf, int port_buflen) @@ -119,6 +122,7 @@ int analyze_jwt (const cjwt_t *jwt, char *url_buf, int url_buflen, time_t exp_time, cur_time; int http_match; + init_jwt_expiration (); if (!claims) { ParodusError ("Private claims not found in jwt\n"); return TOKEN_ERR_INVALID_JWT_CONTENT; @@ -149,6 +153,7 @@ int analyze_jwt (const cjwt_t *jwt, char *url_buf, int url_buflen, ParodusError ("Invalid endpoint claim in JWT\n"); return TOKEN_ERR_BAD_ENDPOINT; } + jwt_expiration = exp_time; ParodusInfo ("JWT is_http strncmp: %d\n", http_match); return http_match; @@ -474,6 +479,25 @@ static void get_dns_txt_record_id (char *buf) } #endif +void init_jwt_expiration (void) +{ + jwt_expiration = (time_t) -1; +} + +int jwt_has_expired (void) +{ + int cur_time; + + if (jwt_expiration == (time_t) -1) + return (int) false; + cur_time = time(NULL); + if (jwt_expiration >= time(NULL)) + return (int) false; + ParodusError ("JWT Expired\n"); + show_times (jwt_expiration, cur_time); + return (int) true; +} + int allow_insecure_conn(char *url_buf, int url_buflen, char *port_buf, int port_buflen) { @@ -482,7 +506,8 @@ int allow_insecure_conn(char *url_buf, int url_buflen, char *jwt_token, *key; cjwt_t *jwt = NULL; char dns_txt_record_id[TXT_REC_ID_MAXSIZE]; - + + init_jwt_expiration (); jwt_token = malloc (NS_MAXBUF); if (NULL == jwt_token) { ParodusError ("Unable to allocate jwt_token in allow_insecure_conn\n"); @@ -542,6 +567,7 @@ int allow_insecure_conn(char *url_buf, int url_buflen, (void) port_buf; (void) port_buflen; int insecure = TOKEN_NO_DNS_QUERY; + init_jwt_expiration (); #endif ParodusPrint ("Allow Insecure %d\n", insecure); return insecure; diff --git a/src/token.h b/src/token.h index 5c5e0917..12ed4535 100644 --- a/src/token.h +++ b/src/token.h @@ -89,4 +89,17 @@ int allow_insecure_conn(char *url_buf, int url_buflen, char *port_buf, int port_buflen); +/** + * initialize variable used to track jwt expiration. + * +*/ +void init_jwt_expiration (void); + +/** + * check if jwt has expired + * +*/ +int jwt_has_expired (void); + + #endif diff --git a/tests/test_conn_interface.c b/tests/test_conn_interface.c index 8e051474..4bc6e5a6 100644 --- a/tests/test_conn_interface.c +++ b/tests/test_conn_interface.c @@ -36,6 +36,9 @@ ParodusMsg *ParodusMsgQ; extern bool close_retry; extern pthread_mutex_t close_mut; extern volatile unsigned int heartBeatTimer; +extern time_t jwt_expiration; +extern void init_jwt_expiration (void); + /*----------------------------------------------------------------------------*/ /* Mocks */ /*----------------------------------------------------------------------------*/ @@ -161,11 +164,12 @@ void initKeypress() /* Tests */ /*----------------------------------------------------------------------------*/ -void test_createSocketConnection() +void test_createSocketConn_ping1() // ping timeout with close_retry false { noPollCtx *ctx; ParodusCfg cfg; memset(&cfg,0,sizeof(ParodusCfg)); + init_jwt_expiration(); pthread_mutex_lock (&close_mut); close_retry = false; @@ -200,11 +204,13 @@ void test_createSocketConnection() createSocketConnection(initKeypress); } -void test_createSocketConnection1() +void test_createSocketConn_ping2() // ping timeout with close_retry true { noPollCtx *ctx; ParodusCfg cfg; memset(&cfg,0, sizeof(ParodusCfg)); + init_jwt_expiration(); + pthread_mutex_lock (&close_mut); close_retry = true; pthread_mutex_unlock (&close_mut); @@ -236,7 +242,95 @@ void test_createSocketConnection1() } -void test_createSocketConnection2() +#ifdef FEATURE_DNS_QUERY +void test_createSocketConn_jwtexp1() // jwt expiration with close_retry false +{ + noPollCtx *ctx; + ParodusCfg cfg; + memset(&cfg,0,sizeof(ParodusCfg)); + cfg.webpa_ping_timeout = 1; + set_parodus_cfg(&cfg); + + jwt_expiration = time(NULL) - 5; + + pthread_mutex_lock (&close_mut); + close_retry = false; + pthread_mutex_unlock (&close_mut); + expect_function_call(nopoll_thread_handlers); + + will_return(nopoll_ctx_new, (intptr_t)&ctx); + expect_function_call(nopoll_ctx_new); + expect_function_call(nopoll_log_set_handler); + will_return(createNopollConnection, nopoll_true); + expect_function_call(createNopollConnection); + expect_function_call(packMetaData); + + expect_function_calls(StartThread, 4); + expect_function_call(initKeypress); + will_return(nopoll_loop_wait, 1); + expect_function_call(nopoll_loop_wait); + + expect_function_call(set_global_reconnect_reason); + will_return(get_global_conn, (intptr_t)NULL); + expect_function_call(set_global_reconnect_status); + expect_function_call(get_global_conn); + expect_function_call(close_and_unref_connection); + expect_function_call(set_global_conn); + will_return(createNopollConnection, nopoll_true); + expect_function_call(createNopollConnection); + will_return(get_global_conn, (intptr_t)NULL); + expect_function_call(get_global_conn); + expect_function_call(close_and_unref_connection); + expect_function_call(nopoll_ctx_unref); + expect_function_call(nopoll_cleanup_library); + createSocketConnection(initKeypress); +} + +void test_createSocketConn_jwtexp2() // jwt expiration with close_retry true +{ + noPollCtx *ctx; + ParodusCfg cfg; + memset(&cfg,0, sizeof(ParodusCfg)); + cfg.webpa_ping_timeout = 1; + set_parodus_cfg(&cfg); + + jwt_expiration = time(NULL) - 5; + + pthread_mutex_lock (&close_mut); + close_retry = true; + pthread_mutex_unlock (&close_mut); + expect_function_call(nopoll_thread_handlers); + + will_return(nopoll_ctx_new, (intptr_t)&ctx); + expect_function_call(nopoll_ctx_new); + expect_function_call(nopoll_log_set_handler); + will_return(createNopollConnection, nopoll_true); + expect_function_call(createNopollConnection); + expect_function_call(packMetaData); + + expect_function_calls(StartThread, 4); + will_return(nopoll_loop_wait, 1); + expect_function_call(nopoll_loop_wait); + + will_return(get_global_conn, (intptr_t)NULL); + expect_function_call(get_global_conn); + expect_function_call(close_and_unref_connection); + expect_function_call(set_global_conn); + will_return(createNopollConnection, nopoll_true); + expect_function_call(createNopollConnection); + will_return(get_global_conn, (intptr_t)NULL); + expect_function_call(get_global_conn); + expect_function_call(close_and_unref_connection); + expect_function_call(nopoll_ctx_unref); + expect_function_call(nopoll_cleanup_library); + createSocketConnection(NULL); + +} + +#endif + + +void test_createSocketConnection1() { noPollCtx *ctx; ParodusCfg cfg; @@ -252,8 +346,10 @@ void test_createSocketConnection2() parStrncpy(cfg.webpa_interface_used , "eth0", sizeof(cfg.webpa_interface_used)); parStrncpy(cfg.webpa_protocol , "WebPA-1.6", sizeof(cfg.webpa_protocol)); parStrncpy(cfg.webpa_uuid , "1234567-345456546", sizeof(cfg.webpa_uuid)); + cfg.webpa_ping_timeout = 1; set_parodus_cfg(&cfg); + init_jwt_expiration (); pthread_mutex_lock (&close_mut); close_retry = false; @@ -333,9 +429,13 @@ void err_createSocketConnection() int main(void) { const struct CMUnitTest tests[] = { - cmocka_unit_test(test_createSocketConnection), + cmocka_unit_test(test_createSocketConn_ping1), + cmocka_unit_test(test_createSocketConn_ping2), +#ifdef FEATURE_DNS_QUERY + cmocka_unit_test(test_createSocketConn_jwtexp1), + cmocka_unit_test(test_createSocketConn_jwtexp2), +#endif cmocka_unit_test(test_createSocketConnection1), - cmocka_unit_test(test_createSocketConnection2), cmocka_unit_test(err_createSocketConnection), }; From 532500719c313466e8ffe565abaaad70e36a2950 Mon Sep 17 00:00:00 2001 From: Bill Williams Date: Fri, 20 Apr 2018 10:06:22 -0700 Subject: [PATCH 2/2] Revert Parodus_Print --- src/connection.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/connection.c b/src/connection.c index 4b7b36b8..5583eb78 100644 --- a/src/connection.c +++ b/src/connection.c @@ -35,7 +35,6 @@ #define HTTP_CUSTOM_HEADER_COUNT 5 #define INITIAL_CJWT_RETRY -2 -#define Parodus_Print printf /*----------------------------------------------------------------------------*/ /* File Scoped Variables */ @@ -194,12 +193,12 @@ int createNopollConnection(noPollCtx *ctx) } if(allow_insecure <= 0) { - Parodus_Print("secure true\n"); + ParodusPrint("secure true\n"); connection = nopoll_tls_common_conn(ctx,server_Address, port, extra_headers,&fallback); } else { - Parodus_Print("secure false\n"); + ParodusPrint("secure false\n"); noPollConnOpts * opts; opts = createConnOpts(extra_headers, false); connection = nopoll_conn_new_opts (ctx, opts,server_Address,port,NULL,get_parodus_cfg()->webpa_path_url,NULL,NULL);// WEBPA-787