/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
#include <openssl/opensslconf.h>
-#ifdef OPENSSL_NO_OCSP
-NON_EMPTY_TRANSLATION_UNIT
-#else
-# ifdef OPENSSL_SYS_VMS
-# define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined
- * on OpenVMS */
-# endif
+#ifdef OPENSSL_SYS_VMS
+ /* So fd_set and friends get properly defined on OpenVMS */
+# define _XOPEN_SOURCE_EXTENDED
+#endif
-# include <stdio.h>
-# include <stdlib.h>
-# include <string.h>
-# include <time.h>
-# include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
/* Needs to be included before the openssl headers */
-# include "apps.h"
-# include "progs.h"
-# include "internal/sockets.h"
-# include <openssl/e_os2.h>
-# include <openssl/crypto.h>
-# include <openssl/err.h>
-# include <openssl/ssl.h>
-# include <openssl/evp.h>
-# include <openssl/bn.h>
-# include <openssl/x509v3.h>
-# include <openssl/rand.h>
+#include "apps.h"
+#include "progs.h"
+#include "internal/sockets.h"
+#include <openssl/e_os2.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/x509v3.h>
+#include <openssl/rand.h>
+
+DEFINE_STACK_OF(OCSP_CERTID)
+DEFINE_STACK_OF(CONF_VALUE)
+DEFINE_STACK_OF(X509)
+DEFINE_STACK_OF_STRING()
#ifndef HAVE_FORK
# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS)
# define NO_FORK
#endif
-# if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \
+#if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \
&& !defined(OPENSSL_NO_POSIX_IO)
-# define OCSP_DAEMON
-# include <sys/types.h>
-# include <sys/wait.h>
-# include <syslog.h>
-# include <signal.h>
-# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */
-# else
-# undef LOG_INFO
-# undef LOG_WARNING
-# undef LOG_ERR
-# define LOG_INFO 0
-# define LOG_WARNING 1
-# define LOG_ERR 2
-# endif
+# define OCSP_DAEMON
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <syslog.h>
+# include <signal.h>
+# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */
+#else
+# undef LOG_INFO
+# undef LOG_WARNING
+# undef LOG_ERR
+# define LOG_INFO 0
+# define LOG_WARNING 1
+# define LOG_ERR 2
+#endif
-# if defined(OPENSSL_SYS_VXWORKS)
+#if defined(OPENSSL_SYS_VXWORKS)
/* not supported */
int setpgid(pid_t pid, pid_t pgid)
{
errno = ENOSYS;
return (pid_t) -1;
}
-# endif
+#endif
/* Maximum leeway in validity period: default 5 minutes */
-# define MAX_VALIDITY_PERIOD (5 * 60)
+#define MAX_VALIDITY_PERIOD (5 * 60)
static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
const EVP_MD *cert_id_md, X509 *issuer,
static char *prog;
static int multi = 0;
-# ifdef OCSP_DAEMON
+#ifdef OCSP_DAEMON
static int acfd = (int) INVALID_SOCKET;
static int index_changed(CA_DB *);
static void spawn_loop(void);
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
+#endif
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_RCID,
OPT_V_ENUM,
OPT_MD,
- OPT_MULTI
+ OPT_MULTI, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ocsp_options[] = {
"Connection timeout (in seconds) to the OCSP responder"},
{"resp_no_certs", OPT_RESP_NO_CERTS, '-',
"Don't include any certificates in response"},
-# ifdef OCSP_DAEMON
+#ifdef OCSP_DAEMON
{"multi", OPT_MULTI, 'p', "run multiple responder processes"},
-# endif
+#endif
{"no_certs", OPT_NO_CERTS, '-',
"Don't include any certificates in signed request"},
{"badsig", OPT_BADSIG, '-',
{"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"},
OPT_V_OPTIONS,
+ OPT_PROV_OPTIONS,
{NULL}
};
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;
}
if ((issuers = sk_X509_new_null()) == NULL)
goto end;
}
- sk_X509_push(issuers, issuer);
+ if (!sk_X509_push(issuers, issuer))
+ goto end;
break;
case OPT_CERT:
X509_free(cert);
trailing_md = 1;
break;
case OPT_MULTI:
-# ifdef OCSP_DAEMON
+#ifdef OCSP_DAEMON
multi = atoi(opt_arg());
-# endif
+#endif
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
break;
}
}
}
}
-# ifdef OCSP_DAEMON
+#ifdef OCSP_DAEMON
if (multi && acbio != NULL)
spawn_loop();
if (acbio != NULL && req_timeout > 0)
redo_accept:
if (acbio != NULL) {
-# ifdef OCSP_DAEMON
+#ifdef OCSP_DAEMON
if (index_changed(rdb)) {
CA_DB *newrdb = load_index(ridx_filename, NULL);
ridx_filename);
}
}
-# endif
+#endif
req = NULL;
if (!do_responder(&req, &cbio, acbio, req_timeout))
if (cbio != NULL)
send_ocsp_response(cbio, resp);
} else if (host != NULL) {
-# ifndef OPENSSL_NO_SOCK
+#ifndef OPENSSL_NO_SOCK
resp = process_responder(req, host, path,
port, use_ssl, headers, req_timeout);
if (resp == NULL)
goto end;
-# else
+#else
BIO_printf(bio_err,
"Error creating connect BIO - sockets not supported.\n");
goto end;
-# endif
+#endif
} else if (respin != NULL) {
derbio = bio_open_default(respin, 'r', FORMAT_ASN1);
if (derbio == NULL)
va_list ap;
va_start(ap, fmt);
-# ifdef OCSP_DAEMON
+#ifdef OCSP_DAEMON
if (multi) {
char buf[1024];
if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0) {
if (level >= LOG_ERR)
ERR_print_errors_cb(print_syslog, &level);
}
-# endif
+#endif
if (!multi) {
BIO_printf(bio_err, "%s: ", prog);
BIO_vprintf(bio_err, fmt, ap);
va_end(ap);
}
-# ifdef OCSP_DAEMON
+#ifdef OCSP_DAEMON
static int print_syslog(const char *str, size_t len, void *levPtr)
{
syslog(LOG_INFO, "terminating on signal: %d", termsig);
killall(0, kidpids);
}
-# endif
+#endif
static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
const EVP_MD *cert_id_md, X509 *issuer,
STACK_OF(OCSP_CERTID) *ids)
{
OCSP_CERTID *id;
- X509_NAME *iname;
+ const X509_NAME *iname;
ASN1_BIT_STRING *ikey;
ASN1_INTEGER *sno;
static BIO *init_responder(const char *port)
{
-# ifdef OPENSSL_NO_SOCK
+#ifdef OPENSSL_NO_SOCK
BIO_printf(bio_err,
"Error setting up accept BIO - sockets not supported.\n");
return NULL;
-# else
+#else
BIO *acbio = NULL, *bufbio = NULL;
bufbio = BIO_new(BIO_f_buffer());
BIO_free_all(acbio);
BIO_free(bufbio);
return NULL;
-# endif
+#endif
}
-# ifndef OPENSSL_NO_SOCK
+#ifndef OPENSSL_NO_SOCK
/*
* Decode %xx URL-decoding in-place. Ignores mal-formed sequences.
*/
*out = '\0';
return (int)(out - save);
}
-# endif
+#endif
-# ifdef OCSP_DAEMON
+#ifdef OCSP_DAEMON
static void socket_timeout(int signum)
{
if (acfd != (int)INVALID_SOCKET)
(void)shutdown(acfd, SHUT_RD);
}
-# endif
+#endif
static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
int timeout)
{
-# ifdef OPENSSL_NO_SOCK
+#ifdef OPENSSL_NO_SOCK
return 0;
-# else
+#else
int len;
OCSP_REQUEST *req = NULL;
char inbuf[2048], reqbuf[2048];
*pcbio = cbio;
client = BIO_get_peer_name(cbio);
-# ifdef OCSP_DAEMON
+# ifdef OCSP_DAEMON
if (timeout > 0) {
(void) BIO_get_fd(cbio, &acfd);
alarm(timeout);
}
-# endif
+# endif
/* Read the request line. */
len = BIO_gets(cbio, reqbuf, sizeof(reqbuf));
break;
}
-# ifdef OCSP_DAEMON
+# ifdef OCSP_DAEMON
/* Clear alarm before we close the client socket */
alarm(0);
timeout = 0;
-# endif
+# endif
/* Try to read OCSP request */
if (getbio != NULL) {
*preq = req;
out:
-# ifdef OCSP_DAEMON
+# ifdef OCSP_DAEMON
if (timeout > 0)
alarm(0);
acfd = (int)INVALID_SOCKET;
-# endif
- return 1;
# endif
+ return 1;
+#endif
}
static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
return 1;
}
-# 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;
-}
-
+#ifndef OPENSSL_NO_SOCK
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;
}
-# endif
-
#endif