From d546e8e267bfddc1ca310dfa8b9a72ab4f9aac7c Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Wed, 17 Feb 2021 17:24:19 +0100 Subject: Generalize schmeme parsing of OSSL_HTTP_parse_url() to OSSL_parse_url() Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/14009) --- crypto/err/openssl.txt | 2 +- crypto/http/http_err.c | 4 +-- crypto/http/http_lib.c | 93 ++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 78 insertions(+), 21 deletions(-) (limited to 'crypto') diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 530e3217e4..e9a179c362 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -757,7 +757,7 @@ HTTP_R_FAILED_READING_DATA:128:failed reading data HTTP_R_INCONSISTENT_CONTENT_LENGTH:120:inconsistent content length HTTP_R_INVALID_PORT_NUMBER:123:invalid port number HTTP_R_INVALID_URL_PATH:125:invalid url path -HTTP_R_INVALID_URL_PREFIX:124:invalid url prefix +HTTP_R_INVALID_URL_SCHEME:124:invalid url scheme HTTP_R_MAX_RESP_LEN_EXCEEDED:117:max resp len exceeded HTTP_R_MISSING_ASN1_ENCODING:110:missing asn1 encoding HTTP_R_MISSING_CONTENT_TYPE:121:missing content type diff --git a/crypto/http/http_err.c b/crypto/http/http_err.c index 20235ba0f8..2bb6d97290 100644 --- a/crypto/http/http_err.c +++ b/crypto/http/http_err.c @@ -32,8 +32,8 @@ static const ERR_STRING_DATA HTTP_str_reasons[] = { {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INVALID_PORT_NUMBER), "invalid port number"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INVALID_URL_PATH), "invalid url path"}, - {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INVALID_URL_PREFIX), - "invalid url prefix"}, + {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INVALID_URL_SCHEME), + "invalid url scheme"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MAX_RESP_LEN_EXCEEDED), "max resp len exceeded"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MISSING_ASN1_ENCODING), diff --git a/crypto/http/http_lib.c b/crypto/http/http_lib.c index 3c894d8629..6b8c15471e 100644 --- a/crypto/http/http_lib.c +++ b/crypto/http/http_lib.c @@ -36,21 +36,21 @@ static void free_pstring(char **pstr) } } -int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost, - char **pport, int *pport_num, - char **ppath, char **pquery, char **pfrag) +int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost, + char **pport, int *pport_num, + char **ppath, char **pquery, char **pfrag) { const char *p, *tmp; + const char *scheme, *scheme_end; const char *user, *user_end; const char *host, *host_end; - const char *port = OSSL_HTTP_PORT, *port_end; + const char *port, *port_end; unsigned int portnum; const char *path, *path_end; const char *query, *query_end; const char *frag, *frag_end; - if (pssl != NULL) - *pssl = 0; + init_pstring(pscheme); init_pstring(puser); init_pstring(phost); init_pstring(pport); @@ -63,19 +63,15 @@ int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost, return 0; } - /* check for optional prefix "http[s]://" */ + /* check for optional prefix "://" */ + scheme = scheme_end = url; p = strstr(url, "://"); if (p == NULL) { p = url; - } else { /* p points to end of scheme name */ - if (strncmp(url, OSSL_HTTPS_NAME, strlen(OSSL_HTTPS_NAME)) == 0) { - if (pssl != NULL) - *pssl = 1; - port = OSSL_HTTPS_PORT; - } else if (strncmp(url, OSSL_HTTP_NAME, strlen(OSSL_HTTP_NAME)) != 0) { - ERR_raise(ERR_LIB_HTTP, HTTP_R_INVALID_URL_PREFIX); - goto err; - } + } else { + scheme_end = p; + if (scheme_end == scheme) + goto parse_err; p += strlen("://"); } @@ -110,11 +106,12 @@ int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost, } /* parse optional port specification starting with ':' */ + port = "0"; /* default */ if (*p == ':') port = ++p; /* remaining port spec handling is also done for the default values */ /* make sure a decimal port number is given */ - if (!sscanf(port, "%u", &portnum) || portnum < 1 || portnum > 65535) { + if (!sscanf(port, "%u", &portnum) || portnum > 65535) { ERR_raise(ERR_LIB_HTTP, HTTP_R_INVALID_PORT_NUMBER); goto err; } @@ -150,7 +147,8 @@ int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost, frag = tmp + 1; } - if (!copy_substring(phost, host, host_end) + if (!copy_substring(pscheme, scheme, scheme_end) + || !copy_substring(phost, host, host_end) || !copy_substring(pport, port, port_end) || !copy_substring(puser, user, user_end) || !copy_substring(pquery, query, query_end) @@ -174,6 +172,8 @@ int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost, ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_URL); err: + free_pstring(pscheme); + free_pstring(puser); free_pstring(phost); free_pstring(pport); free_pstring(ppath); @@ -182,6 +182,63 @@ int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost, return 0; } +int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost, + char **pport, int *pport_num, + char **ppath, char **pquery, char **pfrag) +{ + char *scheme, *port; + int ssl = 0, portnum; + + init_pstring(pport); + if (pssl != NULL) + *pssl = 0; + if (!OSSL_parse_url(url, &scheme, puser, phost, &port, pport_num, + ppath, pquery, pfrag)) + return 0; + + /* check for optional HTTP scheme "http[s]" */ + if (strcmp(scheme, OSSL_HTTPS_NAME) == 0) { + ssl = 1; + if (pssl != NULL) + *pssl = ssl; + } else if (*scheme != '\0' && strcmp(scheme, OSSL_HTTP_NAME) != 0) { + ERR_raise(ERR_LIB_HTTP, HTTP_R_INVALID_URL_SCHEME); + OPENSSL_free(scheme); + OPENSSL_free(port); + goto err; + } + OPENSSL_free(scheme); + + if (strcmp(port, "0") == 0) { + /* set default port */ + OPENSSL_free(port); + port = ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT; + if (!ossl_assert(sscanf(port, "%d", &portnum) == 1)) + goto err; + if (pport_num != NULL) + *pport_num = portnum; + if (pport != NULL) { + *pport = OPENSSL_strdup(port); + if (*pport == NULL) + goto err; + } + } else { + if (pport != NULL) + *pport = port; + else + OPENSSL_free(port); + } + return 1; + + err: + free_pstring(puser); + free_pstring(phost); + free_pstring(ppath); + free_pstring(pquery); + free_pstring(pfrag); + return 0; +} + int http_use_proxy(const char *no_proxy, const char *server) { size_t sl; -- cgit v1.2.3