From 56ab5f13fe2b02433e63a14dd100b385b3354e41 Mon Sep 17 00:00:00 2001 From: Sadhyama Vengilat Date: Sat, 9 Feb 2019 20:12:32 +0530 Subject: [PATCH 01/11] Add libcurl dependency in parodus --- CHANGELOG.md | 1 + CMakeLists.txt | 13 +++++++++++++ src/CMakeLists.txt | 1 + tests/CMakeLists.txt | 16 ++++++++-------- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d94e8cbe..f05d90c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fixed main loop to keep calling svc_alive_task during a cloud disconnect and retry - change svc alive back to a separate thread. Shut it down with pthread_cond_timedwait - Refactored Upsteam RETRIEVE flow +- Added common themis JWT support for parodus ## [1.0.1] - 2018-07-18 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c3e1605..7284f6d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ include_directories(${INCLUDE_DIR} ${INCLUDE_DIR}/cjson ${INCLUDE_DIR}/nopoll ${INCLUDE_DIR}/msgpack + ${INCLUDE_DIR}/curl ${INCLUDE_DIR}/trower-base64 ${INCLUDE_DIR}/wrp-c ${INCLUDE_DIR}/libparodus @@ -134,6 +135,18 @@ add_library(libmsgpack STATIC SHARED IMPORTED) add_dependencies(libmsgpack msgpack) +# curl external dependency +#------------------------------------------------------------------------------- +ExternalProject_Add(curl + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/_prefix/curl + GIT_REPOSITORY https://github.com/curl/curl.git + GIT_TAG "curl-7_63_0" + CMAKE_ARGS += -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} -DBUILD_TESTING=OFF +) +add_library(libcurl STATIC SHARED IMPORTED) +add_dependencies(libcurl curl) + + # cimplog external dependency #------------------------------------------------------------------------------- ExternalProject_Add(cimplog diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dd7a9f63..6d586462 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,6 +30,7 @@ target_link_libraries (parodus ${CMAKE_THREAD_LIBS_INIT} -lwrp-c -lmsgpackc + -lcurl -ltrower-base64 -lnopoll -luuid diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 699e38a8..6b145b9a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -123,7 +123,7 @@ set (CONN_SRC ../src/connection.c ../src/config.c ../src/spin_thread.c ../src/heartBeat.c ../src/close_retry.c) #set(CONN_SRC ../src/connection.c ${PARODUS_COMMON_SRC}) add_executable(test_connection test_connection.c ${CONN_SRC}) -target_link_libraries (test_connection ${PARODUS_COMMON_LIBS} -lcmocka) +target_link_libraries (test_connection ${PARODUS_COMMON_LIBS} -lcmocka -lcurl -luuid) #------------------------------------------------------------------------------- # test_connection - function createNopollConnection @@ -155,7 +155,7 @@ endif (ENABLE_SESHAT) add_executable(test_client_list ${CLIST_SRC}) #target_link_libraries (test_client_list ${PARODUS_CONN_LIBS} ${PARODUS_COMMON_LIBS}) -target_link_libraries (test_client_list ${PARODUS_COMMON_LIBS}) +target_link_libraries (test_client_list ${PARODUS_COMMON_LIBS} -lcurl -luuid) #------------------------------------------------------------------------------- # test_service_alive @@ -172,7 +172,7 @@ endif (ENABLE_SESHAT) add_executable(test_service_alive ${SVA_SRC}) #target_link_libraries (test_service_alive ${PARODUS_CONN_LIBS} ${PARODUS_COMMON_LIBS}) -target_link_libraries (test_service_alive ${PARODUS_COMMON_LIBS}) +target_link_libraries (test_service_alive ${PARODUS_COMMON_LIBS} -lcurl -luuid) #------------------------------------------------------------------------------- # test_config @@ -181,7 +181,7 @@ add_test(NAME test_config COMMAND ${MEMORY_CHECK} ./test_config) add_executable(test_config test_config.c ../src/config.c ../src/string_helpers.c) target_link_libraries (test_config -lcmocka -Wl,--no-as-needed -lcimplog - -lcjson -lcjwt -ltrower-base64 -lssl -lcrypto -lrt -lm + -lcjson -lcjwt -ltrower-base64 -lssl -lcrypto -lrt -lm -lcurl -luuid ) #------------------------------------------------------------------------------- @@ -203,7 +203,7 @@ target_link_libraries (test_crud_tasks -lcmocka ${PARODUS_COMMON_LIBS} ) #------------------------------------------------------------------------------- add_test(NAME test_crud_internal COMMAND ${MEMORY_CHECK} ./test_crud_internal) add_executable(test_crud_internal test_crud_internal.c ../src/config.c ../src/close_retry.c ../src/string_helpers.c ../src/crud_internal.c ) -target_link_libraries (test_crud_internal -lcmocka ${PARODUS_COMMON_LIBS} ) +target_link_libraries (test_crud_internal -lcmocka ${PARODUS_COMMON_LIBS} -lcurl -luuid) #------------------------------------------------------------------------------- # test_upstream @@ -259,14 +259,14 @@ else() set(CONIFC_SRC ${CONIFC_SRC} ../src/seshat_interface_stub.c) endif (ENABLE_SESHAT) add_executable(test_conn_interface ${CONIFC_SRC}) -target_link_libraries (test_conn_interface -lcmocka ${PARODUS_COMMON_LIBS} ) +target_link_libraries (test_conn_interface -lcmocka ${PARODUS_COMMON_LIBS} -lcurl -luuid ) #------------------------------------------------------------------------------- # test_ParodusInternal #------------------------------------------------------------------------------- add_test(NAME test_ParodusInternal COMMAND ${MEMORY_CHECK} ./test_ParodusInternal) add_executable(test_ParodusInternal test_ParodusInternal.c ../src/ParodusInternal.c ../src/config.c ../src/string_helpers.c) -target_link_libraries (test_ParodusInternal -lcmocka ${PARODUS_COMMON_LIBS} ) +target_link_libraries (test_ParodusInternal -lcmocka ${PARODUS_COMMON_LIBS} -lcurl -luuid) #------------------------------------------------------------------------------- # test_partners_check @@ -306,7 +306,7 @@ endif (FEATURE_DNS_QUERY) add_executable(test_token ${TOKEN_SRC} ) #target_link_libraries (test_token ${PARODUS_COMMON_LIBS} ${PARODUS_JWT_LIBS} -lcmocka ) -target_link_libraries (test_token ${PARODUS_COMMON_LIBS} -lcmocka ) +target_link_libraries (test_token ${PARODUS_COMMON_LIBS} -lcmocka -lcurl -luuid) #------------------------------------------------------------------------------- # test_seshat_interface - registerWithSeshat From 4bd9e871258a354774c3f9ba0d051a6685ebbdec Mon Sep 17 00:00:00 2001 From: Sadhyama Vengilat Date: Sat, 9 Feb 2019 20:19:06 +0530 Subject: [PATCH 02/11] Add new cmd line argument for client-cert-path and token-server-url --- src/config.c | 34 ++++++++++++++++++++++++++++++++++ src/config.h | 2 ++ 2 files changed, 36 insertions(+) diff --git a/src/config.c b/src/config.c index e633b7fd..a9b64bf0 100644 --- a/src/config.c +++ b/src/config.c @@ -389,6 +389,8 @@ int parseCommandLine(int argc,char **argv,ParodusCfg * cfg) {"token-read-script", required_argument, 0, 'T'}, {"boot-time-retry-wait", required_argument, 0, 'w'}, {"token-acquisition-script", required_argument, 0, 'J'}, + {"client-cert-path", required_argument, 0, 'P'}, + {"token-server-url", required_argument, 0, 'U'}, {"crud-config-file", required_argument, 0, 'C'}, {0, 0, 0, 0} }; @@ -405,6 +407,8 @@ int parseCommandLine(int argc,char **argv,ParodusCfg * cfg) cfg->jwt_algo = 0; parStrncpy (cfg->jwt_key, "", sizeof(cfg->jwt_key)); cfg->crud_config_file = NULL; + cfg->client_cert_path = NULL; + cfg->token_server_url = NULL; cfg->cloud_status = NULL; cfg->cloud_disconnect = NULL; optind = 1; /* We need this if parseCommandLine is called again */ @@ -564,6 +568,16 @@ int parseCommandLine(int argc,char **argv,ParodusCfg * cfg) ParodusInfo("crud_config_file is %s\n", cfg->crud_config_file); break; + case 'P': + cfg->client_cert_path = strdup(optarg); + ParodusInfo("client_cert_path is %s\n", cfg->client_cert_path); + break; + + case 'U': + cfg->token_server_url = strdup(optarg); + ParodusInfo("token_server_url is %s\n", cfg->token_server_url); + break; + case '?': /* getopt_long already printed an error message. */ break; @@ -694,6 +708,8 @@ void setDefaultValuesToCfg(ParodusCfg *cfg) parStrncpy(cfg->webpa_uuid, "1234567-345456546",sizeof(cfg->webpa_uuid)); ParodusPrint("cfg->webpa_uuid is :%s\n", cfg->webpa_uuid); cfg->crud_config_file = NULL; + cfg->client_cert_path = NULL; + cfg->token_server_url = NULL; cfg->cloud_status = CLOUD_STATUS_OFFLINE; ParodusInfo("Default cloud_status is %s\n", cfg->cloud_status); @@ -869,6 +885,24 @@ void loadParodusCfg(ParodusCfg * config,ParodusCfg *cfg) { ParodusPrint("crud_config_file is NULL. set to empty\n"); } + + if(config->client_cert_path != NULL) + { + cfg->client_cert_path = strdup(config->client_cert_path); + } + else + { + ParodusPrint("client_cert_path is NULL. set to empty\n"); + } + + if(config->token_server_url != NULL) + { + cfg->token_server_url = strdup(config->token_server_url); + } + else + { + ParodusPrint("token_server_url is NULL. set to empty\n"); + } } diff --git a/src/config.h b/src/config.h index 28ae3e0e..ce2a4dda 100644 --- a/src/config.h +++ b/src/config.h @@ -99,6 +99,8 @@ typedef struct char webpa_auth_token[4096]; char token_acquisition_script[64]; char token_read_script[64]; + char *client_cert_path; + char *token_server_url; char *crud_config_file; char *cloud_status; char *cloud_disconnect; From 29f00e58506064ee633e7892e1a16c992fd64a79 Mon Sep 17 00:00:00 2001 From: Sadhyama Vengilat Date: Sat, 9 Feb 2019 20:25:56 +0530 Subject: [PATCH 03/11] Remove themis create read scripts command line arguments --- src/config.c | 53 --------------------------------------------- tests/test_config.c | 23 +------------------- 2 files changed, 1 insertion(+), 75 deletions(-) diff --git a/src/config.c b/src/config.c index a9b64bf0..86bfb83c 100644 --- a/src/config.c +++ b/src/config.c @@ -141,31 +141,6 @@ void read_key_from_file (const char *fname, char *buf, size_t buflen) ParodusInfo ("%d bytes read\n", nbytes); } -void execute_token_script(char *token, char *name, size_t len, char *mac, char *serNum) -{ - FILE* out = NULL, *file = NULL; - char command[MAX_BUF_SIZE] = {'\0'}; - if(strlen(name)>0) - { - file = fopen(name, "r"); - if(file) - { - snprintf(command,sizeof(command),"%s %s %s",name,serNum,mac); - out = popen(command, "r"); - if(out) - { - fgets(token, len, out); - pclose(out); - } - fclose(file); - } - else - { - ParodusError ("File %s open error\n", name); - } - } -} - // strips ':' characters // verifies that there exactly 12 characters int parse_mac_address (char *target, const char *arg) @@ -386,9 +361,7 @@ int parseCommandLine(int argc,char **argv,ParodusCfg * cfg) {"ssl-cert-path", required_argument, 0, 'c'}, {"force-ipv4", no_argument, 0, '4'}, {"force-ipv6", no_argument, 0, '6'}, - {"token-read-script", required_argument, 0, 'T'}, {"boot-time-retry-wait", required_argument, 0, 'w'}, - {"token-acquisition-script", required_argument, 0, 'J'}, {"client-cert-path", required_argument, 0, 'P'}, {"token-server-url", required_argument, 0, 'U'}, {"crud-config-file", required_argument, 0, 'C'}, @@ -550,14 +523,6 @@ int parseCommandLine(int argc,char **argv,ParodusCfg * cfg) cfg->flags |= FLAGS_IPV6_ONLY; break; - case 'J': - parStrncpy(cfg->token_acquisition_script, optarg,sizeof(cfg->token_acquisition_script)); - break; - - case 'T': - parStrncpy(cfg->token_read_script, optarg,sizeof(cfg->token_read_script)); - break; - case 'w': cfg->boot_retry_wait = parse_num_arg (optarg, "boot-time-retry-wait"); ParodusInfo("boot_retry_wait is %d\n",cfg->boot_retry_wait); @@ -850,24 +815,6 @@ void loadParodusCfg(ParodusCfg * config,ParodusCfg *cfg) ParodusPrint("cert_path is NULL. set to empty\n"); } - if(strlen(config->token_acquisition_script )!=0) - { - parStrncpy(cfg->token_acquisition_script, config->token_acquisition_script,sizeof(cfg->token_acquisition_script)); - } - else - { - ParodusPrint("token_acquisition_script is NULL. read from tmp file\n"); - } - - if(strlen(config->token_read_script )!=0) - { - parStrncpy(cfg->token_read_script, config->token_read_script,sizeof(cfg->token_read_script)); - } - else - { - ParodusPrint("token_read_script is NULL. read from tmp file\n"); - } - cfg->boot_time = config->boot_time; cfg->webpa_ping_timeout = config->webpa_ping_timeout; cfg->webpa_backoff_max = config->webpa_backoff_max; diff --git a/tests/test_config.c b/tests/test_config.c index 65e11360..0a7e0b00 100644 --- a/tests/test_config.c +++ b/tests/test_config.c @@ -37,7 +37,6 @@ extern int parse_webpa_url (const char *full_url, char **server_addr, unsigned int *port); extern unsigned int get_algo_mask (const char *algo_str); extern unsigned int parse_num_arg (const char *arg, const char *arg_name); -extern void execute_token_script(char *token, char *name, size_t len, char *mac, char *serNum); extern void createNewAuthToken(char *newToken, size_t len); /*----------------------------------------------------------------------------*/ @@ -184,8 +183,6 @@ void test_parseCommandLine() #endif "--force-ipv4", "--force-ipv6", - "--token-read-script=/tmp/token.sh", - "--token-acquisition-script=/tmp/token.sh", "--ssl-cert-path=/etc/ssl/certs/ca-certificates.crt", #ifdef FEATURE_DNS_QUERY "--acquire-jwt=1", @@ -317,8 +314,6 @@ void test_loadParodusCfg() Cfg->jwt_algo = 1025; parStrncpy(Cfg->jwt_key, "AGdyuwyhwl2ow2ydsoioiygkshwdthuwd",sizeof(Cfg->jwt_key)); #endif - parStrncpy(Cfg->token_acquisition_script , "/tmp/token.sh", sizeof(Cfg->token_acquisition_script)); - parStrncpy(Cfg->token_read_script , "/tmp/token.sh", sizeof(Cfg->token_read_script)); parStrncpy(Cfg->cert_path, "/etc/ssl.crt",sizeof(Cfg->cert_path)); #ifdef ENABLE_SESHAT parStrncpy(Cfg->seshat_url, "ipc://tmp/seshat_service.url", sizeof(Cfg->seshat_url)); @@ -340,8 +335,6 @@ void test_loadParodusCfg() assert_int_equal( (int) tmpcfg.jwt_algo, 1025); assert_string_equal(tmpcfg.jwt_key, "AGdyuwyhwl2ow2ydsoioiygkshwdthuwd"); #endif - assert_string_equal( tmpcfg.token_acquisition_script,"/tmp/token.sh"); - assert_string_equal( tmpcfg.token_read_script,"/tmp/token.sh"); assert_string_equal(tmpcfg.cert_path, "/etc/ssl.crt"); #ifdef ENABLE_SESHAT assert_string_equal(tmpcfg.seshat_url, "ipc://tmp/seshat_service.url"); @@ -553,20 +546,7 @@ void test_get_algo_mask () #endif } -void test_execute_token_script() -{ - char *cmd1 = "../../tests/return_ser_mac.bsh"; - char *cmd2 = "nosuch"; - char token[32]; - - memset (token, '\0', sizeof(token)); - execute_token_script (token, cmd1, sizeof(token), "mac123", "ser456"); - assert_string_equal (token, "SER_MAC ser456 mac123"); - - memset (token, '\0', sizeof(token)); - execute_token_script (token, cmd2, sizeof(token), "mac123", "ser456"); - assert_string_equal (token, ""); -} + void test_new_auth_token () { @@ -618,7 +598,6 @@ int main(void) //cmocka_unit_test(test_parodusGitVersion), cmocka_unit_test(test_setDefaultValuesToCfg), cmocka_unit_test(err_setDefaultValuesToCfg), - cmocka_unit_test(test_execute_token_script), cmocka_unit_test(test_new_auth_token) }; From 5a60847e28ab62fb3faeff5075d0134fc2770b4c Mon Sep 17 00:00:00 2001 From: Sadhyama Vengilat Date: Sat, 9 Feb 2019 20:28:27 +0530 Subject: [PATCH 04/11] Themis JWT token fetch using libcurl --- src/config.c | 294 +++++++++++++++++++++++++++++++++++++------ src/config.h | 9 +- src/conn_interface.c | 2 + src/connection.c | 5 +- src/main.c | 2 + 5 files changed, 273 insertions(+), 39 deletions(-) diff --git a/src/config.c b/src/config.c index 86bfb83c..63d784c5 100644 --- a/src/config.c +++ b/src/config.c @@ -26,9 +26,13 @@ #include "config.h" #include "ParodusInternal.h" #include +#include +#include +#include -#define MAX_BUF_SIZE 128 - +#define MAX_BUF_SIZE 128 +#define CURL_TIMEOUT_SEC 25L +#define MAX_CURL_RETRY_COUNT 3 /*----------------------------------------------------------------------------*/ /* File Scoped Variables */ /*----------------------------------------------------------------------------*/ @@ -36,7 +40,7 @@ static ParodusCfg parodusCfg; static unsigned int rsa_algorithms = (1<token_acquisition_script,sizeof(output),get_parodus_cfg()->hw_mac,get_parodus_cfg()->hw_serial_number); - if (strlen(output)>0 && strcmp(output,"SUCCESS")==0) + CURL *curl; + CURLcode res; + CURLcode time_res; + struct curl_slist *list = NULL; + struct curl_slist *headers_list = NULL; + + char *mac_header = NULL; + char *serial_header = NULL; + char *uuid_header = NULL; + char *transaction_uuid = NULL; + double total; + long response_code; + + struct token_data data; + data.size = 0; + + curl = curl_easy_init(); + if(curl) { - //Call read script - execute_token_script(newToken,get_parodus_cfg()->token_read_script,len,get_parodus_cfg()->hw_mac,get_parodus_cfg()->hw_serial_number); - } - else + //this memory will be dynamically grown by write call back fn as required + data.data = (char *) malloc(sizeof(char) * 1); + if(NULL == data.data) + { + ParodusError("Failed to allocate memory.\n"); + return -1; + } + data.data[0] = '\0'; + + createCurlheader(mac_header, serial_header, uuid_header, transaction_uuid, list, &headers_list); + + curl_easy_setopt(curl, CURLOPT_URL, get_parodus_cfg()->token_server_url); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, CURL_TIMEOUT_SEC); + + if(get_parodus_cfg()->webpa_interface_used !=NULL && strlen(get_parodus_cfg()->webpa_interface_used) >0) + { + curl_easy_setopt(curl, CURLOPT_INTERFACE, get_parodus_cfg()->webpa_interface_used); + } + /* set callback for writing received data */ + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_fn); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers_list); + + /* setting curl resolve option as default mode. + If any failure, retry with v4 first and then v6 mode. */ + + if(r_count == 1) + { + ParodusInfo("curl Ip resolve option set as V4 mode\n"); + curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + } + else if(r_count == 2) + { + ParodusInfo("curl Ip resolve option set as V6 mode\n"); + curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); + } + else + { + ParodusInfo("curl Ip resolve option set as default mode\n"); + curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER); + } + + /* set the cert for client authentication */ + curl_easy_setopt(curl, CURLOPT_SSLCERT, get_parodus_cfg()->client_cert_path); + + curl_easy_setopt(curl, CURLOPT_CAINFO, get_parodus_cfg()->cert_path); + + /* disconnect if it is failed to validate server's cert */ + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + ParodusInfo("themis curl response %d http_code %d\n", res, response_code); + + time_res = curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total); + if(time_res == 0) + { + ParodusInfo("curl response Time: %.1f seconds\n", total); + } + curl_slist_free_all(headers_list); + if(res != 0) + { + ParodusError("curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + curl_easy_cleanup(curl); + if(data.data) + { + free(data.data); + data.data = NULL; + } + return -1; + } + else + { + if(response_code == 200) + { + ParodusInfo("cURL success\n"); + strncpy(newToken, data.data, len); + } + } + if(data.data) + { + free(data.data); + data.data = NULL; + } + curl_easy_cleanup(curl); + } + else { - ParodusError("Failed to create new token\n"); + ParodusError("curl init failure\n"); + return -1; } + + return 0; } /* -* Fetches authorization token from the output of read script. If read script returns "ERROR" -* it will call createNewAuthToken to create and read new token +* @brief Fetches authorization token and update to parodus config. + This will do curl retry in case of any failure till it reaches max curl retry count. + * @param[in] cfg Global parodus config structure to update webpa_auth_token */ void getAuthToken(ParodusCfg *cfg) { - //local var to update cfg->webpa_auth_token only in success case - char output[4069] = {'\0'} ; - - if( strlen(cfg->token_read_script) !=0 && strlen(cfg->token_acquisition_script) !=0) - { - execute_token_script(output,cfg->token_read_script,sizeof(output),cfg->hw_mac,cfg->hw_serial_number); - - if ((strlen(output) == 0)) - { - ParodusError("Unable to get auth token\n"); - } - else if(strcmp(output,"ERROR")==0) + int status = -1; + int retry_count = 0; + + if( cfg->hw_mac != NULL && strlen(cfg->hw_mac) !=0 ) + { + if( cfg->client_cert_path !=NULL && strlen(cfg->client_cert_path) !=0 ) { - ParodusInfo("Failed to read token from %s. Proceeding to create new token.\n",cfg->token_read_script); - //Call create/acquisition script - createNewAuthToken(cfg->webpa_auth_token, sizeof(cfg->webpa_auth_token)); + while(1) + { + //Fetch new auth token using libcurl + status = requestNewAuthToken(cfg->webpa_auth_token, sizeof(cfg->webpa_auth_token), retry_count); + if(status == 0) + { + ParodusInfo("cfg->webpa_auth_token created successfully\n"); + break; + } + else + { + ParodusError("Failed to create new token\n"); + retry_count++; + ParodusError("Curl execution is failed, retry attempt: %d\n", retry_count); + } + + if(retry_count == MAX_CURL_RETRY_COUNT) + { + ParodusError("Curl retry is reached to max %d attempts, proceeding without token\n", retry_count); + break; + } + } } else { - ParodusInfo("update cfg->webpa_auth_token in success case\n"); - parStrncpy(cfg->webpa_auth_token, output, sizeof(cfg->webpa_auth_token)); + ParodusInfo("client_cert_path is NULL\n"); + } + } + else + { + ParodusError("hw_mac is NULL, failed to fetch auth token\n"); + } +} + +/* @brief callback function for writing libcurl received data + * @param[in] buffer curl delivered data which need to be saved. + * @param[in] size size is always 1 + * @param[in] nmemb size of delivered data + * @param[out] data curl response data saved. +*/ +size_t write_callback_fn(void *buffer, size_t size, size_t nmemb, struct token_data *data) +{ + size_t index = data->size; + size_t n = (size * nmemb); + char* tmp; + + data->size += (size * nmemb); + + tmp = realloc(data->data, data->size + 1); /* +1 for '\0' */ + + if(tmp) { + data->data = tmp; + } else { + if(data->data) { + free(data->data); + } + ParodusError("Failed to allocate memory for data\n"); + return 0; + } + + memcpy((data->data + index), buffer, n); + data->data[data->size] = '\0'; + + return size * nmemb; +} + +/* @brief function to generate random uuid. +*/ +char* generate_trans_uuid() +{ + char *transID = NULL; + uuid_t transaction_Id; + char *trans_id = NULL; + trans_id = (char *)malloc(37); + uuid_generate_random(transaction_Id); + uuid_unparse(transaction_Id, trans_id); + + if(trans_id !=NULL) + { + transID = trans_id; + } + return transID; +} + +/* @brief function to create curl header contains mac, serial number and uuid. + * @param[in] mac_header mac address header key value pair + * @param[in] serial_header serial number key value pair + * @param[in] uuid_header transaction uuid key value pair + * @param[in] list temp curl header list + * @param[out] header_list output curl header list +*/ +void createCurlheader(char *mac_header, char *serial_header, char *uuid_header, char *transaction_uuid, struct curl_slist *list, struct curl_slist **header_list) +{ + mac_header = (char *) malloc(sizeof(char)*MAX_BUF_SIZE); + if(mac_header !=NULL) + { + snprintf(mac_header, MAX_BUF_SIZE, "X-Midt-Mac-Address: %s", get_parodus_cfg()->hw_mac); + ParodusPrint("mac_header formed %s\n", mac_header); + list = curl_slist_append(list, mac_header); + free(mac_header); + mac_header = NULL; + } + + serial_header = (char *) malloc(sizeof(char)*MAX_BUF_SIZE); + if(serial_header !=NULL) + { + snprintf(serial_header, MAX_BUF_SIZE, "X-Midt-Serial-Number: %s", get_parodus_cfg()->hw_serial_number); + ParodusPrint("serial_header formed %s\n", serial_header); + list = curl_slist_append(list, serial_header); + free(serial_header); + serial_header = NULL; + } + + transaction_uuid = generate_trans_uuid(); + if(transaction_uuid !=NULL) + { + uuid_header = (char *) malloc(sizeof(char)*MAX_BUF_SIZE); + if(uuid_header !=NULL) + { + snprintf(uuid_header, MAX_BUF_SIZE, "X-Midt-Uuid: %s", transaction_uuid); + ParodusInfo("uuid_header formed %s\n", uuid_header); + list = curl_slist_append(list, uuid_header); + free(transaction_uuid); + transaction_uuid = NULL; + free(uuid_header); + uuid_header = NULL; } } else { - ParodusInfo("Both read and write file are NULL \n"); + ParodusError("Failed to generate transaction_uuid\n"); } + *header_list = list; } void setDefaultValuesToCfg(ParodusCfg *cfg) diff --git a/src/config.h b/src/config.h index ce2a4dda..142e7049 100644 --- a/src/config.h +++ b/src/config.h @@ -107,6 +107,11 @@ typedef struct unsigned int boot_retry_wait; } ParodusCfg; +struct token_data { + size_t size; + char* data; +}; + #define FLAGS_IPV6_ONLY (1 << 0) #define FLAGS_IPV4_ONLY (1 << 1) #define FLAGS_IPV6_IPV4 (FLAGS_IPV6_ONLY | FLAGS_IPV4_ONLY) @@ -116,7 +121,7 @@ typedef struct /*----------------------------------------------------------------------------*/ void loadParodusCfg(ParodusCfg * config,ParodusCfg *cfg); -void createNewAuthToken(char *newToken, size_t len); +int requestNewAuthToken(char *newToken, size_t len, int r_count); /** * parse command line arguments and create config structure @@ -151,6 +156,8 @@ void reset_cloud_disconnect_reason(ParodusCfg *cfg); */ int parse_webpa_url (const char *full_url, char **server_addr, unsigned int *port); +size_t write_callback_fn(void *buffer, size_t size, size_t nmemb, struct token_data *data); +char* generate_trans_uuid(); #ifdef __cplusplus } diff --git a/src/conn_interface.c b/src/conn_interface.c index d7d0e100..da0bab2b 100644 --- a/src/conn_interface.c +++ b/src/conn_interface.c @@ -36,6 +36,7 @@ #include "crud_interface.h" #include "heartBeat.h" #include "close_retry.h" +#include #ifdef FEATURE_DNS_QUERY #include #endif @@ -205,6 +206,7 @@ void createSocketConnection(void (* initKeypress)()) close_and_unref_connection(get_global_conn()); nopoll_ctx_unref(ctx); nopoll_cleanup_library(); + curl_global_cleanup(); } void shutdownSocketConnection(void) { diff --git a/src/connection.c b/src/connection.c index 2764cb7a..74ee761b 100644 --- a/src/connection.c +++ b/src/connection.c @@ -297,10 +297,9 @@ void set_current_server (create_connection_ctx_t *ctx) void set_extra_headers (create_connection_ctx_t *ctx, int reauthorize) { - if (reauthorize && (strlen(get_parodus_cfg()->token_acquisition_script) >0)) + if (reauthorize && (get_parodus_cfg()->client_cert_path !=NULL &&strlen(get_parodus_cfg()->client_cert_path) >0)) { - createNewAuthToken(get_parodus_cfg()->webpa_auth_token, - sizeof(get_parodus_cfg()->webpa_auth_token)); + getAuthToken(get_parodus_cfg()); } ctx->extra_headers = build_extra_hdrs (&ctx->header_info); diff --git a/src/main.c b/src/main.c index 35e77481..9d2e2912 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,7 @@ #include "config.h" #include "conn_interface.h" #include "parodus_log.h" +#include #ifdef INCLUDE_BREAKPAD #include "breakpad_wrapper.h" #else @@ -80,6 +81,7 @@ int main( int argc, char **argv) if (0 != parseCommandLine(argc,argv,cfg)) { abort(); } + curl_global_init(CURL_GLOBAL_DEFAULT); getAuthToken(cfg); createSocketConnection( NULL); From 25a6a99c69922162f6f47ec94cc28c6a36fb7cbe Mon Sep 17 00:00:00 2001 From: Sadhyama Vengilat Date: Sat, 9 Feb 2019 20:33:18 +0530 Subject: [PATCH 05/11] Added unit tests for themis curl changes --- README.md | 10 +- tests/test_config.c | 283 ++++++++++++++++++++++++++++++++++++---- tests/test_connection.c | 11 +- 3 files changed, 270 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index ea6e5fd2..72adb3bc 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,9 @@ make test - /force-ipv6 -Forcefully connect parodus to ipv6 address (optional argument) -- /token-read-script -Script to get auth token for establishing secure connection (absolute path where that script is present) -optional argument +- /client-cert-path -client cert location to request auth token for establishing secure connection (absolute path where client cert is present) -optional argument -- /token-acquisition-script -Script to create new auth token for establishing secure connection (absolute path where that script is present) -optional argument +- /token-server-url -server url to request new auth token for establishing secure connection -optional argument - /crud-config-file -Config json file to store objects during create, retrieve, update and delete (CRUD) operations -optional argument @@ -82,17 +82,17 @@ make test ``` # Seshat & FEATURE_DNS_QUERY Enabled -./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --acquire-jwt=1 --dns-txt-url=somebody.net --jwt-public-key-file=webpa-rs256.pem --jwt-algo=RS256 --seshat-url=tcp://127.0.0.1:7777 --token-read-script=/usr/ccsp/parodus/parodus_token1.sh --token-acquisition-script=/usr/ccsp/parodus/parodus_token2.sh --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json +./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --acquire-jwt=1 --dns-txt-url=somebody.net --jwt-public-key-file=webpa-rs256.pem --jwt-algo=RS256 --seshat-url=tcp://127.0.0.1:7777 --client-cert-path=/tmp/clientcert.mch --token-server-url=somebody.net:8080 --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json # Seshat is not enabled -./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --acquire-jwt=1 --dns-txt-url=somebody.net --jwt-public-key-file=webpa-rs256.pem --jwt-algo=RS256 --token-read-script=/usr/ccsp/parodus/parodus_token1.sh --token-acquisition-script=/usr/ccsp/parodus/parodus_token2.sh --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json +./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --acquire-jwt=1 --dns-txt-url=somebody.net --jwt-public-key-file=webpa-rs256.pem --jwt-algo=RS256 --client-cert-path=/tmp/clientcert.mch --token-server-url=somebody.net:8080 --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json # When both Seshat & FEATURE_DNS_QUERY not Enabled -./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --token-read-script=/usr/ccsp/parodus/parodus_token1.sh --token-acquisition-script=/usr/ccsp/parodus/parodus_token2.sh --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json +./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --client-cert-path=/tmp/clientcert.mch --token-server-url=somebody.net:8080 --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json ``` diff --git a/tests/test_config.c b/tests/test_config.c index 0a7e0b00..c86eb3f9 100644 --- a/tests/test_config.c +++ b/tests/test_config.c @@ -37,7 +37,7 @@ extern int parse_webpa_url (const char *full_url, char **server_addr, unsigned int *port); extern unsigned int get_algo_mask (const char *algo_str); extern unsigned int parse_num_arg (const char *arg, const char *arg_name); -extern void createNewAuthToken(char *newToken, size_t len); +extern int requestNewAuthToken(char *newToken, size_t len, int r_count); /*----------------------------------------------------------------------------*/ /* Mocks */ @@ -52,6 +52,29 @@ void create_token_script(char *fname) sprintf(command, "chmod +x %s",fname); system(command); } + +typedef void CURL; + +typedef enum { + CURLINFO_RESPONSE_CODE = 2, + CURLINFO_TOTAL_TIME +} CURLINFO; + +int curl_easy_perform(CURL *curl) +{ + UNUSED(curl); + function_called(); + return (int) mock(); +} + +int curl_easy_getinfo(CURL *curl, CURLINFO CURLINFO_RESPONSE_CODE, long response_code) +{ + UNUSED(curl); + UNUSED(CURLINFO_RESPONSE_CODE); + UNUSED(response_code); + function_called(); + return (int) mock(); +} /*----------------------------------------------------------------------------*/ /* Tests */ /*----------------------------------------------------------------------------*/ @@ -183,7 +206,10 @@ void test_parseCommandLine() #endif "--force-ipv4", "--force-ipv6", + "--boot-time-retry-wait=10", "--ssl-cert-path=/etc/ssl/certs/ca-certificates.crt", + "--client-cert-path=testcert", + "--token-server-url=https://dev.comcast.net/token", #ifdef FEATURE_DNS_QUERY "--acquire-jwt=1", "--dns-txt-url=mydns.mycom.net", @@ -211,6 +237,7 @@ void test_parseCommandLine() assert_string_equal( parodusCfg.hw_last_reboot_reason, "unknown"); assert_string_equal( parodusCfg.fw_name, "TG1682_DEV_master_2016000000sdy"); assert_int_equal( (int) parodusCfg.webpa_ping_timeout,180); + assert_int_equal( (int) parodusCfg.boot_retry_wait,10); assert_string_equal( parodusCfg.webpa_interface_used, "br0"); assert_string_equal( parodusCfg.webpa_url, "http://127.0.0.1"); assert_int_equal( (int) parodusCfg.webpa_backoff_max,0); @@ -221,18 +248,28 @@ void test_parseCommandLine() assert_string_equal( parodusCfg.seshat_url, "ipc://127.0.0.1:7777"); #endif assert_int_equal( (int) parodusCfg.flags, FLAGS_IPV6_ONLY|FLAGS_IPV4_ONLY); - sprintf(expectedToken,"secure-token-%s-%s",parodusCfg.hw_serial_number,parodusCfg.hw_mac); - getAuthToken(&parodusCfg); - set_parodus_cfg(&parodusCfg); + set_parodus_cfg(&parodusCfg); + will_return (curl_easy_perform, 0); + expect_function_calls (curl_easy_perform, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, -1); + expect_function_calls (curl_easy_getinfo, 1); + getAuthToken(&parodusCfg); assert_string_equal( get_parodus_cfg()->webpa_auth_token,expectedToken); assert_string_equal( parodusCfg.cert_path,"/etc/ssl/certs/ca-certificates.crt"); + assert_string_equal( parodusCfg.client_cert_path,"testcert"); + assert_string_equal( parodusCfg.token_server_url,"https://dev.comcast.net/token"); #ifdef FEATURE_DNS_QUERY assert_int_equal( (int) parodusCfg.acquire_jwt, 1); assert_string_equal(parodusCfg.dns_txt_url, "mydns.mycom.net"); assert_int_equal( (int) parodusCfg.jwt_algo, 1024); assert_string_equal ( get_parodus_cfg()->jwt_key, jwt_key); #endif + assert_int_equal( (int) parodusCfg.boot_retry_wait, 10); assert_string_equal(parodusCfg.crud_config_file, "parodus_cfg.json"); } @@ -319,6 +356,8 @@ void test_loadParodusCfg() parStrncpy(Cfg->seshat_url, "ipc://tmp/seshat_service.url", sizeof(Cfg->seshat_url)); #endif Cfg->crud_config_file = strdup("parodus_cfg.json"); + Cfg->client_cert_path = strdup("testcert"); + Cfg->token_server_url = strdup("https://dev.comcast.net/token"); memset(&tmpcfg,0,sizeof(ParodusCfg)); loadParodusCfg(Cfg,&tmpcfg); @@ -329,6 +368,8 @@ void test_loadParodusCfg() assert_string_equal( tmpcfg.local_url, "tcp://10.0.0.1:6000"); assert_string_equal( tmpcfg.partner_id, "shaw"); assert_string_equal( tmpcfg.webpa_protocol, protocol); + assert_string_equal(tmpcfg.client_cert_path, "testcert"); + assert_string_equal(tmpcfg.token_server_url, "https://dev.comcast.net/token"); #ifdef FEATURE_DNS_QUERY assert_int_equal( (int) tmpcfg.acquire_jwt, 1); assert_string_equal(tmpcfg.dns_txt_url, "mydns"); @@ -546,32 +587,223 @@ void test_get_algo_mask () #endif } +void getAuthToken_Null() +{ + ParodusCfg cfg; + memset(&cfg,0,sizeof(cfg)); + parStrncpy(cfg.hw_mac , "123567892366", sizeof(cfg.hw_mac)); + cfg.client_cert_path = NULL; + getAuthToken(&cfg); + set_parodus_cfg(&cfg); + assert( cfg.client_cert_path == NULL); +} + +void getAuthToken_MacNull() +{ + ParodusCfg cfg; + memset(&cfg,0,sizeof(cfg)); + cfg.client_cert_path = NULL; + getAuthToken(&cfg); + set_parodus_cfg(&cfg); + assert( cfg.client_cert_path == NULL); +} + +void test_requestNewAuthToken_init_fail () +{ + char token[32]; + ParodusCfg cfg; + int output = -1; + memset(&cfg,0,sizeof(cfg)); + + cfg.token_server_url = strdup("https://dev.comcast.net/token"); + parStrncpy(cfg.cert_path , "/etc/ssl/certs/ca-certificates.crt", sizeof(cfg.cert_path)); + parStrncpy(cfg.hw_serial_number, "Fer23u948590", sizeof(cfg.hw_serial_number)); + parStrncpy(cfg.hw_mac , "123567892366", sizeof(cfg.hw_mac)); + + set_parodus_cfg(&cfg); + + will_return (curl_easy_perform, -1); + expect_function_calls (curl_easy_perform, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, -1); + expect_function_calls (curl_easy_getinfo, 1); + + requestNewAuthToken (token, sizeof(token), 2); + assert_int_equal (output, -1); + free(cfg.token_server_url); +} + + +void test_requestNewAuthToken_failure () +{ + char token[32]; + ParodusCfg cfg; + int output = -1; + memset(&cfg,0,sizeof(cfg)); + + cfg.token_server_url = strdup("https://dev.comcast.net/token"); + parStrncpy(cfg.cert_path , "/etc/ssl/certs/ca-certificates.crt", sizeof(cfg.cert_path)); + parStrncpy(cfg.hw_serial_number, "Fer23u948590", sizeof(cfg.hw_serial_number)); + parStrncpy(cfg.hw_mac , "123567892366", sizeof(cfg.hw_mac)); + set_parodus_cfg(&cfg); + + will_return (curl_easy_perform, -1); + expect_function_calls (curl_easy_perform, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, -1); + expect_function_calls (curl_easy_getinfo, 1); + + requestNewAuthToken (token, sizeof(token), 2); + assert_int_equal (output, -1); + free(cfg.token_server_url); +} -void test_new_auth_token () +void test_requestNewAuthToken () { - char token[64]; + char token[1024]; ParodusCfg cfg; + int output = -1; memset(&cfg,0,sizeof(cfg)); - parStrncpy (cfg.token_acquisition_script, "../../tests/return_success.bsh", - sizeof(cfg.token_acquisition_script)); - parStrncpy (cfg.token_read_script, "../../tests/return_ser_mac.bsh", - sizeof(cfg.token_read_script)); + cfg.token_server_url = strdup("https://dev.comcast.net/token"); + parStrncpy(cfg.cert_path , "/etc/ssl/certs/ca-certificates.crt", sizeof(cfg.cert_path)); + parStrncpy(cfg.webpa_interface_used , "eth0", sizeof(cfg.webpa_interface_used)); parStrncpy(cfg.hw_serial_number, "Fer23u948590", sizeof(cfg.hw_serial_number)); parStrncpy(cfg.hw_mac , "123567892366", sizeof(cfg.hw_mac)); - - set_parodus_cfg(&cfg); - createNewAuthToken (token, sizeof(token)); - assert_string_equal (token, "SER_MAC Fer23u948590 123567892366"); - - memset (token, 0, sizeof(token)); - parStrncpy (cfg.token_acquisition_script, "../../tests/return_failure.bsh", - sizeof(cfg.token_acquisition_script)); set_parodus_cfg(&cfg); - createNewAuthToken (token, sizeof(token)); - assert_string_equal (token, ""); - + + will_return (curl_easy_perform, 0); + expect_function_calls (curl_easy_perform, 1); + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + output = requestNewAuthToken (token, sizeof(token), 1); + assert_int_equal (output, 0); + free(cfg.token_server_url); +} + +void test_getAuthToken () +{ + ParodusCfg cfg; + memset(&cfg,0,sizeof(cfg)); + + cfg.token_server_url = strdup("https://dev.comcast.net/token"); + cfg.client_cert_path = strdup("testcert"); + parStrncpy(cfg.cert_path , "/etc/ssl/certs/ca-certificates.crt", sizeof(cfg.cert_path)); + parStrncpy(cfg.webpa_interface_used , "eth0", sizeof(cfg.webpa_interface_used)); + parStrncpy(cfg.hw_serial_number, "Fer23u948590", sizeof(cfg.hw_serial_number)); + parStrncpy(cfg.hw_mac , "123567892366", sizeof(cfg.hw_mac)); + set_parodus_cfg(&cfg); + + will_return (curl_easy_perform, -1); + expect_function_calls (curl_easy_perform, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_perform, -1); + expect_function_calls (curl_easy_perform, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_perform, 0); + expect_function_calls (curl_easy_perform, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + getAuthToken(&cfg); + + assert( cfg.webpa_auth_token != NULL); + + free(cfg.client_cert_path); + free(cfg.token_server_url); +} + +void test_getAuthTokenFailure () +{ + ParodusCfg cfg; + memset(&cfg,0,sizeof(cfg)); + + cfg.token_server_url = strdup("https://dev.comcast.net/token"); + cfg.client_cert_path = strdup("testcert"); + parStrncpy(cfg.cert_path , "/etc/ssl/certs/ca-certificates.crt", sizeof(cfg.cert_path)); + parStrncpy(cfg.webpa_interface_used , "eth0", sizeof(cfg.webpa_interface_used)); + parStrncpy(cfg.hw_serial_number, "Fer23u948590", sizeof(cfg.hw_serial_number)); + parStrncpy(cfg.hw_mac , "123567892366", sizeof(cfg.hw_mac)); + set_parodus_cfg(&cfg); + will_return (curl_easy_perform, -1); + expect_function_calls (curl_easy_perform, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_perform, -1); + expect_function_calls (curl_easy_perform, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_perform, -1); + expect_function_calls (curl_easy_perform, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + getAuthToken(&cfg); + + assert_string_equal( cfg.webpa_auth_token, ""); + + free(cfg.client_cert_path); + free(cfg.token_server_url); +} + +void test_write_callback_fn () +{ + void *buffer; + size_t size = 1; + size_t nmemb =8; + int out_len=0; + struct token_data data; + data.size = 0; + buffer = strdup("response"); + + data.data = (char *) malloc(sizeof(char) * 5); + data.data[0] = '\0'; + + out_len = write_callback_fn(buffer, size, nmemb, &data); + assert_string_equal(data.data, buffer); + assert_int_equal( out_len, strlen(buffer)); + free(data.data); } /*----------------------------------------------------------------------------*/ @@ -598,7 +830,14 @@ int main(void) //cmocka_unit_test(test_parodusGitVersion), cmocka_unit_test(test_setDefaultValuesToCfg), cmocka_unit_test(err_setDefaultValuesToCfg), - cmocka_unit_test(test_new_auth_token) + cmocka_unit_test(test_requestNewAuthToken), + cmocka_unit_test(test_requestNewAuthToken_init_fail), + cmocka_unit_test(test_requestNewAuthToken_failure), + cmocka_unit_test(getAuthToken_Null), + cmocka_unit_test(getAuthToken_MacNull), + cmocka_unit_test(test_getAuthToken), + cmocka_unit_test(test_getAuthTokenFailure), + cmocka_unit_test(test_write_callback_fn), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/tests/test_connection.c b/tests/test_connection.c index 340a067a..b14e69f8 100644 --- a/tests/test_connection.c +++ b/tests/test_connection.c @@ -381,7 +381,6 @@ void test_set_extra_headers () create_connection_ctx_t ctx; ParodusCfg cfg; const char *expected_extra_headers = - "\r\nAuthorization: Bearer SER_MAC Fer23u948590 123567892366" "\r\nX-WebPA-Device-Name: mac:123567892366" "\r\nX-WebPA-Device-Protocols: wrp-0.11,getset-0.1" "\r\nUser-Agent: WebPA-1.6 (2.364s2; TG1682/ARRISGroup,Inc.;)" @@ -390,15 +389,13 @@ void test_set_extra_headers () memset(&cfg,0,sizeof(cfg)); memset (&ctx, 0, sizeof(ctx)); - parStrncpy (cfg.token_acquisition_script, "../../tests/return_success.bsh", - sizeof(cfg.token_acquisition_script)); - parStrncpy (cfg.token_read_script, "../../tests/return_ser_mac.bsh", - sizeof(cfg.token_read_script)); + cfg.client_cert_path = strdup("testcert"); parStrncpy(cfg.hw_serial_number, "Fer23u948590", sizeof(cfg.hw_serial_number)); parStrncpy(cfg.hw_mac , "123567892366", sizeof(cfg.hw_mac)); parStrncpy(cfg.hw_model, "TG1682", sizeof(cfg.hw_model)); parStrncpy(cfg.hw_manufacturer , "ARRISGroup,Inc.", sizeof(cfg.hw_manufacturer)); parStrncpy(cfg.fw_name , "2.364s2", sizeof(cfg.fw_name)); + parStrncpy(cfg.cert_path , "/etc/ssl/certs/ca-certificates.crt", sizeof(cfg.cert_path)); parStrncpy(cfg.webpa_protocol , "WebPA-1.6", sizeof(cfg.webpa_protocol)); set_parodus_cfg(&cfg); @@ -410,9 +407,9 @@ void test_set_extra_headers () assert_string_equal (ctx.header_info.conveyHeader, "WebPA-1.6 (TG1682)"); set_extra_headers (&ctx, true); - assert_string_equal (get_parodus_cfg()->webpa_auth_token, - "SER_MAC Fer23u948590 123567892366"); assert_string_equal (ctx.extra_headers, expected_extra_headers); + if(cfg.client_cert_path !=NULL) { + free(cfg.client_cert_path); } free (ctx.extra_headers); free_header_info (&ctx.header_info); From c2edbbc0745aed27a44111c4d008798d6dbd4b28 Mon Sep 17 00:00:00 2001 From: shilpa24balaji Date: Fri, 15 Feb 2019 12:33:41 -0800 Subject: [PATCH 06/11] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f05d90c1..6822e9ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [Unreleased] +- Security: Add support to use auth token during initial connect to cloud + ## [1.0.2] - 2019-02-08 - Refactored connection.c and updated corresponding unit tests - Additional `/cloud-status` and `/cloud-disconnect` fields. From 0875751c3facb3ba387a20c3dbde9aa1f08138d8 Mon Sep 17 00:00:00 2001 From: shilpa24balaji Date: Fri, 15 Feb 2019 12:34:22 -0800 Subject: [PATCH 07/11] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6822e9ca..c43dc7f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] -- Security: Add support to use auth token during initial connect to cloud +- Security: Added support to use auth token during initial connect to cloud ## [1.0.2] - 2019-02-08 - Refactored connection.c and updated corresponding unit tests From c7c93254ff9213b4fa215c692b25e429ec87d933 Mon Sep 17 00:00:00 2001 From: shilpa24balaji Date: Fri, 15 Feb 2019 12:38:45 -0800 Subject: [PATCH 08/11] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 72adb3bc..0b9648f2 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,9 @@ make test - /force-ipv6 -Forcefully connect parodus to ipv6 address (optional argument) -- /client-cert-path -client cert location to request auth token for establishing secure connection (absolute path where client cert is present) -optional argument +- /client-cert-path -MTLS client cert location to request auth token for establishing secure connection [absolute path where client cert is present] (optional argument) -- /token-server-url -server url to request new auth token for establishing secure connection -optional argument +- /token-server-url -complete server url with API path to request new auth token for establishing secure connection (optional argument) - /crud-config-file -Config json file to store objects during create, retrieve, update and delete (CRUD) operations -optional argument @@ -82,17 +82,17 @@ make test ``` # Seshat & FEATURE_DNS_QUERY Enabled -./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --acquire-jwt=1 --dns-txt-url=somebody.net --jwt-public-key-file=webpa-rs256.pem --jwt-algo=RS256 --seshat-url=tcp://127.0.0.1:7777 --client-cert-path=/tmp/clientcert.mch --token-server-url=somebody.net:8080 --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json +./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=https://somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --acquire-jwt=1 --dns-txt-url=somebody.net --jwt-public-key-file=webpa-rs256.pem --jwt-algo=RS256 --seshat-url=tcp://127.0.0.1:7777 --client-cert-path=/tmp/clientcert.mch --token-server-url=https://somebody.net:8080/token --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json # Seshat is not enabled -./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --acquire-jwt=1 --dns-txt-url=somebody.net --jwt-public-key-file=webpa-rs256.pem --jwt-algo=RS256 --client-cert-path=/tmp/clientcert.mch --token-server-url=somebody.net:8080 --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json +./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=https://somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --acquire-jwt=1 --dns-txt-url=somebody.net --jwt-public-key-file=webpa-rs256.pem --jwt-algo=RS256 --client-cert-path=/tmp/clientcert.mch --token-server-url=https://somebody.net:8080/token --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json # When both Seshat & FEATURE_DNS_QUERY not Enabled -./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --client-cert-path=/tmp/clientcert.mch --token-server-url=somebody.net:8080 --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json +./parodus --hw-model=TGXXX --hw-serial-number=E8GBUEXXXXXXXXX --hw-manufacturer=ARRIS --hw-mac=14cfexxxxxxx --hw-last-reboot-reason=unknown --fw-name=TG1682_DEV_master_20170512115046sdy --boot-time=1494590301 --webpa-ping-timeout=180 --webpa-interface-used=eth0 --webpa-url=https://somebody.net:8080 --webpa-backoff-max=9 --parodus-local-url=tcp://127.0.0.1:6666 --partner-id=comcast --ssl-cert-path=/etc/ssl/certs/ca-certificates.crt --client-cert-path=/tmp/clientcert.mch --token-server-url=https://somebody.net:8080/token --force-ipv4 --crud-config-file=/tmp/parodus_cfg.json ``` From 8a3e4507ef797503afe8be23582ed21f347a0cfd Mon Sep 17 00:00:00 2001 From: shilpa24balaji Date: Fri, 15 Feb 2019 12:41:13 -0800 Subject: [PATCH 09/11] Update config.c --- src/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 63d784c5..153f8320 100644 --- a/src/config.c +++ b/src/config.c @@ -756,7 +756,7 @@ void getAuthToken(ParodusCfg *cfg) } else { - ParodusInfo("client_cert_path is NULL\n"); + ParodusError("client_cert_path is NULL, failed to fetch auth token\n"); } } else From 3814f873bcb3821bdbac0addf6be85feaa18898c Mon Sep 17 00:00:00 2001 From: shilpa24balaji Date: Fri, 15 Feb 2019 12:41:48 -0800 Subject: [PATCH 10/11] Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c43dc7f9..c16869c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fixed main loop to keep calling svc_alive_task during a cloud disconnect and retry - change svc alive back to a separate thread. Shut it down with pthread_cond_timedwait - Refactored Upsteam RETRIEVE flow -- Added common themis JWT support for parodus ## [1.0.1] - 2018-07-18 ### Added From 1b903521d2161f471a49ea8e98f3f36c2aeedc47 Mon Sep 17 00:00:00 2001 From: shilpa24balaji Date: Fri, 15 Feb 2019 12:43:14 -0800 Subject: [PATCH 11/11] Update connection.c --- src/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connection.c b/src/connection.c index 74ee761b..5c9cbfa5 100644 --- a/src/connection.c +++ b/src/connection.c @@ -297,7 +297,7 @@ void set_current_server (create_connection_ctx_t *ctx) void set_extra_headers (create_connection_ctx_t *ctx, int reauthorize) { - if (reauthorize && (get_parodus_cfg()->client_cert_path !=NULL &&strlen(get_parodus_cfg()->client_cert_path) >0)) + if (reauthorize && (get_parodus_cfg()->client_cert_path !=NULL && strlen(get_parodus_cfg()->client_cert_path) >0)) { getAuthToken(get_parodus_cfg()); }