mirror of
https://github.com/openssl/openssl.git
synced 2025-01-18 13:44:20 +08:00
Generalize the HTTP client so far implemented mostly in crypto/ocsp/ocsp_ht.c
The new client has become an independent libcrpyto module in crypto/http/ and * can handle any types of requests and responses (ASN.1-encoded and plain) * does not include potentially busy loops when waiting for responses but * makes use of a new timeout mechanism integrated with socket-based BIO * supports the use of HTTP proxies and TLS, including HTTPS over proxies * supports HTTP redirection via codes 301 and 302 for GET requests * returns more useful diagnostics in various error situations Also adapts - and strongly simplifies - hitherto uses of HTTP in crypto/ocsp/, crypto/x509/x_all.c, apps/lib/apps.c, and apps/{ocsp,s_client,s_server}.c Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com> (Merged from https://github.com/openssl/openssl/pull/10667)
This commit is contained in:
parent
bcbb30afe2
commit
29f178bddf
@ -28,12 +28,14 @@
|
||||
# include <openssl/txt_db.h>
|
||||
# include <openssl/engine.h>
|
||||
# include <openssl/ocsp.h>
|
||||
# include <openssl/http.h>
|
||||
# include <signal.h>
|
||||
# include "apps_ui.h"
|
||||
# include "opt.h"
|
||||
# include "fmt.h"
|
||||
# include "platform.h"
|
||||
|
||||
/* also in include/internal/sockets.h */
|
||||
# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE)
|
||||
# define openssl_fdset(a,b) FD_SET((unsigned int)a, b)
|
||||
# else
|
||||
@ -215,6 +217,30 @@ void print_cert_checks(BIO *bio, X509 *x,
|
||||
|
||||
void store_setup_crl_download(X509_STORE *st);
|
||||
|
||||
typedef struct app_http_tls_info_st {
|
||||
const char *server;
|
||||
const char *port;
|
||||
int use_proxy;
|
||||
long timeout;
|
||||
SSL_CTX *ssl_ctx;
|
||||
} APP_HTTP_TLS_INFO;
|
||||
BIO *app_http_tls_cb(BIO *hbio, /* APP_HTTP_TLS_INFO */ void *arg,
|
||||
int connect, int detail);
|
||||
# ifndef OPENSSL_NO_SOCK
|
||||
ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
|
||||
const char *proxy_port, SSL_CTX *ssl_ctx,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
long timeout, const char *expected_content_type,
|
||||
const ASN1_ITEM *it);
|
||||
ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
|
||||
const char *path, const char *proxy,
|
||||
const char *proxy_port, SSL_CTX *ctx,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
const char *content_type,
|
||||
ASN1_VALUE *req, const ASN1_ITEM *req_it,
|
||||
long timeout, const ASN1_ITEM *rsp_it);
|
||||
# endif
|
||||
|
||||
# define EXT_COPY_NONE 0
|
||||
# define EXT_COPY_ADD 1
|
||||
# define EXT_COPY_ALL 2
|
||||
|
187
apps/lib/apps.c
187
apps/lib/apps.c
@ -441,62 +441,14 @@ static int load_pkcs12(BIO *in, const char *desc,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
|
||||
static int load_cert_crl_http(const char *url, X509 **pcert, X509_CRL **pcrl)
|
||||
{
|
||||
char *host = NULL, *port = NULL, *path = NULL;
|
||||
BIO *bio = NULL;
|
||||
OCSP_REQ_CTX *rctx = NULL;
|
||||
int use_ssl, rv = 0;
|
||||
if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl))
|
||||
goto err;
|
||||
if (use_ssl) {
|
||||
BIO_puts(bio_err, "https not supported\n");
|
||||
goto err;
|
||||
}
|
||||
bio = BIO_new_connect(host);
|
||||
if (!bio || !BIO_set_conn_port(bio, port))
|
||||
goto err;
|
||||
rctx = OCSP_REQ_CTX_new(bio, 1024);
|
||||
if (rctx == NULL)
|
||||
goto err;
|
||||
if (!OCSP_REQ_CTX_http(rctx, "GET", path))
|
||||
goto err;
|
||||
if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host))
|
||||
goto err;
|
||||
if (pcert) {
|
||||
do {
|
||||
rv = X509_http_nbio(rctx, pcert);
|
||||
} while (rv == -1);
|
||||
} else {
|
||||
do {
|
||||
rv = X509_CRL_http_nbio(rctx, pcrl);
|
||||
} while (rv == -1);
|
||||
}
|
||||
|
||||
err:
|
||||
OPENSSL_free(host);
|
||||
OPENSSL_free(path);
|
||||
OPENSSL_free(port);
|
||||
BIO_free_all(bio);
|
||||
OCSP_REQ_CTX_free(rctx);
|
||||
if (rv != 1) {
|
||||
BIO_printf(bio_err, "Error loading %s from %s\n",
|
||||
pcert ? "certificate" : "CRL", url);
|
||||
ERR_print_errors(bio_err);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
X509 *load_cert(const char *file, int format, const char *cert_descrip)
|
||||
{
|
||||
X509 *x = NULL;
|
||||
BIO *cert;
|
||||
|
||||
if (format == FORMAT_HTTP) {
|
||||
#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
|
||||
load_cert_crl_http(file, &x, NULL);
|
||||
#if !defined(OPENSSL_NO_SOCK)
|
||||
x = X509_load_http(file, NULL, NULL, 0 /* timeout */);
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
@ -537,8 +489,8 @@ X509_CRL *load_crl(const char *infile, int format)
|
||||
BIO *in = NULL;
|
||||
|
||||
if (format == FORMAT_HTTP) {
|
||||
#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
|
||||
load_cert_crl_http(infile, NULL, &x);
|
||||
#if !defined(OPENSSL_NO_SOCK)
|
||||
x = X509_CRL_load_http(infile, NULL, NULL, 0 /* timeout */);
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
@ -1981,6 +1933,137 @@ void store_setup_crl_download(X509_STORE *st)
|
||||
X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
static const char *tls_error_hint(void)
|
||||
{
|
||||
unsigned long err = ERR_peek_error();
|
||||
|
||||
if (ERR_GET_LIB(err) != ERR_LIB_SSL)
|
||||
err = ERR_peek_last_error();
|
||||
if (ERR_GET_LIB(err) != ERR_LIB_SSL)
|
||||
return NULL;
|
||||
|
||||
switch (ERR_GET_REASON(err)) {
|
||||
case SSL_R_WRONG_VERSION_NUMBER:
|
||||
return "The server does not support (a suitable version of) TLS";
|
||||
case SSL_R_UNKNOWN_PROTOCOL:
|
||||
return "The server does not support HTTPS";
|
||||
case SSL_R_CERTIFICATE_VERIFY_FAILED:
|
||||
return "Cannot authenticate server via its TLS certificate, likely due to mismatch with our trusted TLS certs or missing revocation status";
|
||||
case SSL_AD_REASON_OFFSET + TLS1_AD_UNKNOWN_CA:
|
||||
return "Server did not accept our TLS certificate, likely due to mismatch with server's trust anchor or missing revocation status";
|
||||
case SSL_AD_REASON_OFFSET + SSL3_AD_HANDSHAKE_FAILURE:
|
||||
return "TLS handshake failure. Possibly the server requires our TLS certificate but did not receive it";
|
||||
default: /* no error or no hint available for error */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* HTTP callback function that supports TLS connection also via HTTPS proxy */
|
||||
BIO *app_http_tls_cb(BIO *hbio, void *arg, int connect, int detail)
|
||||
{
|
||||
APP_HTTP_TLS_INFO *info = (APP_HTTP_TLS_INFO *)arg;
|
||||
SSL_CTX *ssl_ctx = info->ssl_ctx;
|
||||
SSL *ssl;
|
||||
BIO *sbio = NULL;
|
||||
|
||||
if (connect && detail) { /* connecting with TLS */
|
||||
if ((info->use_proxy
|
||||
&& !OSSL_HTTP_proxy_connect(hbio, info->server, info->port,
|
||||
NULL, NULL, /* no proxy credentials */
|
||||
info->timeout, bio_err, opt_getprog()))
|
||||
|| (sbio = BIO_new(BIO_f_ssl())) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (ssl_ctx == NULL || (ssl = SSL_new(ssl_ctx)) == NULL) {
|
||||
BIO_free(sbio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SSL_set_tlsext_host_name(ssl, info->server);
|
||||
|
||||
SSL_set_connect_state(ssl);
|
||||
BIO_set_ssl(sbio, ssl, BIO_CLOSE);
|
||||
|
||||
hbio = BIO_push(sbio, hbio);
|
||||
} else if (!connect && !detail) { /* disconnecting after error */
|
||||
const char *hint = tls_error_hint();
|
||||
if (hint != NULL)
|
||||
ERR_add_error_data(1, hint);
|
||||
/*
|
||||
* If we pop sbio and BIO_free() it this may lead to libssl double free.
|
||||
* Rely on BIO_free_all() done by OSSL_HTTP_transfer() in http_client.c
|
||||
*/
|
||||
}
|
||||
return hbio;
|
||||
}
|
||||
|
||||
ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
|
||||
const char *proxy_port, SSL_CTX *ssl_ctx,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
long timeout, const char *expected_content_type,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
APP_HTTP_TLS_INFO info;
|
||||
char *server;
|
||||
char *port;
|
||||
int use_ssl;
|
||||
ASN1_VALUE *resp = NULL;
|
||||
|
||||
if (url == NULL || it == NULL) {
|
||||
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!OSSL_HTTP_parse_url(url, &server, &port, NULL /* ppath */, &use_ssl))
|
||||
return NULL;
|
||||
if (use_ssl && ssl_ctx == NULL) {
|
||||
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
|
||||
ERR_add_error_data(1, "missing SSL_CTX");
|
||||
goto end;
|
||||
}
|
||||
|
||||
info.server = server;
|
||||
info.port = port;
|
||||
info.use_proxy = proxy != NULL;
|
||||
info.timeout = timeout;
|
||||
info.ssl_ctx = ssl_ctx;
|
||||
resp = OSSL_HTTP_get_asn1(url, proxy, proxy_port,
|
||||
NULL, NULL, app_http_tls_cb, &info,
|
||||
headers, 0 /* maxline */, 0 /* max_resp_len */,
|
||||
timeout, expected_content_type, it);
|
||||
end:
|
||||
OPENSSL_free(server);
|
||||
OPENSSL_free(port);
|
||||
return resp;
|
||||
|
||||
}
|
||||
|
||||
ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
|
||||
const char *path, const char *proxy,
|
||||
const char *proxy_port, SSL_CTX *ssl_ctx,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
const char *content_type,
|
||||
ASN1_VALUE *req, const ASN1_ITEM *req_it,
|
||||
long timeout, const ASN1_ITEM *rsp_it)
|
||||
{
|
||||
APP_HTTP_TLS_INFO info;
|
||||
|
||||
info.server = host;
|
||||
info.port = port;
|
||||
info.use_proxy = proxy != NULL;
|
||||
info.timeout = timeout;
|
||||
info.ssl_ctx = ssl_ctx;
|
||||
return OSSL_HTTP_post_asn1(host, port, path, ssl_ctx != NULL,
|
||||
proxy, proxy_port,
|
||||
NULL, NULL, app_http_tls_cb, &info,
|
||||
headers, content_type, req, req_it,
|
||||
0 /* maxline */,
|
||||
0 /* max_resp_len */, timeout, NULL, rsp_it);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Platform-specific sections
|
||||
*/
|
||||
|
123
apps/ocsp.c
123
apps/ocsp.c
@ -118,13 +118,6 @@ static int print_syslog(const char *str, size_t len, void *levPtr);
|
||||
static void socket_timeout(int signum);
|
||||
# endif
|
||||
|
||||
# ifndef OPENSSL_NO_SOCK
|
||||
static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
|
||||
const char *path,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
OCSP_REQUEST *req, int req_timeout);
|
||||
# endif
|
||||
|
||||
typedef enum OPTION_choice {
|
||||
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
|
||||
OPT_OUTFILE, OPT_TIMEOUT, OPT_URL, OPT_HOST, OPT_PORT,
|
||||
@ -315,7 +308,8 @@ int ocsp_main(int argc, char **argv)
|
||||
OPENSSL_free(tport);
|
||||
OPENSSL_free(tpath);
|
||||
thost = tport = tpath = NULL;
|
||||
if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) {
|
||||
if (!OSSL_HTTP_parse_url(opt_arg(),
|
||||
&host, &port, &path, &use_ssl)) {
|
||||
BIO_printf(bio_err, "%s Error parsing URL\n", prog);
|
||||
goto end;
|
||||
}
|
||||
@ -1541,133 +1535,34 @@ static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
|
||||
}
|
||||
|
||||
# ifndef OPENSSL_NO_SOCK
|
||||
static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
|
||||
const char *path,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
OCSP_REQUEST *req, int req_timeout)
|
||||
{
|
||||
int fd;
|
||||
int rv;
|
||||
int i;
|
||||
int add_host = 1;
|
||||
OCSP_REQ_CTX *ctx = NULL;
|
||||
OCSP_RESPONSE *rsp = NULL;
|
||||
fd_set confds;
|
||||
struct timeval tv;
|
||||
|
||||
if (req_timeout != -1)
|
||||
BIO_set_nbio(cbio, 1);
|
||||
|
||||
rv = BIO_do_connect(cbio);
|
||||
|
||||
if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) {
|
||||
BIO_puts(bio_err, "Error connecting BIO\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (BIO_get_fd(cbio, &fd) < 0) {
|
||||
BIO_puts(bio_err, "Can't get connection fd\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (req_timeout != -1 && rv <= 0) {
|
||||
FD_ZERO(&confds);
|
||||
openssl_fdset(fd, &confds);
|
||||
tv.tv_usec = 0;
|
||||
tv.tv_sec = req_timeout;
|
||||
rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
|
||||
if (rv == 0) {
|
||||
BIO_puts(bio_err, "Timeout on connect\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
|
||||
CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i);
|
||||
if (add_host == 1 && strcasecmp("host", hdr->name) == 0)
|
||||
add_host = 0;
|
||||
if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (add_host == 1 && OCSP_REQ_CTX_add1_header(ctx, "Host", host) == 0)
|
||||
goto err;
|
||||
|
||||
if (!OCSP_REQ_CTX_set1_req(ctx, req))
|
||||
goto err;
|
||||
|
||||
for (;;) {
|
||||
rv = OCSP_sendreq_nbio(&rsp, ctx);
|
||||
if (rv != -1)
|
||||
break;
|
||||
if (req_timeout == -1)
|
||||
continue;
|
||||
FD_ZERO(&confds);
|
||||
openssl_fdset(fd, &confds);
|
||||
tv.tv_usec = 0;
|
||||
tv.tv_sec = req_timeout;
|
||||
if (BIO_should_read(cbio)) {
|
||||
rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
|
||||
} else if (BIO_should_write(cbio)) {
|
||||
rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
|
||||
} else {
|
||||
BIO_puts(bio_err, "Unexpected retry condition\n");
|
||||
goto err;
|
||||
}
|
||||
if (rv == 0) {
|
||||
BIO_puts(bio_err, "Timeout on request\n");
|
||||
break;
|
||||
}
|
||||
if (rv == -1) {
|
||||
BIO_puts(bio_err, "Select error\n");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
err:
|
||||
OCSP_REQ_CTX_free(ctx);
|
||||
|
||||
return rsp;
|
||||
}
|
||||
|
||||
OCSP_RESPONSE *process_responder(OCSP_REQUEST *req,
|
||||
const char *host, const char *path,
|
||||
const char *port, int use_ssl,
|
||||
STACK_OF(CONF_VALUE) *headers,
|
||||
int req_timeout)
|
||||
{
|
||||
BIO *cbio = NULL;
|
||||
SSL_CTX *ctx = NULL;
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
|
||||
cbio = BIO_new_connect(host);
|
||||
if (cbio == NULL) {
|
||||
BIO_printf(bio_err, "Error creating connect BIO\n");
|
||||
goto end;
|
||||
}
|
||||
if (port != NULL)
|
||||
BIO_set_conn_port(cbio, port);
|
||||
if (use_ssl == 1) {
|
||||
BIO *sbio;
|
||||
ctx = SSL_CTX_new(TLS_client_method());
|
||||
if (ctx == NULL) {
|
||||
BIO_printf(bio_err, "Error creating SSL context.\n");
|
||||
goto end;
|
||||
}
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
|
||||
sbio = BIO_new_ssl(ctx, 1);
|
||||
cbio = BIO_push(sbio, cbio);
|
||||
}
|
||||
|
||||
resp = query_responder(cbio, host, path, headers, req, req_timeout);
|
||||
resp = (OCSP_RESPONSE *)
|
||||
app_http_post_asn1(host, port, path, NULL, NULL /* no proxy used */,
|
||||
ctx, headers, "application/ocsp-request",
|
||||
(ASN1_VALUE *)req, ASN1_ITEM_rptr(OCSP_REQUEST),
|
||||
req_timeout, ASN1_ITEM_rptr(OCSP_RESPONSE));
|
||||
|
||||
if (resp == NULL)
|
||||
BIO_printf(bio_err, "Error querying OCSP responder\n");
|
||||
|
||||
end:
|
||||
BIO_free_all(cbio);
|
||||
SSL_CTX_free(ctx);
|
||||
return resp;
|
||||
}
|
||||
|
130
apps/s_client.c
130
apps/s_client.c
@ -75,7 +75,6 @@ static void print_stuff(BIO *berr, SSL *con, int full);
|
||||
static int ocsp_resp_cb(SSL *s, void *arg);
|
||||
#endif
|
||||
static int ldap_ExtendedResponse_parse(const char *buf, long rem);
|
||||
static char *base64encode (const void *buf, size_t len);
|
||||
static int is_dNS_name(const char *host);
|
||||
|
||||
static int saved_errno;
|
||||
@ -949,7 +948,7 @@ int s_client_main(int argc, char **argv)
|
||||
int prexit = 0;
|
||||
int sdebug = 0;
|
||||
int reconnect = 0, verify = SSL_VERIFY_NONE, vpmtouched = 0;
|
||||
int ret = 1, in_init = 1, i, nbio_test = 0, s = -1, k, width, state = 0;
|
||||
int ret = 1, in_init = 1, i, nbio_test = 0, sock = -1, k, width, state = 0;
|
||||
int sbuf_len, sbuf_off, cmdletters = 1;
|
||||
int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0;
|
||||
int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0;
|
||||
@ -2095,16 +2094,16 @@ int s_client_main(int argc, char **argv)
|
||||
}
|
||||
|
||||
re_start:
|
||||
if (init_client(&s, host, port, bindhost, bindport, socket_family,
|
||||
if (init_client(&sock, host, port, bindhost, bindport, socket_family,
|
||||
socket_type, protocol) == 0) {
|
||||
BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error());
|
||||
BIO_closesocket(s);
|
||||
BIO_closesocket(sock);
|
||||
goto end;
|
||||
}
|
||||
BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);
|
||||
BIO_printf(bio_c_out, "CONNECTED(%08X)\n", sock);
|
||||
|
||||
if (c_nbio) {
|
||||
if (!BIO_socket_nbio(s, 1)) {
|
||||
if (!BIO_socket_nbio(sock, 1)) {
|
||||
ERR_print_errors(bio_err);
|
||||
goto end;
|
||||
}
|
||||
@ -2116,21 +2115,21 @@ int s_client_main(int argc, char **argv)
|
||||
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (protocol == IPPROTO_SCTP)
|
||||
sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE);
|
||||
sbio = BIO_new_dgram_sctp(sock, BIO_NOCLOSE);
|
||||
else
|
||||
#endif
|
||||
sbio = BIO_new_dgram(s, BIO_NOCLOSE);
|
||||
sbio = BIO_new_dgram(sock, BIO_NOCLOSE);
|
||||
|
||||
if ((peer_info.addr = BIO_ADDR_new()) == NULL) {
|
||||
BIO_printf(bio_err, "memory allocation failure\n");
|
||||
BIO_closesocket(s);
|
||||
BIO_closesocket(sock);
|
||||
goto end;
|
||||
}
|
||||
if (!BIO_sock_info(s, BIO_SOCK_INFO_ADDRESS, &peer_info)) {
|
||||
if (!BIO_sock_info(sock, BIO_SOCK_INFO_ADDRESS, &peer_info)) {
|
||||
BIO_printf(bio_err, "getsockname:errno=%d\n",
|
||||
get_last_socket_error());
|
||||
BIO_ADDR_free(peer_info.addr);
|
||||
BIO_closesocket(s);
|
||||
BIO_closesocket(sock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@ -2167,7 +2166,7 @@ int s_client_main(int argc, char **argv)
|
||||
}
|
||||
} else
|
||||
#endif /* OPENSSL_NO_DTLS */
|
||||
sbio = BIO_new_socket(s, BIO_NOCLOSE);
|
||||
sbio = BIO_new_socket(sock, BIO_NOCLOSE);
|
||||
|
||||
if (nbio_test) {
|
||||
BIO *test;
|
||||
@ -2398,83 +2397,9 @@ int s_client_main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case PROTO_CONNECT:
|
||||
{
|
||||
enum {
|
||||
error_proto, /* Wrong protocol, not even HTTP */
|
||||
error_connect, /* CONNECT failed */
|
||||
success
|
||||
} foundit = error_connect;
|
||||
BIO *fbio = BIO_new(BIO_f_buffer());
|
||||
|
||||
BIO_push(fbio, sbio);
|
||||
BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n", connectstr);
|
||||
/*
|
||||
* Workaround for broken proxies which would otherwise close
|
||||
* the connection when entering tunnel mode (eg Squid 2.6)
|
||||
*/
|
||||
BIO_printf(fbio, "Proxy-Connection: Keep-Alive\r\n");
|
||||
|
||||
/* Support for basic (base64) proxy authentication */
|
||||
if (proxyuser != NULL) {
|
||||
size_t l;
|
||||
char *proxyauth, *proxyauthenc;
|
||||
|
||||
l = strlen(proxyuser);
|
||||
if (proxypass != NULL)
|
||||
l += strlen(proxypass);
|
||||
proxyauth = app_malloc(l + 2, "Proxy auth string");
|
||||
BIO_snprintf(proxyauth, l + 2, "%s:%s", proxyuser,
|
||||
(proxypass != NULL) ? proxypass : "");
|
||||
proxyauthenc = base64encode(proxyauth, strlen(proxyauth));
|
||||
BIO_printf(fbio, "Proxy-Authorization: Basic %s\r\n",
|
||||
proxyauthenc);
|
||||
OPENSSL_clear_free(proxyauth, strlen(proxyauth));
|
||||
OPENSSL_clear_free(proxyauthenc, strlen(proxyauthenc));
|
||||
}
|
||||
|
||||
/* Terminate the HTTP CONNECT request */
|
||||
BIO_printf(fbio, "\r\n");
|
||||
(void)BIO_flush(fbio);
|
||||
/*
|
||||
* The first line is the HTTP response. According to RFC 7230,
|
||||
* it's formatted exactly like this:
|
||||
*
|
||||
* HTTP/d.d ddd Reason text\r\n
|
||||
*/
|
||||
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
|
||||
if (mbuf_len < (int)strlen("HTTP/1.0 200")) {
|
||||
BIO_printf(bio_err,
|
||||
"%s: HTTP CONNECT failed, insufficient response "
|
||||
"from proxy (got %d octets)\n", prog, mbuf_len);
|
||||
(void)BIO_flush(fbio);
|
||||
BIO_pop(fbio);
|
||||
BIO_free(fbio);
|
||||
goto shut;
|
||||
}
|
||||
if (mbuf[8] != ' ') {
|
||||
BIO_printf(bio_err,
|
||||
"%s: HTTP CONNECT failed, incorrect response "
|
||||
"from proxy\n", prog);
|
||||
foundit = error_proto;
|
||||
} else if (mbuf[9] != '2') {
|
||||
BIO_printf(bio_err, "%s: HTTP CONNECT failed: %s ", prog,
|
||||
&mbuf[9]);
|
||||
} else {
|
||||
foundit = success;
|
||||
}
|
||||
if (foundit != error_proto) {
|
||||
/* Read past all following headers */
|
||||
do {
|
||||
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
|
||||
} while (mbuf_len > 2);
|
||||
}
|
||||
(void)BIO_flush(fbio);
|
||||
BIO_pop(fbio);
|
||||
BIO_free(fbio);
|
||||
if (foundit != success) {
|
||||
goto shut;
|
||||
}
|
||||
}
|
||||
if (!OSSL_HTTP_proxy_connect(sbio, host, port, proxyuser, proxypass,
|
||||
0 /* no timeout */, bio_err, prog))
|
||||
goto shut;
|
||||
break;
|
||||
case PROTO_IRC:
|
||||
{
|
||||
@ -3192,8 +3117,8 @@ int s_client_main(int argc, char **argv)
|
||||
timeout.tv_usec = 500000; /* some extreme round-trip */
|
||||
do {
|
||||
FD_ZERO(&readfds);
|
||||
openssl_fdset(s, &readfds);
|
||||
} while (select(s + 1, &readfds, NULL, NULL, &timeout) > 0
|
||||
openssl_fdset(sock, &readfds);
|
||||
} while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0
|
||||
&& BIO_read(sbio, sbuf, BUFSIZZ) > 0);
|
||||
|
||||
BIO_closesocket(SSL_get_fd(con));
|
||||
@ -3570,29 +3495,6 @@ static int ldap_ExtendedResponse_parse(const char *buf, long rem)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* BASE64 encoder: used only for encoding basic proxy authentication credentials
|
||||
*/
|
||||
static char *base64encode (const void *buf, size_t len)
|
||||
{
|
||||
int i;
|
||||
size_t outl;
|
||||
char *out;
|
||||
|
||||
/* Calculate size of encoded data */
|
||||
outl = (len / 3);
|
||||
if (len % 3 > 0)
|
||||
outl++;
|
||||
outl <<= 2;
|
||||
out = app_malloc(outl + 1, "base64 encode buffer");
|
||||
|
||||
i = EVP_EncodeBlock((unsigned char *)out, buf, len);
|
||||
assert(i <= (int)outl);
|
||||
if (i < 0)
|
||||
*out = '\0';
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Host dNS Name verifier: used for checking that the hostname is in dNS format
|
||||
* before setting it as SNI
|
||||
|
@ -526,8 +526,8 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
|
||||
x = SSL_get_certificate(s);
|
||||
aia = X509_get1_ocsp(x);
|
||||
if (aia != NULL) {
|
||||
if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
|
||||
&host, &port, &path, &use_ssl)) {
|
||||
if (!OSSL_HTTP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
|
||||
&host, &port, &path, &use_ssl)) {
|
||||
BIO_puts(bio_err, "cert_status: can't parse AIA URL\n");
|
||||
goto err;
|
||||
}
|
||||
@ -1387,10 +1387,9 @@ int s_server_main(int argc, char *argv[])
|
||||
case OPT_STATUS_URL:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
s_tlsextstatus = 1;
|
||||
if (!OCSP_parse_url(opt_arg(),
|
||||
&tlscstatp.host,
|
||||
&tlscstatp.port,
|
||||
&tlscstatp.path, &tlscstatp.use_ssl)) {
|
||||
if (!OSSL_HTTP_parse_url(opt_arg(),
|
||||
&tlscstatp.host, &tlscstatp.port,
|
||||
&tlscstatp.path, &tlscstatp.use_ssl)) {
|
||||
BIO_printf(bio_err, "Error parsing URL\n");
|
||||
goto end;
|
||||
}
|
||||
@ -3545,7 +3544,7 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
|
||||
{
|
||||
unsigned int count = 0;
|
||||
unsigned int session_id_prefix_len = strlen(session_id_prefix);
|
||||
|
||||
|
||||
do {
|
||||
if (RAND_bytes(id, *id_len) <= 0)
|
||||
return 0;
|
||||
|
@ -5,7 +5,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 conf \
|
||||
md2 md4 md5 sha mdc2 hmac ripemd whrlpool poly1305 \
|
||||
siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \
|
||||
seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \
|
||||
err comp ocsp cms ts srp cmac ct async ess crmf cmp serializer \
|
||||
err comp http ocsp cms ts srp cmac ct async ess crmf cmp serializer \
|
||||
ffc
|
||||
|
||||
LIBS=../libcrypto
|
||||
|
@ -819,7 +819,7 @@ int OSSL_CMP_CTX_set_proxyPort(OSSL_CMP_CTX *ctx, int port)
|
||||
* sets the http connect/disconnect callback function to be used for HTTP(S)
|
||||
* returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_http_cb_t cb)
|
||||
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
|
@ -67,6 +67,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NULL_ARGUMENT), "null argument"},
|
||||
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKISTATUSINFO_NOT_FOUND),
|
||||
"pkistatusinfo not found"},
|
||||
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE),
|
||||
"potentially invalid certificate"},
|
||||
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
|
||||
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
|
||||
"unknown algorithm id"},
|
||||
|
@ -44,7 +44,7 @@ struct ossl_cmp_ctx_st {
|
||||
int totaltimeout; /* maximum number seconds an enrollment may take, incl. */
|
||||
/* attempts polling for a response if a 'waiting' PKIStatus is received */
|
||||
time_t end_time; /* session start time + totaltimeout */
|
||||
OSSL_cmp_http_cb_t http_cb;
|
||||
OSSL_HTTP_bio_cb_t http_cb;
|
||||
void *http_cb_arg; /* allows to store optional argument to cb */
|
||||
|
||||
/* server authentication */
|
||||
|
@ -76,6 +76,7 @@ static ERR_STRING_DATA ERR_str_libraries[] = {
|
||||
{ERR_PACK(ERR_LIB_ESS, 0, 0), "ESS routines"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, 0), "Provider routines"},
|
||||
{ERR_PACK(ERR_LIB_OSSL_SERIALIZER, 0, 0), "SERIALIZER routines"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, 0), "HTTP routines"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "internal/dso.h"
|
||||
#include <openssl/engineerr.h>
|
||||
#include <openssl/uierr.h>
|
||||
#include <openssl/httperr.h>
|
||||
#include <openssl/ocsperr.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/tserr.h>
|
||||
@ -85,6 +86,7 @@ int err_load_crypto_strings_int(void)
|
||||
# ifndef OPENSSL_NO_ENGINE
|
||||
ERR_load_ENGINE_strings() == 0 ||
|
||||
# endif
|
||||
ERR_load_HTTP_strings() == 0 ||
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
ERR_load_OCSP_strings() == 0 ||
|
||||
# endif
|
||||
|
@ -41,6 +41,7 @@ L ESS include/openssl/ess.h crypto/ess/ess_err.c
|
||||
L PROP include/internal/property.h crypto/property/property_err.c
|
||||
L PROV providers/common/include/prov/providercommon.h providers/common/provider_err.c
|
||||
L OSSL_SERIALIZER include/openssl/serializer.h crypto/serializer/serializer_err.c
|
||||
L HTTP include/openssl/http.h crypto/http/http_err.c
|
||||
|
||||
# additional header files to be scanned for function names
|
||||
L NONE include/openssl/x509_vfy.h NONE
|
||||
|
@ -940,11 +940,9 @@ OCSP_F_OCSP_CHECK_IDS:107:ocsp_check_ids
|
||||
OCSP_F_OCSP_CHECK_ISSUER:108:ocsp_check_issuer
|
||||
OCSP_F_OCSP_CHECK_VALIDITY:115:OCSP_check_validity
|
||||
OCSP_F_OCSP_MATCH_ISSUERID:109:ocsp_match_issuerid
|
||||
OCSP_F_OCSP_PARSE_URL:114:OCSP_parse_url
|
||||
OCSP_F_OCSP_REQUEST_SIGN:110:OCSP_request_sign
|
||||
OCSP_F_OCSP_REQUEST_VERIFY:116:OCSP_request_verify
|
||||
OCSP_F_OCSP_RESPONSE_GET1_BASIC:111:OCSP_response_get1_basic
|
||||
OCSP_F_PARSE_HTTP_LINE1:118:parse_http_line1
|
||||
OSSL_STORE_F_FILE_CTRL:129:file_ctrl
|
||||
OSSL_STORE_F_FILE_FIND:138:file_find
|
||||
OSSL_STORE_F_FILE_GET_PASS:118:file_get_pass
|
||||
@ -2100,6 +2098,7 @@ CMP_R_MULTIPLE_SAN_SOURCES:102:multiple san sources
|
||||
CMP_R_NO_STDIO:194:no stdio
|
||||
CMP_R_NULL_ARGUMENT:103:null argument
|
||||
CMP_R_PKISTATUSINFO_NOT_FOUND:132:pkistatusinfo not found
|
||||
CMP_R_POTENTIALLY_INVALID_CERTIFICATE:139:potentially invalid certificate
|
||||
CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
|
||||
CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id
|
||||
CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type
|
||||
@ -2527,6 +2526,28 @@ EVP_R_WRAP_MODE_NOT_ALLOWED:170:wrap mode not allowed
|
||||
EVP_R_WRONG_FINAL_BLOCK_LENGTH:109:wrong final block length
|
||||
EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE:191:xts data unit is too large
|
||||
EVP_R_XTS_DUPLICATED_KEYS:192:xts duplicated keys
|
||||
HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN:108:asn1 len exceeds max resp len
|
||||
HTTP_R_CONNECT_FAILURE:100:connect failure
|
||||
HTTP_R_ERROR_PARSING_ASN1_LENGTH:109:error parsing asn1 length
|
||||
HTTP_R_ERROR_PARSING_CONTENT_LENGTH:119:error parsing content length
|
||||
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_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
|
||||
HTTP_R_MISSING_REDIRECT_LOCATION:111:missing redirect location
|
||||
HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP:112:redirection from https to http
|
||||
HTTP_R_REDIRECTION_NOT_ENABLED:116:redirection not enabled
|
||||
HTTP_R_RESPONSE_LINE_TOO_LONG:113:response line too long
|
||||
HTTP_R_SERVER_RESPONSE_PARSE_ERROR:104:server response parse error
|
||||
HTTP_R_SERVER_SENT_ERROR:105:server sent error
|
||||
HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION:106:server sent wrong http version
|
||||
HTTP_R_STATUS_CODE_UNSUPPORTED:114:status code unsupported
|
||||
HTTP_R_TLS_NOT_ENABLED:107:tls not enabled
|
||||
HTTP_R_TOO_MANY_REDIRECTIONS:115:too many redirections
|
||||
HTTP_R_UNEXPECTED_CONTENT_TYPE:118:unexpected content type
|
||||
KDF_R_BAD_ENCODING:122:bad encoding
|
||||
KDF_R_BAD_LENGTH:123:bad length
|
||||
KDF_R_BOTH_MODE_AND_MODE_INT:127:both mode and mode int
|
||||
@ -2561,7 +2582,6 @@ OCSP_R_CERTIFICATE_VERIFY_ERROR:101:certificate verify error
|
||||
OCSP_R_DIGEST_ERR:102:digest err
|
||||
OCSP_R_ERROR_IN_NEXTUPDATE_FIELD:122:error in nextupdate field
|
||||
OCSP_R_ERROR_IN_THISUPDATE_FIELD:123:error in thisupdate field
|
||||
OCSP_R_ERROR_PARSING_URL:121:error parsing url
|
||||
OCSP_R_MISSING_OCSPSIGNING_USAGE:103:missing ocspsigning usage
|
||||
OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE:124:nextupdate before thisupdate
|
||||
OCSP_R_NOT_BASIC_RESPONSE:104:not basic response
|
||||
@ -2575,8 +2595,6 @@ OCSP_R_REQUEST_NOT_SIGNED:128:request not signed
|
||||
OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA:111:\
|
||||
response contains no revocation data
|
||||
OCSP_R_ROOT_CA_NOT_TRUSTED:112:root ca not trusted
|
||||
OCSP_R_SERVER_RESPONSE_ERROR:114:server response error
|
||||
OCSP_R_SERVER_RESPONSE_PARSE_ERROR:115:server response parse error
|
||||
OCSP_R_SIGNATURE_FAILURE:117:signature failure
|
||||
OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND:118:signer certificate not found
|
||||
OCSP_R_STATUS_EXPIRED:125:status expired
|
||||
|
2
crypto/http/build.info
Normal file
2
crypto/http/build.info
Normal file
@ -0,0 +1,2 @@
|
||||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]=http_client.c http_err.c http_lib.c
|
1238
crypto/http/http_client.c
Normal file
1238
crypto/http/http_client.c
Normal file
File diff suppressed because it is too large
Load Diff
67
crypto/http/http_err.c
Normal file
67
crypto/http/http_err.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/httperr.h>
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static const ERR_STRING_DATA HTTP_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN),
|
||||
"asn1 len exceeds max resp len"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_CONNECT_FAILURE), "connect failure"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_PARSING_ASN1_LENGTH),
|
||||
"error parsing asn1 length"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_PARSING_CONTENT_LENGTH),
|
||||
"error parsing content length"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_PARSING_URL), "error parsing url"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_RECEIVING), "error receiving"},
|
||||
{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_MAX_RESP_LEN_EXCEEDED),
|
||||
"max resp len exceeded"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MISSING_ASN1_ENCODING),
|
||||
"missing asn1 encoding"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MISSING_CONTENT_TYPE),
|
||||
"missing content type"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MISSING_REDIRECT_LOCATION),
|
||||
"missing redirect location"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP),
|
||||
"redirection from https to http"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_REDIRECTION_NOT_ENABLED),
|
||||
"redirection not enabled"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_LINE_TOO_LONG),
|
||||
"response line too long"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR),
|
||||
"server response parse error"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_SENT_ERROR), "server sent error"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION),
|
||||
"server sent wrong http version"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_STATUS_CODE_UNSUPPORTED),
|
||||
"status code unsupported"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_TLS_NOT_ENABLED), "tls not enabled"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_TOO_MANY_REDIRECTIONS),
|
||||
"too many redirections"},
|
||||
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_UNEXPECTED_CONTENT_TYPE),
|
||||
"unexpected content type"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
int ERR_load_HTTP_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_reason_error_string(HTTP_str_reasons[0].error) == NULL)
|
||||
ERR_load_strings_const(HTTP_str_reasons);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
116
crypto/http/http_lib.c
Normal file
116
crypto/http/http_lib.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/http.h>
|
||||
#include <openssl/httperr.h>
|
||||
#include <openssl/err.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Parse a URL and split it up into host, port and path components and
|
||||
* whether it indicates SSL/TLS. Return 1 on success, 0 on error.
|
||||
*/
|
||||
|
||||
int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport,
|
||||
char **ppath, int *pssl)
|
||||
{
|
||||
char *p, *buf;
|
||||
char *host;
|
||||
char *port = "80";
|
||||
|
||||
if (url == NULL) {
|
||||
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (phost != NULL)
|
||||
*phost = NULL;
|
||||
if (pport != NULL)
|
||||
*pport = NULL;
|
||||
if (ppath != NULL)
|
||||
*ppath = NULL;
|
||||
if (pssl != NULL)
|
||||
*pssl = 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 || p - buf > 5 /* strlen("https") */) {
|
||||
p = buf;
|
||||
} else {
|
||||
*(p++) = '\0';
|
||||
|
||||
if (strcmp(buf, "https") == 0) {
|
||||
if (pssl != NULL)
|
||||
*pssl = 1;
|
||||
port = "443";
|
||||
} else if (strcmp(buf, "http") != 0) {
|
||||
goto parse_err;
|
||||
}
|
||||
|
||||
/* Check for double slash */
|
||||
if ((p[0] != '/') || (p[1] != '/'))
|
||||
goto parse_err;
|
||||
p += 2;
|
||||
}
|
||||
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;
|
||||
if (host[0] == '[') {
|
||||
/* ipv6 literal */
|
||||
host++;
|
||||
p = strchr(host, ']');
|
||||
if (p == NULL)
|
||||
goto parse_err;
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
/* Look for optional ':' for port number */
|
||||
if ((p = strchr(p, ':'))) {
|
||||
*p = '\0';
|
||||
port = p + 1;
|
||||
}
|
||||
if (phost != NULL && (*phost = OPENSSL_strdup(host)) == NULL)
|
||||
goto err;
|
||||
if (pport != NULL && (*pport = OPENSSL_strdup(port)) == NULL)
|
||||
goto err;
|
||||
|
||||
OPENSSL_free(buf);
|
||||
return 1;
|
||||
|
||||
parse_err:
|
||||
HTTPerr(0, HTTP_R_ERROR_PARSING_URL);
|
||||
|
||||
err:
|
||||
if (ppath != NULL) {
|
||||
OPENSSL_free(*ppath);
|
||||
*ppath = NULL;
|
||||
}
|
||||
if (pport != NULL) {
|
||||
OPENSSL_free(*pport);
|
||||
*pport = NULL;
|
||||
}
|
||||
if (phost != NULL) {
|
||||
OPENSSL_free(*phost);
|
||||
*phost = NULL;
|
||||
}
|
||||
OPENSSL_free(buf);
|
||||
return 0;
|
||||
}
|
51
crypto/http/http_local.h
Normal file
51
crypto/http/http_local.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright Siemens AG 2018-2020
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OSSL_CRYPTO_HTTP_LOCAL_H
|
||||
# define OSSL_CRYPTO_HTTP_LOCAL_H
|
||||
|
||||
# include <openssl/ocsp.h>
|
||||
|
||||
/* name aliases for legacy names with name prefix "OCSP_" */
|
||||
typedef OCSP_REQ_CTX OSSL_HTTP_REQ_CTX;
|
||||
/* functions meanwhile only used internally */
|
||||
# define OSSL_HTTP_REQ_CTX_new OCSP_REQ_CTX_new
|
||||
# define OSSL_HTTP_REQ_CTX_free OCSP_REQ_CTX_free
|
||||
# define OSSL_HTTP_REQ_CTX_header OCSP_REQ_CTX_http
|
||||
# define OSSL_HTTP_REQ_CTX_add1_header OCSP_REQ_CTX_add1_header
|
||||
# define OSSL_HTTP_REQ_CTX_i2d OCSP_REQ_CTX_i2d
|
||||
# define OSSL_HTTP_REQ_CTX_nbio OCSP_REQ_CTX_nbio
|
||||
# ifndef OPENSSL_NO_SOCK
|
||||
# define OSSL_HTTP_REQ_CTX_sendreq_d2i OCSP_REQ_CTX_nbio_d2i
|
||||
# endif
|
||||
/* functions that are meanwhile unused */
|
||||
# define OSSL_HTTP_REQ_CTX_get0_mem_bio OCSP_REQ_CTX_get0_mem_bio /* undoc'd */
|
||||
# define OSSL_HTTP_REQ_CTX_set_max_response_length OCSP_set_max_response_length
|
||||
|
||||
BIO *HTTP_asn1_item2bio(const ASN1_ITEM *it, ASN1_VALUE *val);
|
||||
OSSL_HTTP_REQ_CTX *HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int use_http_proxy,
|
||||
const char *server, const char *port,
|
||||
const char *path,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
const char *content_type, BIO *req_mem,
|
||||
int maxline, unsigned long max_resp_len,
|
||||
int timeout,
|
||||
const char *expected_content_type,
|
||||
int expect_asn1);
|
||||
ASN1_VALUE *HTTP_sendreq_bio(BIO *bio, OSSL_HTTP_bio_cb_t bio_update_fn,
|
||||
void *arg, const char *server, const char *port,
|
||||
const char *path, int use_ssl, int use_proxy,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
const char *content_type,
|
||||
ASN1_VALUE *req, const ASN1_ITEM *req_it,
|
||||
int maxline, unsigned long max_resp_len,
|
||||
int timeout, const ASN1_ITEM *rsp_it);
|
||||
|
||||
#endif /* !defined OSSL_CRYPTO_HTTP_LOCAL_H */
|
@ -1,4 +1,4 @@
|
||||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]=\
|
||||
ocsp_asn.c ocsp_ext.c ocsp_ht.c ocsp_lib.c ocsp_cl.c \
|
||||
ocsp_asn.c ocsp_ext.c ocsp_http.c ocsp_lib.c ocsp_cl.c \
|
||||
ocsp_srv.c ocsp_prn.c ocsp_vfy.c ocsp_err.c v3_ocsp.c
|
||||
|
@ -21,7 +21,6 @@ static const ERR_STRING_DATA OCSP_str_reasons[] = {
|
||||
"error in nextupdate field"},
|
||||
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ERROR_IN_THISUPDATE_FIELD),
|
||||
"error in thisupdate field"},
|
||||
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ERROR_PARSING_URL), "error parsing url"},
|
||||
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_MISSING_OCSPSIGNING_USAGE),
|
||||
"missing ocspsigning usage"},
|
||||
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE),
|
||||
@ -41,10 +40,6 @@ static const ERR_STRING_DATA OCSP_str_reasons[] = {
|
||||
"response contains no revocation data"},
|
||||
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ROOT_CA_NOT_TRUSTED),
|
||||
"root ca not trusted"},
|
||||
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SERVER_RESPONSE_ERROR),
|
||||
"server response error"},
|
||||
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SERVER_RESPONSE_PARSE_ERROR),
|
||||
"server response parse error"},
|
||||
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SIGNATURE_FAILURE), "signature failure"},
|
||||
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND),
|
||||
"signer certificate not found"},
|
||||
|
@ -1,502 +0,0 @@
|
||||
/*
|
||||
* Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "e_os.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "crypto/ctype.h"
|
||||
#include <string.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/ocsp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/buffer.h>
|
||||
|
||||
/* Stateful OCSP request code, supporting non-blocking I/O */
|
||||
|
||||
/* Opaque OCSP request status structure */
|
||||
|
||||
struct ocsp_req_ctx_st {
|
||||
int state; /* Current I/O state */
|
||||
unsigned char *iobuf; /* Line buffer */
|
||||
int iobuflen; /* Line buffer length */
|
||||
BIO *io; /* BIO to perform I/O with */
|
||||
BIO *mem; /* Memory BIO response is built into */
|
||||
unsigned long asn1_len; /* ASN1 length of response */
|
||||
unsigned long max_resp_len; /* Maximum length of response */
|
||||
};
|
||||
|
||||
#define OCSP_MAX_RESP_LENGTH (100 * 1024)
|
||||
#define OCSP_MAX_LINE_LEN 4096;
|
||||
|
||||
/* OCSP states */
|
||||
|
||||
/* If set no reading should be performed */
|
||||
#define OHS_NOREAD 0x1000
|
||||
/* Error condition */
|
||||
#define OHS_ERROR (0 | OHS_NOREAD)
|
||||
/* First line being read */
|
||||
#define OHS_FIRSTLINE 1
|
||||
/* MIME headers being read */
|
||||
#define OHS_HEADERS 2
|
||||
/* OCSP initial header (tag + length) being read */
|
||||
#define OHS_ASN1_HEADER 3
|
||||
/* OCSP content octets being read */
|
||||
#define OHS_ASN1_CONTENT 4
|
||||
/* First call: ready to start I/O */
|
||||
#define OHS_ASN1_WRITE_INIT (5 | OHS_NOREAD)
|
||||
/* Request being sent */
|
||||
#define OHS_ASN1_WRITE (6 | OHS_NOREAD)
|
||||
/* Request being flushed */
|
||||
#define OHS_ASN1_FLUSH (7 | OHS_NOREAD)
|
||||
/* Completed */
|
||||
#define OHS_DONE (8 | OHS_NOREAD)
|
||||
/* Headers set, no final \r\n included */
|
||||
#define OHS_HTTP_HEADER (9 | OHS_NOREAD)
|
||||
|
||||
static int parse_http_line1(char *line);
|
||||
|
||||
OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline)
|
||||
{
|
||||
OCSP_REQ_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx));
|
||||
|
||||
if (rctx == NULL)
|
||||
return NULL;
|
||||
rctx->state = OHS_ERROR;
|
||||
rctx->max_resp_len = OCSP_MAX_RESP_LENGTH;
|
||||
rctx->mem = BIO_new(BIO_s_mem());
|
||||
rctx->io = io;
|
||||
if (maxline > 0)
|
||||
rctx->iobuflen = maxline;
|
||||
else
|
||||
rctx->iobuflen = OCSP_MAX_LINE_LEN;
|
||||
rctx->iobuf = OPENSSL_malloc(rctx->iobuflen);
|
||||
if (rctx->iobuf == NULL || rctx->mem == NULL) {
|
||||
OCSP_REQ_CTX_free(rctx);
|
||||
return NULL;
|
||||
}
|
||||
return rctx;
|
||||
}
|
||||
|
||||
void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx)
|
||||
{
|
||||
if (!rctx)
|
||||
return;
|
||||
BIO_free(rctx->mem);
|
||||
OPENSSL_free(rctx->iobuf);
|
||||
OPENSSL_free(rctx);
|
||||
}
|
||||
|
||||
BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx)
|
||||
{
|
||||
return rctx->mem;
|
||||
}
|
||||
|
||||
void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len)
|
||||
{
|
||||
if (len == 0)
|
||||
rctx->max_resp_len = OCSP_MAX_RESP_LENGTH;
|
||||
else
|
||||
rctx->max_resp_len = len;
|
||||
}
|
||||
|
||||
int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it, ASN1_VALUE *val)
|
||||
{
|
||||
static const char req_hdr[] =
|
||||
"Content-Type: application/ocsp-request\r\n"
|
||||
"Content-Length: %d\r\n\r\n";
|
||||
int reqlen = ASN1_item_i2d(val, NULL, it);
|
||||
if (BIO_printf(rctx->mem, req_hdr, reqlen) <= 0)
|
||||
return 0;
|
||||
if (ASN1_item_i2d_bio(it, rctx->mem, val) <= 0)
|
||||
return 0;
|
||||
rctx->state = OHS_ASN1_WRITE_INIT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx,
|
||||
ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int rv, len;
|
||||
const unsigned char *p;
|
||||
|
||||
rv = OCSP_REQ_CTX_nbio(rctx);
|
||||
if (rv != 1)
|
||||
return rv;
|
||||
|
||||
len = BIO_get_mem_data(rctx->mem, &p);
|
||||
*pval = ASN1_item_d2i(NULL, &p, len, it);
|
||||
if (*pval == NULL) {
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path)
|
||||
{
|
||||
static const char http_hdr[] = "%s %s HTTP/1.0\r\n";
|
||||
|
||||
if (path == NULL)
|
||||
path = "/";
|
||||
|
||||
if (BIO_printf(rctx->mem, http_hdr, op, path) <= 0)
|
||||
return 0;
|
||||
rctx->state = OHS_HTTP_HEADER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req)
|
||||
{
|
||||
return OCSP_REQ_CTX_i2d(rctx, ASN1_ITEM_rptr(OCSP_REQUEST),
|
||||
(ASN1_VALUE *)req);
|
||||
}
|
||||
|
||||
int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx,
|
||||
const char *name, const char *value)
|
||||
{
|
||||
if (!name)
|
||||
return 0;
|
||||
if (BIO_puts(rctx->mem, name) <= 0)
|
||||
return 0;
|
||||
if (value) {
|
||||
if (BIO_write(rctx->mem, ": ", 2) != 2)
|
||||
return 0;
|
||||
if (BIO_puts(rctx->mem, value) <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (BIO_write(rctx->mem, "\r\n", 2) != 2)
|
||||
return 0;
|
||||
rctx->state = OHS_HTTP_HEADER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req,
|
||||
int maxline)
|
||||
{
|
||||
|
||||
OCSP_REQ_CTX *rctx = NULL;
|
||||
rctx = OCSP_REQ_CTX_new(io, maxline);
|
||||
if (rctx == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!OCSP_REQ_CTX_http(rctx, "POST", path))
|
||||
goto err;
|
||||
|
||||
if (req && !OCSP_REQ_CTX_set1_req(rctx, req))
|
||||
goto err;
|
||||
|
||||
return rctx;
|
||||
|
||||
err:
|
||||
OCSP_REQ_CTX_free(rctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the HTTP response. This will look like this: "HTTP/1.0 200 OK". We
|
||||
* need to obtain the numeric code and (optional) informational message.
|
||||
*/
|
||||
|
||||
static int parse_http_line1(char *line)
|
||||
{
|
||||
int retcode;
|
||||
char *p, *q, *r;
|
||||
/* Skip to first white space (passed protocol info) */
|
||||
|
||||
for (p = line; *p && !ossl_isspace(*p); p++)
|
||||
continue;
|
||||
if (*p == '\0') {
|
||||
OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip past white space to start of response code */
|
||||
while (*p && ossl_isspace(*p))
|
||||
p++;
|
||||
|
||||
if (*p == '\0') {
|
||||
OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find end of response code: first whitespace after start of code */
|
||||
for (q = p; *q && !ossl_isspace(*q); q++)
|
||||
continue;
|
||||
|
||||
if (*q == '\0') {
|
||||
OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set end of response code and start of message */
|
||||
*q++ = 0;
|
||||
|
||||
/* Attempt to parse numeric code */
|
||||
retcode = strtoul(p, &r, 10);
|
||||
|
||||
if (*r)
|
||||
return 0;
|
||||
|
||||
/* Skip over any leading white space in message */
|
||||
while (*q && ossl_isspace(*q))
|
||||
q++;
|
||||
|
||||
if (*q) {
|
||||
/*
|
||||
* Finally zap any trailing white space in message (include CRLF)
|
||||
*/
|
||||
|
||||
/* We know q has a non white space character so this is OK */
|
||||
for (r = q + strlen(q) - 1; ossl_isspace(*r); r--)
|
||||
*r = 0;
|
||||
}
|
||||
if (retcode != 200) {
|
||||
OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_ERROR);
|
||||
if (*q == '\0')
|
||||
ERR_add_error_data(2, "Code=", p);
|
||||
else
|
||||
ERR_add_error_data(4, "Code=", p, ",Reason=", q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx)
|
||||
{
|
||||
int i, n;
|
||||
const unsigned char *p;
|
||||
next_io:
|
||||
if (!(rctx->state & OHS_NOREAD)) {
|
||||
n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen);
|
||||
|
||||
if (n <= 0) {
|
||||
if (BIO_should_retry(rctx->io))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write data to memory BIO */
|
||||
|
||||
if (BIO_write(rctx->mem, rctx->iobuf, n) != n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (rctx->state) {
|
||||
case OHS_HTTP_HEADER:
|
||||
/* Last operation was adding headers: need a final \r\n */
|
||||
if (BIO_write(rctx->mem, "\r\n", 2) != 2) {
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
rctx->state = OHS_ASN1_WRITE_INIT;
|
||||
|
||||
/* fall thru */
|
||||
case OHS_ASN1_WRITE_INIT:
|
||||
rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL);
|
||||
rctx->state = OHS_ASN1_WRITE;
|
||||
|
||||
/* fall thru */
|
||||
case OHS_ASN1_WRITE:
|
||||
n = BIO_get_mem_data(rctx->mem, &p);
|
||||
|
||||
i = BIO_write(rctx->io, p + (n - rctx->asn1_len), rctx->asn1_len);
|
||||
|
||||
if (i <= 0) {
|
||||
if (BIO_should_retry(rctx->io))
|
||||
return -1;
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rctx->asn1_len -= i;
|
||||
|
||||
if (rctx->asn1_len > 0)
|
||||
goto next_io;
|
||||
|
||||
rctx->state = OHS_ASN1_FLUSH;
|
||||
|
||||
(void)BIO_reset(rctx->mem);
|
||||
|
||||
/* fall thru */
|
||||
case OHS_ASN1_FLUSH:
|
||||
|
||||
i = BIO_flush(rctx->io);
|
||||
|
||||
if (i > 0) {
|
||||
rctx->state = OHS_FIRSTLINE;
|
||||
goto next_io;
|
||||
}
|
||||
|
||||
if (BIO_should_retry(rctx->io))
|
||||
return -1;
|
||||
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
|
||||
case OHS_ERROR:
|
||||
return 0;
|
||||
|
||||
case OHS_FIRSTLINE:
|
||||
case OHS_HEADERS:
|
||||
|
||||
/* Attempt to read a line in */
|
||||
|
||||
next_line:
|
||||
/*
|
||||
* Due to &%^*$" memory BIO behaviour with BIO_gets we have to check
|
||||
* there's a complete line in there before calling BIO_gets or we'll
|
||||
* just get a partial read.
|
||||
*/
|
||||
n = BIO_get_mem_data(rctx->mem, &p);
|
||||
if ((n <= 0) || !memchr(p, '\n', n)) {
|
||||
if (n >= rctx->iobuflen) {
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
goto next_io;
|
||||
}
|
||||
n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen);
|
||||
|
||||
if (n <= 0) {
|
||||
if (BIO_should_retry(rctx->mem))
|
||||
goto next_io;
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Don't allow excessive lines */
|
||||
if (n == rctx->iobuflen) {
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First line */
|
||||
if (rctx->state == OHS_FIRSTLINE) {
|
||||
if (parse_http_line1((char *)rctx->iobuf)) {
|
||||
rctx->state = OHS_HEADERS;
|
||||
goto next_line;
|
||||
} else {
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Look for blank line: end of headers */
|
||||
for (p = rctx->iobuf; *p; p++) {
|
||||
if ((*p != '\r') && (*p != '\n'))
|
||||
break;
|
||||
}
|
||||
if (*p)
|
||||
goto next_line;
|
||||
|
||||
rctx->state = OHS_ASN1_HEADER;
|
||||
|
||||
}
|
||||
|
||||
/* Fall thru */
|
||||
|
||||
case OHS_ASN1_HEADER:
|
||||
/*
|
||||
* Now reading ASN1 header: can read at least 2 bytes which is enough
|
||||
* for ASN1 SEQUENCE header and either length field or at least the
|
||||
* length of the length field.
|
||||
*/
|
||||
n = BIO_get_mem_data(rctx->mem, &p);
|
||||
if (n < 2)
|
||||
goto next_io;
|
||||
|
||||
/* Check it is an ASN1 SEQUENCE */
|
||||
if (*p++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) {
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check out length field */
|
||||
if (*p & 0x80) {
|
||||
/*
|
||||
* If MSB set on initial length octet we can now always read 6
|
||||
* octets: make sure we have them.
|
||||
*/
|
||||
if (n < 6)
|
||||
goto next_io;
|
||||
n = *p & 0x7F;
|
||||
/* Not NDEF or excessive length */
|
||||
if (!n || (n > 4)) {
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
p++;
|
||||
rctx->asn1_len = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
rctx->asn1_len <<= 8;
|
||||
rctx->asn1_len |= *p++;
|
||||
}
|
||||
|
||||
if (rctx->asn1_len > rctx->max_resp_len) {
|
||||
rctx->state = OHS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rctx->asn1_len += n + 2;
|
||||
} else
|
||||
rctx->asn1_len = *p + 2;
|
||||
|
||||
rctx->state = OHS_ASN1_CONTENT;
|
||||
|
||||
/* Fall thru */
|
||||
|
||||
case OHS_ASN1_CONTENT:
|
||||
n = BIO_get_mem_data(rctx->mem, NULL);
|
||||
if (n < (int)rctx->asn1_len)
|
||||
goto next_io;
|
||||
|
||||
rctx->state = OHS_DONE;
|
||||
return 1;
|
||||
|
||||
case OHS_DONE:
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx)
|
||||
{
|
||||
return OCSP_REQ_CTX_nbio_d2i(rctx,
|
||||
(ASN1_VALUE **)presp,
|
||||
ASN1_ITEM_rptr(OCSP_RESPONSE));
|
||||
}
|
||||
|
||||
/* Blocking OCSP request handler: now a special case of non-blocking I/O */
|
||||
|
||||
OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req)
|
||||
{
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
OCSP_REQ_CTX *ctx;
|
||||
int rv;
|
||||
|
||||
ctx = OCSP_sendreq_new(b, path, req, -1);
|
||||
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
rv = OCSP_sendreq_nbio(&resp, ctx);
|
||||
} while ((rv == -1) && BIO_should_retry(b));
|
||||
|
||||
OCSP_REQ_CTX_free(ctx);
|
||||
|
||||
if (rv)
|
||||
return resp;
|
||||
|
||||
return NULL;
|
||||
}
|
65
crypto/ocsp/ocsp_http.c
Normal file
65
crypto/ocsp/ocsp_http.c
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/ocsp.h>
|
||||
#include <openssl/http.h>
|
||||
#include "../http/http_local.h"
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
|
||||
int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, const OCSP_REQUEST *req)
|
||||
{
|
||||
return OCSP_REQ_CTX_i2d(rctx, "application/ocsp-request",
|
||||
ASN1_ITEM_rptr(OCSP_REQUEST), (ASN1_VALUE *)req);
|
||||
}
|
||||
|
||||
OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req,
|
||||
int maxline)
|
||||
{
|
||||
BIO *req_mem = HTTP_asn1_item2bio(ASN1_ITEM_rptr(OCSP_REQUEST),
|
||||
(ASN1_VALUE *)req);
|
||||
OCSP_REQ_CTX *res =
|
||||
HTTP_REQ_CTX_new(io, io, 0 /* no HTTP proxy used */, NULL, NULL, path,
|
||||
NULL /* headers */, "application/ocsp-request",
|
||||
req_mem /* may be NULL */,
|
||||
maxline, 0 /* default max_resp_len */,
|
||||
0 /* no timeout, blocking indefinite */, NULL,
|
||||
1 /* expect_asn1 */);
|
||||
BIO_free(req_mem);
|
||||
return res;
|
||||
}
|
||||
|
||||
# ifndef OPENSSL_NO_SOCK
|
||||
int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx)
|
||||
{
|
||||
*presp = (OCSP_RESPONSE *)
|
||||
OCSP_REQ_CTX_nbio_d2i(rctx, ASN1_ITEM_rptr(OCSP_RESPONSE));
|
||||
return *presp != NULL;
|
||||
}
|
||||
|
||||
OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req)
|
||||
{
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
OCSP_REQ_CTX *ctx;
|
||||
int rv;
|
||||
|
||||
ctx = OCSP_sendreq_new(b, path, req, -1 /* default max resp line length */);
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
rv = OCSP_sendreq_nbio(&resp, ctx);
|
||||
|
||||
/* this indirectly calls ERR_clear_error(): */
|
||||
OCSP_REQ_CTX_free(ctx);
|
||||
|
||||
return rv == 1 ? resp : NULL;
|
||||
}
|
||||
# endif /* !defined(OPENSSL_NO_SOCK) */
|
||||
|
||||
#endif /* !defined(OPENSSL_NO_OCSP) */
|
@ -109,111 +109,4 @@ int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b)
|
||||
return ASN1_INTEGER_cmp(&a->serialNumber, &b->serialNumber);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a URL and split it up into host, port and path components and
|
||||
* whether it is SSL.
|
||||
*/
|
||||
|
||||
int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
|
||||
int *pssl)
|
||||
{
|
||||
char *p, *buf;
|
||||
|
||||
char *host, *port;
|
||||
|
||||
*phost = NULL;
|
||||
*pport = NULL;
|
||||
*ppath = NULL;
|
||||
|
||||
/* dup the buffer since we are going to mess with it */
|
||||
buf = OPENSSL_strdup(url);
|
||||
if (!buf)
|
||||
goto mem_err;
|
||||
|
||||
/* Check for initial colon */
|
||||
p = strchr(buf, ':');
|
||||
if (p == NULL)
|
||||
goto parse_err;
|
||||
|
||||
*(p++) = '\0';
|
||||
|
||||
if (strcmp(buf, "http") == 0) {
|
||||
*pssl = 0;
|
||||
port = "80";
|
||||
} else if (strcmp(buf, "https") == 0) {
|
||||
*pssl = 1;
|
||||
port = "443";
|
||||
} else
|
||||
goto parse_err;
|
||||
|
||||
/* Check for double slash */
|
||||
if ((p[0] != '/') || (p[1] != '/'))
|
||||
goto parse_err;
|
||||
|
||||
p += 2;
|
||||
|
||||
host = p;
|
||||
|
||||
/* Check for trailing part of path */
|
||||
p = strchr(p, '/');
|
||||
if (p == NULL)
|
||||
*ppath = OPENSSL_strdup("/");
|
||||
else {
|
||||
*ppath = OPENSSL_strdup(p);
|
||||
/* Set start of path to 0 so hostname is valid */
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
if (*ppath == NULL)
|
||||
goto mem_err;
|
||||
|
||||
p = host;
|
||||
if (host[0] == '[') {
|
||||
/* ipv6 literal */
|
||||
host++;
|
||||
p = strchr(host, ']');
|
||||
if (p == NULL)
|
||||
goto parse_err;
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
/* Look for optional ':' for port number */
|
||||
if ((p = strchr(p, ':'))) {
|
||||
*p = 0;
|
||||
port = p + 1;
|
||||
}
|
||||
|
||||
*pport = OPENSSL_strdup(port);
|
||||
if (*pport == NULL)
|
||||
goto mem_err;
|
||||
|
||||
*phost = OPENSSL_strdup(host);
|
||||
|
||||
if (*phost == NULL)
|
||||
goto mem_err;
|
||||
|
||||
OPENSSL_free(buf);
|
||||
|
||||
return 1;
|
||||
|
||||
mem_err:
|
||||
OCSPerr(OCSP_F_OCSP_PARSE_URL, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
|
||||
parse_err:
|
||||
OCSPerr(OCSP_F_OCSP_PARSE_URL, OCSP_R_ERROR_PARSING_URL);
|
||||
|
||||
err:
|
||||
OPENSSL_free(buf);
|
||||
OPENSSL_free(*ppath);
|
||||
*ppath = NULL;
|
||||
OPENSSL_free(*pport);
|
||||
*pport = NULL;
|
||||
OPENSSL_free(*phost);
|
||||
*phost = NULL;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
IMPLEMENT_ASN1_DUP_FUNCTION(OCSP_CERTID)
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
#include "crypto/x509.h"
|
||||
#include <openssl/ocsp.h>
|
||||
#include <openssl/http.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/x509v3.h>
|
||||
@ -123,11 +123,21 @@ int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx)
|
||||
&x->sig_alg, &x->signature, &x->cert_info, ctx);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert)
|
||||
#if !defined(OPENSSL_NO_SOCK)
|
||||
static ASN1_VALUE *simple_get_asn1(const char *url, BIO *bio, BIO *rbio,
|
||||
int timeout, const ASN1_ITEM *it)
|
||||
{
|
||||
return OCSP_REQ_CTX_nbio_d2i(rctx,
|
||||
(ASN1_VALUE **)pcert, ASN1_ITEM_rptr(X509));
|
||||
return OSSL_HTTP_get_asn1(url, NULL, NULL /* no proxy and port */, bio,
|
||||
rbio, NULL /* no callback for SSL/TLS */, NULL,
|
||||
NULL /* headers */, 1024 /* maxline */,
|
||||
0 /* max_resp_len */, timeout,
|
||||
NULL /* expected_content_type */, it);
|
||||
}
|
||||
|
||||
X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout)
|
||||
{
|
||||
return (X509 *)simple_get_asn1(url, bio, rbio, timeout,
|
||||
ASN1_ITEM_rptr(X509));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -159,12 +169,11 @@ int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx)
|
||||
&x->crl, ctx);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl)
|
||||
#if !defined(OPENSSL_NO_SOCK)
|
||||
X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout)
|
||||
{
|
||||
return OCSP_REQ_CTX_nbio_d2i(rctx,
|
||||
(ASN1_VALUE **)pcrl,
|
||||
ASN1_ITEM_rptr(X509_CRL));
|
||||
return (X509_CRL *)simple_get_asn1(url, bio, rbio, timeout,
|
||||
ASN1_ITEM_rptr(X509_CRL));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -10,22 +10,22 @@ OCSP_REQ_CTX_set1_req, OCSP_sendreq_bio - OCSP responder query functions
|
||||
|
||||
#include <openssl/ocsp.h>
|
||||
|
||||
OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req,
|
||||
int maxline);
|
||||
OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path,
|
||||
OCSP_REQUEST *req, int maxline);
|
||||
|
||||
int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx);
|
||||
|
||||
void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
|
||||
|
||||
void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len);
|
||||
void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx,
|
||||
unsigned long len);
|
||||
|
||||
int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx,
|
||||
const char *name, const char *value);
|
||||
|
||||
int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req);
|
||||
int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, const OCSP_REQUEST *req);
|
||||
|
||||
OCSP_RESPONSE *OCSP_sendreq_bio(BIO *io, const char *path, OCSP_REQUEST *req,
|
||||
int maxline);
|
||||
OCSP_RESPONSE *OCSP_sendreq_bio(BIO *io, const char *path, OCSP_REQUEST *req);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
@ -35,14 +35,14 @@ response header maximum line length of B<maxline>. If B<maxline> is zero a
|
||||
default value of 4k is used. The OCSP request B<req> may be set to B<NULL>
|
||||
and provided later if required.
|
||||
|
||||
OCSP_sendreq_nbio() performs non-blocking I/O on the OCSP request context
|
||||
B<rctx>. When the operation is complete it returns the response in B<*presp>.
|
||||
OCSP_sendreq_nbio() performs I/O on the OCSP request context B<rctx>.
|
||||
When the operation is complete it returns the response in B<*presp>.
|
||||
|
||||
OCSP_REQ_CTX_free() frees up the OCSP context B<rctx>.
|
||||
|
||||
OCSP_set_max_response_length() sets the maximum response length for B<rctx>
|
||||
to B<len>. If the response exceeds this length an error occurs. If not
|
||||
set a default value of 100k is used.
|
||||
OCSP_set_max_response_length() sets the maximum response length
|
||||
for B<rctx> to B<len>. If the response exceeds this length an error occurs.
|
||||
If not set a default value of 100k is used.
|
||||
|
||||
OCSP_REQ_CTX_add1_header() adds header B<name> with value B<value> to the
|
||||
context B<rctx>. It can be called more than once to add multiple headers.
|
||||
@ -55,23 +55,21 @@ function should be called after any calls to OCSP_REQ_CTX_add1_header().
|
||||
|
||||
OCSP_sendreq_bio() performs an OCSP request using the responder B<io>, the URL
|
||||
path B<path>, the OCSP request B<req> and with a response header maximum line
|
||||
length of B<maxline>. If B<maxline> is zero a default value of 4k is used.
|
||||
length 4k. It waits indefinitely on a response.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
OCSP_sendreq_new() returns a valid B<OCSP_REQ_CTX> structure or B<NULL> if
|
||||
an error occurred.
|
||||
OCSP_sendreq_new() returns a valid B<OCSP_REQ_CTX> structure or B<NULL>
|
||||
if an error occurred.
|
||||
|
||||
OCSP_sendreq_nbio() returns B<1> if the operation was completed successfully,
|
||||
B<-1> if the operation should be retried and B<0> if an error occurred.
|
||||
|
||||
OCSP_REQ_CTX_add1_header() and OCSP_REQ_CTX_set1_req() return B<1> for success
|
||||
and B<0> for failure.
|
||||
OCSP_sendreq_nbio(), OCSP_REQ_CTX_add1_header() and OCSP_REQ_CTX_set1_req()
|
||||
return B<1> for success and B<0> for failure.
|
||||
|
||||
OCSP_sendreq_bio() returns the B<OCSP_RESPONSE> structure sent by the
|
||||
responder or B<NULL> if an error occurred.
|
||||
|
||||
OCSP_REQ_CTX_free() and OCSP_set_max_response_length() do not return values.
|
||||
OCSP_REQ_CTX_free() and OCSP_set_max_response_length()
|
||||
do not return values.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
@ -92,14 +90,9 @@ a Host header for B<ocsp.com> you would call:
|
||||
|
||||
OCSP_REQ_CTX_add1_header(ctx, "Host", "ocsp.com");
|
||||
|
||||
If OCSP_sendreq_nbio() indicates an operation should be retried the
|
||||
corresponding BIO can be examined to determine which operation (read or
|
||||
write) should be retried and appropriate action taken (for example a select()
|
||||
call on the underlying socket).
|
||||
|
||||
OCSP_sendreq_bio() does not support retries and so cannot handle non-blocking
|
||||
I/O efficiently. It is retained for compatibility and its use in new
|
||||
applications is not recommended.
|
||||
OCSP_sendreq_bio() does not support timeout nor setting extra headers.
|
||||
It is retained for compatibility.
|
||||
Better use B<OCSP_sendreq_nbio()> instead.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
|
@ -16,7 +16,6 @@ OSSL_CMP_CTX_set_serverPort,
|
||||
OSSL_CMP_CTX_set1_proxyName,
|
||||
OSSL_CMP_CTX_set_proxyPort,
|
||||
OSSL_CMP_DEFAULT_PORT,
|
||||
OSSL_cmp_http_cb_t,
|
||||
OSSL_CMP_CTX_set_http_cb,
|
||||
OSSL_CMP_CTX_set_http_cb_arg,
|
||||
OSSL_CMP_CTX_get_http_cb_arg,
|
||||
@ -84,14 +83,11 @@ OSSL_CMP_CTX_set1_senderNonce
|
||||
int OSSL_CMP_CTX_set1_proxyName(OSSL_CMP_CTX *ctx, const char *name);
|
||||
int OSSL_CMP_CTX_set_proxyPort(OSSL_CMP_CTX *ctx, int port);
|
||||
#define OSSL_CMP_DEFAULT_PORT 80
|
||||
typedef BIO *(*OSSL_cmp_http_cb_t)(OSSL_CMP_CTX *ctx, BIO *hbio,
|
||||
unsigned long detail);
|
||||
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_http_cb_t cb);
|
||||
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, HTTP_bio_cb_t cb);
|
||||
int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
|
||||
void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx);
|
||||
typedef int (*OSSL_cmp_transfer_cb_t)(OSSL_CMP_CTX *ctx,
|
||||
const OSSL_CMP_MSG *req,
|
||||
OSSL_CMP_MSG **res);
|
||||
typedef OSSL_CMP_MSG *(*OSSL_cmp_transfer_cb_t)(OSSL_CMP_CTX *ctx,
|
||||
const OSSL_CMP_MSG *req);
|
||||
int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx,
|
||||
OSSL_cmp_transfer_cb_t cb);
|
||||
int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
|
||||
@ -324,22 +320,22 @@ for connecting to the CA server.
|
||||
OSSL_CMP_CTX_set_proxyPort() sets the port of the HTTP proxy.
|
||||
Port defaults to OSSL_CMP_DEFAULT_PORT = 80 if not set explicitly.
|
||||
|
||||
OSSL_CMP_CTX_set_http_cb() sets the optional http connect/disconnect callback
|
||||
OSSL_CMP_CTX_set_http_cb() sets the optional BIO connect/disconnect callback
|
||||
function, which has the prototype
|
||||
|
||||
typedef BIO *(*OSSL_cmp_http_cb_t)(OSSL_CMP_CTX *ctx, BIO *hbio,
|
||||
unsigned long detail);
|
||||
typedef BIO *(*HTTP_bio_cb_t) (BIO *bio, void *ctx, int connect, int detail);
|
||||
|
||||
It may modify the HTTP BIO given in the B<hbio> argument
|
||||
used by OSSL_CMP_MSG_http_perform().
|
||||
On connect the B<detail> argument is 1.
|
||||
On disconnect it is 0 if no error occurred or else the last error code.
|
||||
For instance, on connect a TLS BIO may be prepended to implement HTTPS,
|
||||
and on disconnect some error diagnostics and/or cleanup may be done.
|
||||
The callback function should return NULL to indicate failure.
|
||||
It may make use of a custom defined argument stored in the ctx
|
||||
by means of OSSL_CMP_CTX_set_http_cb_arg(),
|
||||
which may be retrieved again through OSSL_CMP_CTX_get_http_cb_arg().
|
||||
The callback may modify the BIO B<bio> provided by OSSL_CMP_MSG_http_perform(),
|
||||
whereby it may make use of a custom defined argument B<ctx>
|
||||
stored in the OSSL_CMP_CTX by means of OSSL_CMP_CTX_set_http_cb_arg().
|
||||
During connection establishment, just after calling BIO_connect_retry(),
|
||||
the function is invoked with the B<connect> argument being 1 and the B<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 in case 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.
|
||||
After disconnect the modified BIO will be deallocated using BIO_free_all().
|
||||
|
||||
OSSL_CMP_CTX_set_http_cb_arg() sets an argument, respectively a pointer to
|
||||
a structure containing arguments,
|
||||
@ -354,18 +350,17 @@ OSSL_CMP_CTX_set_http_cb_arg() or NULL if unset.
|
||||
OSSL_CMP_CTX_set_transfer_cb() sets the message transfer callback function,
|
||||
which has the type
|
||||
|
||||
typedef int (*OSSL_cmp_transfer_cb_t)(const OSSL_CMP_CTX *ctx,
|
||||
const OSSL_CMP_MSG *req,
|
||||
OSSL_CMP_MSG **res);
|
||||
typedef OSSL_CMP_MSG *(*OSSL_cmp_transfer_cb_t) (OSSL_CMP_CTX *ctx,
|
||||
const OSSL_CMP_MSG *req);
|
||||
|
||||
Returns 1 on success, 0 on error.
|
||||
|
||||
Default is NULL, which implies the use of L<OSSL_CMP_MSG_http_perform(3)>.
|
||||
The callback should send the CMP request it obtains via the B<req> parameter
|
||||
and on success place the response in the B<*res> output parameter.
|
||||
The callback should send the CMP request message it obtains via the B<req>
|
||||
parameter and on success return the response.
|
||||
The transfer callback may make use of a custom defined argument stored in
|
||||
the ctx by means of OSSL_CMP_CTX_set_transfer_cb_arg(), which may be retrieved
|
||||
again through OSSL_CMP_CTX_get_transfer_cb_arg().
|
||||
On success the cb must return 0, else a CMP error reason code defined in cmp.h.
|
||||
|
||||
|
||||
OSSL_CMP_CTX_set_transfer_cb_arg() sets an argument, respectively a pointer to a
|
||||
|
210
doc/man3/OSSL_HTTP_transfer.pod
Normal file
210
doc/man3/OSSL_HTTP_transfer.pod
Normal file
@ -0,0 +1,210 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
OSSL_HTTP_get,
|
||||
OSSL_HTTP_get_asn1,
|
||||
OSSL_HTTP_post_asn1,
|
||||
OSSL_HTTP_transfer,
|
||||
OSSL_HTTP_bio_cb_t,
|
||||
OSSL_HTTP_proxy_connect,
|
||||
OSSL_HTTP_parse_url
|
||||
- http client functions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
#include <openssl/http.h>
|
||||
|
||||
typedef BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg,
|
||||
int connect, int detail);
|
||||
BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *proxy_port,
|
||||
BIO *bio, BIO *rbio,
|
||||
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
int maxline, unsigned long max_resp_len, int timeout,
|
||||
const char *expected_content_type, int expect_asn1);
|
||||
ASN1_VALUE *OSSL_HTTP_get_asn1(const char *url,
|
||||
const char *proxy, const char *proxy_port,
|
||||
BIO *bio, BIO *rbio,
|
||||
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
int maxline, unsigned long max_resp_len,
|
||||
int timeout, const char *expected_content_type,
|
||||
const ASN1_ITEM *it);
|
||||
ASN1_VALUE *OSSL_HTTP_post_asn1(const char *server, const char *port,
|
||||
const char *path, int use_ssl,
|
||||
const char *proxy, const char *proxy_port,
|
||||
BIO *bio, BIO *rbio,
|
||||
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
const char *content_type,
|
||||
ASN1_VALUE *req, const ASN1_ITEM *req_it,
|
||||
int maxline, unsigned long max_resp_len,
|
||||
int timeout, const char *expected_ct,
|
||||
const ASN1_ITEM *rsp_it);
|
||||
BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path,
|
||||
int use_ssl, const char *proxy, const char *proxy_port,
|
||||
BIO *bio, BIO *rbio,
|
||||
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
const char *content_type, BIO *req_mem,
|
||||
int maxline, unsigned long max_resp_len, int timeout,
|
||||
const char *expected_ct, int expect_asn1,
|
||||
char **redirection_url);
|
||||
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_HTTP_parse_url(const char *url, char **phost, char **pport,
|
||||
char **ppath, int *pssl);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
OSSL_HTTP_get() uses HTTP GET to obtain data (of any type) from the given B<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>
|
||||
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>, which 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.
|
||||
The optional list B<headers> may contain additional custom HTTP header lines.
|
||||
The expected structure of the response is specified by B<rsp_it>.
|
||||
On success it returns the response as a pointer to B<ASN1_VALUE>.
|
||||
|
||||
OSSL_HTTP_transfer() exchanges an HTTP request and response with
|
||||
the given B<server> and optional B<port> and B<path>, which 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>
|
||||
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
|
||||
L<OPENSSL_free(3)>.
|
||||
|
||||
The above functions have the following parameters in common.
|
||||
|
||||
If the B<proxy> parameter is not NULL the HTTP client functions connect
|
||||
via the given proxy and the optionally given B<proxy_port>.
|
||||
Proxying plain HTTP is supported directly,
|
||||
while using a proxy for HTTPS connections requires a suitable callback function
|
||||
such as OSSL_HTTP_proxy_connect(), described below.
|
||||
|
||||
Typically the B<bio> and B<rbio> parameters are NULL and the client creates a
|
||||
network BIO internally for connecting to the given server and port (optionally
|
||||
via a proxy and its port), and uses it for exchanging the request and response.
|
||||
If B<bio> is given and B<rbio> is NULL then the client uses this BIO instead.
|
||||
If both B<bio> and B<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>.
|
||||
|
||||
The B<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,
|
||||
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.
|
||||
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)
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
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>,
|
||||
which may for instance refer to an I<SSL_CTX> structure.
|
||||
During connection establishment, just after calling BIO_connect_retry(),
|
||||
the function is invoked with the B<connect> argument being 1 and the B<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.
|
||||
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.
|
||||
Here is a simple example that supports TLS connections (but not via a proxy):
|
||||
|
||||
BIO *http_tls_cb(BIO *hbio, void *arg, int connect, int detail)
|
||||
{
|
||||
SSL_CTX *ctx = (SSL_CTX *)arg;
|
||||
|
||||
if (connect && detail) { /* connecting with TLS */
|
||||
BIO *sbio = BIO_new_ssl(ctx, 1);
|
||||
hbio = sbio != NULL ? BIO_push(sbio, hbio) : NULL;
|
||||
} else if (!connect && !detail) { /* disconnecting after error */
|
||||
/* optionally add diagnostics here */
|
||||
}
|
||||
return hbio;
|
||||
}
|
||||
|
||||
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 HTTP proxy.
|
||||
It promotes the given BIO B<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>.
|
||||
The B<timeout> parameter is used as described above.
|
||||
Since this function is typically called by appplications such as
|
||||
L<openssl-s_client(1)> it uses the B<bio_err> and B<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.
|
||||
The port component is optional and defaults to "443" for HTTPS, else "80".
|
||||
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.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
OSSL_HTTP_get(), OSSL_HTTP_get_asn1(), OSSL_HTTP_post_asn1(), and
|
||||
OSSL_HTTP_transfer() return on success the data received via HTTP, else NULL.
|
||||
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 HISTORY
|
||||
|
||||
OSSL_HTTP_get(), OSSL_HTTP_get_asn1(), OSSL_HTTP_post_asn1(),
|
||||
OSSL_HTTP_proxy_connect(), and OSSL_HTTP_parse_url() were added in OpenSSL 3.0.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
in the file LICENSE in the source distribution or at
|
||||
L<https://www.openssl.org/source/license.html>.
|
||||
|
||||
=cut
|
63
doc/man3/X509_load_http.pod
Normal file
63
doc/man3/X509_load_http.pod
Normal file
@ -0,0 +1,63 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
X509_load_http,
|
||||
X509_http_nbio,
|
||||
X509_CRL_load_http,
|
||||
X509_CRL_http_nbio
|
||||
- certificate and CRL loading functions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
#include <openssl/x509.h>
|
||||
|
||||
X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
|
||||
X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
|
||||
|
||||
#define X509_http_nbio(url)
|
||||
#define X509_CRL_http_nbio(url)
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
X509_load_http() and X509_CRL_load_http() loads a certificate or a CRL,
|
||||
respectively, in ASN.1 format using HTTP from the given B<url>.
|
||||
|
||||
If B<bio> is given and B<rbio> is NULL then this BIO is used instead of an
|
||||
interal one for connecting, writing the request, and reading the response.
|
||||
If both B<bio> and B<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.
|
||||
|
||||
If the B<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.
|
||||
|
||||
X509_http_nbio() and X509_CRL_http_nbio() are macros for backward compatibility
|
||||
that have the same effect as the functions above but with infinite timeout
|
||||
and without the possiblity to specify custom BIOs.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
On success the function yield the loaded value, else NULL.
|
||||
Error conditions include connection/transfer timeout, parse errors, etc.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<OSSL_HTTP_get_asn1(3)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
X509_load_http() and X509_CRL_load_http() were added in OpenSSL 3.0.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
in the file LICENSE in the source distribution or at
|
||||
L<https://www.openssl.org/source/license.html>.
|
||||
|
||||
=cut
|
@ -18,6 +18,7 @@
|
||||
# include <openssl/crmf.h>
|
||||
# include <openssl/cmperr.h>
|
||||
# include <openssl/cmp_util.h>
|
||||
# include <openssl/http.h>
|
||||
|
||||
/* explicit #includes not strictly needed since implied by the above: */
|
||||
# include <openssl/types.h>
|
||||
@ -274,14 +275,11 @@ int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port);
|
||||
int OSSL_CMP_CTX_set1_proxyName(OSSL_CMP_CTX *ctx, const char *name);
|
||||
int OSSL_CMP_CTX_set_proxyPort(OSSL_CMP_CTX *ctx, int port);
|
||||
# define OSSL_CMP_DEFAULT_PORT 80
|
||||
typedef BIO *(*OSSL_cmp_http_cb_t) (OSSL_CMP_CTX *ctx, BIO *hbio,
|
||||
unsigned long detail);
|
||||
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_http_cb_t cb);
|
||||
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb);
|
||||
int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
|
||||
void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx);
|
||||
typedef int (*OSSL_cmp_transfer_cb_t) (OSSL_CMP_CTX *ctx,
|
||||
const OSSL_CMP_MSG *req,
|
||||
OSSL_CMP_MSG **res);
|
||||
typedef OSSL_CMP_MSG *(*OSSL_cmp_transfer_cb_t) (OSSL_CMP_CTX *ctx,
|
||||
const OSSL_CMP_MSG *req);
|
||||
int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_transfer_cb_t cb);
|
||||
int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
|
||||
void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx);
|
||||
|
@ -63,6 +63,7 @@ int ERR_load_CMP_strings(void);
|
||||
# define CMP_R_NO_STDIO 194
|
||||
# define CMP_R_NULL_ARGUMENT 103
|
||||
# define CMP_R_PKISTATUSINFO_NOT_FOUND 132
|
||||
# define CMP_R_POTENTIALLY_INVALID_CERTIFICATE 139
|
||||
# define CMP_R_UNEXPECTED_PKIBODY 133
|
||||
# define CMP_R_UNKNOWN_ALGORITHM_ID 134
|
||||
# define CMP_R_UNKNOWN_CERT_TYPE 135
|
||||
|
@ -113,6 +113,7 @@ struct err_state_st {
|
||||
# define ERR_LIB_PROV 57
|
||||
# define ERR_LIB_CMP 58
|
||||
# define ERR_LIB_OSSL_SERIALIZER 59
|
||||
# define ERR_LIB_HTTP 60
|
||||
|
||||
# define ERR_LIB_USER 128
|
||||
|
||||
@ -140,6 +141,7 @@ struct err_state_st {
|
||||
# define EVPerr(f, r) ERR_raise_data(ERR_LIB_EVP, (r), NULL)
|
||||
# define FIPSerr(f, r) ERR_raise_data(ERR_LIB_FIPS, (r), NULL)
|
||||
# define HMACerr(f, r) ERR_raise_data(ERR_LIB_HMAC, (r), NULL)
|
||||
# define HTTPerr(f, r) ERR_raise_data(ERR_LIB_HTTP, (r), NULL)
|
||||
# define KDFerr(f, r) ERR_raise_data(ERR_LIB_KDF, (r), NULL)
|
||||
# define OBJerr(f, r) ERR_raise_data(ERR_LIB_OBJ, (r), NULL)
|
||||
# define OCSPerr(f, r) ERR_raise_data(ERR_LIB_OCSP, (r), NULL)
|
||||
|
72
include/openssl/http.h
Normal file
72
include/openssl/http.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright Siemens AG 2018-2020
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_HTTP_H
|
||||
# define OPENSSL_HTTP_H
|
||||
# pragma once
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# include <openssl/bio.h>
|
||||
# include <openssl/asn1.h>
|
||||
# include <openssl/conf.h>
|
||||
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
typedef BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg, int connect, int detail);
|
||||
# ifndef OPENSSL_NO_SOCK
|
||||
BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *proxy_port,
|
||||
BIO *bio, BIO *rbio,
|
||||
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
int maxline, unsigned long max_resp_len, int timeout,
|
||||
const char *expected_content_type, int expect_asn1);
|
||||
ASN1_VALUE *OSSL_HTTP_get_asn1(const char *url,
|
||||
const char *proxy, const char *proxy_port,
|
||||
BIO *bio, BIO *rbio,
|
||||
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
int maxline, unsigned long max_resp_len,
|
||||
int timeout, const char *expected_content_type,
|
||||
const ASN1_ITEM *it);
|
||||
ASN1_VALUE *OSSL_HTTP_post_asn1(const char *server, const char *port,
|
||||
const char *path, int use_ssl,
|
||||
const char *proxy, const char *proxy_port,
|
||||
BIO *bio, BIO *rbio,
|
||||
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
const char *content_type,
|
||||
ASN1_VALUE *req, const ASN1_ITEM *req_it,
|
||||
int maxline, unsigned long max_resp_len,
|
||||
int timeout, const char *expected_ct,
|
||||
const ASN1_ITEM *rsp_it);
|
||||
BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path,
|
||||
int use_ssl, const char *proxy, const char *proxy_port,
|
||||
BIO *bio, BIO *rbio,
|
||||
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
const char *content_type, BIO *req_mem,
|
||||
int maxline, unsigned long max_resp_len, int timeout,
|
||||
const char *expected_ct, int expect_asn1,
|
||||
char **redirection_url);
|
||||
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);
|
||||
# endif
|
||||
int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport,
|
||||
char **ppath, int *pssl);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
#endif /* !defined OPENSSL_HTTP_H */
|
55
include/openssl/httperr.h
Normal file
55
include/openssl/httperr.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_HTTPERR_H
|
||||
# define OPENSSL_HTTPERR_H
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
# include <openssl/symhacks.h>
|
||||
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
int ERR_load_HTTP_strings(void);
|
||||
|
||||
/*
|
||||
* HTTP function codes.
|
||||
*/
|
||||
# ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||
# endif
|
||||
|
||||
/*
|
||||
* HTTP reason codes.
|
||||
*/
|
||||
# define HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN 108
|
||||
# define HTTP_R_CONNECT_FAILURE 100
|
||||
# define HTTP_R_ERROR_PARSING_ASN1_LENGTH 109
|
||||
# define HTTP_R_ERROR_PARSING_CONTENT_LENGTH 119
|
||||
# define HTTP_R_ERROR_PARSING_URL 101
|
||||
# define HTTP_R_ERROR_RECEIVING 103
|
||||
# define HTTP_R_ERROR_SENDING 102
|
||||
# define HTTP_R_INCONSISTENT_CONTENT_LENGTH 120
|
||||
# define HTTP_R_MAX_RESP_LEN_EXCEEDED 117
|
||||
# define HTTP_R_MISSING_ASN1_ENCODING 110
|
||||
# define HTTP_R_MISSING_CONTENT_TYPE 121
|
||||
# define HTTP_R_MISSING_REDIRECT_LOCATION 111
|
||||
# define HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP 112
|
||||
# define HTTP_R_REDIRECTION_NOT_ENABLED 116
|
||||
# define HTTP_R_RESPONSE_LINE_TOO_LONG 113
|
||||
# define HTTP_R_SERVER_RESPONSE_PARSE_ERROR 104
|
||||
# define HTTP_R_SERVER_SENT_ERROR 105
|
||||
# define HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION 106
|
||||
# define HTTP_R_STATUS_CODE_UNSUPPORTED 114
|
||||
# define HTTP_R_TLS_NOT_ENABLED 107
|
||||
# define HTTP_R_TOO_MANY_REDIRECTIONS 115
|
||||
# define HTTP_R_UNEXPECTED_CONTENT_TYPE 118
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@ -162,20 +162,32 @@ DECLARE_ASN1_DUP_FUNCTION(OCSP_CERTID)
|
||||
OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req);
|
||||
OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req,
|
||||
int maxline);
|
||||
int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx);
|
||||
# ifndef OPENSSL_NO_SOCK
|
||||
int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx);
|
||||
OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline);
|
||||
# endif
|
||||
/* The following functions are used only internally */
|
||||
int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx);
|
||||
OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *wbio, BIO *rbio,
|
||||
int method_GET, int maxline,
|
||||
unsigned long max_resp_len, int timeout,
|
||||
const char *expected_content_type,
|
||||
int expect_asn1);
|
||||
void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
|
||||
void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len);
|
||||
int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it,
|
||||
ASN1_VALUE *val);
|
||||
int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, ASN1_VALUE **pval,
|
||||
const ASN1_ITEM *it);
|
||||
int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const char *content_type,
|
||||
const ASN1_ITEM *it, ASN1_VALUE *req);
|
||||
# ifndef OPENSSL_NO_SOCK
|
||||
ASN1_VALUE *OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it);
|
||||
# endif
|
||||
BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx);
|
||||
int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path);
|
||||
int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req);
|
||||
int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx,
|
||||
const char *server, const char *port, const char *path);
|
||||
int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx,
|
||||
const char *name, const char *value);
|
||||
/* End of functions used only internally */
|
||||
|
||||
/* TODO: remove this (documented but) meanwhile obsolete function? */
|
||||
int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, const OCSP_REQUEST *req);
|
||||
|
||||
OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject,
|
||||
const X509 *issuer);
|
||||
@ -237,8 +249,7 @@ int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
|
||||
int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
|
||||
X509_STORE *store, unsigned long flags);
|
||||
|
||||
int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
|
||||
int *pssl);
|
||||
# define OCSP_parse_url OSSL_HTTP_parse_url /* for backward compatibility */
|
||||
|
||||
int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
|
||||
int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
|
||||
@ -359,5 +370,5 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
# endif /* !defined OPENSSL_NO_OCSP */
|
||||
#endif
|
||||
|
@ -45,11 +45,9 @@ int ERR_load_OCSP_strings(void);
|
||||
# define OCSP_F_OCSP_CHECK_ISSUER 0
|
||||
# define OCSP_F_OCSP_CHECK_VALIDITY 0
|
||||
# define OCSP_F_OCSP_MATCH_ISSUERID 0
|
||||
# define OCSP_F_OCSP_PARSE_URL 0
|
||||
# define OCSP_F_OCSP_REQUEST_SIGN 0
|
||||
# define OCSP_F_OCSP_REQUEST_VERIFY 0
|
||||
# define OCSP_F_OCSP_RESPONSE_GET1_BASIC 0
|
||||
# define OCSP_F_PARSE_HTTP_LINE1 0
|
||||
# endif
|
||||
|
||||
/*
|
||||
@ -59,7 +57,6 @@ int ERR_load_OCSP_strings(void);
|
||||
# define OCSP_R_DIGEST_ERR 102
|
||||
# define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD 122
|
||||
# define OCSP_R_ERROR_IN_THISUPDATE_FIELD 123
|
||||
# define OCSP_R_ERROR_PARSING_URL 121
|
||||
# define OCSP_R_MISSING_OCSPSIGNING_USAGE 103
|
||||
# define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE 124
|
||||
# define OCSP_R_NOT_BASIC_RESPONSE 104
|
||||
@ -71,8 +68,6 @@ int ERR_load_OCSP_strings(void);
|
||||
# define OCSP_R_REQUEST_NOT_SIGNED 128
|
||||
# define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111
|
||||
# define OCSP_R_ROOT_CA_NOT_TRUSTED 112
|
||||
# define OCSP_R_SERVER_RESPONSE_ERROR 114
|
||||
# define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 115
|
||||
# define OCSP_R_SIGNATURE_FAILURE 117
|
||||
# define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND 118
|
||||
# define OCSP_R_STATUS_EXPIRED 125
|
||||
|
@ -184,7 +184,7 @@ typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS;
|
||||
|
||||
typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
|
||||
|
||||
typedef struct ocsp_req_ctx_st OCSP_REQ_CTX;
|
||||
typedef struct ossl_http_req_ctx_st OCSP_REQ_CTX; /* backward compatibility */
|
||||
typedef struct ocsp_response_st OCSP_RESPONSE;
|
||||
typedef struct ocsp_responder_id_st OCSP_RESPID;
|
||||
|
||||
|
@ -372,16 +372,10 @@ int X509_signature_print(BIO *bp, const X509_ALGOR *alg,
|
||||
|
||||
int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
|
||||
int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx);
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert);
|
||||
# endif
|
||||
int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md);
|
||||
int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx);
|
||||
int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
|
||||
int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx);
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl);
|
||||
# endif
|
||||
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md);
|
||||
|
||||
int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
|
||||
@ -395,6 +389,13 @@ int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type,
|
||||
int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type,
|
||||
unsigned char *md, unsigned int *len);
|
||||
|
||||
# if !defined(OPENSSL_NO_SOCK)
|
||||
X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
|
||||
# define X509_http_nbio(url) X509_load_http(url, NULL, NULL, 0)
|
||||
X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
|
||||
# define X509_CRL_http_nbio(url) X509_CRL_load_http(url, NULL, NULL, 0)
|
||||
# endif
|
||||
|
||||
# ifndef OPENSSL_NO_STDIO
|
||||
X509 *d2i_X509_fp(FILE *fp, X509 **x509);
|
||||
int i2d_X509_fp(FILE *fp, const X509 *x509);
|
||||
|
@ -328,6 +328,14 @@ IF[{- !$disabled{tests} -}]
|
||||
INCLUDE[ocspapitest]=../include ../apps/include
|
||||
DEPEND[ocspapitest]=../libcrypto libtestutil.a
|
||||
|
||||
IF[{- !$disabled{sock} -}]
|
||||
PROGRAMS{noinst}=http_test
|
||||
ENDIF
|
||||
|
||||
SOURCE[http_test]=http_test.c
|
||||
INCLUDE[http_test]=../include ../apps/include
|
||||
DEPEND[http_test]=../libcrypto libtestutil.a
|
||||
|
||||
SOURCE[dtlstest]=dtlstest.c ssltestlib.c
|
||||
INCLUDE[dtlstest]=../include ../apps/include
|
||||
DEPEND[dtlstest]=../libcrypto ../libssl libtestutil.a
|
||||
|
@ -301,15 +301,15 @@ static int test_cmp_ctx_log_cb(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
static BIO *test_http_cb(OSSL_CMP_CTX *ctx, BIO *hbio, unsigned long detail)
|
||||
static BIO *test_http_cb(BIO *bio, void *arg, int use_ssl, int detail)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int test_transfer_cb(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
|
||||
OSSL_CMP_MSG **res)
|
||||
static OSSL_CMP_MSG *test_transfer_cb(OSSL_CMP_CTX *ctx,
|
||||
const OSSL_CMP_MSG *req)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int test_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
|
||||
@ -537,6 +537,7 @@ static X509_STORE *X509_STORE_new_1(void)
|
||||
STACK_OF(TYPE)*, NULL, IS_0, \
|
||||
sk_##TYPE##_new_null(), sk_##TYPE##_free)
|
||||
|
||||
typedef OSSL_HTTP_bio_cb_t OSSL_cmp_http_cb_t;
|
||||
#define DEFINE_SET_CB_TEST(FIELD) \
|
||||
static OSSL_cmp_##FIELD##_t OSSL_CMP_CTX_get_##FIELD(const CMP_CTX *ctx) \
|
||||
{ \
|
||||
|
181
test/http_test.c
Normal file
181
test/http_test.c
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright Siemens AG 2020
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/http.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "testutil.h"
|
||||
|
||||
static const ASN1_ITEM *x509_it = NULL;
|
||||
static X509 *x509 = NULL;
|
||||
#define SERVER "mock.server"
|
||||
#define PORT "81"
|
||||
#define RPATH "path/any.crt"
|
||||
static const char *rpath;
|
||||
|
||||
static X509 *load_pem_cert(const char *file)
|
||||
{
|
||||
X509 *cert = NULL;
|
||||
BIO *bio = NULL;
|
||||
|
||||
if (!TEST_ptr(bio = BIO_new(BIO_s_file())))
|
||||
return NULL;
|
||||
if (TEST_int_gt(BIO_read_filename(bio, file), 0))
|
||||
(void)TEST_ptr(cert = PEM_read_bio_X509(bio, NULL, NULL, NULL));
|
||||
|
||||
BIO_free(bio);
|
||||
return cert;
|
||||
}
|
||||
|
||||
/*
|
||||
* pretty trivial HTTP mock server:
|
||||
* for POST, copy request headers+body from mem BIO 'in' as response to 'out'
|
||||
* for GET, first redirect the request then respond with 'rsp' of ASN1 type 'it'
|
||||
*/
|
||||
static int mock_http_server(BIO *in, BIO *out,
|
||||
ASN1_VALUE *rsp, const ASN1_ITEM *it)
|
||||
{
|
||||
const char *req;
|
||||
long count = BIO_get_mem_data(in, (unsigned char **)&req);
|
||||
const char *hdr = (char *)req;
|
||||
int is_get = count >= 4 && strncmp(hdr, "GET ", 4) == 0;
|
||||
int len;
|
||||
|
||||
/* first line should contain "<GET or POST> <rpath> HTTP/1.x" */
|
||||
if (is_get)
|
||||
hdr += 4;
|
||||
else if (TEST_true(count >= 5 && strncmp(hdr, "POST ", 5) == 0))
|
||||
hdr += 5;
|
||||
else
|
||||
return 0;
|
||||
|
||||
while (*rpath == '/')
|
||||
rpath++;
|
||||
while (*hdr == '/')
|
||||
hdr++;
|
||||
len = strlen(rpath);
|
||||
if (!TEST_strn_eq(hdr, rpath, len) || !TEST_char_eq(hdr++[len], ' '))
|
||||
return 0;
|
||||
hdr += len;
|
||||
len = strlen("HTTP/1.");
|
||||
if (!TEST_strn_eq(hdr, "HTTP/1.", len))
|
||||
return 0;
|
||||
hdr += len;
|
||||
/* check for HTTP version 1.0 .. 1.1 */
|
||||
if (!TEST_char_le('0', *hdr) || !TEST_char_le(*hdr++, '1'))
|
||||
return 0;
|
||||
if (!TEST_char_eq(*hdr++, '\r') || !TEST_char_eq(*hdr++, '\n'))
|
||||
return 0;
|
||||
count -= (hdr - req);
|
||||
if (count <= 0 || out == NULL)
|
||||
return 0;
|
||||
|
||||
if (is_get && strcmp(rpath, RPATH) == 0) {
|
||||
rpath = "path/new.crt";
|
||||
return BIO_printf(out, "HTTP/1.1 301 Moved Permanently\r\n"
|
||||
"Location: /%s\r\n\r\n", rpath) > 0; /* same server */
|
||||
}
|
||||
if (BIO_printf(out, "HTTP/1.1 200 OK\r\n") <= 0)
|
||||
return 0;
|
||||
if (is_get) { /* construct new header and body */
|
||||
if ((len = ASN1_item_i2d(rsp, NULL, it)) <= 0)
|
||||
return 0;
|
||||
if (BIO_printf(out, "Content-Type: application/x-x509-ca-cert\r\n"
|
||||
"Content-Length: %d\r\n\r\n", len) <= 0)
|
||||
return 0;
|
||||
return ASN1_item_i2d_bio(it, out, rsp);
|
||||
} else {
|
||||
return BIO_write(out, hdr, count) == count; /* echo header and body */
|
||||
}
|
||||
}
|
||||
|
||||
static long http_bio_cb_ex(BIO *bio, int oper, const char *argp, size_t len,
|
||||
int cmd, long argl, int ret, size_t *processed)
|
||||
{
|
||||
|
||||
if (oper == (BIO_CB_CTRL | BIO_CB_RETURN) && cmd == BIO_CTRL_FLUSH)
|
||||
ret = mock_http_server(bio, (BIO *)BIO_get_callback_arg(bio),
|
||||
(ASN1_VALUE *)x509, x509_it);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_http_x509(int do_get)
|
||||
{
|
||||
X509 *rcert = NULL;
|
||||
BIO *wbio = BIO_new(BIO_s_mem());
|
||||
BIO *rbio = BIO_new(BIO_s_mem());
|
||||
STACK_OF(CONF_VALUE) *headers = NULL;
|
||||
int res = 0;
|
||||
|
||||
if (wbio == NULL || rbio == NULL)
|
||||
goto err;
|
||||
BIO_set_callback_ex(wbio, http_bio_cb_ex);
|
||||
BIO_set_callback_arg(wbio, (char *)rbio);
|
||||
|
||||
rpath = RPATH;
|
||||
rcert = (X509 *)
|
||||
(do_get ?
|
||||
OSSL_HTTP_get_asn1("http://"SERVER":"PORT"/"RPATH,
|
||||
NULL /* proxy */, NULL /* proxy_port */,
|
||||
wbio, rbio, NULL /* bio_update_fn */, NULL,
|
||||
headers, 0 /* maxline */,
|
||||
0 /* max_resp_len */, 0 /* timeout */,
|
||||
"application/x-x509-ca-cert", x509_it)
|
||||
:
|
||||
OSSL_HTTP_post_asn1(SERVER, PORT, RPATH, 0 /* use_ssl */,
|
||||
NULL /* proxy */, NULL /* proxy_port */,
|
||||
wbio, rbio, NULL /* bio_update_fn */, NULL,
|
||||
headers, "application/x-x509-ca-cert",
|
||||
(ASN1_VALUE *)x509, x509_it, 0 /* maxline */,
|
||||
0 /* max_resp_len */, 0 /* timeout */,
|
||||
"application/x-x509-ca-cert", x509_it)
|
||||
);
|
||||
res = TEST_ptr(rcert) && TEST_int_eq(X509_cmp(x509, rcert), 0);
|
||||
|
||||
err:
|
||||
X509_free(rcert);
|
||||
BIO_free(wbio);
|
||||
BIO_free(rbio);
|
||||
sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int test_http_get_x509(void)
|
||||
{
|
||||
return test_http_x509(1);
|
||||
}
|
||||
|
||||
static int test_http_post_x509(void)
|
||||
{
|
||||
return test_http_x509(0);
|
||||
}
|
||||
|
||||
void cleanup_tests(void)
|
||||
{
|
||||
X509_free(x509);
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
if (!test_skip_common_options()) {
|
||||
TEST_error("Error parsing test options\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
x509_it = ASN1_ITEM_rptr(X509);
|
||||
if (!TEST_ptr((x509 = load_pem_cert(test_get_argument(0)))))
|
||||
return 1;
|
||||
|
||||
ADD_TEST(test_http_get_x509);
|
||||
ADD_TEST(test_http_post_x509);
|
||||
return 1;
|
||||
}
|
21
test/recipes/80-test_http.t
Normal file
21
test/recipes/80-test_http.t
Normal file
@ -0,0 +1,21 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
|
||||
use OpenSSL::Test qw/:DEFAULT srctop_file/;
|
||||
use OpenSSL::Test::Utils;
|
||||
|
||||
setup("test_http");
|
||||
|
||||
plan tests => 1;
|
||||
|
||||
SKIP: {
|
||||
skip "sockets disabled", 1 if disabled("sock");
|
||||
ok(run(test(["http_test",
|
||||
srctop_file("test", "certs", "ca-cert.pem")])));
|
||||
}
|
@ -42,6 +42,7 @@ s/ENGINEerr\(\w+, *(\w+)\)/ERR_raise(ERR_LIB_ENGINE, $1)/;
|
||||
s/ESSerr\(\w+, *(\w+)\)/ERR_raise(ERR_LIB_ESS, $1)/;
|
||||
s/EVPerr\(\w+, *(\w+)\)/ERR_raise(ERR_LIB_EVP, $1)/;
|
||||
s/FIPSerr\(\w+, *(\w+)\)/ERR_raise(ERR_LIB_FIPS, $1)/;
|
||||
s/HTTPerr\(\w+, *(\w+)\)/ERR_raise(ERR_LIB_HTTP, $1)/;
|
||||
s/KDFerr\(\w+, *(\w+)\)/ERR_raise(ERR_LIB_KDF, $1)/;
|
||||
s/OBJerr\(\w+, *(\w+)\)/ERR_raise(ERR_LIB_OBJ, $1)/;
|
||||
s/OCSPerr\(\w+, *(\w+)\)/ERR_raise(ERR_LIB_OCSP, $1)/;
|
||||
|
@ -245,7 +245,7 @@ RSA_get_ex_data 249 3_0_0 EXIST::FUNCTION:RSA
|
||||
EVP_PKEY_meth_get_decrypt 250 3_0_0 EXIST::FUNCTION:
|
||||
DES_cfb_encrypt 251 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_3_0,DES
|
||||
CMS_SignerInfo_set1_signer_cert 252 3_0_0 EXIST::FUNCTION:CMS
|
||||
X509_CRL_http_nbio 253 3_0_0 EXIST::FUNCTION:OCSP
|
||||
X509_CRL_load_http 253 3_0_0 EXIST::FUNCTION:SOCK
|
||||
ENGINE_register_all_ciphers 254 3_0_0 EXIST::FUNCTION:ENGINE
|
||||
SXNET_new 255 3_0_0 EXIST::FUNCTION:
|
||||
EVP_camellia_256_ctr 256 3_0_0 EXIST::FUNCTION:CAMELLIA
|
||||
@ -266,7 +266,7 @@ WHIRLPOOL_Init 271 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_3
|
||||
EVP_OpenInit 272 3_0_0 EXIST::FUNCTION:RSA
|
||||
OCSP_response_get1_basic 273 3_0_0 EXIST::FUNCTION:OCSP
|
||||
CRYPTO_gcm128_tag 274 3_0_0 EXIST::FUNCTION:
|
||||
OCSP_parse_url 275 3_0_0 EXIST::FUNCTION:OCSP
|
||||
OSSL_HTTP_parse_url 275 3_0_0 EXIST::FUNCTION:
|
||||
UI_get0_test_string 276 3_0_0 EXIST::FUNCTION:
|
||||
CRYPTO_secure_free 277 3_0_0 EXIST::FUNCTION:
|
||||
DSA_print_fp 278 3_0_0 EXIST::FUNCTION:DSA,STDIO
|
||||
@ -615,7 +615,7 @@ UI_get0_result_string 629 3_0_0 EXIST::FUNCTION:
|
||||
TS_RESP_CTX_add_policy 630 3_0_0 EXIST::FUNCTION:TS
|
||||
X509_REQ_dup 631 3_0_0 EXIST::FUNCTION:
|
||||
d2i_DSA_PUBKEY_fp 633 3_0_0 EXIST::FUNCTION:DSA,STDIO
|
||||
OCSP_REQ_CTX_nbio_d2i 634 3_0_0 EXIST::FUNCTION:OCSP
|
||||
OCSP_REQ_CTX_nbio_d2i 634 3_0_0 EXIST::FUNCTION:OCSP,SOCK
|
||||
d2i_X509_REQ_fp 635 3_0_0 EXIST::FUNCTION:STDIO
|
||||
DH_OpenSSL 636 3_0_0 EXIST::FUNCTION:DH
|
||||
BN_get_rfc3526_prime_8192 637 3_0_0 EXIST::FUNCTION:DH
|
||||
@ -1243,7 +1243,7 @@ TS_REQ_set_cert_req 1271 3_0_0 EXIST::FUNCTION:TS
|
||||
TXT_DB_get_by_index 1272 3_0_0 EXIST::FUNCTION:
|
||||
X509_check_ca 1273 3_0_0 EXIST::FUNCTION:
|
||||
DH_get_2048_224 1274 3_0_0 EXIST::FUNCTION:DH
|
||||
X509_http_nbio 1275 3_0_0 EXIST::FUNCTION:OCSP
|
||||
X509_load_http 1275 3_0_0 EXIST::FUNCTION:SOCK
|
||||
i2d_AUTHORITY_INFO_ACCESS 1276 3_0_0 EXIST::FUNCTION:
|
||||
EVP_get_cipherbyname 1277 3_0_0 EXIST::FUNCTION:
|
||||
CONF_dump_fp 1278 3_0_0 EXIST::FUNCTION:STDIO
|
||||
@ -3615,7 +3615,7 @@ EVP_CIPHER_CTX_encrypting 3694 3_0_0 EXIST::FUNCTION:
|
||||
EC_KEY_can_sign 3695 3_0_0 EXIST::FUNCTION:EC
|
||||
PEM_write_bio_RSAPublicKey 3696 3_0_0 EXIST::FUNCTION:RSA
|
||||
X509_CRL_set1_lastUpdate 3697 3_0_0 EXIST::FUNCTION:
|
||||
OCSP_sendreq_nbio 3698 3_0_0 EXIST::FUNCTION:OCSP
|
||||
OCSP_sendreq_nbio 3698 3_0_0 EXIST::FUNCTION:OCSP,SOCK
|
||||
PKCS8_encrypt 3699 3_0_0 EXIST::FUNCTION:
|
||||
i2d_PKCS7_fp 3700 3_0_0 EXIST::FUNCTION:STDIO
|
||||
i2d_X509_REQ 3701 3_0_0 EXIST::FUNCTION:
|
||||
@ -4923,3 +4923,9 @@ RAND_DRBG_get_callback_data ? 3_0_0 EXIST::FUNCTION:
|
||||
BIO_wait ? 3_0_0 EXIST::FUNCTION:SOCK
|
||||
BIO_socket_wait ? 3_0_0 EXIST::FUNCTION:SOCK
|
||||
BIO_connect_retry ? 3_0_0 EXIST::FUNCTION:SOCK
|
||||
ERR_load_HTTP_strings ? 3_0_0 EXIST::FUNCTION:
|
||||
OSSL_HTTP_get ? 3_0_0 EXIST::FUNCTION:SOCK
|
||||
OSSL_HTTP_get_asn1 ? 3_0_0 EXIST::FUNCTION:SOCK
|
||||
OSSL_HTTP_post_asn1 ? 3_0_0 EXIST::FUNCTION:SOCK
|
||||
OSSL_HTTP_transfer ? 3_0_0 EXIST::FUNCTION:SOCK
|
||||
OSSL_HTTP_proxy_connect ? 3_0_0 EXIST::FUNCTION:SOCK
|
||||
|
@ -597,6 +597,7 @@ ERR_load_ENGINE_strings(3)
|
||||
ERR_load_ERR_strings(3)
|
||||
ERR_load_ESS_strings(3)
|
||||
ERR_load_EVP_strings(3)
|
||||
ERR_load_HTTP_strings(3)
|
||||
ERR_load_KDF_strings(3)
|
||||
ERR_load_OBJ_strings(3)
|
||||
ERR_load_OCSP_strings(3)
|
||||
@ -1314,7 +1315,6 @@ X509_CRL_diff(3)
|
||||
X509_CRL_get_lastUpdate(3)
|
||||
X509_CRL_get_meth_data(3)
|
||||
X509_CRL_get_nextUpdate(3)
|
||||
X509_CRL_http_nbio(3)
|
||||
X509_CRL_it(3)
|
||||
X509_CRL_print(3)
|
||||
X509_CRL_print_ex(3)
|
||||
@ -1460,7 +1460,6 @@ X509_get_default_private_dir(3)
|
||||
X509_get_pubkey_parameters(3)
|
||||
X509_get_signature_type(3)
|
||||
X509_gmtime_adj(3)
|
||||
X509_http_nbio(3)
|
||||
X509_issuer_and_serial_hash(3)
|
||||
X509_issuer_name_hash(3)
|
||||
X509_issuer_name_hash_old(3)
|
||||
|
@ -37,6 +37,8 @@ GEN_SESSION_CB datatype
|
||||
OPENSSL_Applink external
|
||||
OPENSSL_CTX datatype
|
||||
NAMING_AUTHORITY datatype
|
||||
OCSP_parse_url define
|
||||
OSSL_HTTP_bio_cb_t datatype
|
||||
OSSL_PARAM datatype
|
||||
OSSL_PROVIDER datatype
|
||||
OSSL_SERIALIZER datatype
|
||||
@ -369,7 +371,6 @@ OSSL_CMP_log4 define
|
||||
OSSL_CMP_severity datatype
|
||||
OSSL_CMP_warn define
|
||||
OSSL_cmp_certConf_cb_t datatype
|
||||
OSSL_cmp_http_cb_t datatype
|
||||
OSSL_cmp_log_cb_t datatype
|
||||
OSSL_cmp_transfer_cb_t datatype
|
||||
OSSL_PARAM_TYPE define
|
||||
@ -548,6 +549,8 @@ SSLv23_client_method define
|
||||
SSLv23_method define
|
||||
SSLv23_server_method define
|
||||
TLS_DEFAULT_CIPHERSUITES define deprecated 3.0.0
|
||||
X509_CRL_http_nbio define
|
||||
X509_http_nbio define
|
||||
X509_STORE_set_lookup_crls_cb define
|
||||
X509_STORE_set_verify_func define
|
||||
EVP_PKEY_CTX_set1_id define
|
||||
|
Loading…
Reference in New Issue
Block a user