From cd9fd246795629a43cc98f42b01156ca88f7102e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Petr=20P=C3=ADsa=C5=99?= Date: Sun, 1 Sep 2019 19:06:31 +0200 Subject: [PATCH] Various corrections for the MEP login feature Code style adjustements. Check fir curl_easy_escape() and strtol() failure. Document testing MEP credentials. Document authorship. --- AUTHORS | 1 + README | 8 ++++-- src/isds.c | 25 ++++++++++++++-- src/soap.c | 80 +++++++++++++++++++++++++--------------------------- test/online/common.c | 22 +++++++-------- 5 files changed, 78 insertions(+), 58 deletions(-) diff --git a/AUTHORS b/AUTHORS index e4251d8..0ba6d6a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,5 +8,6 @@ MinGW support: Martin Doucha C++ and OS X portability: +Mobile key authentication: OpenSSL back-end: Karel Slany diff --git a/README b/README index 76b8d64..850f412 100644 --- a/README +++ b/README @@ -41,6 +41,8 @@ library. Preliminary library self-tests are located in `test' directory. Test data and message examples are stored in `server/messages' directory. Credentials for testing account can be passed to example clients and on-line -tests by environmental variables `ISDS_USERNAME' and `ISDS_PASSWORD' or by -saving them into `test_credentials' in build root directory (first line is -user name, second line is password). Environmental variables take precedence. +tests by environmental variables `ISDS_USERNAME', `ISDS_PASSWORD', and +`ISDS_CODE_MEP' or by saving them into `test_credentials' (first line is the +user name, second line is the password) and `test_credentials_mep' (first list +is tge use name, second line is the MEP code) in a build root directory. +Environmental variables take precedence. diff --git a/src/isds.c b/src/isds.c index 01a98e1..fe19c85 100644 --- a/src/isds.c +++ b/src/isds.c @@ -1531,6 +1531,25 @@ isds_error isds_login(struct isds_ctx *context, const char *url, #endif } + +/* Connect and log into ISDS server using the MEP login method. + * All arguments are copied, you don't have to keep them after successful + * return. + * @url is base address of ISDS web service. Pass extern isds_mep_locator to use + * the production ISDS environment (pass extern isds_mep_testing_locator to + * access the testing environment). Passing null causes the production + * environment locator to be used. + * @username is the username of ISDS user or box ID + * @code is the communication code. The code is generated when enabling + * the mobile key authentication and can be found in the web-based portal + * of the data-box service. + * @return: + * IE_SUCCESS if authentication succeeds + * IE_NOT_LOGGED_IN if authentication fails + * IE_PARTIAL_SUCCESS if MEP authentication has been requested, fine-grade + * resolution is returned via @mep->resolution, keep arguments unchanged and + * repeat the function call as long as IE_PARTIAL_SUCCESS is being returned; + * or other appropriate error. */ isds_error isds_login_mep(struct isds_ctx *context, const char *url, const char *username, const char *code, struct isds_mep *mep) { #if HAVE_LIBCURL @@ -1546,7 +1565,6 @@ isds_error isds_login_mep(struct isds_ctx *context, const char *url, zfree(context->long_message); #if HAVE_LIBCURL - context->type = CTX_TYPE_ISDS; if ((NULL != username) && (NULL != code) && (NULL != mep)) { @@ -1579,6 +1597,9 @@ isds_error isds_login_mep(struct isds_ctx *context, const char *url, app_name = ""; } char *escaped_app_name = curl_easy_escape(context->curl, app_name, 0); + if (NULL == escaped_app_name) { + return IE_NOMEM; + } if (-1 == isds_asprintf(&context->url, authenticator_uri, url, escaped_app_name, url)) { curl_free(escaped_app_name); @@ -1646,7 +1667,7 @@ isds_error isds_login_mep(struct isds_ctx *context, const char *url, /* Remove credentials */ _isds_discard_credentials(context, 0); - + /* Destroy log-in request */ xmlFreeNode(request); diff --git a/src/soap.c b/src/soap.c index 48ac269..9ff04fe 100644 --- a/src/soap.c +++ b/src/soap.c @@ -1091,9 +1091,7 @@ leave: * @len String length * @return server response code or MEP_RESOLUTION_UNKNOWN if the code was not * recognised. */ -static -isds_mep_resolution mep_ws_state_response(const char *str, size_t len) -{ +static isds_mep_resolution mep_ws_state_response(const char *str, size_t len) { isds_mep_resolution res = MEP_RESOLUTION_UNKNOWN; /* Default error. */ if ((str == NULL) || (len == 0)) { @@ -1109,25 +1107,25 @@ isds_mep_resolution mep_ws_state_response(const char *str, size_t len) char *endptr; long num = strtol(tmp_str, &endptr, 10); - if (*endptr != '\0') { + if (*endptr != '\0' || LONG_MIN == num || LONG_MAX == num) { return res; } switch (num) { - case -1: - res = MEP_RESOLUTION_UNRECOGNISED; - break; - case 1: - res = MEP_RESOLUTION_ACK_REQUESTED; - break; - case 2: - res = MEP_RESOLUTION_ACK; - break; - case 3: - res = MEP_RESOLUTION_ACK_EXPIRED; - break; - default: - break; + case -1: + res = MEP_RESOLUTION_UNRECOGNISED; + break; + case 1: + res = MEP_RESOLUTION_ACK_REQUESTED; + break; + case 2: + res = MEP_RESOLUTION_ACK; + break; + case 3: + res = MEP_RESOLUTION_ACK_EXPIRED; + break; + default: + break; } free(tmp_str); @@ -1135,14 +1133,14 @@ isds_mep_resolution mep_ws_state_response(const char *str, size_t len) return res; } + /* Build SOAP request. * @context needed for error logging, * @request is XML node set with SOAP request body, * @http_request_ptr the address of a pointer to an automatically allocated * buffer to which the request data are written. */ -static -isds_error build_http_request(struct isds_ctx *context, +static isds_error build_http_request(struct isds_ctx *context, const xmlNodePtr request, xmlBufferPtr *http_request_ptr) { isds_error err = IE_SUCCESS; @@ -1553,28 +1551,26 @@ redirect: context->mep_credentials->resolution = mep_ws_state_response(http_response, response_length); switch (context->mep_credentials->resolution) { - case MEP_RESOLUTION_ACK_REQUESTED: - /* Waiting for the user to acknowledge the login request - * in the mobile application. This may take a while. - * Return with partial success. Don't close communication - * context. */ - err = IE_PARTIAL_SUCCESS; - goto leave; - break; - case MEP_RESOLUTION_ACK: - /* Immediately redirect to login finalisation. */ - free(context->mep_credentials->intermediate_uri); - context->mep_credentials->intermediate_uri = NULL; - err = IE_PARTIAL_SUCCESS; - goto redirect; - break; - default: - free(context->mep_credentials->intermediate_uri); - context->mep_credentials->intermediate_uri = NULL; - err = IE_NOT_LOGGED_IN; - /* No SOAP data are returned here just plain response code. */ - goto leave; - break; + case MEP_RESOLUTION_ACK_REQUESTED: + /* Waiting for the user to acknowledge the login request + * in the mobile application. This may take a while. + * Return with partial success. Don't close communication + * context. */ + err = IE_PARTIAL_SUCCESS; + goto leave; + break; + case MEP_RESOLUTION_ACK: + /* Immediately redirect to login finalisation. */ + zfree(context->mep_credentials->intermediate_uri); + err = IE_PARTIAL_SUCCESS; + goto redirect; + break; + default: + zfree(context->mep_credentials->intermediate_uri); + err = IE_NOT_LOGGED_IN; + /* No SOAP data are returned here just plain response code. */ + goto leave; + break; } } break; diff --git a/test/online/common.c b/test/online/common.c index cc753e8..2d33cbf 100644 --- a/test/online/common.c +++ b/test/online/common.c @@ -6,12 +6,12 @@ char credentials_pwd_file[] = "../../test_credentials"; char credentials_mep_file[] = "../../test_credentials_mep"; -static int read_config(const char *cred_file, char **line, int order) { +static int read_config(const char *credentials_file, char **line, int order) { FILE *file; size_t length = 0; char *eol; - if (NULL == cred_file) { + if (NULL == credentials_file) { return -1; } @@ -19,16 +19,16 @@ static int read_config(const char *cred_file, char **line, int order) { free(*line); *line = NULL; - file = fopen(cred_file, "r"); + file = fopen(credentials_file, "r"); if (!file) { - fprintf(stderr, "Could open %s\n", cred_file); + fprintf(stderr, "Could open %s\n", credentials_file); return -1; } for (int i = 0; i < order; i++) { if (-1 == getline(line, &length, file)) { fprintf(stderr, "Could not read line #%d from %s: ", - i + 1, cred_file); + i + 1, credentials_file); if (ferror(file)) fprintf(stderr, "error occured\n"); else if (feof(file)) @@ -51,22 +51,22 @@ static int read_config(const char *cred_file, char **line, int order) { } const char *username(void) { - static char *username; + static char *username = NULL; - if (!username) { + if (NULL == username) { username = getenv("ISDS_USERNAME"); - if (!username) + if (NULL == username) read_config(credentials_pwd_file, &username, 1); } return username; } const char *password(void) { - static char *password; + static char *password = NULL; - if (!password) { + if (NULL == password) { password = getenv("ISDS_PASSWORD"); - if (!password) + if (NULL == password) read_config(credentials_pwd_file, &password, 2); } return password; -- 2.11.4.GIT