Merge sslsplit develop changes

pull/13/head
Soner Tari 6 years ago
parent e8054deed3
commit 0c8348db75

@ -1,7 +1,10 @@
# Authors
SSLsplit was written and is being maintained by
[Daniel Roethlisberger](https://daniel.roe.ch/).
SSLsplit was written by
[Daniel Roethlisberger](https://github.com/droe).
SSLsplit is currently maintained by
[Daniel Roethlisberger](https://github.com/droe) and
[Soner Tari](https://github.com/sonertari).
The following individuals have contributed to the codebase by submitting
patches or pull requests, in chronological order of their first contribution:
@ -22,6 +25,7 @@ patches or pull requests, in chronological order of their first contribution:
- Hilko Bengen ([hillu](https://github.com/hillu))
- Philip Duldig ([pduldig-at-tw](https://github.com/pduldig-at-tw))
- Levente Polyak ([anthraxx](https://github.com/anthraxx))
- Nick French ([naf419](https://github.com/naf419))
Many more individuals have contributed by reporting bugs or feature requests.
See [issue tracker on Github][1], `NEWS.md` and `git log` for details.

@ -240,6 +240,7 @@ ifdef OPENSSL_BASE
OPENSSL_FIND:= $(wildcard $(OPENSSL_BASE)/$(OPENSSL_PAT))
else
OPENSSL_FIND:= $(wildcard \
/usr/local/opt/openssl/$(OPENSSL_PAT) \
/opt/local/$(OPENSSL_PAT) \
/usr/local/$(OPENSSL_PAT) \
/usr/$(OPENSSL_PAT))
@ -257,6 +258,7 @@ ifdef LIBEVENT_BASE
LIBEVENT_FIND:= $(wildcard $(LIBEVENT_BASE)/$(LIBEVENT_PAT))
else
LIBEVENT_FIND:= $(wildcard \
/usr/local/opt/libevent/$(LIBEVENT_PAT) \
/opt/local/$(LIBEVENT_PAT) \
/usr/local/$(LIBEVENT_PAT) \
/usr/$(LIBEVENT_PAT))
@ -274,6 +276,7 @@ ifdef CHECK_BASE
CHECK_FIND:= $(wildcard $(CHECK_BASE)/$(CHECK_PAT))
else
CHECK_FIND:= $(wildcard \
/usr/local/opt/check/$(CHECK_PAT) \
/opt/local/$(CHECK_PAT) \
/usr/local/$(CHECK_PAT) \
/usr/$(CHECK_PAT))
@ -414,6 +417,9 @@ test: $(TARGET).test
$(MAKE) -C extra/pki testreqs session
./$(TARGET).test
sudotest: test
sudo ./$(TARGET).test
$(TARGET).test: $(TOBJS)
$(CC) $(LDFLAGS) $(TPKG_LDFLAGS) -o $@ $^ $(LIBS) $(TPKG_LIBS)

@ -1,10 +1,21 @@
### SSLsplit develop
- Add -f option for loading configuration from file (pull req #193).
- Add `sudotest` target with unit tests which require privileges to run.
- Minor bugfixes and improvements.
### SSLsplit 0.5.3 2018-07-20
- Add -a and -b for initial basic client certificate support (pull req #194
by @naf419, issue #46).
- Respect `SOURCE_DATE_EPOCH` for reproducible builds (pull req #192 by
@anthraxx).
- Sign using SHA-256 instead of SHA-1 when key type of server and key type
of used CA certificate differ (issue #189).
- Fix keyUsage to match the type of leaf key used instead of copying from
upstream certificate (issue #195).
- Fix build with OpenSSL 1.1.1 (pull req #186 by @sonertari, issue #183).
- Fix build on FreeBSD 12 (patch-proc.c r436571 from FreeBSD ports).
- Minor bugfixes and improvements.

@ -139,6 +139,7 @@ With OpenSSL, libevent 2.x, pkg-config and check available, run:
make
make test # optional unit tests
make sudotest # optional unit tests requiring privileges
make install # optional install
Dependencies are autoconfigured using pkg-config. If dependencies are not
@ -147,7 +148,7 @@ respective locations manually by setting `OPENSSL_BASE`, `LIBEVENT_BASE` and/or
`CHECK_BASE` to the respective prefixes.
You can override the default install prefix (`/usr/local`) by setting `PREFIX`.
For more build options see `GNUmakefile`.
For more build options see `GNUmakefile` and `defaults.h`.
## Documentation

@ -34,10 +34,16 @@
*/
/*
* User to drop privileges to by default.
* User to drop privileges to by default. This user needs to be allowed to
* create outbound TCP connections, and in some configurations, perform DNS
* resolution.
*
* Packagers may want to use a specific service user account instead of
* overloading nobody with yet another use case. Using nobody for source
* builds makes sense because chances are high that it exists.
* builds makes sense because chances are high that it exists. Good practice
* is to create a dedicated user for sslsplit.
*
* Make sure to also patch the manual page if you patch this.
*/
#define DFLT_DROPUSER "nobody"

@ -0,0 +1,86 @@
/*-
* SSLsplit - transparent SSL/TLS interception
* https://www.roe.ch/SSLsplit
*
* Copyright (c) 2009-2018, Daniel Roethlisberger <daniel@roe.ch>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "sys.h"
#include "defaults.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <check.h>
#define CONNECT_CMD "openssl s_client -connect www.google.com:443" \
" -quiet -no_ign_eof </dev/null >/dev/null 2>/dev/null"
START_TEST(defaults_dropuser_01)
{
fail_unless(0 == sys_privdrop(DFLT_DROPUSER, NULL, NULL),
"privdrop failed");
}
END_TEST
/*
* This test is designed to fail in the third assertion if the currently
* configured default dropuser is not allowed to make outbound network
* connections.
*/
START_TEST(defaults_dropuser_02)
{
fail_unless(0 == system(CONNECT_CMD),
"connect failed for user running tests");
fail_unless(0 == sys_privdrop(DFLT_DROPUSER, NULL, NULL),
"privdrop failed");
fail_unless(0 == system(CONNECT_CMD),
"connect failed for default dropuser " DFLT_DROPUSER);
}
END_TEST
Suite *
defaults_suite(void)
{
Suite *s;
TCase *tc;
s = suite_create("defaults");
tc = tcase_create("dropuser");
if (getuid() == 0) {
tcase_add_test(tc, defaults_dropuser_01);
tcase_add_test(tc, defaults_dropuser_02);
} else {
fprintf(stderr, "2 tests omitted because "
"not running as root\n");
}
suite_add_tcase(s, tc);
return s;
}
/* vim: set noet ft=c: */

@ -116,7 +116,7 @@ session.pem: server.pem
$(OPENSSL) s_server -accept 46143 -cert server.pem -quiet $(NO_SSL2) & \
pid=$$! ; \
sleep 1 ; \
echo q | $(OPENSSL) s_client -connect localhost:46143 \
echo q | $(OPENSSL) s_client -connect 127.0.0.1:46143 \
-quiet -no_ign_eof -sess_out $@ ; \
kill $$pid
test -r $@

@ -140,6 +140,8 @@ main_usage(void)
" -O deny all OCSP requests on all proxyspecs\n"
" -P passthrough SSL connections if they cannot be split because of\n"
" client cert auth or no matching cert and no CA (default: drop)\n"
" -a pemfile use cert from pemfile when destination requests client certs\n"
" -b pemfile use key from pemfile when destination requests client certs\n"
#ifndef OPENSSL_NO_DH
" -g pemfile use DH group params from pemfile (default: keyfiles or auto)\n"
#define OPT_g "g:"
@ -304,8 +306,8 @@ main(int argc, char *argv[])
natengine = NULL;
}
while ((ch = getopt(argc, argv, OPT_g OPT_G OPT_Z OPT_i "k:c:C:K:t:"
"OPs:r:R:e:Eu:m:j:p:l:L:S:F:M:dD::VhW:w:q:f:I")) != -1) {
while ((ch = getopt(argc, argv, OPT_g OPT_G OPT_Z OPT_i "k:c:C:K:t:OPa:"
"b:s:r:R:e:Eu:m:j:p:l:L:S:F:M:dD::VhW:w:q:f:I")) != -1) {
switch (ch) {
case 'f':
if (opts->conffile)
@ -339,6 +341,12 @@ main(int argc, char *argv[])
case 'P':
opts_set_passthrough(opts);
break;
case 'a':
opts_set_clientcrt(opts, argv0, optarg);
break;
case 'b':
opts_set_clientkey(opts, argv0, optarg);
break;
#ifndef OPENSSL_NO_DH
case 'g':
opts_set_dh(opts, argv0, optarg);
@ -715,6 +723,10 @@ main(int argc, char *argv[])
strerror(errno), errno);
exit(EXIT_FAILURE);
}
log_dbg_printf("Dropped privs to user %s group %s chroot %s\n",
opts->dropuser ? opts->dropuser : "-",
opts->dropgroup ? opts->dropgroup : "-",
opts->jaildir ? opts->jaildir : "-");
if (ssl_reinit() == -1) {
fprintf(stderr, "%s: failed to reinit SSL\n", argv0);
goto out_sslreinit_failed;

@ -79,6 +79,7 @@ Suite * base64_suite(void);
Suite * url_suite(void);
Suite * util_suite(void);
Suite * pxythrmgr_suite(void);
Suite * defaults_suite(void);
int
main(UNUSED int argc, UNUSED char *argv[])
@ -102,6 +103,7 @@ main(UNUSED int argc, UNUSED char *argv[])
srunner_add_suite(sr, url_suite());
srunner_add_suite(sr, util_suite());
srunner_add_suite(sr, pxythrmgr_suite());
srunner_add_suite(sr, defaults_suite());
srunner_run_all(sr, CK_NORMAL);
nfail = srunner_ntests_failed(sr);
srunner_free(sr);

@ -36,7 +36,7 @@
#include <event2/util.h>
// The longest natengine is "netfilter"
/* The longest natengine is "netfilter" */
#define NATENGINE_SIZE 10
typedef int (*nat_lookup_cb_t)(struct sockaddr *, socklen_t *, evutil_socket_t,

@ -78,6 +78,12 @@ void
opts_free(opts_t *opts)
{
sk_X509_pop_free(opts->chain, X509_free);
if (opts->clientcrt) {
X509_free(opts->clientcrt);
}
if (opts->clientkey) {
EVP_PKEY_free(opts->clientkey);
}
if (opts->cacrt) {
X509_free(opts->cacrt);
}
@ -257,7 +263,7 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine, proxyspec_t **o
spec->next = *opts_spec;
*opts_spec = spec;
// Defaults
/* Defaults */
spec->ssl = 0;
spec->http = 0;
spec->upgrade = 0;
@ -265,7 +271,7 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine, proxyspec_t **o
spec->pop3 = 0;
spec->smtp = 0;
if (!strcmp(**argv, "tcp")) {
// use defaults
/* use defaults */
} else
if (!strcmp(**argv, "ssl")) {
spec->ssl = 1;
@ -561,7 +567,7 @@ opts_set_cacrt(opts_t *opts, const char *argv0, const char *optarg)
opts->dh = ssl_dh_load(optarg);
}
#endif /* !OPENSSL_NO_DH */
fprintf(stderr, "CACrt: %s\n", optarg);
fprintf(stderr, "CACert: %s\n", optarg);
}
void
@ -720,6 +726,48 @@ opts_unset_passthrough(opts_t *opts)
opts->passthrough = 0;
}
void
opts_set_clientcrt(opts_t *opts, const char *argv0, const char *optarg)
{
if (opts->clientcrt)
X509_free(opts->clientcrt);
opts->clientcrt = ssl_x509_load(optarg);
if (!opts->clientcrt) {
fprintf(stderr, "%s: error loading cli"
"ent cert from '%s':\n",
argv0, optarg);
if (errno) {
fprintf(stderr, "%s\n",
strerror(errno));
} else {
ERR_print_errors_fp(stderr);
}
exit(EXIT_FAILURE);
}
fprintf(stderr, "ClientCert: %s\n", optarg);
}
void
opts_set_clientkey(opts_t *opts, const char *argv0, const char *optarg)
{
if (opts->clientkey)
EVP_PKEY_free(opts->clientkey);
opts->clientkey = ssl_key_load(optarg);
if (!opts->clientkey) {
fprintf(stderr, "%s: error loading cli"
"ent key from '%s':\n",
argv0, optarg);
if (errno) {
fprintf(stderr, "%s\n",
strerror(errno));
} else {
ERR_print_errors_fp(stderr);
}
exit(EXIT_FAILURE);
}
fprintf(stderr, "ClientKey: %s\n", optarg);
}
#ifndef OPENSSL_NO_DH
void
opts_set_dh(opts_t *opts, const char *argv0, const char *optarg)
@ -1227,7 +1275,7 @@ opts_unset_allow_wrong_host(opts_t *opts)
static int
check_value_yesno(char *value, char *name, int line_num)
{
// Compare strlen(s2)+1 chars to match exactly
/* Compare strlen(s2)+1 chars to match exactly */
if (!strncmp(value, "yes", 4)) {
return 1;
} else if (!strncmp(value, "no", 3)) {
@ -1271,16 +1319,16 @@ load_conffile(opts_t *opts, const char *argv0, const char *prev_natengine)
}
line_num++;
// Skip white space
/* Skip white space */
for (name = line; *name == ' ' || *name == '\t'; name++);
// Skip comments and empty lines
/* Skip comments and empty lines */
if ((name[0] == '\0') || (name[0] == '#') || (name[0] == ';') ||
(name[0] == '\r') || (name[0] == '\n')) {
continue;
}
// Skip to the end of option name and terminate it with '\0'
/* Skip to the end of option name and terminate it with '\0' */
for (n = name;; n++) {
if (*n == ' ' || *n == '\t') {
*n = '\0';
@ -1293,21 +1341,21 @@ load_conffile(opts_t *opts, const char *argv0, const char *prev_natengine)
}
}
// No value
/* No value */
if (n == NULL) {
fprintf(stderr, "Error in conf file: No value at line %d\n", line_num);
goto leave;
}
// Skip white space before value
/* Skip white space before value */
while (*n == ' ' || *n == '\t') {
n++;
}
value = n;
// Find end of value and terminate it with '\0'
// Find first occurrence of trailing white space
/* Find end of value and terminate it with '\0'
Find first occurrence of trailing white space */
value_end = NULL;
for (v = value;; v++) {
if (*v == '\0') {
@ -1330,11 +1378,15 @@ load_conffile(opts_t *opts, const char *argv0, const char *prev_natengine)
*value_end = '\0';
}
// Compare strlen(s2)+1 chars to match exactly
/* Compare strlen(s2)+1 chars to match exactly */
if (!strncmp(name, "CACert", 7)) {
opts_set_cacrt(opts, argv0, value);
} else if (!strncmp(name, "CAKey", 6)) {
opts_set_cakey(opts, argv0, value);
} else if (!strncmp(name, "ClientCert", 11)) {
opts_set_clientcrt(opts, argv0, value);
} else if (!strncmp(name, "ClientKey", 10)) {
opts_set_clientkey(opts, argv0, value);
} else if (!strncmp(name, "CAChain", 8)) {
opts_set_chain(opts, argv0, value);
} else if (!strncmp(name, "LeafCerts", 10)) {
@ -1431,14 +1483,14 @@ load_conffile(opts_t *opts, const char *argv0, const char *prev_natengine)
} else if (!strncmp(name, "DebugLevel", 11)) {
opts_set_debug_level(value);
} else if (!strncmp(name, "ProxySpec", 10)) {
// Use MAX_TOKEN instead of computing the actual number of tokens in value
/* Use MAX_TOKEN instead of computing the actual number of tokens in value */
char **argv = malloc(sizeof(char *) * MAX_TOKEN);
char **save_argv = argv;
int argc = 0;
char *p, *last = NULL;
for ((p = strtok_r(value, " ", &last)); p; (p = strtok_r(NULL, " ", &last))) {
// Limit max # token
/* Limit max # token */
if (argc < MAX_TOKEN) {
argv[argc++] = p;
} else {

@ -112,6 +112,8 @@ typedef struct opts {
EVP_PKEY *cakey;
EVP_PKEY *key;
STACK_OF(X509) *chain;
X509 *clientcrt;
EVP_PKEY *clientkey;
#ifndef OPENSSL_NO_DH
DH *dh;
#endif /* !OPENSSL_NO_DH */
@ -155,6 +157,8 @@ void opts_set_certgendir_writeall(opts_t *, const char *, const char *) NONNULL(
void opts_set_certgendir_writegencerts(opts_t *, const char *, const char *) NONNULL(1,2,3);
void opts_set_deny_ocsp(opts_t *) NONNULL(1);
void opts_set_passthrough(opts_t *) NONNULL(1);
void opts_set_clientcrt(opts_t *, const char *, const char *) NONNULL(1,2,3);
void opts_set_clientkey(opts_t *, const char *, const char *) NONNULL(1,2,3);
#ifndef OPENSSL_NO_DH
void opts_set_dh(opts_t *, const char *, const char *) NONNULL(1,2,3);
#endif /* !OPENSSL_NO_DH */

@ -1339,6 +1339,15 @@ pxy_dstssl_create(pxy_conn_ctx_t *ctx)
SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, NULL);
}
if (ctx->opts->clientcrt) {
if (!SSL_CTX_use_certificate(sslctx, ctx->opts->clientcrt))
log_dbg_printf("loading client certificate failed");
}
if (ctx->opts->clientkey) {
if (!SSL_CTX_use_PrivateKey(sslctx, ctx->opts->clientkey))
log_dbg_printf("loading client key failed");
}
ssl = SSL_new(sslctx);
SSL_CTX_free(sslctx); /* SSL_new() increments refcount */
if (!ssl) {

53
ssl.c

@ -264,7 +264,7 @@ ssl_openssl_version(void)
*/
static int ssl_initialized = 0;
#if defined(OPENSSL_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
#if defined(OPENSSL_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
struct CRYPTO_dynlock_value {
pthread_mutex_t mutex;
};
@ -372,7 +372,7 @@ ssl_init(void)
OpenSSL_add_all_algorithms();
/* thread-safety */
#if defined(OPENSSL_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
#if defined(OPENSSL_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
ssl_mutex_num = CRYPTO_num_locks();
ssl_mutex = malloc(ssl_mutex_num * sizeof(*ssl_mutex));
for (int i = 0; i < ssl_mutex_num; i++) {
@ -441,7 +441,7 @@ ssl_reinit(void)
if (!ssl_initialized)
return 0;
#if defined(OPENSSL_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
#if defined(OPENSSL_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
for (int i = 0; i < ssl_mutex_num; i++) {
if (pthread_mutex_init(&ssl_mutex[i], NULL)) {
return -1;
@ -466,7 +466,7 @@ ssl_fini(void)
ERR_remove_state(0); /* current thread */
#endif
#if defined(OPENSSL_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
#if defined(OPENSSL_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
CRYPTO_set_locking_callback(NULL);
CRYPTO_set_dynlock_create_callback(NULL);
CRYPTO_set_dynlock_lock_callback(NULL);
@ -881,6 +881,36 @@ ssl_x509_serial_copyrand(X509 *dstcrt, X509 *srccrt)
return 0;
}
/*
* Returns the appropriate key usage strings for the type of server key.
* Return value should conceptually be const, but OpenSSL does not use const
* appropriately.
*/
static char *
ssl_key_usage_for_key(EVP_PKEY *key)
{
switch (EVP_PKEY_type(EVP_PKEY_base_id(key))) {
#ifndef OPENSSL_NO_RSA
case EVP_PKEY_RSA:
return "keyEncipherment,digitalSignature";
#endif /* !OPENSSL_NO_RSA */
#ifndef OPENSSL_NO_DH
case EVP_PKEY_DH:
return "keyAgreement";
#endif /* !OPENSSL_NO_DH */
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
return "digitalSignature";
#endif /* !OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_ECDSA
case EVP_PKEY_EC:
return "digitalSignature,keyAgreement";
#endif /* !OPENSSL_NO_ECDSA */
default:
return "keyEncipherment,keyAgreement,digitalSignature";
}
}
/*
* Create a fake X509v3 certificate, signed by the provided CA,
* based on the original certificate retrieved from the real server.
@ -934,12 +964,9 @@ ssl_x509_forge(X509 *cacrt, EVP_PKEY *cakey, X509 *origcrt, EVP_PKEY *key,
if (rv == -1)
goto errout;
rv = ssl_x509_v3ext_copy_by_nid(crt, origcrt,
NID_key_usage);
if (rv == 0)
rv = ssl_x509_v3ext_add(&ctx, crt, "keyUsage",
"digitalSignature,"
"keyEncipherment");
/* key usage depends on the key type, do not copy from original */
rv = ssl_x509_v3ext_add(&ctx, crt, "keyUsage",
ssl_key_usage_for_key(key));
if (rv == -1)
goto errout;
@ -1426,7 +1453,7 @@ ssl_x509_fingerprint(X509 *crt, int colons)
void
ssl_dh_refcount_inc(DH *dh)
{
#if defined(OPENSSL_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
#if defined(OPENSSL_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
CRYPTO_add(&dh->references, 1, CRYPTO_LOCK_DH);
#else /* !OPENSSL_THREADS */
DH_up_ref(dh);
@ -1441,7 +1468,7 @@ ssl_dh_refcount_inc(DH *dh)
void
ssl_key_refcount_inc(EVP_PKEY *key)
{
#if defined(OPENSSL_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
#if defined(OPENSSL_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
CRYPTO_add(&key->references, 1, CRYPTO_LOCK_EVP_PKEY);
#else /* !OPENSSL_THREADS */
EVP_PKEY_up_ref(key);
@ -1456,7 +1483,7 @@ ssl_key_refcount_inc(EVP_PKEY *key)
void
ssl_x509_refcount_inc(X509 *crt)
{
#if defined(OPENSSL_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
#if defined(OPENSSL_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
CRYPTO_add(&crt->references, 1, CRYPTO_LOCK_X509);
#else /* !OPENSSL_THREADS */
X509_up_ref(crt);

Loading…
Cancel
Save