|
|
|
@ -208,6 +208,7 @@ IMPLEMENT_ASN1_FUNCTIONS(MsCtlContent)
|
|
|
|
|
|
|
|
|
|
/* Prototypes */
|
|
|
|
|
static ASN1_INTEGER *create_nonce(int bits);
|
|
|
|
|
static char *clrdp_url_get_x509(X509 *cert);
|
|
|
|
|
static time_t time_t_get_asn1_time(const ASN1_TIME *s);
|
|
|
|
|
static time_t time_t_get_si_time(PKCS7_SIGNER_INFO *si);
|
|
|
|
|
static ASN1_UTCTIME *asn1_time_get_si_time(PKCS7_SIGNER_INFO *si);
|
|
|
|
@ -221,10 +222,10 @@ static int X509_attribute_chain_append_object(STACK_OF(X509_ATTRIBUTE) **unauth_
|
|
|
|
|
static STACK_OF(PKCS7) *signature_list_create(PKCS7 *p7);
|
|
|
|
|
static int PKCS7_compare(const PKCS7 *const *a, const PKCS7 *const *b);
|
|
|
|
|
static PKCS7 *pkcs7_get_sigfile(FILE_FORMAT_CTX *ctx);
|
|
|
|
|
static void print_cert(X509 *cert, int i);
|
|
|
|
|
static int x509_store_load_crlfile(X509_STORE *store, char *cafile, char *crlfile);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int blob_has_nl = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
A timestamp request looks like this:
|
|
|
|
|
|
|
|
|
@ -523,8 +524,6 @@ static int attach_authenticode_response(PKCS7 *p7, PKCS7 *resp, int verbose)
|
|
|
|
|
return 0; /* OK */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef ENABLE_CURL
|
|
|
|
|
|
|
|
|
|
static void print_proxy(char *proxy)
|
|
|
|
|
{
|
|
|
|
|
if (proxy) {
|
|
|
|
@ -545,6 +544,11 @@ static void print_proxy(char *proxy)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if OPENSSL_VERSION_NUMBER<0x30000000L
|
|
|
|
|
#ifdef ENABLE_CURL
|
|
|
|
|
|
|
|
|
|
static int blob_has_nl = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Callback for writing received data
|
|
|
|
|
*/
|
|
|
|
@ -565,15 +569,15 @@ static size_t curl_write(void *ptr, size_t sz, size_t nmemb, void *stream)
|
|
|
|
|
* Get data from HTTP server.
|
|
|
|
|
* [out] http_code: HTTP status
|
|
|
|
|
* [in] url: URL of the CRL distribution point or Time-Stamp Authority HTTP server
|
|
|
|
|
* [in] bout: timestamp request
|
|
|
|
|
* [in] req: timestamp request
|
|
|
|
|
* [in] proxy: proxy to getting the timestamp through
|
|
|
|
|
* [in] noverifypeer: do not verify the Time-Stamp Authority's SSL certificate
|
|
|
|
|
* [in] verbose: additional output mode
|
|
|
|
|
* [in] content: CRL distribution point (0), RFC3161 TSA (1), Authenticode TSA (2)
|
|
|
|
|
* [returns] pointer to BIO with X509 Certificate Revocation List
|
|
|
|
|
* [in] rfc3161: Authenticode / RFC3161 Timestamp switch
|
|
|
|
|
* [returns] pointer to BIO with X509 Certificate Revocation List or timestamp response
|
|
|
|
|
*/
|
|
|
|
|
static BIO *bio_get_http(long *http_code, char *url, BIO *bout, char *proxy,
|
|
|
|
|
int noverifypeer, int verbose, int content)
|
|
|
|
|
static BIO *bio_get_http_curl(long *http_code, char *url, BIO *req, char *proxy,
|
|
|
|
|
int noverifypeer, int verbose, int rfc3161)
|
|
|
|
|
{
|
|
|
|
|
CURL *curl;
|
|
|
|
|
struct curl_slist *slist = NULL;
|
|
|
|
@ -621,24 +625,23 @@ static BIO *bio_get_http(long *http_code, char *url, BIO *bout, char *proxy,
|
|
|
|
|
printf("CURL failure: %s %s\n", curl_easy_strerror(res), url);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (content == 1) {
|
|
|
|
|
if (req) { /* POST */
|
|
|
|
|
if (rfc3161) {
|
|
|
|
|
/* RFC3161 Timestamp */
|
|
|
|
|
slist = curl_slist_append(slist, "Content-Type: application/timestamp-query");
|
|
|
|
|
slist = curl_slist_append(slist, "Accept: application/timestamp-reply");
|
|
|
|
|
} else if (content == 2) {
|
|
|
|
|
} else {
|
|
|
|
|
/* Authenticode Timestamp */
|
|
|
|
|
slist = curl_slist_append(slist, "Content-Type: application/octet-stream");
|
|
|
|
|
slist = curl_slist_append(slist, "Accept: application/octet-stream");
|
|
|
|
|
}
|
|
|
|
|
if (content > 0) {
|
|
|
|
|
/* Timestamp */
|
|
|
|
|
slist = curl_slist_append(slist, "User-Agent: Transport");
|
|
|
|
|
slist = curl_slist_append(slist, "Cache-Control: no-cache");
|
|
|
|
|
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
|
|
|
|
|
if (res != CURLE_OK) {
|
|
|
|
|
printf("CURL failure: %s %s\n", curl_easy_strerror(res), url);
|
|
|
|
|
}
|
|
|
|
|
len = BIO_get_mem_data(bout, &p);
|
|
|
|
|
len = BIO_get_mem_data(req, &p);
|
|
|
|
|
res = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
|
|
|
|
|
if (res != CURLE_OK) {
|
|
|
|
|
printf("CURL failure: %s %s\n", curl_easy_strerror(res), url);
|
|
|
|
@ -679,12 +682,285 @@ static BIO *bio_get_http(long *http_code, char *url, BIO *bout, char *proxy,
|
|
|
|
|
}
|
|
|
|
|
/* End a libcurl easy handle */
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
if (req && !rfc3161) {
|
|
|
|
|
/* BASE64 encoded Authenticode Timestamp */
|
|
|
|
|
BIO *b64 = BIO_new(BIO_f_base64());
|
|
|
|
|
|
|
|
|
|
if (!blob_has_nl)
|
|
|
|
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
|
|
|
|
bin = BIO_push(b64, bin);
|
|
|
|
|
}
|
|
|
|
|
return bin;
|
|
|
|
|
}
|
|
|
|
|
#endif /* ENABLE_CURL */
|
|
|
|
|
|
|
|
|
|
#else /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
|
|
|
|
|
|
|
|
|
/* HTTP callback function that supports TLS connection also via HTTPS proxy */
|
|
|
|
|
static BIO *http_tls_cb(BIO *bio, void *arg, int connect, int detail)
|
|
|
|
|
{
|
|
|
|
|
HTTP_TLS_Info *info = (HTTP_TLS_Info *)arg;
|
|
|
|
|
SSL_CTX *ssl_ctx = info->ssl_ctx;
|
|
|
|
|
|
|
|
|
|
if (ssl_ctx == NULL) {
|
|
|
|
|
/* not using TLS */
|
|
|
|
|
return bio;
|
|
|
|
|
}
|
|
|
|
|
if (connect && detail) {
|
|
|
|
|
/* connecting with TLS */
|
|
|
|
|
SSL *ssl;
|
|
|
|
|
BIO *sbio = NULL;
|
|
|
|
|
|
|
|
|
|
if (info->use_proxy && !OSSL_HTTP_proxy_connect(bio, info->server,
|
|
|
|
|
info->port, NULL, NULL, info->timeout, NULL, NULL)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
sbio = BIO_new(BIO_f_ssl());
|
|
|
|
|
if (sbio == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
ssl = SSL_new(ssl_ctx);
|
|
|
|
|
if (ssl == 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);
|
|
|
|
|
bio = BIO_push(sbio, bio);
|
|
|
|
|
}
|
|
|
|
|
return bio;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int verify_callback(int ok, X509_STORE_CTX *ctx)
|
|
|
|
|
{
|
|
|
|
|
if (!ok) {
|
|
|
|
|
int error = X509_STORE_CTX_get_error(ctx);
|
|
|
|
|
|
|
|
|
|
print_cert(X509_STORE_CTX_get_current_cert(ctx), 0);
|
|
|
|
|
if (error == X509_V_ERR_UNABLE_TO_GET_CRL) {
|
|
|
|
|
char *url = clrdp_url_get_x509(X509_STORE_CTX_get_current_cert(ctx));
|
|
|
|
|
|
|
|
|
|
printf("\tWarning: Ignoring \'%s\' error for CRL validation\n",
|
|
|
|
|
X509_verify_cert_error_string(error));
|
|
|
|
|
printf("\nUse the \"-HTTPS-CRLfile\" option to verify CRL\n");
|
|
|
|
|
if (url) {
|
|
|
|
|
printf("HTTPS's CRL distribution point: %s\n", url);
|
|
|
|
|
OPENSSL_free(url);
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
printf("\tError: %s\n", X509_verify_cert_error_string(error));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Decode a curl response from BIO and write it into the PKCS7 structure
|
|
|
|
|
* Read data from socket BIO
|
|
|
|
|
* [in] s_bio: socket BIO
|
|
|
|
|
* [in] rctx: open connection context
|
|
|
|
|
* [in] use_ssl: HTTPS request switch
|
|
|
|
|
* [returns] memory BIO
|
|
|
|
|
*/
|
|
|
|
|
static BIO *socket_bio_read(BIO *s_bio, OSSL_HTTP_REQ_CTX *rctx, int use_ssl)
|
|
|
|
|
{
|
|
|
|
|
int retry = 1, ok = 0, written = 0, resp_len = 0;
|
|
|
|
|
char *buf = OPENSSL_malloc(OSSL_HTTP_DEFAULT_MAX_RESP_LEN);
|
|
|
|
|
BIO *resp = BIO_new(BIO_s_mem());
|
|
|
|
|
|
|
|
|
|
if (rctx) {
|
|
|
|
|
resp_len = (int)OSSL_HTTP_REQ_CTX_get_resp_len(rctx);
|
|
|
|
|
}
|
|
|
|
|
if (resp_len == 0) {
|
|
|
|
|
if (use_ssl)
|
|
|
|
|
BIO_ssl_shutdown(s_bio);
|
|
|
|
|
else {
|
|
|
|
|
int fd = (int)BIO_get_fd(s_bio, NULL);
|
|
|
|
|
|
|
|
|
|
if (fd >= 0) {
|
|
|
|
|
#ifdef WIN32
|
|
|
|
|
(void)shutdown(fd, SD_SEND);
|
|
|
|
|
#else /* WIN32 */
|
|
|
|
|
(void)shutdown(fd, SHUT_WR);
|
|
|
|
|
#endif /* WIN32 */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ERR_clear_error();
|
|
|
|
|
while (retry) {
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
n = BIO_read(s_bio, buf, OSSL_HTTP_DEFAULT_MAX_RESP_LEN);
|
|
|
|
|
if (n > 0) {
|
|
|
|
|
written += BIO_write(resp, buf, n);
|
|
|
|
|
} else if (BIO_eof(s_bio) == 1) {
|
|
|
|
|
ok = 1;
|
|
|
|
|
retry = 0; /* EOF */
|
|
|
|
|
} else if (BIO_should_retry(s_bio)) {
|
|
|
|
|
} else {
|
|
|
|
|
unsigned long err = ERR_get_error();
|
|
|
|
|
|
|
|
|
|
if (err == 0) {
|
|
|
|
|
ok = 1;
|
|
|
|
|
retry = 0; /* use_ssl EOF */
|
|
|
|
|
} else {
|
|
|
|
|
printf("\nHTTP failure: error %ld: %s\n", err, ERR_reason_error_string(err));
|
|
|
|
|
retry = 0; /* FAILED */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (resp_len > 0 && resp_len == written) {
|
|
|
|
|
ok = 1;
|
|
|
|
|
retry = 0; /* all response has been read */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
OSSL_HTTP_close(rctx, ok);
|
|
|
|
|
OPENSSL_free(buf);
|
|
|
|
|
if (!ok) {
|
|
|
|
|
BIO_free_all(resp);
|
|
|
|
|
resp = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return resp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* pkcs7-signedData bytes found indicates DER form
|
|
|
|
|
* in otherwise BASE64 encoded
|
|
|
|
|
* '\n' newline character means BASE64 line with newline at the end
|
|
|
|
|
* in otherwise BIO_FLAGS_BASE64_NO_NL flag must me set
|
|
|
|
|
* [in, out] resp: memory BIO with Authenticode Timestamp data
|
|
|
|
|
* [returns] none
|
|
|
|
|
*/
|
|
|
|
|
static void check_authenticode_timestamp(BIO **resp)
|
|
|
|
|
{
|
|
|
|
|
u_char *ptr = NULL;
|
|
|
|
|
const u_char pkcs7_signed[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02};
|
|
|
|
|
int i, len, pkcs7_signed_len, found = 0;
|
|
|
|
|
|
|
|
|
|
len = (int)BIO_get_mem_data(*resp, &ptr);
|
|
|
|
|
if (len <= 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
pkcs7_signed_len = (int)sizeof pkcs7_signed;
|
|
|
|
|
for (i = 0; i <= len - pkcs7_signed_len; i++) {
|
|
|
|
|
if (memcmp(ptr + i, pkcs7_signed, (size_t)pkcs7_signed_len) == 0) {
|
|
|
|
|
found = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!found) {
|
|
|
|
|
/* BASE64 encoded Authenticode Timestamp */
|
|
|
|
|
BIO *b64 = BIO_new(BIO_f_base64());
|
|
|
|
|
|
|
|
|
|
if (!memchr(ptr, '\n', (size_t)len)) {
|
|
|
|
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
|
|
|
|
} else {
|
|
|
|
|
BIO *bio_mem = BIO_new_mem_buf(ptr, len);
|
|
|
|
|
BIO_push(b64, bio_mem);
|
|
|
|
|
}
|
|
|
|
|
*resp = BIO_push(b64, *resp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get data from HTTP server.
|
|
|
|
|
* [in] url: URL of the CRL distribution point or Time-Stamp Authority HTTP server
|
|
|
|
|
* [in] req: timestamp request
|
|
|
|
|
* [in] proxy: proxy to getting the timestamp through
|
|
|
|
|
* [in] rfc3161: Authenticode / RFC3161 Timestamp switch
|
|
|
|
|
* [in] cafile: file contains concatenated CA certificates in PEM format
|
|
|
|
|
* [in] crlfile: file contains Certificate Revocation List (CRLs)
|
|
|
|
|
* [returns] pointer to BIO with X509 Certificate Revocation List or timestamp response
|
|
|
|
|
*/
|
|
|
|
|
static BIO *bio_get_http(char *url, BIO *req, char *proxy, int rfc3161, char *cafile, char *crlfile)
|
|
|
|
|
{
|
|
|
|
|
BIO *tmp_bio = NULL, *s_bio = NULL, *resp = NULL;
|
|
|
|
|
OSSL_HTTP_REQ_CTX *rctx = NULL;
|
|
|
|
|
HTTP_TLS_Info info;
|
|
|
|
|
SSL_CTX *ssl_ctx = NULL;
|
|
|
|
|
char *server = NULL, *port = NULL, *path = NULL;
|
|
|
|
|
int timeout = -1; /* blocking mode, exactly one try, see BIO_do_connect_retry() */
|
|
|
|
|
int keep_alive = 1; /* prefer */
|
|
|
|
|
int use_ssl = 0;
|
|
|
|
|
|
|
|
|
|
if (!url) {
|
|
|
|
|
return NULL; /* FAILED */
|
|
|
|
|
}
|
|
|
|
|
print_proxy(proxy);
|
|
|
|
|
printf("Connecting to %s\n", url);
|
|
|
|
|
|
|
|
|
|
if (!OSSL_HTTP_parse_url(url, &use_ssl, NULL, &server, &port, NULL, &path, NULL, NULL)) {
|
|
|
|
|
return NULL; /* FAILED */
|
|
|
|
|
}
|
|
|
|
|
if (use_ssl) {
|
|
|
|
|
X509_STORE *store = NULL;
|
|
|
|
|
|
|
|
|
|
ssl_ctx = SSL_CTX_new(TLS_client_method());
|
|
|
|
|
if (cafile) {
|
|
|
|
|
printf("HTTPS-CAfile: %s\n", cafile);
|
|
|
|
|
if (crlfile)
|
|
|
|
|
printf("HTTPS-CRLfile: %s\n", crlfile);
|
|
|
|
|
store = SSL_CTX_get_cert_store(ssl_ctx);
|
|
|
|
|
if (x509_store_load_crlfile(store, cafile, crlfile))
|
|
|
|
|
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, verify_callback);
|
|
|
|
|
else
|
|
|
|
|
printf("Warning: HTTPS verification was skipped\n");
|
|
|
|
|
} else {
|
|
|
|
|
printf("Warning: HTTPS verification was skipped\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
info.server = server;
|
|
|
|
|
info.port = port;
|
|
|
|
|
info.use_proxy = OSSL_HTTP_adapt_proxy(proxy, NULL, server, use_ssl) != NULL;
|
|
|
|
|
info.timeout = timeout;
|
|
|
|
|
info.ssl_ctx = ssl_ctx;
|
|
|
|
|
|
|
|
|
|
if (!req) { /* GET */
|
|
|
|
|
const char *expected_content_type = "application/pkix-crl";
|
|
|
|
|
|
|
|
|
|
s_bio = OSSL_HTTP_get(url, proxy, NULL, NULL, NULL, http_tls_cb, &info, 0,
|
|
|
|
|
NULL, expected_content_type, 0, 0, timeout);
|
|
|
|
|
} else { /* POST */
|
|
|
|
|
const char *content_type = "application/timestamp-query"; /* RFC3161 Timestamp */
|
|
|
|
|
const char *expected_content_type = "application/timestamp-reply";
|
|
|
|
|
|
|
|
|
|
if (!rfc3161) {
|
|
|
|
|
u_char *p = NULL;
|
|
|
|
|
long len = BIO_get_mem_data(req, &p);
|
|
|
|
|
|
|
|
|
|
tmp_bio = BIO_new(BIO_s_mem());
|
|
|
|
|
BIO_write(tmp_bio, p, (int)len);
|
|
|
|
|
req = BIO_push(tmp_bio, req);
|
|
|
|
|
content_type = "application/octet-stream"; /* Authenticode Timestamp */
|
|
|
|
|
expected_content_type = "application/octet-stream";
|
|
|
|
|
}
|
|
|
|
|
s_bio = OSSL_HTTP_transfer(&rctx, server, port, path, use_ssl, proxy, NULL,
|
|
|
|
|
NULL, NULL, http_tls_cb, &info, 0, NULL, content_type, req,
|
|
|
|
|
expected_content_type, 0, 0, timeout, keep_alive);
|
|
|
|
|
BIO_free(tmp_bio);
|
|
|
|
|
}
|
|
|
|
|
OPENSSL_free(server);
|
|
|
|
|
OPENSSL_free(port);
|
|
|
|
|
OPENSSL_free(path);
|
|
|
|
|
SSL_CTX_free(ssl_ctx);
|
|
|
|
|
|
|
|
|
|
if (s_bio) {
|
|
|
|
|
resp = socket_bio_read(s_bio, rctx, use_ssl);
|
|
|
|
|
BIO_free_all(s_bio);
|
|
|
|
|
if (resp && req && !rfc3161)
|
|
|
|
|
check_authenticode_timestamp(&resp);
|
|
|
|
|
} else {
|
|
|
|
|
printf("\nHTTP failure: Failed to get data from %s\n", url);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return resp;
|
|
|
|
|
}
|
|
|
|
|
#endif /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Decode a HTTP response from BIO and write it into the PKCS7 structure
|
|
|
|
|
* Add timestamp to the PKCS7 SignerInfo structure:
|
|
|
|
|
* sig->d.sign->signer_info->unauth_attr
|
|
|
|
|
* [in, out] p7: new PKCS#7 signature
|
|
|
|
@ -695,54 +971,58 @@ static BIO *bio_get_http(long *http_code, char *url, BIO *bout, char *proxy,
|
|
|
|
|
*/
|
|
|
|
|
static int add_timestamp(PKCS7 *p7, FILE_FORMAT_CTX *ctx, char *url, int rfc3161)
|
|
|
|
|
{
|
|
|
|
|
BIO *bout, *bin;
|
|
|
|
|
BIO *req, *resp;
|
|
|
|
|
int verbose = ctx->options->verbose || ctx->options->ntsurl == 1;
|
|
|
|
|
int res = 1;
|
|
|
|
|
long http_code = -1;
|
|
|
|
|
|
|
|
|
|
/* Encode timestamp request */
|
|
|
|
|
if (rfc3161) {
|
|
|
|
|
bout = bio_encode_rfc3161_request(p7, ctx->options->md);
|
|
|
|
|
req = bio_encode_rfc3161_request(p7, ctx->options->md);
|
|
|
|
|
} else {
|
|
|
|
|
bout = bio_encode_authenticode_request(p7);
|
|
|
|
|
req = bio_encode_authenticode_request(p7);
|
|
|
|
|
}
|
|
|
|
|
if (!bout) {
|
|
|
|
|
if (!req) {
|
|
|
|
|
return 1; /* FAILED */
|
|
|
|
|
}
|
|
|
|
|
#ifdef ENABLE_CURL
|
|
|
|
|
#if OPENSSL_VERSION_NUMBER<0x30000000L
|
|
|
|
|
#ifndef ENABLE_CURL
|
|
|
|
|
(void)url;
|
|
|
|
|
(void)rfc3161;
|
|
|
|
|
printf("Could NOT find CURL\n");
|
|
|
|
|
BIO_free_all(req);
|
|
|
|
|
return NULL; /* FAILED */
|
|
|
|
|
#else /* ENABLE_CURL */
|
|
|
|
|
if (rfc3161) {
|
|
|
|
|
bin = bio_get_http(&http_code, url, bout, ctx->options->proxy,
|
|
|
|
|
resp = bio_get_http_curl(&http_code, url, req, ctx->options->proxy,
|
|
|
|
|
ctx->options->noverifypeer, verbose, 1);
|
|
|
|
|
} else {
|
|
|
|
|
bin = bio_get_http(&http_code, url, bout, ctx->options->proxy,
|
|
|
|
|
ctx->options->noverifypeer, verbose, 2);
|
|
|
|
|
resp = bio_get_http_curl(&http_code, url, req, ctx->options->proxy,
|
|
|
|
|
ctx->options->noverifypeer, verbose, 0);
|
|
|
|
|
}
|
|
|
|
|
BIO_free_all(bout);
|
|
|
|
|
#else /* ENABLE_CURL */
|
|
|
|
|
/* TODO implement an HTTP session */
|
|
|
|
|
printf("Could NOT find CURL\n");
|
|
|
|
|
return 1; /* FAILED */
|
|
|
|
|
#endif /* ENABLE_CURL */
|
|
|
|
|
|
|
|
|
|
if (bin) {
|
|
|
|
|
#else /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
|
|
|
|
if (rfc3161) {
|
|
|
|
|
resp = bio_get_http(url, req, ctx->options->proxy, 1,
|
|
|
|
|
ctx->options->noverifypeer ? NULL : ctx->options->https_cafile,
|
|
|
|
|
ctx->options->noverifypeer ? NULL : ctx->options->https_crlfile);
|
|
|
|
|
} else {
|
|
|
|
|
resp = bio_get_http(url, req, ctx->options->proxy, 0,
|
|
|
|
|
ctx->options->noverifypeer ? NULL : ctx->options->https_cafile,
|
|
|
|
|
ctx->options->noverifypeer ? NULL : ctx->options->https_crlfile);
|
|
|
|
|
}
|
|
|
|
|
#endif /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
|
|
|
|
BIO_free_all(req);
|
|
|
|
|
if (resp != NULL) {
|
|
|
|
|
if (rfc3161) {
|
|
|
|
|
/* decode a RFC 3161 response from BIO */
|
|
|
|
|
TS_RESP *response = d2i_TS_RESP_bio(bin, NULL);
|
|
|
|
|
BIO_free_all(bin);
|
|
|
|
|
TS_RESP *response = d2i_TS_RESP_bio(resp, NULL);
|
|
|
|
|
|
|
|
|
|
res = attach_rfc3161_response(p7, response, verbose);
|
|
|
|
|
TS_RESP_free(response);
|
|
|
|
|
} else {
|
|
|
|
|
/* decode an authenticode response from BIO */
|
|
|
|
|
PKCS7 *response;
|
|
|
|
|
BIO *b64, *b64_bin;
|
|
|
|
|
|
|
|
|
|
b64 = BIO_new(BIO_f_base64());
|
|
|
|
|
if (!blob_has_nl)
|
|
|
|
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
|
|
|
|
b64_bin = BIO_push(b64, bin);
|
|
|
|
|
response = d2i_PKCS7_bio(b64_bin, NULL);
|
|
|
|
|
BIO_free_all(b64_bin);
|
|
|
|
|
PKCS7 *response = d2i_PKCS7_bio(resp, NULL);
|
|
|
|
|
|
|
|
|
|
res = attach_authenticode_response(p7, response, verbose);
|
|
|
|
|
}
|
|
|
|
@ -751,11 +1031,11 @@ static int add_timestamp(PKCS7 *p7, FILE_FORMAT_CTX *ctx, char *url, int rfc3161
|
|
|
|
|
printf("Failed to convert timestamp reply from %s; "
|
|
|
|
|
"HTTP status %ld\n", url, http_code);
|
|
|
|
|
} else {
|
|
|
|
|
printf("Failed to convert timestamp reply from %s; "
|
|
|
|
|
"no HTTP status available", url);
|
|
|
|
|
printf("Failed to convert timestamp reply from %s\n", url);
|
|
|
|
|
}
|
|
|
|
|
ERR_print_errors_fp(stdout);
|
|
|
|
|
}
|
|
|
|
|
BIO_free_all(resp);
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
@ -1445,7 +1725,7 @@ static int trusted_cert(X509 *cert, int error) {
|
|
|
|
|
return 0; /* FAILED */
|
|
|
|
|
}
|
|
|
|
|
if (on_list(hex, fingerprints)) {
|
|
|
|
|
printf("\tWarning: Ignoring %s error for Windows certificate whitelist\n",
|
|
|
|
|
printf("\tWarning: Ignoring \'%s\' error for Windows certificate whitelist\n",
|
|
|
|
|
X509_verify_cert_error_string(error));
|
|
|
|
|
OPENSSL_free(hex);
|
|
|
|
|
return 1; /* trusted */
|
|
|
|
@ -1468,7 +1748,7 @@ static int verify_ca_callback(int ok, X509_STORE_CTX *ctx)
|
|
|
|
|
if (trusted_cert(current_cert, error)) {
|
|
|
|
|
return 1;
|
|
|
|
|
} else if (error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
|
|
|
|
|
printf("\tError: Unable to get local CA certificate; %s\n",
|
|
|
|
|
printf("\tError: Certificate not found in local repository: %s\n",
|
|
|
|
|
X509_verify_cert_error_string(error));
|
|
|
|
|
} else {
|
|
|
|
|
printf("\tError: %s\n", X509_verify_cert_error_string(error));
|
|
|
|
@ -1488,11 +1768,11 @@ static int verify_crl_callback(int ok, X509_STORE_CTX *ctx)
|
|
|
|
|
if (trusted_cert(current_cert, error)) {
|
|
|
|
|
return 1;
|
|
|
|
|
} else if (error == X509_V_ERR_CERT_HAS_EXPIRED) {
|
|
|
|
|
printf("\tWarning: Ignoring %s error for CRL validation\n",
|
|
|
|
|
printf("\tWarning: Ignoring \'%s\' error for CRL validation\n",
|
|
|
|
|
X509_verify_cert_error_string(error));
|
|
|
|
|
return 1;
|
|
|
|
|
} else if (error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
|
|
|
|
|
printf("\tError: Unable to get local CA certificate; %s\n",
|
|
|
|
|
printf("\tError: Certificate not found in local repository: %s\n",
|
|
|
|
|
X509_verify_cert_error_string(error));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
@ -1661,24 +1941,28 @@ out:
|
|
|
|
|
/*
|
|
|
|
|
* Get Certificate Revocation List from a CRL distribution point
|
|
|
|
|
* and write it into the X509_CRL structure.
|
|
|
|
|
* [in] proxy: proxy to getting CRL through
|
|
|
|
|
* [in] ctx: structure holds input and output data
|
|
|
|
|
* [in] url: URL of the CRL distribution point server
|
|
|
|
|
* [returns] X509 Certificate Revocation List
|
|
|
|
|
*/
|
|
|
|
|
static X509_CRL *x509_crl_get(char *proxy, char *url)
|
|
|
|
|
static X509_CRL *x509_crl_get(FILE_FORMAT_CTX *ctx, char *url)
|
|
|
|
|
{
|
|
|
|
|
X509_CRL *crl;
|
|
|
|
|
BIO *bio = NULL;
|
|
|
|
|
#ifdef ENABLE_CURL
|
|
|
|
|
long http_code = -1;
|
|
|
|
|
|
|
|
|
|
bio = bio_get_http(&http_code, url, NULL, proxy, 0, 1, 0);
|
|
|
|
|
#else /* ENABLE_CURL */
|
|
|
|
|
/* TODO implement an HTTP session */
|
|
|
|
|
(void)proxy;
|
|
|
|
|
#if OPENSSL_VERSION_NUMBER<0x30000000L
|
|
|
|
|
#ifndef ENABLE_CURL
|
|
|
|
|
printf("Could NOT find CURL\n");
|
|
|
|
|
return NULL; /* FAILED */
|
|
|
|
|
#else /* ENABLE_CURL */
|
|
|
|
|
long http_code = -1;
|
|
|
|
|
bio = bio_get_http_curl(&http_code, url, NULL, ctx->options->proxy, 0, 1, 0);
|
|
|
|
|
#endif /* ENABLE_CURL */
|
|
|
|
|
#else /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
|
|
|
|
bio = bio_get_http(url, NULL, ctx->options->proxy, 0,
|
|
|
|
|
ctx->options->noverifypeer ? NULL : ctx->options->https_cafile,
|
|
|
|
|
ctx->options->noverifypeer ? NULL : ctx->options->https_crlfile);
|
|
|
|
|
#endif /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
|
|
|
|
if (!bio) {
|
|
|
|
|
printf("Warning: Faild to get CRL from %s\n\n", url);
|
|
|
|
|
return NULL; /* FAILED */
|
|
|
|
@ -1879,7 +2163,7 @@ static int verify_timestamp(FILE_FORMAT_CTX *ctx, PKCS7 *p7, CMS_ContentInfo *ti
|
|
|
|
|
printf("Ignored TSA's CRL distribution point: %s\n", url);
|
|
|
|
|
} else {
|
|
|
|
|
printf("TSA's CRL distribution point: %s\n", url);
|
|
|
|
|
crl = x509_crl_get(ctx->options->proxy, url);
|
|
|
|
|
crl = x509_crl_get(ctx, url);
|
|
|
|
|
}
|
|
|
|
|
OPENSSL_free(url);
|
|
|
|
|
if (!crl && !ctx->options->tsa_crlfile) {
|
|
|
|
@ -2041,7 +2325,7 @@ static int verify_authenticode(FILE_FORMAT_CTX *ctx, PKCS7 *p7, time_t time, X50
|
|
|
|
|
printf("Ignored CRL distribution point: %s\n", url);
|
|
|
|
|
} else {
|
|
|
|
|
printf("CRL distribution point: %s\n", url);
|
|
|
|
|
crl = x509_crl_get(ctx->options->proxy, url);
|
|
|
|
|
crl = x509_crl_get(ctx, url);
|
|
|
|
|
}
|
|
|
|
|
OPENSSL_free(url);
|
|
|
|
|
if (!crl && !ctx->options->crlfile) {
|
|
|
|
@ -2737,7 +3021,7 @@ static int verify_signature(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
|
|
|
|
time = INVALID_TIME;
|
|
|
|
|
} else {
|
|
|
|
|
int timeok = verify_timestamp(ctx, p7, timestamp, time);
|
|
|
|
|
printf("Timestamp Server Signature verification: %s\n", timeok ? "ok" : "failed");
|
|
|
|
|
printf("\nTimestamp Server Signature verification: %s\n", timeok ? "ok" : "failed");
|
|
|
|
|
if (!timeok) {
|
|
|
|
|
time = INVALID_TIME;
|
|
|
|
|
}
|
|
|
|
@ -3035,8 +3319,10 @@ static void free_options(GLOBAL_OPTIONS *options)
|
|
|
|
|
{
|
|
|
|
|
/* If memory has not been allocated nothing is done */
|
|
|
|
|
OPENSSL_free(options->cafile);
|
|
|
|
|
OPENSSL_free(options->tsa_cafile);
|
|
|
|
|
OPENSSL_free(options->crlfile);
|
|
|
|
|
OPENSSL_free(options->https_cafile);
|
|
|
|
|
OPENSSL_free(options->https_crlfile);
|
|
|
|
|
OPENSSL_free(options->tsa_cafile);
|
|
|
|
|
OPENSSL_free(options->tsa_crlfile);
|
|
|
|
|
/* If key is NULL nothing is done */
|
|
|
|
|
EVP_PKEY_free(options->pkey);
|
|
|
|
@ -3095,6 +3381,8 @@ static void usage(const char *argv0, const char *cmd)
|
|
|
|
|
printf("%12s[ -ts <timestampurl> [ -ts ... ] [ -p <proxy> ] [ -noverifypeer ] ]\n", "");
|
|
|
|
|
printf("%12s[ -TSA-certs <TSA-certfile> ] [ -TSA-key <TSA-keyfile> ]\n", "");
|
|
|
|
|
printf("%12s[ -TSA-time <unix-time> ]\n", "");
|
|
|
|
|
printf("%12s[ -HTTPS-CAfile <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -HTTPS-CRLfile <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -time <unix-time> ]\n", "");
|
|
|
|
|
printf("%12s[ -addUnauthenticatedBlob ]\n", "");
|
|
|
|
|
printf("%12s[ -nest ]\n", "");
|
|
|
|
@ -3116,6 +3404,8 @@ static void usage(const char *argv0, const char *cmd)
|
|
|
|
|
printf("%12s[ -ts <timestampurl> [ -ts ... ] [ -p <proxy> ] [ -noverifypeer ] ]\n", "");
|
|
|
|
|
printf("%12s[ -TSA-certs <TSA-certfile> ] [ -TSA-key <TSA-keyfile> ]\n", "");
|
|
|
|
|
printf("%12s[ -TSA-time <unix-time> ]\n", "");
|
|
|
|
|
printf("%12s[ -HTTPS-CAfile <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -HTTPS-CRLfile <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -h {md5,sha1,sha2(56),sha384,sha512} ]\n", "");
|
|
|
|
|
printf("%12s[ -index <index> ]\n", "");
|
|
|
|
|
printf("%12s[ -verbose ]\n", "");
|
|
|
|
@ -3146,6 +3436,8 @@ static void usage(const char *argv0, const char *cmd)
|
|
|
|
|
printf("%12s[ -c | -catalog <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -CAfile <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -CRLfile <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -HTTPS-CAfile <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -HTTPS-CRLfile <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -TSA-CAfile <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -TSA-CRLfile <infile> ]\n", "");
|
|
|
|
|
printf("%12s[ -p <proxy> ]\n", "");
|
|
|
|
@ -3183,6 +3475,7 @@ static void help_for(const char *argv0, const char *cmd)
|
|
|
|
|
const char *cmds_certs[] = {"sign", NULL};
|
|
|
|
|
const char *cmds_comm[] = {"sign", NULL};
|
|
|
|
|
const char *cmds_CRLfile[] = {"attach-signature", "verify", NULL};
|
|
|
|
|
const char *cmds_CRLfileHTTPS[] = {"add", "sign", "verify", NULL};
|
|
|
|
|
const char *cmds_CRLfileTSA[] = {"attach-signature", "verify", NULL};
|
|
|
|
|
const char *cmds_h[] = {"add", "attach-signature", "sign", "extract-data", NULL};
|
|
|
|
|
const char *cmds_i[] = {"sign", NULL};
|
|
|
|
@ -3215,6 +3508,7 @@ static void help_for(const char *argv0, const char *cmd)
|
|
|
|
|
const char *cmds_ignore_cdp[] = {"verify", NULL};
|
|
|
|
|
const char *cmds_t[] = {"add", "sign", NULL};
|
|
|
|
|
const char *cmds_ts[] = {"add", "sign", NULL};
|
|
|
|
|
const char *cmds_CAfileHTTPS[] = {"add", "sign", "verify", NULL};
|
|
|
|
|
const char *cmds_CAfileTSA[] = {"attach-signature", "verify", NULL};
|
|
|
|
|
const char *cmds_certsTSA[] = {"add", "sign", NULL};
|
|
|
|
|
const char *cmds_keyTSA[] = {"add", "sign", NULL};
|
|
|
|
@ -3366,6 +3660,10 @@ static void help_for(const char *argv0, const char *cmd)
|
|
|
|
|
}
|
|
|
|
|
if (on_list(cmd, cmds_time))
|
|
|
|
|
printf("%-24s= the unix-time to set the signing and/or verifying time\n", "-time");
|
|
|
|
|
if (on_list(cmd, cmds_CAfileHTTPS))
|
|
|
|
|
printf("%-24s= the file containing one or more HTTPS certificates in PEM format\n", "-HTTPS-CAfile");
|
|
|
|
|
if (on_list(cmd, cmds_CRLfileHTTPS))
|
|
|
|
|
printf("%-24s= the file containing one or more HTTPS CRLs in PEM format\n", "-HTTPS-CRLfile");
|
|
|
|
|
if (on_list(cmd, cmds_CAfileTSA))
|
|
|
|
|
printf("%-24s= the file containing one or more Time-Stamp Authority certificates in PEM format\n", "-TSA-CAfile");
|
|
|
|
|
if (on_list(cmd, cmds_CRLfileTSA))
|
|
|
|
@ -3932,11 +4230,13 @@ static void print_version(void)
|
|
|
|
|
printf("%s, using:\n", "osslsigncode custom build");
|
|
|
|
|
#endif /* PACKAGE_STRING */
|
|
|
|
|
printf("\t%s (Library: %s)\n", OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
|
|
|
|
|
#if OPENSSL_VERSION_NUMBER<0x30000000L
|
|
|
|
|
#ifdef ENABLE_CURL
|
|
|
|
|
printf("\t%s\n", curl_version());
|
|
|
|
|
#else /* ENABLE_CURL */
|
|
|
|
|
printf("\t%s\n", "no libcurl available");
|
|
|
|
|
#endif /* ENABLE_CURL */
|
|
|
|
|
#endif /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
|
|
|
|
if (cafile) {
|
|
|
|
|
printf("Default -CAfile location: %s\n", cafile);
|
|
|
|
|
OPENSSL_free(cafile);
|
|
|
|
@ -4073,8 +4373,9 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
|
|
|
|
|
if (cmd == CMD_HELP) {
|
|
|
|
|
return 0; /* FAILED */
|
|
|
|
|
}
|
|
|
|
|
if (cmd == CMD_VERIFY || cmd == CMD_ATTACH) {
|
|
|
|
|
if (cmd == CMD_SIGN || cmd == CMD_VERIFY || cmd == CMD_ATTACH) {
|
|
|
|
|
options->cafile = get_cafile();
|
|
|
|
|
options->https_cafile = get_cafile();
|
|
|
|
|
options->tsa_cafile = get_cafile();
|
|
|
|
|
}
|
|
|
|
|
for (argc--,argv++; argc >= 1; argc--,argv++) {
|
|
|
|
@ -4283,6 +4584,21 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
|
|
|
|
|
return 0; /* FAILED */
|
|
|
|
|
}
|
|
|
|
|
options->crlfile = OPENSSL_strdup(*++argv);
|
|
|
|
|
} else if ((cmd == CMD_SIGN || cmd == CMD_ADD || cmd == CMD_VERIFY)
|
|
|
|
|
&& !strcmp(*argv, "-HTTPS-CAfile")) {
|
|
|
|
|
if (--argc < 1) {
|
|
|
|
|
usage(argv0, "all");
|
|
|
|
|
return 0; /* FAILED */
|
|
|
|
|
}
|
|
|
|
|
OPENSSL_free(options->https_cafile);
|
|
|
|
|
options->https_cafile = OPENSSL_strdup(*++argv);
|
|
|
|
|
} else if ((cmd == CMD_SIGN || cmd == CMD_ADD || cmd == CMD_VERIFY)
|
|
|
|
|
&& !strcmp(*argv, "-HTTPS-CRLfile")) {
|
|
|
|
|
if (--argc < 1) {
|
|
|
|
|
usage(argv0, "all");
|
|
|
|
|
return 0; /* FAILED */
|
|
|
|
|
}
|
|
|
|
|
options->https_crlfile = OPENSSL_strdup(*++argv);
|
|
|
|
|
} else if ((cmd == CMD_VERIFY || cmd == CMD_ATTACH) && (!strcmp(*argv, "-untrusted") || !strcmp(*argv, "-TSA-CAfile"))) {
|
|
|
|
|
if (--argc < 1) {
|
|
|
|
|
usage(argv0, "all");
|
|
|
|
|