summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/err/openssl.txt2
-rw-r--r--crypto/http/http_err.c4
-rw-r--r--crypto/http/http_lib.c93
-rw-r--r--doc/man3/OSSL_HTTP_parse_url.pod34
-rw-r--r--include/openssl/http.h3
-rw-r--r--include/openssl/httperr.h2
-rw-r--r--util/libcrypto.num1
7 files changed, 105 insertions, 34 deletions
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 = 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;
diff --git a/doc/man3/OSSL_HTTP_parse_url.pod b/doc/man3/OSSL_HTTP_parse_url.pod
index 5933e954da..60589b6bf9 100644
--- a/doc/man3/OSSL_HTTP_parse_url.pod
+++ b/doc/man3/OSSL_HTTP_parse_url.pod
@@ -2,6 +2,7 @@
=head1 NAME
+OSSL_parse_url,
OSSL_HTTP_parse_url,
OCSP_parse_url
- http utility functions
@@ -10,6 +11,9 @@ OCSP_parse_url
#include <openssl/http.h>
+ int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost,
+ char **pport, int *pport_num,
+ char **ppath, char **pquery, char **pfrag);
int OSSL_HTTP_parse_url(const char *url,
int *pssl, char **puser, char **phost,
char **pport, int *pport_num,
@@ -24,28 +28,34 @@ L<openssl_user_macros(7)>:
=head1 DESCRIPTION
-OSSL_HTTP_parse_url() parses its input string I<url> as a URL of the form
-C<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]> and splits it up
-into userinfo, host, port, path, query, and fragment components
-and a flag indicating whether it begins with C<https>.
+OSSL_parse_url() parses its input string I<url> as a URL of the form
+C<[scheme://][userinfo@]host[:port][/path][?query][#fragment]> and splits it up
+into scheme, userinfo, host, port, path, query, and fragment components.
The host component may be a DNS name or an IP address
where IPv6 addresses should be enclosed in square brackets C<[> and C<]>.
-The port component is optional and defaults to "443" for HTTPS, else "80".
+The port component is optional and defaults to C<0>.
If given, it must be in decimal form. If the I<pport_num> argument is not NULL
the integer value of the port number is assigned to I<*pport_num> on success.
The path component is also optional and defaults to C</>.
-If I<pssl> is not NULL, I<*pssl> is assigned 1 in case parsing was successful
-and the schema part is present and is C<https>, else 0.
-Each non-NULL result pointer argument I<puser>, I<phost>, I<pport>, I<ppath>,
-I<pquery>, and I<pfrag>, is assigned the respective url component.
+Each non-NULL result pointer argument I<pscheme>, I<puser>, I<phost>, I<pport>,
+I<ppath>, I<pquery>, and I<pfrag>, is assigned the respective url component.
On success, they are guaranteed to contain non-NULL string pointers, else NULL.
It is the reponsibility of the caller to free them using L<OPENSSL_free(3)>.
If I<pquery> is NULL, any given query component is handled as part of the path.
A string returned via I<*ppath> is guaranteed to begin with a C</> character.
-For absent userinfo, query, and fragment components an empty string is given.
+For absent scheme, userinfo, port, query, and fragment components
+an empty string is provided.
+
+OSSL_HTTP_parse_url() is a special form of OSSL_parse_url()
+where the scheme, if given, must be C<http> or C<https>.
+If I<pssl> is not NULL, I<*pssl> is assigned 1 in case parsing was successful
+and the scheme is C<https>, else 0.
+The port component is optional and defaults to C<443> if the scheme is C<https>,
+else C<80>.
-Calling the deprecated fucntion OCSP_parse_url(url, host, port, path, ssl) is
-equivalent to OSSL_HTTP_parse_url(url, ssl, NULL, host, port, NULL, path, NULL, NULL).
+Calling the deprecated function OCSP_parse_url(url, host, port, path, ssl)
+is equivalent to
+OSSL_HTTP_parse_url(url, ssl, NULL, host, port, NULL, path, NULL, NULL).
=head1 RETURN VALUES
diff --git a/include/openssl/http.h b/include/openssl/http.h
index 508428a986..c39049918f 100644
--- a/include/openssl/http.h
+++ b/include/openssl/http.h
@@ -96,6 +96,9 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
const char *proxyuser, const char *proxypass,
int timeout, BIO *bio_err, const char *prog);
+int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost,
+ char **pport, int *pport_num,
+ char **ppath, char **pquery, char **pfrag);
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);
diff --git a/include/openssl/httperr.h b/include/openssl/httperr.h
index 796bc15a49..af5717d3dc 100644
--- a/include/openssl/httperr.h
+++ b/include/openssl/httperr.h
@@ -32,7 +32,7 @@
# define HTTP_R_INCONSISTENT_CONTENT_LENGTH 120
# define HTTP_R_INVALID_PORT_NUMBER 123
# define HTTP_R_INVALID_URL_PATH 125
-# define HTTP_R_INVALID_URL_PREFIX 124
+# define HTTP_R_INVALID_URL_SCHEME 124
# define HTTP_R_MAX_RESP_LEN_EXCEEDED 117
# define HTTP_R_MISSING_ASN1_ENCODING 110
# define HTTP_R_MISSING_CONTENT_TYPE 121
diff --git a/util/libcrypto.num b/util/libcrypto.num
index aa3071ec30..0c5318db8f 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4880,6 +4880,7 @@ ASN1_item_verify_ex ? 3_0_0 EXIST::FUNCTION:
BIO_socket_wait ? 3_0_0 EXIST::FUNCTION:SOCK
BIO_wait ? 3_0_0 EXIST::FUNCTION:
BIO_do_connect_retry ? 3_0_0 EXIST::FUNCTION:
+OSSL_parse_url ? 3_0_0 EXIST::FUNCTION:
OSSL_HTTP_get ? 3_0_0 EXIST::FUNCTION:
OSSL_HTTP_get_asn1 ? 3_0_0 EXIST::FUNCTION:
OSSL_HTTP_post_asn1 ? 3_0_0 EXIST::FUNCTION: