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
{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),
}
}
-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);
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("://");
}
}
/* 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;
}
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)
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);
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;
=head1 NAME
+OSSL_parse_url,
OSSL_HTTP_parse_url,
OCSP_parse_url
- http utility functions
#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,
=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
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);
# 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
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: