mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 05:21:51 +08:00
OSSL_HTTP_parse_url(): add optional port number return parameter and strengthen documentation
Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/12786)
This commit is contained in:
parent
8d6481f532
commit
d7fcee3b3b
@ -2066,7 +2066,7 @@ ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!OSSL_HTTP_parse_url(url, &server, &port, NULL /* ppath */, &use_ssl))
|
||||
if (!OSSL_HTTP_parse_url(url, &server, &port, NULL, NULL, &use_ssl))
|
||||
return NULL;
|
||||
if (use_ssl && ssl_ctx == NULL) {
|
||||
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
|
||||
|
@ -275,7 +275,7 @@ int ocsp_main(int argc, char **argv)
|
||||
OPENSSL_free(tpath);
|
||||
thost = tport = tpath = NULL;
|
||||
if (!OSSL_HTTP_parse_url(opt_arg(),
|
||||
&host, &port, &path, &use_ssl)) {
|
||||
&host, &port, NULL, &path, &use_ssl)) {
|
||||
BIO_printf(bio_err, "%s Error parsing URL\n", prog);
|
||||
goto end;
|
||||
}
|
||||
|
@ -535,7 +535,7 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
|
||||
aia = X509_get1_ocsp(x);
|
||||
if (aia != NULL) {
|
||||
if (!OSSL_HTTP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
|
||||
&host, &port, &path, &use_ssl)) {
|
||||
&host, &port, NULL, &path, &use_ssl)) {
|
||||
BIO_puts(bio_err, "cert_status: can't parse AIA URL\n");
|
||||
goto err;
|
||||
}
|
||||
@ -1405,7 +1405,7 @@ int s_server_main(int argc, char *argv[])
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
s_tlsextstatus = 1;
|
||||
if (!OSSL_HTTP_parse_url(opt_arg(),
|
||||
&tlscstatp.host, &tlscstatp.port,
|
||||
&tlscstatp.host, &tlscstatp.port, NULL,
|
||||
&tlscstatp.path, &tlscstatp.use_ssl)) {
|
||||
BIO_printf(bio_err, "Error parsing URL\n");
|
||||
goto end;
|
||||
|
@ -2637,6 +2637,9 @@ HTTP_R_ERROR_PARSING_URL:101:error parsing url
|
||||
HTTP_R_ERROR_RECEIVING:103:error receiving
|
||||
HTTP_R_ERROR_SENDING:102:error sending
|
||||
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_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
|
||||
|
@ -1005,7 +1005,8 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy,
|
||||
return NULL;
|
||||
|
||||
for (;;) {
|
||||
if (!OSSL_HTTP_parse_url(current_url, &host, &port, &path, &use_ssl))
|
||||
if (!OSSL_HTTP_parse_url(current_url, &host, &port, NULL /* port_num */,
|
||||
&path, &use_ssl))
|
||||
break;
|
||||
|
||||
new_rpath:
|
||||
|
@ -26,6 +26,11 @@ static const ERR_STRING_DATA HTTP_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_SENDING), "error sending"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INCONSISTENT_CONTENT_LENGTH),
|
||||
"inconsistent content length"},
|
||||
{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_MAX_RESP_LEN_EXCEEDED),
|
||||
"max resp len exceeded"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MISSING_ASN1_ENCODING),
|
||||
|
@ -21,19 +21,12 @@
|
||||
*/
|
||||
|
||||
int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport,
|
||||
char **ppath, int *pssl)
|
||||
int *pport_num, char **ppath, int *pssl)
|
||||
{
|
||||
char *p, *buf;
|
||||
char *host;
|
||||
const char *port = OSSL_HTTP_PORT;
|
||||
size_t https_len = strlen(OSSL_HTTPS_NAME);
|
||||
|
||||
if (!ossl_assert(https_len >= strlen(OSSL_HTTP_NAME)))
|
||||
return 0;
|
||||
if (url == NULL) {
|
||||
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
char *host, *host_end;
|
||||
const char *path, *port = OSSL_HTTP_PORT;
|
||||
long portnum = 80;
|
||||
|
||||
if (phost != NULL)
|
||||
*phost = NULL;
|
||||
@ -44,59 +37,90 @@ int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport,
|
||||
if (pssl != NULL)
|
||||
*pssl = 0;
|
||||
|
||||
if (url == NULL) {
|
||||
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* dup the buffer since we are going to mess with it */
|
||||
if ((buf = OPENSSL_strdup(url)) == NULL)
|
||||
goto err;
|
||||
|
||||
/* Check for initial colon */
|
||||
p = strchr(buf, ':');
|
||||
if (p == NULL || (size_t)(p - buf) > https_len) {
|
||||
/* check for optional prefix "http[s]://" */
|
||||
p = strstr(buf, "://");
|
||||
if (p == NULL) {
|
||||
p = buf;
|
||||
} else {
|
||||
*(p++) = '\0';
|
||||
|
||||
*p = '\0'; /* p points to end of scheme name */
|
||||
if (strcmp(buf, OSSL_HTTPS_NAME) == 0) {
|
||||
if (pssl != NULL)
|
||||
*pssl = 1;
|
||||
port = OSSL_HTTPS_PORT;
|
||||
portnum = 443;
|
||||
} else if (strcmp(buf, OSSL_HTTP_NAME) != 0) {
|
||||
goto parse_err;
|
||||
HTTPerr(0, HTTP_R_INVALID_URL_PREFIX);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Check for double slash */
|
||||
if ((p[0] != '/') || (p[1] != '/'))
|
||||
goto parse_err;
|
||||
p += 2;
|
||||
p += 3;
|
||||
}
|
||||
host = p;
|
||||
|
||||
/* Check for trailing part of path */
|
||||
p = strchr(p, '/');
|
||||
if (ppath != NULL && (*ppath = OPENSSL_strdup(p == NULL ? "/" : p)) == NULL)
|
||||
goto err;
|
||||
if (p != NULL)
|
||||
*p = '\0'; /* Set start of path to 0 so hostname[:port] is valid */
|
||||
|
||||
p = host;
|
||||
/* parse host name/address as far as needed here */
|
||||
if (host[0] == '[') {
|
||||
/* ipv6 literal */
|
||||
/* ipv6 literal, which may include ':' */
|
||||
host++;
|
||||
p = strchr(host, ']');
|
||||
if (p == NULL)
|
||||
host_end = strchr(host, ']');
|
||||
if (host_end == NULL)
|
||||
goto parse_err;
|
||||
*p = '\0';
|
||||
p++;
|
||||
*host_end++ = '\0';
|
||||
} else {
|
||||
host_end = strchr(host, ':'); /* look for start of optional port */
|
||||
if (host_end == NULL)
|
||||
host_end = strchr(host, '/'); /* look for start of optional path */
|
||||
if (host_end == NULL)
|
||||
/* the remaining string is just the hostname */
|
||||
host_end = host + strlen(host);
|
||||
}
|
||||
|
||||
/* Look for optional ':' for port number */
|
||||
if ((p = strchr(p, ':'))) {
|
||||
*p = '\0';
|
||||
port = p + 1;
|
||||
/* parse optional port specification starting with ':' */
|
||||
p = host_end;
|
||||
if (*p == ':') {
|
||||
port = ++p;
|
||||
if (pport_num == NULL) {
|
||||
p = strchr(port, '/');
|
||||
if (p == NULL)
|
||||
p = p + strlen(port);
|
||||
} else { /* make sure a numerical port value is given */
|
||||
portnum = strtol(port, &p, 10);
|
||||
if (p == port || (*p != '\0' && *p != '/'))
|
||||
goto parse_err;
|
||||
if (portnum <= 0 || portnum >= 65536) {
|
||||
HTTPerr(0, HTTP_R_INVALID_PORT_NUMBER);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
*host_end = '\0';
|
||||
*p = '\0'; /* terminate port string */
|
||||
|
||||
/* check for optional path at end of url starting with '/' */
|
||||
path = url + (p - buf);
|
||||
/* cannot use p + 1 because *p is '\0' and path must start with '/' */
|
||||
if (*path == '\0') {
|
||||
path = "/";
|
||||
} else if (*path != '/') {
|
||||
HTTPerr(0, HTTP_R_INVALID_URL_PATH);
|
||||
goto parse_err;
|
||||
}
|
||||
|
||||
if (phost != NULL && (*phost = OPENSSL_strdup(host)) == NULL)
|
||||
goto err;
|
||||
if (pport != NULL && (*pport = OPENSSL_strdup(port)) == NULL)
|
||||
goto err;
|
||||
if (pport_num != NULL)
|
||||
*pport_num = (int)portnum;
|
||||
if (ppath != NULL && (*ppath = OPENSSL_strdup(path)) == NULL)
|
||||
goto err;
|
||||
|
||||
OPENSSL_free(buf);
|
||||
return 1;
|
||||
|
@ -55,36 +55,36 @@ OSSL_HTTP_parse_url
|
||||
const char *proxyuser, const char *proxypass,
|
||||
int timeout, BIO *bio_err, const char *prog);
|
||||
int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport,
|
||||
char **ppath, int *pssl);
|
||||
int *pport_num, char **ppath, int *pssl);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
OSSL_HTTP_get() uses HTTP GET to obtain data (of any type) from the given B<url>
|
||||
OSSL_HTTP_get() uses HTTP GET to obtain data (of any type) from the given I<url>
|
||||
and returns it as a memory BIO.
|
||||
|
||||
OSSL_HTTP_get_asn1() uses HTTP GET to obtain an ASN.1-encoded value
|
||||
(e.g., an X.509 certificate) with the expected structure specified by B<it>
|
||||
(e.g., I<ASN1_ITEM_rptr(X509)>) from the given B<url>
|
||||
(e.g., an X.509 certificate) with the expected structure specified by I<it>
|
||||
(e.g., I<ASN1_ITEM_rptr(X509)>) from the given I<url>
|
||||
and returns it on success as a pointer to I<ASN1_VALUE>.
|
||||
|
||||
OSSL_HTTP_post_asn1() uses the HTTP POST method to send a request B<req>
|
||||
with the ASN.1 structure defined in B<req_it> and the given B<content_type> to
|
||||
the given B<server> and optional B<port> and B<path>.
|
||||
If B<use_ssl> is nonzero a TLS connection is requested and the B<bio_update_fn>
|
||||
OSSL_HTTP_post_asn1() uses the HTTP POST method to send a request I<req>
|
||||
with the ASN.1 structure defined in I<req_it> and the given I<content_type> to
|
||||
the given I<server> and optional I<port> and I<path>.
|
||||
If I<use_ssl> is nonzero a TLS connection is requested and the I<bio_update_fn>
|
||||
parameter, described below, must be provided.
|
||||
The optional list B<headers> may contain additional custom HTTP header lines.
|
||||
The expected structure of the response is specified by B<rsp_it>.
|
||||
The optional list I<headers> may contain additional custom HTTP header lines.
|
||||
The expected structure of the response is specified by I<rsp_it>.
|
||||
On success it returns the response as a pointer to B<ASN1_VALUE>.
|
||||
|
||||
OSSL_HTTP_transfer() exchanges any form of HTTP request and response.
|
||||
It implements the core of the functions described above.
|
||||
If B<path> parameter is NULL it defaults to "/".
|
||||
If B<use_ssl> is nonzero a TLS connection is requested
|
||||
and the B<bio_update_fn> parameter, described below, must be provided.
|
||||
If B<req_mem> is NULL it uses the HTTP GET method, else it uses HTTP POST to
|
||||
send a request with the contents of the memory BIO and optional B<content_type>.
|
||||
The optional list B<headers> may contain additional custom HTTP header lines.
|
||||
If B<req_mem> is NULL (i.e., the HTTP method is GET) and B<redirection_url>
|
||||
If I<path> parameter is NULL it defaults to "/".
|
||||
If I<use_ssl> is nonzero a TLS connection is requested
|
||||
and the I<bio_update_fn> parameter, described below, must be provided.
|
||||
If I<req_mem> is NULL it uses the HTTP GET method, else it uses HTTP POST to
|
||||
send a request with the contents of the memory BIO and optional I<content_type>.
|
||||
The optional list I<headers> may contain additional custom HTTP header lines.
|
||||
If I<req_mem> is NULL (i.e., the HTTP method is GET) and I<redirection_url>
|
||||
is not NULL the latter pointer is used to provide any new location that
|
||||
the server may return with HTTP code 301 (MOVED_PERMANENTLY) or 302 (FOUND).
|
||||
In this case the caller is responsible for deallocating this URL with
|
||||
@ -93,71 +93,71 @@ L<OPENSSL_free(3)>.
|
||||
The above functions have the following parameters in common.
|
||||
|
||||
Typically the OpenSSL build supports sockets
|
||||
and the B<bio> and B<rbio> parameters are both NULL.
|
||||
and the I<bio> and I<rbio> parameters are both NULL.
|
||||
In this case the client creates a network BIO internally
|
||||
for connecting to the given B<server>
|
||||
at the specified B<port> (if any, defaulting to 80 for HTTP or 443 for HTTPS),
|
||||
optionally via a B<proxy> (respecting B<no_proxy>) as described below.
|
||||
for connecting to the given I<server>
|
||||
at the specified I<port> (if any, defaulting to 80 for HTTP or 443 for HTTPS),
|
||||
optionally via a I<proxy> (respecting I<no_proxy>) as described below.
|
||||
Then the client uses this internal BIO for exchanging the request and response.
|
||||
If B<bio> is given and B<rbio> is NULL then the client uses this B<bio> instead.
|
||||
If both B<bio> and B<rbio> are given (which may be memory BIOs for instance)
|
||||
If I<bio> is given and I<rbio> is NULL then the client uses this I<bio> instead.
|
||||
If both I<bio> and I<rbio> are given (which may be memory BIOs for instance)
|
||||
then no explicit connection is attempted,
|
||||
B<bio> is used for writing the request, and B<rbio> for reading the response.
|
||||
As soon as the client has flushed B<bio> the server must be ready to provide
|
||||
a response or indicate a waiting condition via B<rbio>.
|
||||
I<bio> is used for writing the request, and I<rbio> for reading the response.
|
||||
As soon as the client has flushed I<bio> the server must be ready to provide
|
||||
a response or indicate a waiting condition via I<rbio>.
|
||||
|
||||
The optional B<proxy> parameter can be used to set the address of the an
|
||||
The optional I<proxy> parameter can be used to set the address of the an
|
||||
HTTP(S) proxy to use (unless overridden by "no_proxy" settings).
|
||||
If TLS is not used this defaults to the environment variable B<http_proxy>
|
||||
if set, else B<HTTP_PROXY>.
|
||||
If B<use_ssl> != 0 it defaults to B<https_proxy> if set, else B<HTTPS_PROXY>.
|
||||
If TLS is not used this defaults to the environment variable C<http_proxy>
|
||||
if set, else C<HTTP_PROXY>.
|
||||
If I<use_ssl> != 0 it defaults to C<https_proxy> if set, else C<HTTPS_PROXY>.
|
||||
An empty proxy string specifies not to use a proxy.
|
||||
Else the format is I<[http[s]://]address[:port][/path]>,
|
||||
Else the format is C<[http[s]://]address[:port][/path]>,
|
||||
where any path given is ignored.
|
||||
The default proxy port number is 80, or 443 in case "https:" is given.
|
||||
The HTTP client functions connect via the given proxy unless the B<server>
|
||||
is found in the optional list B<no_proxy> of proxy hostnames (if not NULL;
|
||||
default is the environment variable B<no_proxy> if set, else B<NO_PROXY>).
|
||||
The HTTP client functions connect via the given proxy unless the I<server>
|
||||
is found in the optional list I<no_proxy> of proxy hostnames (if not NULL;
|
||||
default is the environment variable C<no_proxy> if set, else C<NO_PROXY>).
|
||||
Proxying plain HTTP is supported directly,
|
||||
while using a proxy for HTTPS connections requires a suitable callback function
|
||||
such as B<OSSL_HTTP_proxy_connect()>, described below.
|
||||
such as OSSL_HTTP_proxy_connect(), described below.
|
||||
|
||||
The B<maxline> parameter specifies the response header maximum line length,
|
||||
The I<maxline> parameter specifies the response header maximum line length,
|
||||
where 0 indicates the default value, which currently is 4k.
|
||||
The B<max_resp_len> parameter specifies the maximum response length,
|
||||
The I<max_resp_len> parameter specifies the maximum response length,
|
||||
where 0 indicates the default value, which currently is 100k.
|
||||
|
||||
An ASN.1-encoded response is expected by OSSL_HTTP_get_asn1() and
|
||||
OSSL_HTTP_post_asn1(), while for OSSL_HTTP_get() or OSSL_HTTP_transfer()
|
||||
this is only the case if the B<expect_asn1> parameter is nonzero.
|
||||
this is only the case if the I<expect_asn1> parameter is nonzero.
|
||||
If the response header contains one or more "Content-Length" header lines and/or
|
||||
an ASN.1-encoded response is expected, which should include a total length,
|
||||
the length indications received are checked for consistency
|
||||
and for not exceeding the maximum response length.
|
||||
|
||||
If the parameter B<expected_content_type> (or B<expected_ct>, respectively)
|
||||
If the parameter I<expected_content_type> (or I<expected_ct>, respectively)
|
||||
is not NULL then the HTTP client checks that the given content type string
|
||||
is included in the HTTP header of the response and returns an error if not.
|
||||
|
||||
If the B<timeout> parameter is > 0 this indicates the maximum number of seconds
|
||||
If the I<timeout> parameter is > 0 this indicates the maximum number of seconds
|
||||
to wait until the transfer is complete.
|
||||
A value of 0 enables waiting indefinitely,
|
||||
while a value < 0 immediately leads to a timeout condition.
|
||||
|
||||
The optional parameter B<bio_update_fn> with its optional argument B<arg> may
|
||||
The optional parameter I<bio_update_fn> with its optional argument I<arg> may
|
||||
be used to modify the connection BIO used by the HTTP client (and cannot be
|
||||
used when both B<bio> and B<rbio> are given).
|
||||
B<bio_update_fn> is a BIO connect/disconnect callback function with prototype
|
||||
used when both I<bio> and I<rbio> are given).
|
||||
I<bio_update_fn> is a BIO connect/disconnect callback function with prototype
|
||||
|
||||
BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg, int connect, int detail)
|
||||
|
||||
The callback may modify the HTTP BIO provided in the B<bio> argument,
|
||||
whereby it may make use of a custom defined argument B<arg>,
|
||||
The callback may modify the HTTP BIO provided in the I<bio> argument,
|
||||
whereby it may make use of a custom defined argument I<arg>,
|
||||
which may for instance refer to an I<SSL_CTX> structure.
|
||||
During connection establishment, just after calling BIO_do_connect_retry(),
|
||||
the function is invoked with the B<connect> argument being 1 and the B<detail>
|
||||
the function is invoked with the I<connect> argument being 1 and the I<detail>
|
||||
argument being 1 if HTTPS is requested, i.e., SSL/TLS should be enabled.
|
||||
On disconnect B<connect> is 0 and B<detail> is 1 if no error occurred, else 0.
|
||||
On disconnect I<connect> is 0 and I<detail> is 1 if no error occurred, else 0.
|
||||
For instance, on connect the function may prepend a TLS BIO to implement HTTPS;
|
||||
after disconnect it may do some diagnostic output and/or specific cleanup.
|
||||
The function should return NULL to indicate failure.
|
||||
@ -180,31 +180,39 @@ After disconnect the modified BIO will be deallocated using BIO_free_all().
|
||||
|
||||
OSSL_HTTP_proxy_connect() may be used by an above BIO connect callback function
|
||||
to set up an SSL/TLS connection via an HTTPS proxy.
|
||||
It promotes the given BIO B<bio> representing a connection
|
||||
It promotes the given BIO I<bio> representing a connection
|
||||
pre-established with a TLS proxy using the HTTP CONNECT method,
|
||||
optionally using proxy client credentials B<proxyuser> and B<proxypass>,
|
||||
to connect with TLS protection ultimately to B<server> and B<port>.
|
||||
If the B<port> argument is NULL or the empty string it defaults to "443".
|
||||
The B<timeout> parameter is used as described above.
|
||||
optionally using proxy client credentials I<proxyuser> and I<proxypass>,
|
||||
to connect with TLS protection ultimately to I<server> and I<port>.
|
||||
If the I<port> argument is NULL or the empty string it defaults to "443".
|
||||
The I<timeout> parameter is used as described above.
|
||||
Since this function is typically called by applications such as
|
||||
L<openssl-s_client(1)> it uses the B<bio_err> and B<prog> parameters (unless
|
||||
L<openssl-s_client(1)> it uses the I<bio_err> and I<prog> parameters (unless
|
||||
NULL) to print additional diagnostic information in a user-oriented way.
|
||||
|
||||
OSSL_HTTP_parse_url() parses its input string B<url> as a URL and splits it up
|
||||
into host, port and path components and a flag whether it begins with 'https'.
|
||||
The host component may be a DNS name or an IPv4 or an IPv6 address.
|
||||
OSSL_HTTP_parse_url() parses its input string I<url> as a URL
|
||||
of the form C<[http[s]://]address[:port][/path]> and splits it up into host,
|
||||
port, and path components and a flag indicating whether it begins with 'https'.
|
||||
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".
|
||||
If the I<pport_num> argument is NULL the port specification
|
||||
can be in mnemonic form such as "http" like with L<BIO_set_conn_port(3)>, else
|
||||
it must be in numerical form and its integer value is assigned to B<*pport_num>.
|
||||
The path component is also optional and defaults to "/".
|
||||
As far as the result pointer arguments are not NULL it assigns via
|
||||
them copies of the respective string components.
|
||||
The strings returned this way must be deallocated by the caller using
|
||||
L<OPENSSL_free(3)> unless they are NULL, which is their default value on error.
|
||||
On success the function assigns via each non-NULL result pointer argument
|
||||
I<phost>, I<pport>, I<pport_num>, I<ppath>, and I<pssl>
|
||||
the respective url component.
|
||||
On error, B<*phost>, B<*pport>, and B<*ppath> are assigned to NULL,
|
||||
else they are guaranteed to contain non-NULL string pointers.
|
||||
It is the reponsibility of the caller to free them using L<OPENSSL_free(3)>.
|
||||
A string returned via B<*ppath> is guaranteed to begin with a C</> character.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
The names of the environment variables used by this implementation:
|
||||
B<http_proxy>, B<HTTP_PROXY>, B<https_proxy>, B<HTTPS_PROXY>, B<no_proxy>, and
|
||||
B<NO_PROXY>, have been chosen for maximal compatibility with
|
||||
C<http_proxy>, C<HTTP_PROXY>, C<https_proxy>, C<HTTPS_PROXY>, C<no_proxy>, and
|
||||
C<NO_PROXY>, have been chosen for maximal compatibility with
|
||||
other HTTP client implementations such as wget, curl, and git.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
@ -216,6 +224,10 @@ Error conditions include connection/transfer timeout, parse errors, etc.
|
||||
OSSL_HTTP_proxy_connect() and OSSL_HTTP_parse_url()
|
||||
return 1 on success, 0 on error.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<BIO_set_conn_port(3)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
OSSL_HTTP_get(), OSSL_HTTP_get_asn1(), OSSL_HTTP_post_asn1(),
|
||||
|
@ -74,7 +74,7 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
|
||||
int timeout, BIO *bio_err, const char *prog);
|
||||
|
||||
int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport,
|
||||
char **ppath, int *pssl);
|
||||
int *pport_num, char **ppath, int *pssl);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#ifndef OPENSSL_HTTPERR_H
|
||||
# define OPENSSL_HTTPERR_H
|
||||
# pragma once
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
# include <openssl/symhacks.h>
|
||||
@ -37,6 +38,9 @@ int ERR_load_HTTP_strings(void);
|
||||
# define HTTP_R_ERROR_RECEIVING 103
|
||||
# define HTTP_R_ERROR_SENDING 102
|
||||
# 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_MAX_RESP_LEN_EXCEEDED 117
|
||||
# define HTTP_R_MISSING_ASN1_ENCODING 110
|
||||
# define HTTP_R_MISSING_CONTENT_TYPE 121
|
||||
|
@ -151,6 +151,72 @@ static int test_http_x509(int do_get)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int test_http_url_ok(const char *url, const char *exp_host, int exp_ssl)
|
||||
{
|
||||
char *host, *port, *path;
|
||||
int num, ssl;
|
||||
int res;
|
||||
|
||||
res = TEST_true(OSSL_HTTP_parse_url(url, &host, &port, &num, &path, &ssl))
|
||||
&& TEST_str_eq(host, exp_host)
|
||||
&& TEST_str_eq(port, "65535")
|
||||
&& TEST_int_eq(num, 65535)
|
||||
&& TEST_str_eq(path, "/pkix")
|
||||
&& TEST_int_eq(ssl, exp_ssl);
|
||||
OPENSSL_free(host);
|
||||
OPENSSL_free(port);
|
||||
OPENSSL_free(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int test_http_url_dns(void)
|
||||
{
|
||||
return test_http_url_ok("server:65535/pkix", "server", 0);
|
||||
}
|
||||
|
||||
static int test_http_url_ipv4(void)
|
||||
{
|
||||
return test_http_url_ok("https://1.2.3.4:65535/pkix", "1.2.3.4", 1);
|
||||
}
|
||||
|
||||
static int test_http_url_ipv6(void)
|
||||
{
|
||||
return test_http_url_ok("http://[FF01::101]:65535/pkix", "FF01::101", 0);
|
||||
}
|
||||
|
||||
static int test_http_url_invalid(const char *url)
|
||||
{
|
||||
char *host = "1", *port = "1", *path = "1";
|
||||
int num = 1, ssl = 1;
|
||||
int res;
|
||||
|
||||
res = TEST_false(OSSL_HTTP_parse_url(url, &host, &port, &num, &path, &ssl))
|
||||
&& TEST_ptr_null(host)
|
||||
&& TEST_ptr_null(port)
|
||||
&& TEST_ptr_null(path);
|
||||
if (!res) {
|
||||
OPENSSL_free(host);
|
||||
OPENSSL_free(port);
|
||||
OPENSSL_free(path);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int test_http_url_invalid_prefix(void)
|
||||
{
|
||||
return test_http_url_invalid("htttps://1.2.3.4:65535/pkix");
|
||||
}
|
||||
|
||||
static int test_http_url_invalid_port(void)
|
||||
{
|
||||
return test_http_url_invalid("https://1.2.3.4:65536/pkix");
|
||||
}
|
||||
|
||||
static int test_http_url_invalid_path(void)
|
||||
{
|
||||
return test_http_url_invalid("https://[FF01::101]pkix");
|
||||
}
|
||||
|
||||
static int test_http_get_x509(void)
|
||||
{
|
||||
return test_http_x509(1);
|
||||
@ -177,6 +243,12 @@ int setup_tests(void)
|
||||
if (!TEST_ptr((x509 = load_pem_cert(test_get_argument(0)))))
|
||||
return 1;
|
||||
|
||||
ADD_TEST(test_http_url_dns);
|
||||
ADD_TEST(test_http_url_ipv4);
|
||||
ADD_TEST(test_http_url_ipv6);
|
||||
ADD_TEST(test_http_url_invalid_prefix);
|
||||
ADD_TEST(test_http_url_invalid_port);
|
||||
ADD_TEST(test_http_url_invalid_path);
|
||||
ADD_TEST(test_http_get_x509);
|
||||
ADD_TEST(test_http_post_x509);
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user