Example #1
0
/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
ENGINE *
ENGINE_get_next(ENGINE *e)
{
	ENGINE *ret = NULL;

	if (e == NULL) {
		ENGINEerr(ENGINE_F_ENGINE_GET_NEXT,
		    ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}
	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
	ret = e->next;
	if (ret) {
		/* Return a valid structural refernce to the next ENGINE */
		ret->struct_ref++;
		engine_ref_debug(ret, 0, 1)
	}
	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
	/* Release the structural reference to the previous ENGINE */
	ENGINE_free(e);
	return ret;
}
Example #2
0
void ENGINE_load_qat(void)
{
    ENGINE *toadd;
    int error = 0;
    char error_string[QAT_MAX_ERROR_STRING] = { 0 };

    QAT_DEBUG_LOG_INIT();
    DEBUG("- Starting\n");

    toadd = engine_qat();
    if (toadd == NULL) {
        error = ERR_peek_error();
        ERR_error_string_n(error, error_string, QAT_MAX_ERROR_STRING);
        WARN("Error reported by engine load: %s\n", error_string);
        return;
    }

    DEBUG("adding engine\n");
    ENGINE_add(toadd);
    ENGINE_free(toadd);
    ERR_clear_error();
}
Example #3
0
static ENGINE *engine_ibmca(void)

	{

	ENGINE *ret = ENGINE_new();

	if(!ret)

		return NULL;

	if(!bind_helper(ret))

		{

		ENGINE_free(ret);

		return NULL;

		}

	return ret;

	}
Example #4
0
// Destructor
OSSLCryptoFactory::~OSSLCryptoFactory()
{
#ifdef WITH_GOST
	// Finish the GOST engine
	if (eg != NULL)
	{
		ENGINE_finish(eg);
		ENGINE_free(eg);
		eg = NULL;
	}
#endif

	// Destroy the one-and-only RNG
	delete rng;

	// Recycle locks
	CRYPTO_set_locking_callback(NULL);
	for (unsigned i = 0; i < nlocks; i++)
	{
		MutexFactory::i()->recycleMutex(locks[i]);
	}
	delete[] locks;
}
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
					const char *str, int len)
	{
	int i;
	const EVP_PKEY_ASN1_METHOD *ameth;
	if (len == -1)
		len = TINYCLR_SSL_STRLEN(str);
	if (pe)
		{
#ifndef OPENSSL_NO_ENGINE
		ENGINE *e;
		ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
		if (ameth)
			{
			/* Convert structural into
			 * functional reference
			 */
			if (!ENGINE_init(e))
				ameth = NULL;
			ENGINE_free(e);
			*pe = e;
			return ameth;
			}
#endif
		*pe = NULL;
		}
	for (i = 0; i < EVP_PKEY_asn1_get_count(); i++)
		{
		ameth = EVP_PKEY_asn1_get0(i);
		if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
			continue;
		if (((int)TINYCLR_SSL_STRLEN(ameth->pem_str) == len) && 
			!TINYCLR_SSL_STRNCASECMP(ameth->pem_str, str, len))
			return ameth;
		}
	return NULL;
	}
Example #6
0
int TS_CONF_set_default_engine(const char *name)
{
    ENGINE *e = NULL;
    int ret = 0;

    if (strcmp(name, "builtin") == 0)
        return 1;

    if ((e = ENGINE_by_id(name)) == NULL)
        goto err;
    if (strcmp(name, "chil") == 0)
        ENGINE_ctrl(e, ENGINE_CTRL_CHIL_SET_FORKCHECK, 1, 0, 0);
    if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
        goto err;
    ret = 1;

 err:
    if (!ret) {
        TSerr(TS_F_TS_CONF_SET_DEFAULT_ENGINE, TS_R_COULD_NOT_SET_ENGINE);
        ERR_add_error_data(2, "engine:", name);
    }
    ENGINE_free(e);
    return ret;
}
Example #7
0
int64_t s2n_public_random(int64_t max)
{
    uint64_t r;

    gt_check(max, 0);

    while(1) {
        struct s2n_blob blob = { .data = (void *) &r, sizeof(r) };
        GUARD(s2n_get_public_random_data(&blob));

        /* Imagine an int was one byte and UINT_MAX was 256. If the
         * caller asked for s2n_random(129, ...) we'd end up in
         * trouble. Each number in the range 0...127 would be twice
         * as likely as 128. That's because r == 0 % 129 -> 0, and
         * r == 129 % 129 -> 0, but only r == 128 returns 128,
         * r == 257 is out of range.
         *
         * To de-bias the dice, we discard values of r that are higher
         * that the highest multiple of 'max' an int can support. If
         * max is a uint, then in the worst case we discard 50% - 1 r's.
         * But since 'max' is an int and INT_MAX is <= UINT_MAX / 2,
         * in the worst case we discard 25% - 1 r's.
         */
        if (r < (UINT64_MAX - (UINT64_MAX % max))) {
            return r % max;
        }
    }

    return -1;
}

#ifndef OPENSSL_IS_BORINGSSL

int s2n_openssl_compat_rand(unsigned char *buf, int num)
{
    struct s2n_blob out = {.data = buf, .size = num};

    if(s2n_get_private_random_data(&out) < 0) {
        return 0;
    }
    return 1;
}

int s2n_openssl_compat_status(void)
{
    return 1;
}

int s2n_openssl_compat_init(ENGINE *unused)
{
    return 1;
}

RAND_METHOD s2n_openssl_rand_method = {
    .seed = NULL,
    .bytes = s2n_openssl_compat_rand,
    .cleanup = NULL,
    .add = NULL,
    .pseudorand = s2n_openssl_compat_rand,
    .status = s2n_openssl_compat_status
};
#endif

int s2n_init(void)
{
    GUARD(s2n_mem_init());

    OPEN:
    entropy_fd = open(ENTROPY_SOURCE, O_RDONLY);
    if (entropy_fd == -1) {
        if (errno == EINTR) {
            goto OPEN;
        }
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }

#if defined(MAP_INHERIT_ZERO)
    if ((zero_if_forked_ptr = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE,
                                   MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }

    if (minherit(zero_if_forked_ptr, sizeof(int), MAP_INHERIT_ZERO) == -1) {
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }
#else

    if (pthread_atfork(NULL, NULL, s2n_on_fork) != 0) {
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }
#endif

    GUARD(s2n_check_fork());

#ifndef OPENSSL_IS_BORINGSSL
    /* Create an engine */
    ENGINE *e = ENGINE_new();
    if (e == NULL ||
        ENGINE_set_id(e, "s2n") != 1 ||
        ENGINE_set_name(e, "s2n entropy generator") != 1 ||
        ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) != 1 ||
        ENGINE_set_init_function(e, s2n_openssl_compat_init) != 1 ||
        ENGINE_set_RAND(e, &s2n_openssl_rand_method) != 1 ||
        ENGINE_add(e) != 1 ||
        ENGINE_free(e) != 1) {
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }

    /* Use that engine for rand() */
    e = ENGINE_by_id("s2n");
    if (e == NULL ||
        ENGINE_init(e) != 1 ||
        ENGINE_set_default(e, ENGINE_METHOD_RAND) != 1) {
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }

#endif

    return 0;
}
Example #8
0
int neverbleed_init(neverbleed_t *nb, char *errbuf)
{
    int pipe_fds[2] = {-1, -1}, listen_fd = -1;
    char *tempdir = NULL;

    const RSA_METHOD *default_method = RSA_PKCS1_SSLeay();
    rsa_method.rsa_pub_enc = default_method->rsa_pub_enc;
    rsa_method.rsa_pub_dec = default_method->rsa_pub_dec;
    rsa_method.rsa_verify = default_method->rsa_verify;

    /* setup the daemon */
    if (pipe(pipe_fds) != 0) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "pipe(2) failed:%s", strerror(errno));
        goto Fail;
    }
    fcntl(pipe_fds[1], F_SETFD, O_CLOEXEC);
    if ((tempdir = strdup("/tmp/openssl-privsep.XXXXXX")) == NULL) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "no memory");
        goto Fail;
    }
    if (mkdtemp(tempdir) == NULL) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to create temporary directory under /tmp:%s", strerror(errno));
        goto Fail;
    }
    memset(&nb->sun_, 0, sizeof(nb->sun_));
    nb->sun_.sun_family = AF_UNIX;
    snprintf(nb->sun_.sun_path, sizeof(nb->sun_.sun_path), "%s/_", tempdir);
    RAND_bytes(nb->auth_token, sizeof(nb->auth_token));
    if ((listen_fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "socket(2) failed:%s", strerror(errno));
        goto Fail;
    }
    if (bind(listen_fd, (void *)&nb->sun_, sizeof(nb->sun_)) != 0) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to bind to %s:%s", nb->sun_.sun_path, strerror(errno));
        goto Fail;
    }
    if (listen(listen_fd, SOMAXCONN) != 0) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "listen(2) failed:%s", strerror(errno));
        goto Fail;
    }
    switch (fork()) {
    case -1:
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "fork(2) failed:%s", strerror(errno));
        goto Fail;
    case 0:
        close(pipe_fds[1]);
#ifdef __linux__
        prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
#endif
        memcpy(daemon_auth_token, nb->auth_token, NEVERBLEED_AUTH_TOKEN_SIZE);
        daemon_main(listen_fd, pipe_fds[0], tempdir);
        break;
    default:
        break;
    }
    close(listen_fd);
    listen_fd = -1;
    close(pipe_fds[0]);
    pipe_fds[0] = -1;

    /* setup engine */
    if ((nb->engine = ENGINE_new()) == NULL ||
        !ENGINE_set_id(nb->engine, "neverbleed") ||
        !ENGINE_set_name(nb->engine, "privilege separation software engine") ||
        !ENGINE_set_RSA(nb->engine, &rsa_method)) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to initialize the OpenSSL engine");
        goto Fail;
    }
    ENGINE_add(nb->engine);

    /* setup thread key */
    pthread_key_create(&nb->thread_key, dispose_thread_data);

    free(tempdir);
    return 0;
Fail:
    if (pipe_fds[0] != -1)
        close(pipe_fds[0]);
    if (pipe_fds[1] != -1)
        close(pipe_fds[1]);
    if (tempdir != NULL) {
        unlink_dir(tempdir);
        free(tempdir);
    }
    if (listen_fd != -1)
        close(listen_fd);
    if (nb->engine != NULL) {
        ENGINE_free(nb->engine);
        nb->engine = NULL;
    }
    return -1;
}
Example #9
0
/*
 * This engine is always built into libcrypto, so it doesn't offer any
 * ability to be dynamically loadable.
 */
void engine_load_devcrypto_int()
{
    ENGINE *e = NULL;

    if (access("/dev/crypto", R_OK | W_OK) < 0) {
        fprintf(stderr,
                "/dev/crypto not present, not enabling devcrypto engine\n");
        return;
    }

    prepare_cipher_methods();
#if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
    prepare_digest_methods();
#endif

    if ((e = ENGINE_new()) == NULL)
        return;

    if (!ENGINE_set_id(e, "devcrypto")
        || !ENGINE_set_name(e, "/dev/crypto engine")
        || !ENGINE_set_destroy_function(e, devcrypto_unload)

/*
 * Asymmetric ciphers aren't well supported with /dev/crypto.  Among the BSD
 * implementations, it seems to only exist in FreeBSD, and regarding the
 * parameters in its crypt_kop, the manual crypto(4) has this to say:
 *
 *    The semantics of these arguments are currently undocumented.
 *
 * Reading through the FreeBSD source code doesn't give much more than
 * their CRK_MOD_EXP implementation for ubsec.
 *
 * It doesn't look much better with cryptodev-linux.  They have the crypt_kop
 * structure as well as the command (CRK_*) in cryptodev.h, but no support
 * seems to be implemented at all for the moment.
 *
 * At the time of writing, it seems impossible to write proper support for
 * FreeBSD's asym features without some very deep knowledge and access to
 * specific kernel modules.
 *
 * /Richard Levitte, 2017-05-11
 */
#if 0
# ifndef OPENSSL_NO_RSA
        || !ENGINE_set_RSA(e, devcrypto_rsa)
# endif
# ifndef OPENSSL_NO_DSA
        || !ENGINE_set_DSA(e, devcrypto_dsa)
# endif
# ifndef OPENSSL_NO_DH
        || !ENGINE_set_DH(e, devcrypto_dh)
# endif
# ifndef OPENSSL_NO_EC
        || !ENGINE_set_EC(e, devcrypto_ec)
# endif
#endif
        || !ENGINE_set_ciphers(e, devcrypto_ciphers)
#if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
        || !ENGINE_set_digests(e, devcrypto_digests)
#endif
        ) {
        ENGINE_free(e);
        return;
    }

    ENGINE_add(e);
    ENGINE_free(e);          /* Loose our local reference */
    ERR_clear_error();
}
void
ENGINE_load_cryptodev(void)
{
	ENGINE *engine = ENGINE_new();
	int fd;

	if (engine == NULL)
		return;
	if ((fd = get_dev_crypto()) < 0) {
		ENGINE_free(engine);
		return;
	}

	/*
	 * find out what asymmetric crypto algorithms we support
	 */
	if (ioctl(fd, CIOCASYMFEAT, &cryptodev_asymfeat) == -1) {
		close(fd);
		ENGINE_free(engine);
		return;
	}
	close(fd);

	if (!ENGINE_set_id(engine, "cryptodev") ||
	    !ENGINE_set_name(engine, "BSD cryptodev engine") ||
	    !ENGINE_set_ciphers(engine, cryptodev_engine_ciphers) ||
	    !ENGINE_set_digests(engine, cryptodev_engine_digests) ||
	    !ENGINE_set_ctrl_function(engine, cryptodev_ctrl) ||
	    !ENGINE_set_cmd_defns(engine, cryptodev_defns)) {
		ENGINE_free(engine);
		return;
	}

	if (ENGINE_set_RSA(engine, &cryptodev_rsa)) {
		const RSA_METHOD *rsa_meth = RSA_PKCS1_SSLeay();

		cryptodev_rsa.bn_mod_exp = rsa_meth->bn_mod_exp;
		cryptodev_rsa.rsa_mod_exp = rsa_meth->rsa_mod_exp;
		cryptodev_rsa.rsa_pub_enc = rsa_meth->rsa_pub_enc;
		cryptodev_rsa.rsa_pub_dec = rsa_meth->rsa_pub_dec;
		cryptodev_rsa.rsa_priv_enc = rsa_meth->rsa_priv_enc;
		cryptodev_rsa.rsa_priv_dec = rsa_meth->rsa_priv_dec;
		if (cryptodev_asymfeat & CRF_MOD_EXP) {
			cryptodev_rsa.bn_mod_exp = cryptodev_bn_mod_exp;
			if (cryptodev_asymfeat & CRF_MOD_EXP_CRT)
				cryptodev_rsa.rsa_mod_exp =
				    cryptodev_rsa_mod_exp;
			else
				cryptodev_rsa.rsa_mod_exp =
				    cryptodev_rsa_nocrt_mod_exp;
		}
	}

	if (ENGINE_set_DSA(engine, &cryptodev_dsa)) {
		const DSA_METHOD *meth = DSA_OpenSSL();

		memcpy(&cryptodev_dsa, meth, sizeof(DSA_METHOD));
		if (cryptodev_asymfeat & CRF_DSA_SIGN)
			cryptodev_dsa.dsa_do_sign = cryptodev_dsa_do_sign;
		if (cryptodev_asymfeat & CRF_MOD_EXP) {
			cryptodev_dsa.bn_mod_exp = cryptodev_dsa_bn_mod_exp;
			cryptodev_dsa.dsa_mod_exp = cryptodev_dsa_dsa_mod_exp;
		}
		if (cryptodev_asymfeat & CRF_DSA_VERIFY)
			cryptodev_dsa.dsa_do_verify = cryptodev_dsa_verify;
	}

	if (ENGINE_set_DH(engine, &cryptodev_dh)){
		const DH_METHOD *dh_meth = DH_OpenSSL();

		cryptodev_dh.generate_key = dh_meth->generate_key;
		cryptodev_dh.compute_key = dh_meth->compute_key;
		cryptodev_dh.bn_mod_exp = dh_meth->bn_mod_exp;
		if (cryptodev_asymfeat & CRF_MOD_EXP) {
			cryptodev_dh.bn_mod_exp = cryptodev_mod_exp_dh;
			if (cryptodev_asymfeat & CRF_DH_COMPUTE_KEY)
				cryptodev_dh.compute_key =
				    cryptodev_dh_compute_key;
		}
	}

	ENGINE_add(engine);
	ENGINE_free(engine);
	ERR_clear_error();
}
Example #11
0
// Constructor
OSSLCryptoFactory::OSSLCryptoFactory()
{
	// Multi-thread support
	nlocks = CRYPTO_num_locks();
	locks = new Mutex*[nlocks];
	for (unsigned i = 0; i < nlocks; i++)
	{
		locks[i] = MutexFactory::i()->getMutex();
	}
#ifdef HAVE_PTHREAD_H
	CRYPTO_set_id_callback(id_callback);
#endif
	CRYPTO_set_locking_callback(lock_callback);

#ifdef WITH_FIPS
	// Already in FIPS mode on reenter (avoiding selftests)
	if (!FIPS_mode())
	{
		FipsSelfTestStatus = false;
		if (!FIPS_mode_set(1))
		{
			ERROR_MSG("can't enter into FIPS mode");
			return;
		}
	} else {
		// Undo RAND_cleanup()
		RAND_init_fips();
	}
	FipsSelfTestStatus = true;
#endif

	// Initialise OpenSSL
	OpenSSL_add_all_algorithms();

	// Initialise the one-and-only RNG
	rng = new OSSLRNG();

#ifdef WITH_GOST
	// Load engines
	ENGINE_load_builtin_engines();

	// Initialise the GOST engine
	eg = ENGINE_by_id("gost");
	if (eg == NULL)
	{
		ERROR_MSG("can't get the GOST engine");
		return;
	}
	if (ENGINE_init(eg) <= 0)
	{
		ENGINE_free(eg);
		eg = NULL;
		ERROR_MSG("can't initialize the GOST engine");
		return;
	}
	// better than digest_gost
	EVP_GOST_34_11 = ENGINE_get_digest(eg, NID_id_GostR3411_94);
	if (EVP_GOST_34_11 == NULL)
	{
		ERROR_MSG("can't get the GOST digest");
		goto err;
	}
	// from the openssl.cnf
	if (ENGINE_register_pkey_asn1_meths(eg) <= 0)
	{
		ERROR_MSG("can't register ASN.1 for the GOST engine");
		goto err;
	}
	if (ENGINE_ctrl_cmd_string(eg,
				   "CRYPT_PARAMS",
				   "id-Gost28147-89-CryptoPro-A-ParamSet",
				   0) <= 0)
	{
		ERROR_MSG("can't set params of the GOST engine");
		goto err;
	}
	return;

err:
	ENGINE_finish(eg);
	ENGINE_free(eg);
	eg = NULL;
	return;
#endif
}
Example #12
0
 void operator()(ENGINE* p) const {
     ENGINE_free(p);
 }
Example #13
0
static int int_engine_configure(char *name, char *value, const CONF *cnf)
	{
	int i;
	int ret = 0;
	long do_init = -1;
	STACK_OF(CONF_VALUE) *ecmds;
	CONF_VALUE *ecmd;
	char *ctrlname, *ctrlvalue;
	ENGINE *e = NULL;
	name = skip_dot(name);
#ifdef ENGINE_CONF_DEBUG
	fprintf(stderr, "Configuring engine %s\n", name);
#endif
	/* Value is a section containing ENGINE commands */
	ecmds = NCONF_get_section(cnf, value);

	if (!ecmds)
		{
		ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_SECTION_ERROR);
		return 0;
		}

	for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++)
		{
		ecmd = sk_CONF_VALUE_value(ecmds, i);
		ctrlname = skip_dot(ecmd->name);
		ctrlvalue = ecmd->value;
#ifdef ENGINE_CONF_DEBUG
	fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname, ctrlvalue);
#endif

		/* First handle some special pseudo ctrls */

		/* Override engine name to use */
		if (!strcmp(ctrlname, "engine_id"))
			name = ctrlvalue;
		/* Load a dynamic ENGINE */
		else if (!strcmp(ctrlname, "dynamic_path"))
			{
			e = ENGINE_by_id("dynamic");
			if (!e)
				goto err;
			if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0))
				goto err;
			if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0))
				goto err;
			if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
				goto err;
			}
		/* ... add other pseudos here ... */
		else
			{
			/* At this point we need an ENGINE structural reference
			 * if we don't already have one.
			 */
			if (!e)
				{
				e = ENGINE_by_id(name);
				if (!e)
					return 0;
				}
			/* Allow "EMPTY" to mean no value: this allows a valid
			 * "value" to be passed to ctrls of type NO_INPUT
		 	 */
			if (!strcmp(ctrlvalue, "EMPTY"))
				ctrlvalue = NULL;
			if (!strcmp(ctrlname, "init"))
				{
				if (!NCONF_get_number_e(cnf, value, "init", &do_init))
					goto err;
				if (do_init == 1)
					{
					if (!int_engine_init(e))
						goto err;
					}
				else if (do_init != 0)
					{
					ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_INVALID_INIT_VALUE);
					goto err;
					}
				}
			else if (!strcmp(ctrlname, "default_algorithms"))
				{
				if (!ENGINE_set_default_string(e, ctrlvalue))
					goto err;
				}
			else if (!ENGINE_ctrl_cmd_string(e,
					ctrlname, ctrlvalue, 0))
				return 0;
			}



		}
	if (e && (do_init == -1) && !int_engine_init(e))
		goto err;
	ret = 1;
	err:
	if (e)
		ENGINE_free(e);
	return ret;
	}
Example #14
0
int main(int argc, char *argv[])
{
    const EVP_MD *digest_algo = NULL;
    EVP_PKEY *pkey = NULL;
    EVP_MD_CTX *md_ctx = NULL;
    ENGINE *engine = NULL;
    unsigned char random[RANDOM_SIZE], signature[MAX_SIGSIZE];
    unsigned int siglen = MAX_SIGSIZE;

    int ret, num_processes = 2;
    pid_t pid;

    int rv = 1;

    /* Check arguments */
    if (argc < 2) {
        fprintf(stderr, "Missing required arguments\n");
        usage(argv[0]);
        goto failed;
    }

    if (argc > 4) {
        fprintf(stderr, "Too many arguments\n");
        usage(argv[0]);
        goto failed;
    }

    /* Check PKCS#11 URL */
    if (strncmp(argv[1], "pkcs11:", 7)) {
        fprintf(stderr, "fatal: invalid PKCS#11 URL\n");
        usage(argv[0]);
        goto failed;
    }

    pid = getpid();
    printf("pid %d is the parent\n", pid);

    /* Load configuration file, if provided */
    if (argc >= 3) {
        ret = CONF_modules_load_file(argv[2], "engines", 0);
        if (ret <= 0) {
            fprintf(stderr, "cannot load %s\n", argv[2]);
            error_queue("CONF_modules_load_file", pid);
            goto failed;
        }
        ENGINE_add_conf_module();
    }

    ENGINE_add_conf_module();
#if OPENSSL_VERSION_NUMBER>=0x10100000
	OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
		| OPENSSL_INIT_ADD_ALL_DIGESTS \
		| OPENSSL_INIT_LOAD_CONFIG, NULL);
#else
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();
#endif
    ERR_clear_error();
    ENGINE_load_builtin_engines();

    /* Get structural reference */
    engine = ENGINE_by_id("pkcs11");
    if (engine == NULL) {
        fprintf(stderr, "fatal: engine \"pkcs11\" not available\n");
        error_queue("ENGINE_by_id", pid);
        goto failed;
    }

    /* Set the used  */
    if (argc >= 4) {
        ENGINE_ctrl_cmd(engine, "MODULE_PATH", 0, argv[3], NULL, 1);
    }

    /* Initialize to get the engine functional reference */
    if (ENGINE_init(engine)) {
        pkey = ENGINE_load_private_key(engine, argv[1], 0, 0);
        if (pkey == NULL) {
            error_queue("ENGINE_load_private_key", pid);
            goto failed;
        }

        ENGINE_free(engine);
        engine = NULL;
    }
    else {
        error_queue("ENGINE_init", pid);
        goto failed;
    }

    /* Spawn processes and check child return */
    if (spawn_processes(num_processes)) {
        goto failed;
    }
    pid = getpid();

    /* Generate random data */
    if (!RAND_bytes(random, RANDOM_SIZE)){
        error_queue("RAND_bytes", pid);
        goto failed;
    }

    /* Create context to sign the random data */
    digest_algo = EVP_get_digestbyname("sha256");
    md_ctx = EVP_MD_CTX_create();
    if (EVP_DigestInit(md_ctx, digest_algo) <= 0) {
        error_queue("EVP_DigestInit", pid);
        goto failed;
    }

    EVP_SignInit(md_ctx, digest_algo);
    if (EVP_SignUpdate(md_ctx, random, RANDOM_SIZE) <= 0) {
        error_queue("EVP_SignUpdate", pid);
        goto failed;
    }

    if (EVP_SignFinal(md_ctx, signature, &siglen, pkey) <= 0) {
        error_queue("EVP_SignFinal", pid);
        goto failed;
    }
    EVP_MD_CTX_destroy(md_ctx);

    printf("pid %d: %u-byte signature created\n", pid, siglen);

    /* Now verify the result */
    md_ctx = EVP_MD_CTX_create();
    if (EVP_DigestInit(md_ctx, digest_algo) <= 0) {
        error_queue("EVP_DigestInit", pid);
        goto failed;
    }

    EVP_VerifyInit(md_ctx, digest_algo);
    if (EVP_VerifyUpdate(md_ctx, random, RANDOM_SIZE) <= 0) {
        error_queue("EVP_VerifyUpdate", pid);
        goto failed;
    }

    if (EVP_VerifyFinal(md_ctx, signature, siglen, pkey) <= 0) {
        error_queue("EVP_VerifyFinal", pid);
        goto failed;
    }
    printf("pid %d: Signature matched\n", pid);

    rv = 0;

failed:
    if (md_ctx != NULL)
        EVP_MD_CTX_destroy(md_ctx);
    if (pkey != NULL)
        EVP_PKEY_free(pkey);
    if (engine != NULL)
        ENGINE_free(engine);

    return rv;
}
Example #15
0
static void
ossl_engine_free(void *engine)
{
    ENGINE_free(engine);
}
Example #16
0
int main(int argc, char *argv[])
{
    ENGINE *block[512];
    char buf[256];
    const char *id, *name, *p;
    ENGINE *ptr;
    int loop;
    int to_return = 1;
    ENGINE *new_h1 = NULL;
    ENGINE *new_h2 = NULL;
    ENGINE *new_h3 = NULL;
    ENGINE *new_h4 = NULL;

    p = getenv("OPENSSL_DEBUG_MEMORY");
    if (p != NULL && strcmp(p, "on") == 0)
        CRYPTO_set_mem_debug(1);

    memset(block, 0, sizeof(block));
    if (((new_h1 = ENGINE_new()) == NULL) ||
        !ENGINE_set_id(new_h1, "test_id0") ||
        !ENGINE_set_name(new_h1, "First test item") ||
        ((new_h2 = ENGINE_new()) == NULL) ||
        !ENGINE_set_id(new_h2, "test_id1") ||
        !ENGINE_set_name(new_h2, "Second test item") ||
        ((new_h3 = ENGINE_new()) == NULL) ||
        !ENGINE_set_id(new_h3, "test_id2") ||
        !ENGINE_set_name(new_h3, "Third test item") ||
        ((new_h4 = ENGINE_new()) == NULL) ||
        !ENGINE_set_id(new_h4, "test_id3") ||
        !ENGINE_set_name(new_h4, "Fourth test item")) {
        printf("Couldn't set up test ENGINE structures\n");
        goto end;
    }
    printf("\nenginetest beginning\n\n");
    display_engine_list();
    if (!ENGINE_add(new_h1)) {
        printf("Add failed!\n");
        goto end;
    }
    display_engine_list();
    ptr = ENGINE_get_first();
    if (!ENGINE_remove(ptr)) {
        printf("Remove failed!\n");
        goto end;
    }
    ENGINE_free(ptr);
    display_engine_list();
    if (!ENGINE_add(new_h3) || !ENGINE_add(new_h2)) {
        printf("Add failed!\n");
        goto end;
    }
    display_engine_list();
    if (!ENGINE_remove(new_h2)) {
        printf("Remove failed!\n");
        goto end;
    }
    display_engine_list();
    if (!ENGINE_add(new_h4)) {
        printf("Add failed!\n");
        goto end;
    }
    display_engine_list();
    if (ENGINE_add(new_h3)) {
        printf("Add *should* have failed but didn't!\n");
        goto end;
    } else
        printf("Add that should fail did.\n");
    ERR_clear_error();
    if (ENGINE_remove(new_h2)) {
        printf("Remove *should* have failed but didn't!\n");
        goto end;
    } else
        printf("Remove that should fail did.\n");
    ERR_clear_error();
    if (!ENGINE_remove(new_h3)) {
        printf("Remove failed!\n");
        goto end;
    }
    display_engine_list();
    if (!ENGINE_remove(new_h4)) {
        printf("Remove failed!\n");
        goto end;
    }
    display_engine_list();
    /*
     * Depending on whether there's any hardware support compiled in, this
     * remove may be destined to fail.
     */
    ptr = ENGINE_get_first();
    if (ptr)
        if (!ENGINE_remove(ptr))
            printf("Remove failed!i - probably no hardware "
                   "support present.\n");
    ENGINE_free(ptr);
    display_engine_list();
    if (!ENGINE_add(new_h1) || !ENGINE_remove(new_h1)) {
        printf("Couldn't add and remove to an empty list!\n");
        goto end;
    } else
        printf("Successfully added and removed to an empty list!\n");
    printf("About to beef up the engine-type list\n");
    for (loop = 0; loop < 512; loop++) {
        sprintf(buf, "id%i", loop);
        id = OPENSSL_strdup(buf);
        sprintf(buf, "Fake engine type %i", loop);
        name = OPENSSL_strdup(buf);
        if (((block[loop] = ENGINE_new()) == NULL) ||
            !ENGINE_set_id(block[loop], id) ||
            !ENGINE_set_name(block[loop], name)) {
            printf("Couldn't create block of ENGINE structures.\n"
                   "I'll probably also core-dump now, damn.\n");
            goto end;
        }
    }
    for (loop = 0; loop < 512; loop++) {
        if (!ENGINE_add(block[loop])) {
            printf("\nAdding stopped at %i, (%s,%s)\n",
                   loop, ENGINE_get_id(block[loop]),
                   ENGINE_get_name(block[loop]));
            goto cleanup_loop;
        } else
            printf(".");
        fflush(stdout);
    }
 cleanup_loop:
    printf("\nAbout to empty the engine-type list\n");
    while ((ptr = ENGINE_get_first()) != NULL) {
        if (!ENGINE_remove(ptr)) {
            printf("\nRemove failed!\n");
            goto end;
        }
        ENGINE_free(ptr);
        printf(".");
        fflush(stdout);
    }
    for (loop = 0; loop < 512; loop++) {
        OPENSSL_free((void *)ENGINE_get_id(block[loop]));
        OPENSSL_free((void *)ENGINE_get_name(block[loop]));
    }
    printf("\nTests completed happily\n");
    to_return = 0;
 end:
    if (to_return)
        ERR_print_errors_fp(stderr);
    ENGINE_free(new_h1);
    ENGINE_free(new_h2);
    ENGINE_free(new_h3);
    ENGINE_free(new_h4);
    for (loop = 0; loop < 512; loop++)
        ENGINE_free(block[loop]);

#ifndef OPENSSL_NO_CRYPTO_MDEBUG
    if (CRYPTO_mem_leaks_fp(stderr) <= 0)
        to_return = 1;
#endif
    return to_return;
}
Example #17
0
int main(int argc, char *argv[])
	{
	ENGINE *block[512];
	char *id, *name;
	ENGINE *ptr;
	int loop;
	int to_return = 1;
	ENGINE *new_h1 = NULL;
	ENGINE *new_h2 = NULL;
	ENGINE *new_h3 = NULL;
	ENGINE *new_h4 = NULL;

	ERR_load_crypto_strings();

	memset(block, 0, 512 * sizeof(ENGINE *));
	if(((new_h1 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h1, "test_id0") ||
			!ENGINE_set_name(new_h1, "First test item") ||
			((new_h2 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h2, "test_id1") ||
			!ENGINE_set_name(new_h2, "Second test item") ||
			((new_h3 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h3, "test_id2") ||
			!ENGINE_set_name(new_h3, "Third test item") ||
			((new_h4 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h4, "test_id3") ||
			!ENGINE_set_name(new_h4, "Fourth test item"))
		{
		printf("Couldn't set up test ENGINE structures\n");
		goto end;
		}
	printf("\nenginetest beginning\n\n");
	display_engine_list();
	if(!ENGINE_add(new_h1))
		{
		printf("Add failed!\n");
		goto end;
		}
	display_engine_list();
	ptr = ENGINE_get_first();
	if(!ENGINE_remove(ptr))
		{
		printf("Remove failed!\n");
		goto end;
		}
	if (ptr)
		ENGINE_free(ptr);
	display_engine_list();
	if(!ENGINE_add(new_h3) || !ENGINE_add(new_h2))
		{
		printf("Add failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_remove(new_h2))
		{
		printf("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_add(new_h4))
		{
		printf("Add failed!\n");
		goto end;
		}
	display_engine_list();
	if(ENGINE_add(new_h3))
		{
		printf("Add *should* have failed but didn't!\n");
		goto end;
		}
	else
		printf("Add that should fail did.\n");
	ERR_clear_error();
	if(ENGINE_remove(new_h2))
		{
		printf("Remove *should* have failed but didn't!\n");
		goto end;
		}
	else
		printf("Remove that should fail did.\n");
	ERR_clear_error();
	if(!ENGINE_remove(new_h3))
		{
		printf("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_remove(new_h4))
		{
		printf("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	/* Depending on whether there's any hardware support compiled
	 * in, this remove may be destined to fail. */
	ptr = ENGINE_get_first();
	if(ptr)
		if(!ENGINE_remove(ptr))
			printf("Remove failed!i - probably no hardware "
				"support present.\n");
	if (ptr)
		ENGINE_free(ptr);
	display_engine_list();
	if(!ENGINE_add(new_h1) || !ENGINE_remove(new_h1))
		{
		printf("Couldn't add and remove to an empty list!\n");
		goto end;
		}
	else
		printf("Successfully added and removed to an empty list!\n");
	printf("About to beef up the engine-type list\n");
	for(loop = 0; loop < 512; loop++)
		{
		asprintf(&id, "id%i", loop);
		asprintf(&name, "Fake engine type %i", loop);
		if(((block[loop] = ENGINE_new()) == NULL) ||
				!id || !ENGINE_set_id(block[loop], id) ||
				!name || !ENGINE_set_name(block[loop], name))
			{
			printf("Couldn't create block of ENGINE structures.\n"
				"I'll probably also core-dump now, damn.\n");
			goto end;
			}
		}
	for(loop = 0; loop < 512; loop++)
		{
		if(!ENGINE_add(block[loop]))
			{
			printf("\nAdding stopped at %i, (%s,%s)\n",
				loop, ENGINE_get_id(block[loop]),
				ENGINE_get_name(block[loop]));
			goto cleanup_loop;
			}
		else
			printf("."); fflush(stdout);
		}
cleanup_loop:
	printf("\nAbout to empty the engine-type list\n");
	while((ptr = ENGINE_get_first()) != NULL)
		{
		if(!ENGINE_remove(ptr))
			{
			printf("\nRemove failed!\n");
			goto end;
			}
		ENGINE_free(ptr);
		printf("."); fflush(stdout);
		}
	for(loop = 0; loop < 512; loop++)
		{
		free((void *)ENGINE_get_id(block[loop]));
		free((void *)ENGINE_get_name(block[loop]));
		}
	printf("\nTests completed happily\n");
	to_return = 0;
end:
	if(to_return)
		ERR_print_errors_fp(stderr);
	if(new_h1) ENGINE_free(new_h1);
	if(new_h2) ENGINE_free(new_h2);
	if(new_h3) ENGINE_free(new_h3);
	if(new_h4) ENGINE_free(new_h4);
	for(loop = 0; loop < 512; loop++)
		if(block[loop])
			ENGINE_free(block[loop]);
	ENGINE_cleanup();
	CRYPTO_cleanup_all_ex_data();
	ERR_free_strings();
	ERR_remove_thread_state(NULL);
	CRYPTO_mem_leaks_fp(stderr);
	return to_return;
	}
Example #18
0
void cleanup_tests(void)
{
    ENGINE_free(e);
}
Example #19
0
isc_result_t
dst__openssl_init() {
	isc_result_t result;
#ifdef USE_ENGINE
	/* const char  *name; */
	ENGINE *re;
#endif

#ifdef  DNS_CRYPTO_LEAKS
	CRYPTO_malloc_debug_init();
	CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
#endif
	CRYPTO_set_mem_functions(mem_alloc, mem_realloc, mem_free);
	nlocks = CRYPTO_num_locks();
	locks = mem_alloc(sizeof(isc_mutex_t) * nlocks);
	if (locks == NULL)
		return (ISC_R_NOMEMORY);
	result = isc_mutexblock_init(locks, nlocks);
	if (result != ISC_R_SUCCESS)
		goto cleanup_mutexalloc;
	CRYPTO_set_locking_callback(lock_callback);
	CRYPTO_set_id_callback(id_callback);

	rm = mem_alloc(sizeof(RAND_METHOD));
	if (rm == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup_mutexinit;
	}
	rm->seed = NULL;
	rm->bytes = entropy_get;
	rm->cleanup = NULL;
	rm->add = entropy_add;
	rm->pseudorand = entropy_getpseudo;
	rm->status = entropy_status;
#ifdef USE_ENGINE
	OPENSSL_config(NULL);
#ifdef USE_PKCS11
#ifndef PKCS11_SO_PATH
#define PKCS11_SO_PATH		"/usr/local/lib/engines/engine_pkcs11.so"
#endif
#ifndef PKCS11_MODULE_PATH
#define PKCS11_MODULE_PATH	"/usr/lib/libpkcs11.so"
#endif
	{
		/*
		 * to use this to config the PIN, add in openssl.cnf:
		 *  - at the beginning: "openssl_conf = openssl_def"
		 *  - at any place these sections:
		 * [ openssl_def ]
		 * engines = engine_section
		 * [ engine_section ]
		 * pkcs11 = pkcs11_section
		 * [ pkcs11_section ]
		 * PIN = my___pin
		 */

		const char *pre_cmds[] = {
			"SO_PATH", PKCS11_SO_PATH,
			"LOAD", NULL,
			"MODULE_PATH", PKCS11_MODULE_PATH
		};
		const char *post_cmds[] = {
			/* "PIN", "my___pin" */
		};
		result = dst__openssl_load_engine("pkcs11", "pkcs11",
						  pre_cmds, 0,
						  post_cmds, /*1*/ 0);
		if (result != ISC_R_SUCCESS)
			goto cleanup_rm;
	}
#endif /* USE_PKCS11 */
	if (engine_id != NULL) {
		e = ENGINE_by_id(engine_id);
		if (e == NULL) {
			result = ISC_R_NOTFOUND;
			goto cleanup_rm;
		}
		if (!ENGINE_init(e)) {
			result = ISC_R_FAILURE;
			ENGINE_free(e);
			goto cleanup_rm;
		}
		ENGINE_set_default(e, ENGINE_METHOD_ALL);
		ENGINE_free(e);
	} else {
		ENGINE_register_all_complete();
		for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) {

			/*
			 * Something weird here. If we call ENGINE_finish()
			 * ENGINE_get_default_RAND() will fail.
			 */
			if (ENGINE_init(e)) {
				if (he == NULL)
					he = e;
			}
		}
	}
	re = ENGINE_get_default_RAND();
	if (re == NULL) {
		re = ENGINE_new();
		if (re == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup_rm;
		}
		ENGINE_set_RAND(re, rm);
		ENGINE_set_default_RAND(re);
		ENGINE_free(re);
	} else
		ENGINE_finish(re);

#else
	RAND_set_rand_method(rm);
#endif /* USE_ENGINE */
	return (ISC_R_SUCCESS);

#ifdef USE_ENGINE
 cleanup_rm:
	mem_free(rm);
#endif
 cleanup_mutexinit:
	CRYPTO_set_locking_callback(NULL);
	DESTROYMUTEXBLOCK(locks, nlocks);
 cleanup_mutexalloc:
	mem_free(locks);
	return (result);
}
int main(int argc, char *argv[])
	{
	ENGINE *block[512];
	char buf[256];
	const char *id, *name;
	ENGINE *ptr;
	int loop;
	int to_return = 1;
	ENGINE *new_h1 = NULL;
	ENGINE *new_h2 = NULL;
	ENGINE *new_h3 = NULL;
	ENGINE *new_h4 = NULL;

	/* enable memory leak checking unless explicitly disabled */
	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
		{
		CRYPTO_malloc_debug_init();
		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
		}
	else
		{
		/* OPENSSL_DEBUG_MEMORY=off */
		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
		}
	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
	ERR_load_crypto_strings();

	memset(block, 0, 512 * sizeof(ENGINE *));
	if(((new_h1 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h1, "test_id0") ||
			!ENGINE_set_name(new_h1, "First test item") ||
			((new_h2 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h2, "test_id1") ||
			!ENGINE_set_name(new_h2, "Second test item") ||
			((new_h3 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h3, "test_id2") ||
			!ENGINE_set_name(new_h3, "Third test item") ||
			((new_h4 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h4, "test_id3") ||
			!ENGINE_set_name(new_h4, "Fourth test item"))
		{
		printf("Couldn't set up test ENGINE structures\n");
		goto end;
		}
	printf("\nenginetest beginning\n\n");
	display_engine_list();
	if(!ENGINE_add(new_h1))
		{
		printf("Add failed!\n");
		goto end;
		}
	display_engine_list();
	ptr = ENGINE_get_first();
	if(!ENGINE_remove(ptr))
		{
		printf("Remove failed!\n");
		goto end;
		}
	if (ptr)
		ENGINE_free(ptr);
	display_engine_list();
	if(!ENGINE_add(new_h3) || !ENGINE_add(new_h2))
		{
		printf("Add failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_remove(new_h2))
		{
		printf("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_add(new_h4))
		{
		printf("Add failed!\n");
		goto end;
		}
	display_engine_list();
	if(ENGINE_add(new_h3))
		{
		printf("Add *should* have failed but didn't!\n");
		goto end;
		}
	else
		printf("Add that should fail did.\n");
	ERR_clear_error();
	if(ENGINE_remove(new_h2))
		{
		printf("Remove *should* have failed but didn't!\n");
		goto end;
		}
	else
		printf("Remove that should fail did.\n");
	ERR_clear_error();
	if(!ENGINE_remove(new_h3))
		{
		printf("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_remove(new_h4))
		{
		printf("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	/* Depending on whether there's any hardware support compiled
	 * in, this remove may be destined to fail. */
	ptr = ENGINE_get_first();
	if(ptr)
		if(!ENGINE_remove(ptr))
			printf("Remove failed!i - probably no hardware "
				"support present.\n");
	if (ptr)
		ENGINE_free(ptr);
	display_engine_list();
	if(!ENGINE_add(new_h1) || !ENGINE_remove(new_h1))
		{
		printf("Couldn't add and remove to an empty list!\n");
		goto end;
		}
	else
		printf("Successfully added and removed to an empty list!\n");
	printf("About to beef up the engine-type list\n");
	for(loop = 0; loop < 512; loop++)
		{
		sprintf(buf, "id%i", loop);
		id = BUF_strdup(buf);
		sprintf(buf, "Fake engine type %i", loop);
		name = BUF_strdup(buf);
		if(((block[loop] = ENGINE_new()) == NULL) ||
				!ENGINE_set_id(block[loop], id) ||
				!ENGINE_set_name(block[loop], name))
			{
			printf("Couldn't create block of ENGINE structures.\n"
				"I'll probably also core-dump now, damn.\n");
			goto end;
			}
		}
	for(loop = 0; loop < 512; loop++)
		{
		if(!ENGINE_add(block[loop]))
			{
			printf("\nAdding stopped at %i, (%s,%s)\n",
				loop, ENGINE_get_id(block[loop]),
				ENGINE_get_name(block[loop]));
			goto cleanup_loop;
			}
		else
			printf("."); fflush(stdout);
		}
cleanup_loop:
	printf("\nAbout to empty the engine-type list\n");
	while((ptr = ENGINE_get_first()) != NULL)
		{
		if(!ENGINE_remove(ptr))
			{
			printf("\nRemove failed!\n");
			goto end;
			}
		ENGINE_free(ptr);
		printf("."); fflush(stdout);
		}
	for(loop = 0; loop < 512; loop++)
		{
		OPENSSL_free((void *)ENGINE_get_id(block[loop]));
		OPENSSL_free((void *)ENGINE_get_name(block[loop]));
		}
	printf("\nTests completed happily\n");
	to_return = 0;
end:
	if(to_return)
		ERR_print_errors_fp(stderr);
	if(new_h1) ENGINE_free(new_h1);
	if(new_h2) ENGINE_free(new_h2);
	if(new_h3) ENGINE_free(new_h3);
	if(new_h4) ENGINE_free(new_h4);
	for(loop = 0; loop < 512; loop++)
		if(block[loop])
			ENGINE_free(block[loop]);
	ENGINE_cleanup();
	CRYPTO_cleanup_all_ex_data();
	ERR_free_strings();
	ERR_remove_thread_state(NULL);
	CRYPTO_mem_leaks_fp(stderr);
	return to_return;
	}
Example #21
0
int MAIN(int argc, char **argv)
	{
	int off=0, clr = 0;
	SSL *con=NULL,*con2=NULL;
	X509_STORE *store = NULL;
	int s,k,width,state=0;
	char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL;
	int cbuf_len,cbuf_off;
	int sbuf_len,sbuf_off;
	fd_set readfds,writefds;
	short port=PORT;
	int full_log=1;
	char *host=SSL_HOST_NAME;
	char *cert_file=NULL,*key_file=NULL;
	int cert_format = FORMAT_PEM, key_format = FORMAT_PEM;
	char *passarg = NULL, *pass = NULL;
	X509 *cert = NULL;
	EVP_PKEY *key = NULL;
	char *CApath=NULL,*CAfile=NULL,*cipher=NULL;
	int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0;
	int cutthrough=0;
	int crlf=0;
	int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending;
	SSL_CTX *ctx=NULL;
	int ret=1,in_init=1,i,nbio_test=0;
	int starttls_proto = PROTO_OFF;
	int prexit = 0, vflags = 0;
	SSL_METHOD *meth=NULL;
#ifdef sock_type
#undef sock_type
#endif
	int sock_type=SOCK_STREAM;
	BIO *sbio;
	char *inrand=NULL;
	int mbuf_len=0;
	struct timeval timeout, *timeoutp;
#ifndef OPENSSL_NO_ENGINE
	char *engine_id=NULL;
	char *ssl_client_engine_id=NULL;
	ENGINE *ssl_client_engine=NULL;
#endif
	ENGINE *e=NULL;
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE)
	struct timeval tv;
#endif

#ifndef OPENSSL_NO_TLSEXT
	char *servername = NULL; 
        tlsextctx tlsextcbp = 
        {NULL,0};
#endif
	char *sess_in = NULL;
	char *sess_out = NULL;
	struct sockaddr peer;
	int peerlen = sizeof(peer);
	int enable_timeouts = 0 ;
	long socket_mtu = 0;
#ifndef OPENSSL_NO_JPAKE
	char *jpake_secret = NULL;
#endif

#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
	meth=SSLv23_client_method();
#elif !defined(OPENSSL_NO_SSL3)
	meth=SSLv3_client_method();
#elif !defined(OPENSSL_NO_SSL2)
	meth=SSLv2_client_method();
#endif

	apps_startup();
	c_Pause=0;
	c_quiet=0;
	c_ign_eof=0;
	c_debug=0;
	c_msg=0;
	c_showcerts=0;

	if (bio_err == NULL)
		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);

	if (!load_config(bio_err, NULL))
		goto end;

	if (	((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) ||
		((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) ||
		((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL))
		{
		BIO_printf(bio_err,"out of memory\n");
		goto end;
		}

	verify_depth=0;
	verify_error=X509_V_OK;
#ifdef FIONBIO
	c_nbio=0;
#endif

	argc--;
	argv++;
	while (argc >= 1)
		{
		if	(strcmp(*argv,"-host") == 0)
			{
			if (--argc < 1) goto bad;
			host= *(++argv);
			}
		else if	(strcmp(*argv,"-port") == 0)
			{
			if (--argc < 1) goto bad;
			port=atoi(*(++argv));
			if (port == 0) goto bad;
			}
		else if (strcmp(*argv,"-connect") == 0)
			{
			if (--argc < 1) goto bad;
			if (!extract_host_port(*(++argv),&host,NULL,&port))
				goto bad;
			}
		else if	(strcmp(*argv,"-verify") == 0)
			{
			verify=SSL_VERIFY_PEER;
			if (--argc < 1) goto bad;
			verify_depth=atoi(*(++argv));
			BIO_printf(bio_err,"verify depth is %d\n",verify_depth);
			}
		else if	(strcmp(*argv,"-cert") == 0)
			{
			if (--argc < 1) goto bad;
			cert_file= *(++argv);
			}
		else if	(strcmp(*argv,"-sess_out") == 0)
			{
			if (--argc < 1) goto bad;
			sess_out = *(++argv);
			}
		else if	(strcmp(*argv,"-sess_in") == 0)
			{
			if (--argc < 1) goto bad;
			sess_in = *(++argv);
			}
		else if	(strcmp(*argv,"-certform") == 0)
			{
			if (--argc < 1) goto bad;
			cert_format = str2fmt(*(++argv));
			}
		else if	(strcmp(*argv,"-crl_check") == 0)
			vflags |= X509_V_FLAG_CRL_CHECK;
		else if	(strcmp(*argv,"-crl_check_all") == 0)
			vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
		else if	(strcmp(*argv,"-prexit") == 0)
			prexit=1;
		else if	(strcmp(*argv,"-crlf") == 0)
			crlf=1;
		else if	(strcmp(*argv,"-quiet") == 0)
			{
			c_quiet=1;
			c_ign_eof=1;
			}
		else if	(strcmp(*argv,"-ign_eof") == 0)
			c_ign_eof=1;
		else if	(strcmp(*argv,"-no_ign_eof") == 0)
			c_ign_eof=0;
		else if	(strcmp(*argv,"-pause") == 0)
			c_Pause=1;
		else if	(strcmp(*argv,"-debug") == 0)
			c_debug=1;
#ifndef OPENSSL_NO_TLSEXT
		else if	(strcmp(*argv,"-tlsextdebug") == 0)
			c_tlsextdebug=1;
		else if	(strcmp(*argv,"-status") == 0)
			c_status_req=1;
#endif
#ifdef WATT32
		else if (strcmp(*argv,"-wdebug") == 0)
			dbug_init();
#endif
		else if	(strcmp(*argv,"-msg") == 0)
			c_msg=1;
		else if	(strcmp(*argv,"-showcerts") == 0)
			c_showcerts=1;
		else if	(strcmp(*argv,"-nbio_test") == 0)
			nbio_test=1;
		else if	(strcmp(*argv,"-state") == 0)
			state=1;
#ifndef OPENSSL_NO_SSL2
		else if	(strcmp(*argv,"-ssl2") == 0)
			meth=SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3
		else if	(strcmp(*argv,"-ssl3") == 0)
			meth=SSLv3_client_method();
#endif
#ifndef OPENSSL_NO_TLS1
		else if	(strcmp(*argv,"-tls1") == 0)
			meth=TLSv1_client_method();
#endif
#ifndef OPENSSL_NO_DTLS1
		else if	(strcmp(*argv,"-dtls1") == 0)
			{
			meth=DTLSv1_client_method();
			sock_type=SOCK_DGRAM;
			}
		else if (strcmp(*argv,"-timeout") == 0)
			enable_timeouts=1;
		else if (strcmp(*argv,"-mtu") == 0)
			{
			if (--argc < 1) goto bad;
			socket_mtu = atol(*(++argv));
			}
#endif
		else if (strcmp(*argv,"-bugs") == 0)
			bugs=1;
		else if	(strcmp(*argv,"-keyform") == 0)
			{
			if (--argc < 1) goto bad;
			key_format = str2fmt(*(++argv));
			}
		else if	(strcmp(*argv,"-pass") == 0)
			{
			if (--argc < 1) goto bad;
			passarg = *(++argv);
			}
		else if	(strcmp(*argv,"-key") == 0)
			{
			if (--argc < 1) goto bad;
			key_file= *(++argv);
			}
		else if	(strcmp(*argv,"-reconnect") == 0)
			{
			reconnect=5;
			}
		else if	(strcmp(*argv,"-CApath") == 0)
			{
			if (--argc < 1) goto bad;
			CApath= *(++argv);
			}
		else if	(strcmp(*argv,"-CAfile") == 0)
			{
			if (--argc < 1) goto bad;
			CAfile= *(++argv);
			}
		else if (strcmp(*argv,"-no_tls1") == 0)
			off|=SSL_OP_NO_TLSv1;
		else if (strcmp(*argv,"-no_ssl3") == 0)
			off|=SSL_OP_NO_SSLv3;
		else if (strcmp(*argv,"-no_ssl2") == 0)
			off|=SSL_OP_NO_SSLv2;
#ifndef OPENSSL_NO_TLSEXT
		else if	(strcmp(*argv,"-no_ticket") == 0)
			{ off|=SSL_OP_NO_TICKET; }
#endif
		else if (strcmp(*argv,"-cutthrough") == 0)
			cutthrough=1;
		else if (strcmp(*argv,"-serverpref") == 0)
			off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
		else if (strcmp(*argv,"-legacy_renegotiation") == 0)
			off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
		else if	(strcmp(*argv,"-legacy_server_connect") == 0)
			{ off|=SSL_OP_LEGACY_SERVER_CONNECT; }
		else if	(strcmp(*argv,"-no_legacy_server_connect") == 0)
			{ clr|=SSL_OP_LEGACY_SERVER_CONNECT; }
		else if	(strcmp(*argv,"-cipher") == 0)
			{
			if (--argc < 1) goto bad;
			cipher= *(++argv);
			}
#ifdef FIONBIO
		else if (strcmp(*argv,"-nbio") == 0)
			{ c_nbio=1; }
#endif
		else if	(strcmp(*argv,"-starttls") == 0)
			{
			if (--argc < 1) goto bad;
			++argv;
			if (strcmp(*argv,"smtp") == 0)
				starttls_proto = PROTO_SMTP;
			else if (strcmp(*argv,"pop3") == 0)
				starttls_proto = PROTO_POP3;
			else if (strcmp(*argv,"imap") == 0)
				starttls_proto = PROTO_IMAP;
			else if (strcmp(*argv,"ftp") == 0)
				starttls_proto = PROTO_FTP;
			else if (strcmp(*argv, "xmpp") == 0)
				starttls_proto = PROTO_XMPP;
			else
				goto bad;
			}
#ifndef OPENSSL_NO_ENGINE
		else if	(strcmp(*argv,"-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine_id = *(++argv);
			}
		else if	(strcmp(*argv,"-ssl_client_engine") == 0)
			{
			if (--argc < 1) goto bad;
			ssl_client_engine_id = *(++argv);
			}
#endif
		else if (strcmp(*argv,"-rand") == 0)
			{
			if (--argc < 1) goto bad;
			inrand= *(++argv);
			}
#ifndef OPENSSL_NO_TLSEXT
		else if (strcmp(*argv,"-servername") == 0)
			{
			if (--argc < 1) goto bad;
			servername= *(++argv);
			/* meth=TLSv1_client_method(); */
			}
#endif
#ifndef OPENSSL_NO_JPAKE
		else if (strcmp(*argv,"-jpake") == 0)
			{
			if (--argc < 1) goto bad;
			jpake_secret = *++argv;
			}
#endif
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badop=1;
			break;
			}
		argc--;
		argv++;
		}
	if (badop)
		{
bad:
		sc_usage();
		goto end;
		}

	OpenSSL_add_ssl_algorithms();
	SSL_load_error_strings();

#ifndef OPENSSL_NO_ENGINE
        e = setup_engine(bio_err, engine_id, 1);
	if (ssl_client_engine_id)
		{
		ssl_client_engine = ENGINE_by_id(ssl_client_engine_id);
		if (!ssl_client_engine)
			{
			BIO_printf(bio_err,
					"Error getting client auth engine\n");
			goto end;
			}
		}
#endif
	if (!app_passwd(bio_err, passarg, NULL, &pass, NULL))
		{
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
		}

	if (key_file == NULL)
		key_file = cert_file;


	if (key_file)

		{

		key = load_key(bio_err, key_file, key_format, 0, pass, e,
			       "client certificate private key file");
		if (!key)
			{
			ERR_print_errors(bio_err);
			goto end;
			}

		}

	if (cert_file)

		{
		cert = load_cert(bio_err,cert_file,cert_format,
				NULL, e, "client certificate file");

		if (!cert)
			{
			ERR_print_errors(bio_err);
			goto end;
			}
		}

	if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL
		&& !RAND_status())
		{
		BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
		}
	if (inrand != NULL)
		BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
			app_RAND_load_files(inrand));

	if (bio_c_out == NULL)
		{
		if (c_quiet && !c_debug && !c_msg)
			{
			bio_c_out=BIO_new(BIO_s_null());
			}
		else
			{
			if (bio_c_out == NULL)
				bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE);
			}
		}

	ctx=SSL_CTX_new(meth);
	if (ctx == NULL)
		{
		ERR_print_errors(bio_err);
		goto end;
		}

#ifndef OPENSSL_NO_ENGINE
	if (ssl_client_engine)
		{
		if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine))
			{
			BIO_puts(bio_err, "Error setting client auth engine\n");
			ERR_print_errors(bio_err);
			ENGINE_free(ssl_client_engine);
			goto end;
			}
		ENGINE_free(ssl_client_engine);
		}
#endif

	if (bugs)
		SSL_CTX_set_options(ctx,SSL_OP_ALL|off);
	else
		SSL_CTX_set_options(ctx,off);

	if (clr)
		SSL_CTX_clear_options(ctx, clr);
	/* DTLS: partial reads end up discarding unread UDP bytes :-( 
	 * Setting read ahead solves this problem.
	 */
	if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);

	/* Enable handshake cutthrough for client connections using
	 * strong ciphers. */
	if (cutthrough)
		{
		int ssl_mode = SSL_CTX_get_mode(ctx);
		ssl_mode |= SSL_MODE_HANDSHAKE_CUTTHROUGH;
		SSL_CTX_set_mode(ctx, ssl_mode);
		}

	if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
	if (cipher != NULL)
		if(!SSL_CTX_set_cipher_list(ctx,cipher)) {
		BIO_printf(bio_err,"error setting cipher list\n");
		ERR_print_errors(bio_err);
		goto end;
	}
#if 0
	else
		SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER"));
#endif

	SSL_CTX_set_verify(ctx,verify,verify_callback);
	if (!set_cert_key_stuff(ctx,cert,key))
		goto end;

	if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
		(!SSL_CTX_set_default_verify_paths(ctx)))
		{
		/* BIO_printf(bio_err,"error setting default verify locations\n"); */
		ERR_print_errors(bio_err);
		/* goto end; */
		}

	store = SSL_CTX_get_cert_store(ctx);
	X509_STORE_set_flags(store, vflags);
#ifndef OPENSSL_NO_TLSEXT
	if (servername != NULL)
		{
		tlsextcbp.biodebug = bio_err;
		SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
		SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
		}
#endif

	con=SSL_new(ctx);
	if (sess_in)
		{
		SSL_SESSION *sess;
		BIO *stmp = BIO_new_file(sess_in, "r");
		if (!stmp)
			{
			BIO_printf(bio_err, "Can't open session file %s\n",
						sess_in);
			ERR_print_errors(bio_err);
			goto end;
			}
		sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
		BIO_free(stmp);
		if (!sess)
			{
			BIO_printf(bio_err, "Can't open session file %s\n",
						sess_in);
			ERR_print_errors(bio_err);
			goto end;
			}
		SSL_set_session(con, sess);
		SSL_SESSION_free(sess);
		}
#ifndef OPENSSL_NO_TLSEXT
	if (servername != NULL)
		{
		if (!SSL_set_tlsext_host_name(con,servername))
			{
			BIO_printf(bio_err,"Unable to set TLS servername extension.\n");
			ERR_print_errors(bio_err);
			goto end;
			}
		}
#endif

#ifndef OPENSSL_NO_KRB5
	if (con  &&  (con->kssl_ctx = kssl_ctx_new()) != NULL)
                {
                kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host);
		}
#endif	/* OPENSSL_NO_KRB5  */
/*	SSL_set_cipher_list(con,"RC4-MD5"); */

re_start:

	if (init_client(&s,host,port,sock_type) == 0)
		{
		BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error());
		SHUTDOWN(s);
		goto end;
		}
	BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s);

#ifdef FIONBIO
	if (c_nbio)
		{
		unsigned long l=1;
		BIO_printf(bio_c_out,"turning on non blocking io\n");
		if (BIO_socket_ioctl(s,FIONBIO,&l) < 0)
			{
			ERR_print_errors(bio_err);
			goto end;
			}
		}
#endif                                              
	if (c_Pause & 0x01) con->debug=1;

	if ( SSL_version(con) == DTLS1_VERSION)
		{

		sbio=BIO_new_dgram(s,BIO_NOCLOSE);
		if (getsockname(s, &peer, (void *)&peerlen) < 0)
			{
			BIO_printf(bio_err, "getsockname:errno=%d\n",
				get_last_socket_error());
			SHUTDOWN(s);
			goto end;
			}

		(void)BIO_ctrl_set_connected(sbio, 1, &peer);

		if ( enable_timeouts)
			{
			timeout.tv_sec = 0;
			timeout.tv_usec = DGRAM_RCV_TIMEOUT;
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
			
			timeout.tv_sec = 0;
			timeout.tv_usec = DGRAM_SND_TIMEOUT;
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
			}

		if (socket_mtu > 28)
			{
			SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
			SSL_set_mtu(con, socket_mtu - 28);
			}
		else
			/* want to do MTU discovery */
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
		}
	else
		sbio=BIO_new_socket(s,BIO_NOCLOSE);

	if (nbio_test)
		{
		BIO *test;

		test=BIO_new(BIO_f_nbio_test());
		sbio=BIO_push(test,sbio);
		}

	if (c_debug)
		{
		con->debug=1;
		BIO_set_callback(sbio,bio_dump_callback);
		BIO_set_callback_arg(sbio,(char *)bio_c_out);
		}
	if (c_msg)
		{
		SSL_set_msg_callback(con, msg_cb);
		SSL_set_msg_callback_arg(con, bio_c_out);
		}
#ifndef OPENSSL_NO_TLSEXT
	if (c_tlsextdebug)
		{
		SSL_set_tlsext_debug_callback(con, tlsext_cb);
		SSL_set_tlsext_debug_arg(con, bio_c_out);
		}
	if (c_status_req)
		{
		SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp);
		SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb);
		SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out);
#if 0
{
STACK_OF(OCSP_RESPID) *ids = sk_OCSP_RESPID_new_null();
OCSP_RESPID *id = OCSP_RESPID_new();
id->value.byKey = ASN1_OCTET_STRING_new();
id->type = V_OCSP_RESPID_KEY;
ASN1_STRING_set(id->value.byKey, "Hello World", -1);
sk_OCSP_RESPID_push(ids, id);
SSL_set_tlsext_status_ids(con, ids);
}
#endif
		}
#endif
#ifndef OPENSSL_NO_JPAKE
	if (jpake_secret)
		jpake_client_auth(bio_c_out, sbio, jpake_secret);
#endif

	SSL_set_bio(con,sbio,sbio);
	SSL_set_connect_state(con);

	/* ok, lets connect */
	width=SSL_get_fd(con)+1;

	read_tty=1;
	write_tty=0;
	tty_on=0;
	read_ssl=1;
	write_ssl=1;
	
	cbuf_len=0;
	cbuf_off=0;
	sbuf_len=0;
	sbuf_off=0;

	/* This is an ugly hack that does a lot of assumptions */
	/* We do have to handle multi-line responses which may come
 	   in a single packet or not. We therefore have to use
	   BIO_gets() which does need a buffering BIO. So during
	   the initial chitchat we do push a buffering BIO into the
	   chain that is removed again later on to not disturb the
	   rest of the s_client operation. */
	if (starttls_proto == PROTO_SMTP)
		{
		int foundit=0;
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		/* wait for multi-line response to end from SMTP */
		do
			{
			mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
			}
		while (mbuf_len>3 && mbuf[3]=='-');
		/* STARTTLS command requires EHLO... */
		BIO_printf(fbio,"EHLO openssl.client.net\r\n");
		(void)BIO_flush(fbio);
		/* wait for multi-line response to end EHLO SMTP response */
		do
			{
			mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
			if (strstr(mbuf,"STARTTLS"))
				foundit=1;
			}
		while (mbuf_len>3 && mbuf[3]=='-');
		(void)BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		if (!foundit)
			BIO_printf(bio_err,
				   "didn't found starttls in server response,"
				   " try anyway...\n");
		BIO_printf(sbio,"STARTTLS\r\n");
		BIO_read(sbio,sbuf,BUFSIZZ);
		}
	else if (starttls_proto == PROTO_POP3)
		{
		BIO_read(sbio,mbuf,BUFSIZZ);
		BIO_printf(sbio,"STLS\r\n");
		BIO_read(sbio,sbuf,BUFSIZZ);
		}
	else if (starttls_proto == PROTO_IMAP)
		{
		int foundit=0;
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		BIO_gets(fbio,mbuf,BUFSIZZ);
		/* STARTTLS command requires CAPABILITY... */
		BIO_printf(fbio,". CAPABILITY\r\n");
		(void)BIO_flush(fbio);
		/* wait for multi-line CAPABILITY response */
		do
			{
			mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
			if (strstr(mbuf,"STARTTLS"))
				foundit=1;
			}
		while (mbuf_len>3 && mbuf[0]!='.');
		(void)BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		if (!foundit)
			BIO_printf(bio_err,
				   "didn't found STARTTLS in server response,"
				   " try anyway...\n");
		BIO_printf(sbio,". STARTTLS\r\n");
		BIO_read(sbio,sbuf,BUFSIZZ);
		}
	else if (starttls_proto == PROTO_FTP)
		{
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		/* wait for multi-line response to end from FTP */
		do
			{
			mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
			}
		while (mbuf_len>3 && mbuf[3]=='-');
		(void)BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		BIO_printf(sbio,"AUTH TLS\r\n");
		BIO_read(sbio,sbuf,BUFSIZZ);
		}
	if (starttls_proto == PROTO_XMPP)
		{
		int seen = 0;
		BIO_printf(sbio,"<stream:stream "
		    "xmlns:stream='http://etherx.jabber.org/streams' "
		    "xmlns='jabber:client' to='%s' version='1.0'>", host);
		seen = BIO_read(sbio,mbuf,BUFSIZZ);
		mbuf[seen] = 0;
		while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'"))
			{
			if (strstr(mbuf, "/stream:features>"))
				goto shut;
			seen = BIO_read(sbio,mbuf,BUFSIZZ);
			mbuf[seen] = 0;
			}
		BIO_printf(sbio, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
		seen = BIO_read(sbio,sbuf,BUFSIZZ);
		sbuf[seen] = 0;
		if (!strstr(sbuf, "<proceed"))
			goto shut;
		mbuf[0] = 0;
		}

	for (;;)
		{
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);

		if ((SSL_version(con) == DTLS1_VERSION) &&
			DTLSv1_get_timeout(con, &timeout))
			timeoutp = &timeout;
		else
			timeoutp = NULL;

		if (SSL_in_init(con) && !SSL_total_renegotiations(con))
			{
			in_init=1;
			tty_on=0;
			}
		else
			{
			tty_on=1;
			if (in_init)
				{
				in_init=0;
				if (sess_out)
					{
					BIO *stmp = BIO_new_file(sess_out, "w");
					if (stmp)
						{
						PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con));
						BIO_free(stmp);
						}
					else 
						BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
					}
				print_stuff(bio_c_out,con,full_log);
				if (full_log > 0) full_log--;

				if (starttls_proto)
					{
					BIO_printf(bio_err,"%s",mbuf);
					/* We don't need to know any more */
					starttls_proto = PROTO_OFF;
					}

				if (reconnect)
					{
					reconnect--;
					BIO_printf(bio_c_out,"drop connection and then reconnect\n");
					SSL_shutdown(con);
					SSL_set_connect_state(con);
					SHUTDOWN(SSL_get_fd(con));
					goto re_start;
					}
				}
			}

		ssl_pending = read_ssl && SSL_pending(con);

		if (!ssl_pending)
			{
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE)
			if (tty_on)
				{
				if (read_tty)  FD_SET(fileno(stdin),&readfds);
				if (write_tty) FD_SET(fileno(stdout),&writefds);
				}
			if (read_ssl)
				FD_SET(SSL_get_fd(con),&readfds);
			if (write_ssl)
				FD_SET(SSL_get_fd(con),&writefds);
#else
			if(!tty_on || !write_tty) {
				if (read_ssl)
					FD_SET(SSL_get_fd(con),&readfds);
				if (write_ssl)
					FD_SET(SSL_get_fd(con),&writefds);
			}
#endif
/*			printf("mode tty(%d %d%d) ssl(%d%d)\n",
				tty_on,read_tty,write_tty,read_ssl,write_ssl);*/

			/* Note: under VMS with SOCKETSHR the second parameter
			 * is currently of type (int *) whereas under other
			 * systems it is (void *) if you don't have a cast it
			 * will choke the compiler: if you do have a cast then
			 * you can either go for (int *) or (void *).
			 */
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
                        /* Under Windows/DOS we make the assumption that we can
			 * always write to the tty: therefore if we need to
			 * write to the tty we just fall through. Otherwise
			 * we timeout the select every second and see if there
			 * are any keypresses. Note: this is a hack, in a proper
			 * Windows application we wouldn't do this.
			 */
			i=0;
			if(!write_tty) {
				if(read_tty) {
					tv.tv_sec = 1;
					tv.tv_usec = 0;
					i=select(width,(void *)&readfds,(void *)&writefds,
						 NULL,&tv);
#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
					if(!i && (!_kbhit() || !read_tty) ) continue;
#else
					if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue;
#endif
				} else 	i=select(width,(void *)&readfds,(void *)&writefds,
					 NULL,timeoutp);
			}
#elif defined(OPENSSL_SYS_NETWARE)
			if(!write_tty) {
				if(read_tty) {
					tv.tv_sec = 1;
					tv.tv_usec = 0;
					i=select(width,(void *)&readfds,(void *)&writefds,
						NULL,&tv);
				} else 	i=select(width,(void *)&readfds,(void *)&writefds,
					NULL,timeoutp);
			}
#else
			i=select(width,(void *)&readfds,(void *)&writefds,
				 NULL,timeoutp);
#endif
			if ( i < 0)
				{
				BIO_printf(bio_err,"bad select %d\n",
				get_last_socket_error());
				goto shut;
				/* goto end; */
				}
			}

		if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0)
			{
			BIO_printf(bio_err,"TIMEOUT occured\n");
			}

		if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds))
			{
			k=SSL_write(con,&(cbuf[cbuf_off]),
				(unsigned int)cbuf_len);
			switch (SSL_get_error(con,k))
				{
			case SSL_ERROR_NONE:
				cbuf_off+=k;
				cbuf_len-=k;
				if (k <= 0) goto end;
				/* we have done a  write(con,NULL,0); */
				if (cbuf_len <= 0)
					{
					read_tty=1;
					write_ssl=0;
					}
				else /* if (cbuf_len > 0) */
					{
					read_tty=0;
					write_ssl=1;
					}
				break;
			case SSL_ERROR_WANT_WRITE:
				BIO_printf(bio_c_out,"write W BLOCK\n");
				write_ssl=1;
				read_tty=0;
				break;
			case SSL_ERROR_WANT_READ:
				BIO_printf(bio_c_out,"write R BLOCK\n");
				write_tty=0;
				read_ssl=1;
				write_ssl=0;
				break;
			case SSL_ERROR_WANT_X509_LOOKUP:
				BIO_printf(bio_c_out,"write X BLOCK\n");
				break;
			case SSL_ERROR_ZERO_RETURN:
				if (cbuf_len != 0)
					{
					BIO_printf(bio_c_out,"shutdown\n");
					goto shut;
					}
				else
					{
					read_tty=1;
					write_ssl=0;
					break;
					}
				
			case SSL_ERROR_SYSCALL:
				if ((k != 0) || (cbuf_len != 0))
					{
					BIO_printf(bio_err,"write:errno=%d\n",
						get_last_socket_error());
					goto shut;
					}
				else
					{
					read_tty=1;
					write_ssl=0;
					}
				break;
			case SSL_ERROR_SSL:
				ERR_print_errors(bio_err);
				goto shut;
				}
			}
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE)
		/* Assume Windows/DOS can always write */
		else if (!ssl_pending && write_tty)
#else
		else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds))
#endif
			{
#ifdef CHARSET_EBCDIC
			ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len);
#endif
			i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len);

			if (i <= 0)
				{
				BIO_printf(bio_c_out,"DONE\n");
				goto shut;
				/* goto end; */
				}

			sbuf_len-=i;;
			sbuf_off+=i;
			if (sbuf_len <= 0)
				{
				read_ssl=1;
				write_tty=0;
				}
			}
		else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds))
			{
#ifdef RENEG
{ static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } }
#endif
#if 1
			k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ );
#else
/* Demo for pending and peek :-) */
			k=SSL_read(con,sbuf,16);
{ char zbuf[10240]; 
printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240));
}
#endif

			switch (SSL_get_error(con,k))
				{
			case SSL_ERROR_NONE:
				if (k <= 0)
					goto end;
				sbuf_off=0;
				sbuf_len=k;

				read_ssl=0;
				write_tty=1;
				break;
			case SSL_ERROR_WANT_WRITE:
				BIO_printf(bio_c_out,"read W BLOCK\n");
				write_ssl=1;
				read_tty=0;
				break;
			case SSL_ERROR_WANT_READ:
				BIO_printf(bio_c_out,"read R BLOCK\n");
				write_tty=0;
				read_ssl=1;
				if ((read_tty == 0) && (write_ssl == 0))
					write_ssl=1;
				break;
			case SSL_ERROR_WANT_X509_LOOKUP:
				BIO_printf(bio_c_out,"read X BLOCK\n");
				break;
			case SSL_ERROR_SYSCALL:
				BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error());
				goto shut;
			case SSL_ERROR_ZERO_RETURN:
				BIO_printf(bio_c_out,"closed\n");
				goto shut;
			case SSL_ERROR_SSL:
				ERR_print_errors(bio_err);
				goto shut;
				/* break; */
				}
			}

#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
		else if (_kbhit())
#else
		else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0)))
#endif
#elif defined (OPENSSL_SYS_NETWARE)
        else if (_kbhit())
#else
		else if (FD_ISSET(fileno(stdin),&readfds))
#endif
			{
			if (crlf)
				{
				int j, lf_num;

				i=read(fileno(stdin),cbuf,BUFSIZZ/2);
				lf_num = 0;
				/* both loops are skipped when i <= 0 */
				for (j = 0; j < i; j++)
					if (cbuf[j] == '\n')
						lf_num++;
				for (j = i-1; j >= 0; j--)
					{
					cbuf[j+lf_num] = cbuf[j];
					if (cbuf[j] == '\n')
						{
						lf_num--;
						i++;
						cbuf[j+lf_num] = '\r';
						}
					}
				assert(lf_num == 0);
				}
			else
				i=read(fileno(stdin),cbuf,BUFSIZZ);

			if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q')))
				{
				BIO_printf(bio_err,"DONE\n");
				goto shut;
				}

			if ((!c_ign_eof) && (cbuf[0] == 'R'))
				{
				BIO_printf(bio_err,"RENEGOTIATING\n");
				SSL_renegotiate(con);
				cbuf_len=0;
				}
			else
				{
				cbuf_len=i;
				cbuf_off=0;
#ifdef CHARSET_EBCDIC
				ebcdic2ascii(cbuf, cbuf, i);
#endif
				}

			write_ssl=1;
			read_tty=0;
			}
		}
shut:
	SSL_shutdown(con);
	SHUTDOWN(SSL_get_fd(con));
	ret=0;
end:
	if(prexit) print_stuff(bio_c_out,con,1);
	if (con != NULL) SSL_free(con);
	if (con2 != NULL) SSL_free(con2);
	if (ctx != NULL) SSL_CTX_free(ctx);
	if (cert)
		X509_free(cert);
	if (key)
		EVP_PKEY_free(key);
	if (pass)
		OPENSSL_free(pass);
	if (cbuf != NULL) { OPENSSL_cleanse(cbuf,BUFSIZZ); OPENSSL_free(cbuf); }
	if (sbuf != NULL) { OPENSSL_cleanse(sbuf,BUFSIZZ); OPENSSL_free(sbuf); }
	if (mbuf != NULL) { OPENSSL_cleanse(mbuf,BUFSIZZ); OPENSSL_free(mbuf); }
	if (bio_c_out != NULL)
		{
		BIO_free(bio_c_out);
		bio_c_out=NULL;
		}
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Example #22
0
static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id,
                                   const char *CAfile, const char *cert,
                                   const char *key, const char *dcert,
                                   const char *dkey, const char *cipher_list,
                                   const char *dh_file,
                                   const char *dh_special, int tmp_rsa,
                                   int ctx_options, int out_state,
                                   int out_verify, int verify_mode,
                                   unsigned int verify_depth)
{
    SSL_CTX *ctx = NULL, *ret = NULL;
    const SSL_METHOD *meth;
    ENGINE *e = NULL;

    OpenSSL_add_ssl_algorithms();
    SSL_load_error_strings();

    meth = (server_mode ? SSLv23_server_method() : SSLv23_client_method());
    if (meth == NULL)
        goto err;
    if (engine_id) {
        ENGINE_load_builtin_engines();
        if ((e = ENGINE_by_id(engine_id)) == NULL) {
            fprintf(stderr, "Error obtaining '%s' engine, openssl "
                    "errors follow\n", engine_id);
            goto err;
        }
        if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
            fprintf(stderr, "Error assigning '%s' engine, openssl "
                    "errors follow\n", engine_id);
            goto err;
        }
        ENGINE_free(e);
    }
    if ((ctx = SSL_CTX_new(meth)) == NULL)
        goto err;
    /* cacert */
    if (CAfile) {
        if (!X509_STORE_load_locations(SSL_CTX_get_cert_store(ctx),
                                       CAfile, NULL)) {
            fprintf(stderr, "Error loading CA cert(s) in '%s'\n", CAfile);
            goto err;
        }
        fprintf(stderr, "Info, operating with CA cert(s) in '%s'\n", CAfile);
    } else
        fprintf(stderr, "Info, operating without a CA cert(-list)\n");
    if (!SSL_CTX_set_default_verify_paths(ctx)) {
        fprintf(stderr, "Error setting default verify paths\n");
        goto err;
    }

    /* cert and key */
    if ((cert || key) && !ctx_set_cert(ctx, cert, key))
        goto err;
    /* dcert and dkey */
    if ((dcert || dkey) && !ctx_set_cert(ctx, dcert, dkey))
        goto err;
    /* temporary RSA key generation */
    if (tmp_rsa)
        SSL_CTX_set_tmp_rsa_callback(ctx, cb_generate_tmp_rsa);

    /* cipher_list */
    if (cipher_list) {
        if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) {
            fprintf(stderr, "Error setting cipher list '%s'\n", cipher_list);
            goto err;
        }
        fprintf(stderr, "Info, set cipher list '%s'\n", cipher_list);
    } else
        fprintf(stderr, "Info, operating with default cipher list\n");

    /* dh_file & dh_special */
    if ((dh_file || dh_special) && !ctx_set_dh(ctx, dh_file, dh_special))
        goto err;

    /* ctx_options */
    SSL_CTX_set_options(ctx, ctx_options);

    /* out_state (output of SSL handshake states to screen). */
    if (out_state)
        cb_ssl_info_set_output(stderr);

    /* out_verify */
    if (out_verify > 0) {
        cb_ssl_verify_set_output(stderr);
        cb_ssl_verify_set_level(out_verify);
    }

    /* verify_depth */
    cb_ssl_verify_set_depth(verify_depth);

    /* Success! (includes setting verify_mode) */
    SSL_CTX_set_info_callback(ctx, cb_ssl_info);
    SSL_CTX_set_verify(ctx, verify_mode, cb_ssl_verify);
    ret = ctx;
 err:
    if (!ret) {
        ERR_print_errors_fp(stderr);
        if (ctx)
            SSL_CTX_free(ctx);
    }
    return ret;
}
int MAIN(int argc, char **argv)
	{
	int ret=1,i;
	const char **pp;
	int verbose=0, list_cap=0, test_avail=0, test_avail_noise = 0;
	ENGINE *e;
	STACK *engines = sk_new_null();
	STACK *pre_cmds = sk_new_null();
	STACK *post_cmds = sk_new_null();
	int badops=1;
	BIO *bio_out=NULL;
	const char *indent = "     ";

	apps_startup();
	SSL_load_error_strings();

	if (bio_err == NULL)
		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);

	if (!load_config(bio_err, NULL))
		goto end;
	bio_out=BIO_new_fp(stdout,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
	{
	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	bio_out = BIO_push(tmpbio, bio_out);
	}
#endif

	argc--;
	argv++;
	while (argc >= 1)
		{
		if (strncmp(*argv,"-v",2) == 0)
			{
			if(strspn(*argv + 1, "v") < strlen(*argv + 1))
				goto skip_arg_loop;
			if((verbose=strlen(*argv + 1)) > 4)
				goto skip_arg_loop;
			}
		else if (strcmp(*argv,"-c") == 0)
			list_cap=1;
		else if (strncmp(*argv,"-t",2) == 0)
			{
			test_avail=1;
			if(strspn(*argv + 1, "t") < strlen(*argv + 1))
				goto skip_arg_loop;
			if((test_avail_noise = strlen(*argv + 1) - 1) > 1)
				goto skip_arg_loop;
			}
		else if (strcmp(*argv,"-pre") == 0)
			{
			argc--; argv++;
			if (argc == 0)
				goto skip_arg_loop;
			sk_push(pre_cmds,*argv);
			}
		else if (strcmp(*argv,"-post") == 0)
			{
			argc--; argv++;
			if (argc == 0)
				goto skip_arg_loop;
			sk_push(post_cmds,*argv);
			}
		else if ((strncmp(*argv,"-h",2) == 0) ||
				(strcmp(*argv,"-?") == 0))
			goto skip_arg_loop;
		else
			sk_push(engines,*argv);
		argc--;
		argv++;
		}
	/* Looks like everything went OK */
	badops = 0;
skip_arg_loop:

	if (badops)
		{
		for (pp=engine_usage; (*pp != NULL); pp++)
			BIO_printf(bio_err,"%s",*pp);
		goto end;
		}

	if (sk_num(engines) == 0)
		{
		for(e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e))
			{
			sk_push(engines,(char *)ENGINE_get_id(e));
			}
		}

	for (i=0; i<sk_num(engines); i++)
		{
		const char *id = sk_value(engines,i);
		if ((e = ENGINE_by_id(id)) != NULL)
			{
			const char *name = ENGINE_get_name(e);
			/* Do "id" first, then "name". Easier to auto-parse. */
			BIO_printf(bio_out, "(%s) %s\n", id, name);
			util_do_cmds(e, pre_cmds, bio_out, indent);
			if (strcmp(ENGINE_get_id(e), id) != 0)
				{
				BIO_printf(bio_out, "Loaded: (%s) %s\n",
					ENGINE_get_id(e), ENGINE_get_name(e));
				}
			if (list_cap)
				{
				int cap_size = 256;
				char *cap_buf = NULL;
				int k,n;
				const int *nids;
				ENGINE_CIPHERS_PTR fn_c;
				ENGINE_DIGESTS_PTR fn_d;

				if (ENGINE_get_RSA(e) != NULL
					&& !append_buf(&cap_buf, "RSA",
						&cap_size, 256))
					goto end;
				if (ENGINE_get_DSA(e) != NULL
					&& !append_buf(&cap_buf, "DSA",
						&cap_size, 256))
					goto end;
				if (ENGINE_get_DH(e) != NULL
					&& !append_buf(&cap_buf, "DH",
						&cap_size, 256))
					goto end;
				if (ENGINE_get_RAND(e) != NULL
					&& !append_buf(&cap_buf, "RAND",
						&cap_size, 256))
					goto end;

				fn_c = ENGINE_get_ciphers(e);
				if(!fn_c) goto skip_ciphers;
				n = fn_c(e, NULL, &nids, 0);
				for(k=0 ; k < n ; ++k)
					if(!append_buf(&cap_buf,
						       OBJ_nid2sn(nids[k]),
						       &cap_size, 256))
						goto end;

skip_ciphers:
				fn_d = ENGINE_get_digests(e);
				if(!fn_d) goto skip_digests;
				n = fn_d(e, NULL, &nids, 0);
				for(k=0 ; k < n ; ++k)
					if(!append_buf(&cap_buf,
						       OBJ_nid2sn(nids[k]),
						       &cap_size, 256))
						goto end;

skip_digests:
				if (cap_buf && (*cap_buf != '\0'))
					BIO_printf(bio_out, " [%s]\n", cap_buf);

				OPENSSL_free(cap_buf);
				}
			if(test_avail)
				{
				BIO_printf(bio_out, "%s", indent);
				if (ENGINE_init(e))
					{
					BIO_printf(bio_out, "[ available ]\n");
					util_do_cmds(e, post_cmds, bio_out, indent);
					ENGINE_finish(e);
					}
				else
					{
					BIO_printf(bio_out, "[ unavailable ]\n");
					if(test_avail_noise)
						ERR_print_errors_fp(stdout);
					ERR_clear_error();
					}
				}
			if((verbose > 0) && !util_verbose(e, verbose, bio_out, indent))
				goto end;
			ENGINE_free(e);
			}
		else
			ERR_print_errors(bio_err);
		}

	ret=0;
end:

	ERR_print_errors(bio_err);
	sk_pop_free(engines, identity);
	sk_pop_free(pre_cmds, identity);
	sk_pop_free(post_cmds, identity);
	if (bio_out != NULL) BIO_free_all(bio_out);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Example #24
0
int
s_client_main(int argc, char **argv)
{
	unsigned int off = 0, clr = 0;
	SSL *con = NULL;
	int s, k, width, state = 0, af = AF_UNSPEC;
	char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL;
	int cbuf_len, cbuf_off;
	int sbuf_len, sbuf_off;
	fd_set readfds, writefds;
	char *port = PORT_STR;
	int full_log = 1;
	char *host = SSL_HOST_NAME;
	char *cert_file = NULL, *key_file = NULL;
	int cert_format = FORMAT_PEM, key_format = FORMAT_PEM;
	char *passarg = NULL, *pass = NULL;
	X509 *cert = NULL;
	EVP_PKEY *key = NULL;
	char *CApath = NULL, *CAfile = NULL, *cipher = NULL;
	int reconnect = 0, badop = 0, verify = SSL_VERIFY_NONE, bugs = 0;
	int crlf = 0;
	int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending;
	SSL_CTX *ctx = NULL;
	int ret = 1, in_init = 1, i, nbio_test = 0;
	int starttls_proto = PROTO_OFF;
	int prexit = 0;
	X509_VERIFY_PARAM *vpm = NULL;
	int badarg = 0;
	const SSL_METHOD *meth = NULL;
	int socket_type = SOCK_STREAM;
	BIO *sbio;
	int mbuf_len = 0;
	struct timeval timeout, *timeoutp;
	const char *errstr = NULL;
#ifndef OPENSSL_NO_ENGINE
	char *engine_id = NULL;
	char *ssl_client_engine_id = NULL;
	ENGINE *ssl_client_engine = NULL;
#endif
	ENGINE *e = NULL;
#ifndef OPENSSL_NO_TLSEXT
	char *servername = NULL;
	tlsextctx tlsextcbp =
	{NULL, 0};
#ifndef OPENSSL_NO_NEXTPROTONEG
	const char *next_proto_neg_in = NULL;
#endif
#endif
	char *sess_in = NULL;
	char *sess_out = NULL;
	struct sockaddr peer;
	int peerlen = sizeof(peer);
	int enable_timeouts = 0;
	long socket_mtu = 0;

	meth = SSLv23_client_method();

	c_Pause = 0;
	c_quiet = 0;
	c_ign_eof = 0;
	c_debug = 0;
	c_msg = 0;
	c_showcerts = 0;

	if (((cbuf = malloc(BUFSIZZ)) == NULL) ||
	    ((sbuf = malloc(BUFSIZZ)) == NULL) ||
	    ((mbuf = malloc(BUFSIZZ + 1)) == NULL)) {	/* NUL byte */
		BIO_printf(bio_err, "out of memory\n");
		goto end;
	}
	verify_depth = 0;
	verify_error = X509_V_OK;
	c_nbio = 0;

	argc--;
	argv++;
	while (argc >= 1) {
		if (strcmp(*argv, "-host") == 0) {
			if (--argc < 1)
				goto bad;
			host = *(++argv);
		} else if (strcmp(*argv, "-port") == 0) {
			if (--argc < 1)
				goto bad;
			port = *(++argv);
			if (port == NULL || *port == '\0')
				goto bad;
		} else if (strcmp(*argv, "-connect") == 0) {
			if (--argc < 1)
				goto bad;
			if (!extract_host_port(*(++argv), &host, NULL, &port))
				goto bad;
		} else if (strcmp(*argv, "-verify") == 0) {
			verify = SSL_VERIFY_PEER;
			if (--argc < 1)
				goto bad;
			verify_depth = strtonum(*(++argv), 0, INT_MAX, &errstr);
			if (errstr)
				goto bad;
			BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
		} else if (strcmp(*argv, "-cert") == 0) {
			if (--argc < 1)
				goto bad;
			cert_file = *(++argv);
		} else if (strcmp(*argv, "-sess_out") == 0) {
			if (--argc < 1)
				goto bad;
			sess_out = *(++argv);
		} else if (strcmp(*argv, "-sess_in") == 0) {
			if (--argc < 1)
				goto bad;
			sess_in = *(++argv);
		} else if (strcmp(*argv, "-certform") == 0) {
			if (--argc < 1)
				goto bad;
			cert_format = str2fmt(*(++argv));
		} else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) {
			if (badarg)
				goto bad;
			continue;
		} else if (strcmp(*argv, "-verify_return_error") == 0)
			verify_return_error = 1;
		else if (strcmp(*argv, "-prexit") == 0)
			prexit = 1;
		else if (strcmp(*argv, "-crlf") == 0)
			crlf = 1;
		else if (strcmp(*argv, "-quiet") == 0) {
			c_quiet = 1;
			c_ign_eof = 1;
		} else if (strcmp(*argv, "-ign_eof") == 0)
			c_ign_eof = 1;
		else if (strcmp(*argv, "-no_ign_eof") == 0)
			c_ign_eof = 0;
		else if (strcmp(*argv, "-pause") == 0)
			c_Pause = 1;
		else if (strcmp(*argv, "-debug") == 0)
			c_debug = 1;
#ifndef OPENSSL_NO_TLSEXT
		else if (strcmp(*argv, "-tlsextdebug") == 0)
			c_tlsextdebug = 1;
		else if (strcmp(*argv, "-status") == 0)
			c_status_req = 1;
#endif
		else if (strcmp(*argv, "-msg") == 0)
			c_msg = 1;
		else if (strcmp(*argv, "-showcerts") == 0)
			c_showcerts = 1;
		else if (strcmp(*argv, "-nbio_test") == 0)
			nbio_test = 1;
		else if (strcmp(*argv, "-state") == 0)
			state = 1;
		else if (strcmp(*argv, "-ssl3") == 0)
			meth = SSLv3_client_method();
		else if (strcmp(*argv, "-tls1_2") == 0)
			meth = TLSv1_2_client_method();
		else if (strcmp(*argv, "-tls1_1") == 0)
			meth = TLSv1_1_client_method();
		else if (strcmp(*argv, "-tls1") == 0)
			meth = TLSv1_client_method();
#ifndef OPENSSL_NO_DTLS1
		else if (strcmp(*argv, "-dtls1") == 0) {
			meth = DTLSv1_client_method();
			socket_type = SOCK_DGRAM;
		} else if (strcmp(*argv, "-timeout") == 0)
			enable_timeouts = 1;
		else if (strcmp(*argv, "-mtu") == 0) {
			if (--argc < 1)
				goto bad;
			socket_mtu = strtonum(*(++argv), 0, LONG_MAX, &errstr);
			if (errstr)
				goto bad;
		}
#endif
		else if (strcmp(*argv, "-bugs") == 0)
			bugs = 1;
		else if (strcmp(*argv, "-keyform") == 0) {
			if (--argc < 1)
				goto bad;
			key_format = str2fmt(*(++argv));
		} else if (strcmp(*argv, "-pass") == 0) {
			if (--argc < 1)
				goto bad;
			passarg = *(++argv);
		} else if (strcmp(*argv, "-key") == 0) {
			if (--argc < 1)
				goto bad;
			key_file = *(++argv);
		} else if (strcmp(*argv, "-reconnect") == 0) {
			reconnect = 5;
		} else if (strcmp(*argv, "-CApath") == 0) {
			if (--argc < 1)
				goto bad;
			CApath = *(++argv);
		} else if (strcmp(*argv, "-CAfile") == 0) {
			if (--argc < 1)
				goto bad;
			CAfile = *(++argv);
		} else if (strcmp(*argv, "-no_tls1_2") == 0)
			off |= SSL_OP_NO_TLSv1_2;
		else if (strcmp(*argv, "-no_tls1_1") == 0)
			off |= SSL_OP_NO_TLSv1_1;
		else if (strcmp(*argv, "-no_tls1") == 0)
			off |= SSL_OP_NO_TLSv1;
		else if (strcmp(*argv, "-no_ssl3") == 0)
			off |= SSL_OP_NO_SSLv3;
		else if (strcmp(*argv, "-no_ssl2") == 0)
			off |= SSL_OP_NO_SSLv2;
		else if (strcmp(*argv, "-no_comp") == 0) {
			off |= SSL_OP_NO_COMPRESSION;
		}
#ifndef OPENSSL_NO_TLSEXT
		else if (strcmp(*argv, "-no_ticket") == 0) {
			off |= SSL_OP_NO_TICKET;
		}
#ifndef OPENSSL_NO_NEXTPROTONEG
		else if (strcmp(*argv, "-nextprotoneg") == 0) {
			if (--argc < 1)
				goto bad;
			next_proto_neg_in = *(++argv);
		}
#endif
#endif
		else if (strcmp(*argv, "-serverpref") == 0)
			off |= SSL_OP_CIPHER_SERVER_PREFERENCE;
		else if (strcmp(*argv, "-legacy_renegotiation") == 0)
			; /* no-op */
		else if (strcmp(*argv, "-legacy_server_connect") == 0) {
			off |= SSL_OP_LEGACY_SERVER_CONNECT;
		} else if (strcmp(*argv, "-no_legacy_server_connect") == 0) {
			clr |= SSL_OP_LEGACY_SERVER_CONNECT;
		} else if (strcmp(*argv, "-cipher") == 0) {
			if (--argc < 1)
				goto bad;
			cipher = *(++argv);
		}
		else if (strcmp(*argv, "-nbio") == 0) {
			c_nbio = 1;
		}
		else if (strcmp(*argv, "-starttls") == 0) {
			if (--argc < 1)
				goto bad;
			++argv;
			if (strcmp(*argv, "smtp") == 0)
				starttls_proto = PROTO_SMTP;
			else if (strcmp(*argv, "lmtp") == 0)
				starttls_proto = PROTO_LMTP;
			else if (strcmp(*argv, "pop3") == 0)
				starttls_proto = PROTO_POP3;
			else if (strcmp(*argv, "imap") == 0)
				starttls_proto = PROTO_IMAP;
			else if (strcmp(*argv, "ftp") == 0)
				starttls_proto = PROTO_FTP;
			else if (strcmp(*argv, "xmpp") == 0)
				starttls_proto = PROTO_XMPP;
			else
				goto bad;
		}
#ifndef OPENSSL_NO_ENGINE
		else if (strcmp(*argv, "-engine") == 0) {
			if (--argc < 1)
				goto bad;
			engine_id = *(++argv);
		} else if (strcmp(*argv, "-ssl_client_engine") == 0) {
			if (--argc < 1)
				goto bad;
			ssl_client_engine_id = *(++argv);
		}
#endif
		else if (strcmp(*argv, "-4") == 0) {
			af = AF_INET;
		} else if (strcmp(*argv, "-6") == 0) {
			af = AF_INET6;
		}
#ifndef OPENSSL_NO_TLSEXT
		else if (strcmp(*argv, "-servername") == 0) {
			if (--argc < 1)
				goto bad;
			servername = *(++argv);
			/* meth=TLSv1_client_method(); */
		}
#endif
#ifndef OPENSSL_NO_SRTP
		else if (strcmp(*argv, "-use_srtp") == 0) {
			if (--argc < 1)
				goto bad;
			srtp_profiles = *(++argv);
		}
#endif
		else if (strcmp(*argv, "-keymatexport") == 0) {
			if (--argc < 1)
				goto bad;
			keymatexportlabel = *(++argv);
		} else if (strcmp(*argv, "-keymatexportlen") == 0) {
			const char *errstr;

			if (--argc < 1)
				goto bad;
			keymatexportlen = strtonum(*(++argv), 1, INT_MAX, &errstr);
			if (errstr)
				goto bad;
		} else {
			BIO_printf(bio_err, "unknown option %s\n", *argv);
			badop = 1;
			break;
		}
		argc--;
		argv++;
	}
	if (badop) {
bad:
		if (errstr)
			BIO_printf(bio_err, "invalid argument %s: %s\n",
			    *argv, errstr);
		else
			sc_usage();
		goto end;
	}

#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
	next_proto.status = -1;
	if (next_proto_neg_in) {
		next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in);
		if (next_proto.data == NULL) {
			BIO_printf(bio_err, "Error parsing -nextprotoneg argument\n");
			goto end;
		}
	} else
		next_proto.data = NULL;
#endif

#ifndef OPENSSL_NO_ENGINE
	e = setup_engine(bio_err, engine_id, 1);
	if (ssl_client_engine_id) {
		ssl_client_engine = ENGINE_by_id(ssl_client_engine_id);
		if (!ssl_client_engine) {
			BIO_printf(bio_err,
			    "Error getting client auth engine\n");
			goto end;
		}
	}
#endif
	if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) {
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
	}
	if (key_file == NULL)
		key_file = cert_file;


	if (key_file) {

		key = load_key(bio_err, key_file, key_format, 0, pass, e,
		    "client certificate private key file");
		if (!key) {
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (cert_file) {
		cert = load_cert(bio_err, cert_file, cert_format,
		    NULL, e, "client certificate file");

		if (!cert) {
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (bio_c_out == NULL) {
		if (c_quiet && !c_debug && !c_msg) {
			bio_c_out = BIO_new(BIO_s_null());
		} else {
			if (bio_c_out == NULL)
				bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE);
		}
	}

	ctx = SSL_CTX_new(meth);
	if (ctx == NULL) {
		ERR_print_errors(bio_err);
		goto end;
	}
	if (vpm)
		SSL_CTX_set1_param(ctx, vpm);

#ifndef OPENSSL_NO_ENGINE
	if (ssl_client_engine) {
		if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) {
			BIO_puts(bio_err, "Error setting client auth engine\n");
			ERR_print_errors(bio_err);
			ENGINE_free(ssl_client_engine);
			goto end;
		}
		ENGINE_free(ssl_client_engine);
	}
#endif

#ifndef OPENSSL_NO_SRTP
	if (srtp_profiles != NULL)
		SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles);
#endif
	if (bugs)
		SSL_CTX_set_options(ctx, SSL_OP_ALL | off);
	else
		SSL_CTX_set_options(ctx, off);

	if (clr)
		SSL_CTX_clear_options(ctx, clr);
	/*
	 * DTLS: partial reads end up discarding unread UDP bytes :-( Setting
	 * read ahead solves this problem.
	 */
	if (socket_type == SOCK_DGRAM)
		SSL_CTX_set_read_ahead(ctx, 1);

#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
	if (next_proto.data)
		SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
#endif

	if (state)
		SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
	if (cipher != NULL)
		if (!SSL_CTX_set_cipher_list(ctx, cipher)) {
			BIO_printf(bio_err, "error setting cipher list\n");
			ERR_print_errors(bio_err);
			goto end;
		}

	SSL_CTX_set_verify(ctx, verify, verify_callback);
	if (!set_cert_key_stuff(ctx, cert, key))
		goto end;

	if ((!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) ||
	    (!SSL_CTX_set_default_verify_paths(ctx))) {
		/*
		 * BIO_printf(bio_err,"error setting default verify
		 * locations\n");
		 */
		ERR_print_errors(bio_err);
		/* goto end; */
	}
#ifndef OPENSSL_NO_TLSEXT
	if (servername != NULL) {
		tlsextcbp.biodebug = bio_err;
		SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
		SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
	}
#endif

	con = SSL_new(ctx);
	if (sess_in) {
		SSL_SESSION *sess;
		BIO *stmp = BIO_new_file(sess_in, "r");
		if (!stmp) {
			BIO_printf(bio_err, "Can't open session file %s\n",
			    sess_in);
			ERR_print_errors(bio_err);
			goto end;
		}
		sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
		BIO_free(stmp);
		if (!sess) {
			BIO_printf(bio_err, "Can't open session file %s\n",
			    sess_in);
			ERR_print_errors(bio_err);
			goto end;
		}
		SSL_set_session(con, sess);
		SSL_SESSION_free(sess);
	}
#ifndef OPENSSL_NO_TLSEXT
	if (servername != NULL) {
		if (!SSL_set_tlsext_host_name(con, servername)) {
			BIO_printf(bio_err, "Unable to set TLS servername extension.\n");
			ERR_print_errors(bio_err);
			goto end;
		}
	}
#endif
/*	SSL_set_cipher_list(con,"RC4-MD5"); */

re_start:

	if (init_client(&s, host, port, socket_type, af) == 0) {
		BIO_printf(bio_err, "connect:errno=%d\n", errno);
		shutdown(s, SHUT_RD);
		close(s);
		goto end;
	}
	BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);

	if (c_nbio) {
		unsigned long l = 1;
		BIO_printf(bio_c_out, "turning on non blocking io\n");
		if (BIO_socket_ioctl(s, FIONBIO, &l) < 0) {
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (c_Pause & 0x01)
		SSL_set_debug(con, 1);

	if (SSL_version(con) == DTLS1_VERSION) {

		sbio = BIO_new_dgram(s, BIO_NOCLOSE);
		if (getsockname(s, &peer, (void *) &peerlen) < 0) {
			BIO_printf(bio_err, "getsockname:errno=%d\n",
			    errno);
			shutdown(s, SHUT_RD);
			close(s);
			goto end;
		}
		(void) BIO_ctrl_set_connected(sbio, 1, &peer);

		if (enable_timeouts) {
			timeout.tv_sec = 0;
			timeout.tv_usec = DGRAM_RCV_TIMEOUT;
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);

			timeout.tv_sec = 0;
			timeout.tv_usec = DGRAM_SND_TIMEOUT;
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
		}
		if (socket_mtu > 28) {
			SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
			SSL_set_mtu(con, socket_mtu - 28);
		} else
			/* want to do MTU discovery */
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
	} else
		sbio = BIO_new_socket(s, BIO_NOCLOSE);

	if (nbio_test) {
		BIO *test;

		test = BIO_new(BIO_f_nbio_test());
		sbio = BIO_push(test, sbio);
	}
	if (c_debug) {
		SSL_set_debug(con, 1);
		BIO_set_callback(sbio, bio_dump_callback);
		BIO_set_callback_arg(sbio, (char *) bio_c_out);
	}
	if (c_msg) {
		SSL_set_msg_callback(con, msg_cb);
		SSL_set_msg_callback_arg(con, bio_c_out);
	}
#ifndef OPENSSL_NO_TLSEXT
	if (c_tlsextdebug) {
		SSL_set_tlsext_debug_callback(con, tlsext_cb);
		SSL_set_tlsext_debug_arg(con, bio_c_out);
	}
	if (c_status_req) {
		SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp);
		SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb);
		SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out);
	}
#endif

	SSL_set_bio(con, sbio, sbio);
	SSL_set_connect_state(con);

	/* ok, lets connect */
	width = SSL_get_fd(con) + 1;

	read_tty = 1;
	write_tty = 0;
	tty_on = 0;
	read_ssl = 1;
	write_ssl = 1;

	cbuf_len = 0;
	cbuf_off = 0;
	sbuf_len = 0;
	sbuf_off = 0;

	/* This is an ugly hack that does a lot of assumptions */
	/*
	 * We do have to handle multi-line responses which may come in a
	 * single packet or not. We therefore have to use BIO_gets() which
	 * does need a buffering BIO. So during the initial chitchat we do
	 * push a buffering BIO into the chain that is removed again later on
	 * to not disturb the rest of the s_client operation.
	 */
	if (starttls_proto == PROTO_SMTP || starttls_proto == PROTO_LMTP) {
		int foundit = 0;
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		/* wait for multi-line response to end from SMTP */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		/* STARTTLS command requires EHLO... */
		BIO_printf(fbio, "%cHLO openssl.client.net\r\n",
			   starttls_proto == PROTO_SMTP ? 'E' : 'L');
		(void) BIO_flush(fbio);
		/* wait for multi-line response to end EHLO SMTP response */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
			if (strstr(mbuf, "STARTTLS"))
				foundit = 1;
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		if (!foundit)
			BIO_printf(bio_err,
			    "didn't found starttls in server response,"
			    " try anyway...\n");
		BIO_printf(sbio, "STARTTLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_POP3) {
		mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
		if (mbuf_len == -1) {
			BIO_printf(bio_err, "BIO_read failed\n");
			goto end;
		}
		BIO_printf(sbio, "STLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_IMAP) {
		int foundit = 0;
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		BIO_gets(fbio, mbuf, BUFSIZZ);
		/* STARTTLS command requires CAPABILITY... */
		BIO_printf(fbio, ". CAPABILITY\r\n");
		(void) BIO_flush(fbio);
		/* wait for multi-line CAPABILITY response */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
			if (strstr(mbuf, "STARTTLS"))
				foundit = 1;
		}
		while (mbuf_len > 3 && mbuf[0] != '.');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		if (!foundit)
			BIO_printf(bio_err,
			    "didn't found STARTTLS in server response,"
			    " try anyway...\n");
		BIO_printf(sbio, ". STARTTLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_FTP) {
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		/* wait for multi-line response to end from FTP */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		BIO_printf(sbio, "AUTH TLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	}
	if (starttls_proto == PROTO_XMPP) {
		int seen = 0;
		BIO_printf(sbio, "<stream:stream "
		    "xmlns:stream='http://etherx.jabber.org/streams' "
		    "xmlns='jabber:client' to='%s' version='1.0'>", host);
		seen = BIO_read(sbio, mbuf, BUFSIZZ);
		mbuf[seen] = 0;
		while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")) {
			if (strstr(mbuf, "/stream:features>"))
				goto shut;
			seen = BIO_read(sbio, mbuf, BUFSIZZ);
			mbuf[seen] = 0;
		}
		BIO_printf(sbio, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
		seen = BIO_read(sbio, sbuf, BUFSIZZ);
		sbuf[seen] = 0;
		if (!strstr(sbuf, "<proceed"))
			goto shut;
		mbuf[0] = 0;
	}
	for (;;) {
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);

		if ((SSL_version(con) == DTLS1_VERSION) &&
		    DTLSv1_get_timeout(con, &timeout))
			timeoutp = &timeout;
		else
			timeoutp = NULL;

		if (SSL_in_init(con) && !SSL_total_renegotiations(con)) {
			in_init = 1;
			tty_on = 0;
		} else {
			tty_on = 1;
			if (in_init) {
				in_init = 0;
				if (sess_out) {
					BIO *stmp = BIO_new_file(sess_out, "w");
					if (stmp) {
						PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con));
						BIO_free(stmp);
					} else
						BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
				}
				print_stuff(bio_c_out, con, full_log);
				if (full_log > 0)
					full_log--;

				if (starttls_proto) {
					BIO_write(bio_err, mbuf, mbuf_len);
					/* We don't need to know any more */
					starttls_proto = PROTO_OFF;
				}
				if (reconnect) {
					reconnect--;
					BIO_printf(bio_c_out, "drop connection and then reconnect\n");
					SSL_shutdown(con);
					SSL_set_connect_state(con);
					shutdown(SSL_get_fd(con), SHUT_RD);
					close(SSL_get_fd(con));
					goto re_start;
				}
			}
		}

		ssl_pending = read_ssl && SSL_pending(con);

		/* XXX should add tests for fd_set overflow */

		if (!ssl_pending) {
			if (tty_on) {
				if (read_tty)
					FD_SET(fileno(stdin), &readfds);
				if (write_tty)
					FD_SET(fileno(stdout), &writefds);
			}
			if (read_ssl)
				FD_SET(SSL_get_fd(con), &readfds);
			if (write_ssl)
				FD_SET(SSL_get_fd(con), &writefds);
/*			printf("mode tty(%d %d%d) ssl(%d%d)\n",
				tty_on,read_tty,write_tty,read_ssl,write_ssl);*/

			i = select(width, &readfds, &writefds,
			    NULL, timeoutp);
			if (i < 0) {
				BIO_printf(bio_err, "bad select %d\n",
				    errno);
				goto shut;
				/* goto end; */
			}
		}
		if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) {
			BIO_printf(bio_err, "TIMEOUT occured\n");
		}
		if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) {
			k = SSL_write(con, &(cbuf[cbuf_off]),
			    (unsigned int) cbuf_len);
			switch (SSL_get_error(con, k)) {
			case SSL_ERROR_NONE:
				cbuf_off += k;
				cbuf_len -= k;
				if (k <= 0)
					goto end;
				/* we have done a  write(con,NULL,0); */
				if (cbuf_len <= 0) {
					read_tty = 1;
					write_ssl = 0;
				} else {	/* if (cbuf_len > 0) */
					read_tty = 0;
					write_ssl = 1;
				}
				break;
			case SSL_ERROR_WANT_WRITE:
				BIO_printf(bio_c_out, "write W BLOCK\n");
				write_ssl = 1;
				read_tty = 0;
				break;
			case SSL_ERROR_WANT_READ:
				BIO_printf(bio_c_out, "write R BLOCK\n");
				write_tty = 0;
				read_ssl = 1;
				write_ssl = 0;
				break;
			case SSL_ERROR_WANT_X509_LOOKUP:
				BIO_printf(bio_c_out, "write X BLOCK\n");
				break;
			case SSL_ERROR_ZERO_RETURN:
				if (cbuf_len != 0) {
					BIO_printf(bio_c_out, "shutdown\n");
					ret = 0;
					goto shut;
				} else {
					read_tty = 1;
					write_ssl = 0;
					break;
				}

			case SSL_ERROR_SYSCALL:
				if ((k != 0) || (cbuf_len != 0)) {
					BIO_printf(bio_err, "write:errno=%d\n",
					    errno);
					goto shut;
				} else {
					read_tty = 1;
					write_ssl = 0;
				}
				break;
			case SSL_ERROR_SSL:
				ERR_print_errors(bio_err);
				goto shut;
			}
		} else if (!ssl_pending && FD_ISSET(fileno(stdout), &writefds)) {
			i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len);

			if (i <= 0) {
				BIO_printf(bio_c_out, "DONE\n");
				ret = 0;
				goto shut;
				/* goto end; */
			}
			sbuf_len -= i;
			sbuf_off += i;
			if (sbuf_len <= 0) {
				read_ssl = 1;
				write_tty = 0;
			}
		} else if (ssl_pending || FD_ISSET(SSL_get_fd(con), &readfds)) {
#ifdef RENEG
			{
				static int iiii;
				if (++iiii == 52) {
					SSL_renegotiate(con);
					iiii = 0;
				}
			}
#endif
			k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ );

			switch (SSL_get_error(con, k)) {
			case SSL_ERROR_NONE:
				if (k <= 0)
					goto end;
				sbuf_off = 0;
				sbuf_len = k;

				read_ssl = 0;
				write_tty = 1;
				break;
			case SSL_ERROR_WANT_WRITE:
				BIO_printf(bio_c_out, "read W BLOCK\n");
				write_ssl = 1;
				read_tty = 0;
				break;
			case SSL_ERROR_WANT_READ:
				BIO_printf(bio_c_out, "read R BLOCK\n");
				write_tty = 0;
				read_ssl = 1;
				if ((read_tty == 0) && (write_ssl == 0))
					write_ssl = 1;
				break;
			case SSL_ERROR_WANT_X509_LOOKUP:
				BIO_printf(bio_c_out, "read X BLOCK\n");
				break;
			case SSL_ERROR_SYSCALL:
				ret = errno;
				BIO_printf(bio_err, "read:errno=%d\n", ret);
				goto shut;
			case SSL_ERROR_ZERO_RETURN:
				BIO_printf(bio_c_out, "closed\n");
				ret = 0;
				goto shut;
			case SSL_ERROR_SSL:
				ERR_print_errors(bio_err);
				goto shut;
				/* break; */
			}
		} else if (FD_ISSET(fileno(stdin), &readfds)) {
			if (crlf) {
				int j, lf_num;

				i = read(fileno(stdin), cbuf, BUFSIZZ / 2);
				lf_num = 0;
				/* both loops are skipped when i <= 0 */
				for (j = 0; j < i; j++)
					if (cbuf[j] == '\n')
						lf_num++;
				for (j = i - 1; j >= 0; j--) {
					cbuf[j + lf_num] = cbuf[j];
					if (cbuf[j] == '\n') {
						lf_num--;
						i++;
						cbuf[j + lf_num] = '\r';
					}
				}
				assert(lf_num == 0);
			} else
				i = read(fileno(stdin), cbuf, BUFSIZZ);

			if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) {
				BIO_printf(bio_err, "DONE\n");
				ret = 0;
				goto shut;
			}
			if ((!c_ign_eof) && (cbuf[0] == 'R')) {
				BIO_printf(bio_err, "RENEGOTIATING\n");
				SSL_renegotiate(con);
				cbuf_len = 0;
			} else {
				cbuf_len = i;
				cbuf_off = 0;
			}

			write_ssl = 1;
			read_tty = 0;
		}
	}

	ret = 0;
shut:
	if (in_init)
		print_stuff(bio_c_out, con, full_log);
	SSL_shutdown(con);
	shutdown(SSL_get_fd(con), SHUT_RD);
	close(SSL_get_fd(con));
end:
	if (con != NULL) {
		if (prexit != 0)
			print_stuff(bio_c_out, con, 1);
		SSL_free(con);
	}
#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
	free(next_proto.data);
#endif
	if (ctx != NULL)
		SSL_CTX_free(ctx);
	if (cert)
		X509_free(cert);
	if (key)
		EVP_PKEY_free(key);
	free(pass);
	if (vpm)
		X509_VERIFY_PARAM_free(vpm);
	if (cbuf != NULL) {
		OPENSSL_cleanse(cbuf, BUFSIZZ);
		free(cbuf);
	}
	if (sbuf != NULL) {
		OPENSSL_cleanse(sbuf, BUFSIZZ);
		free(sbuf);
	}
	if (mbuf != NULL) {
		OPENSSL_cleanse(mbuf, BUFSIZZ);
		free(mbuf);
	}
	if (bio_c_out != NULL) {
		BIO_free(bio_c_out);
		bio_c_out = NULL;
	}

	return (ret);
}
Example #25
0
/**
 * @brief Create a context for supporting encryption. Keys, certificates,
 *        algorithms and other parameters will be set per context. More than
 *        one context can be created at one time. A cleanup will be automatically
 *        registered with the given pool to guarantee a graceful shutdown.
 * @param f - context pointer will be written here
 * @param provider - provider to use
 * @param params - array of key parameters
 * @param pool - process pool
 * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
 * if the engine cannot be initialised.
 */
static apr_status_t crypto_make(apr_crypto_t **ff,
        const apr_crypto_driver_t *provider, const char *params,
        apr_pool_t *pool)
{
    apr_crypto_config_t *config = NULL;
    apr_crypto_t *f = apr_pcalloc(pool, sizeof(apr_crypto_t));

    const char *engine = NULL;

    struct {
        const char *field;
        const char *value;
        int set;
    } fields[] = {
        { "engine", NULL, 0 },
        { NULL, NULL, 0 }
    };
    const char *ptr;
    size_t klen;
    char **elts = NULL;
    char *elt;
    int i = 0, j;
    apr_status_t status;

    if (params) {
        if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) {
            return status;
        }
        while ((elt = elts[i])) {
            ptr = strchr(elt, '=');
            if (ptr) {
                for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen)
                    ;
                ptr++;
            }
            else {
                for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen)
                    ;
            }
            elt[klen] = 0;

            for (j = 0; fields[j].field != NULL; ++j) {
                if (!strcasecmp(fields[j].field, elt)) {
                    fields[j].set = 1;
                    if (ptr) {
                        fields[j].value = ptr;
                    }
                    break;
                }
            }

            i++;
        }
        engine = fields[0].value;
    }

    if (!f) {
        return APR_ENOMEM;
    }
    *ff = f;
    f->pool = pool;
    f->provider = provider;
    config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
    if (!config) {
        return APR_ENOMEM;
    }

    f->result = apr_pcalloc(pool, sizeof(apu_err_t));
    if (!f->result) {
        return APR_ENOMEM;
    }

    f->keys = apr_array_make(pool, 10, sizeof(apr_crypto_key_t));
    if (!f->keys) {
        return APR_ENOMEM;
    }

    f->types = apr_hash_make(pool);
    if (!f->types) {
        return APR_ENOMEM;
    }
    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_3des_192));
    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_aes_128));
    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_aes_192));
    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_aes_256));

    f->modes = apr_hash_make(pool);
    if (!f->modes) {
        return APR_ENOMEM;
    }
    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(mode_ecb));
    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(mode_cbc));

    apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
            apr_pool_cleanup_null);

    if (engine) {
        config->engine = ENGINE_by_id(engine);
        if (!config->engine) {
            return APR_ENOENGINE;
        }
        if (!ENGINE_init(config->engine)) {
            ENGINE_free(config->engine);
            config->engine = NULL;
            return APR_EINITENGINE;
        }
    }

    return APR_SUCCESS;

}
Example #26
0
static ENGINE *get_pkcs11_engine(GError **error)
{
	static ENGINE *e = NULL;
	unsigned long err;
	const gchar *data;
	const gchar *env;
	int flags;

	g_return_val_if_fail(error == NULL || *error == NULL, NULL);

	ENGINE_load_builtin_engines();

	e = ENGINE_by_id("pkcs11");
	if (e == NULL) {
		err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
		g_set_error(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_LOAD_FAILED,
				"failed to load PKCS11 engine: %s",
				(flags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));

		goto out;
	}

	env = g_getenv("RAUC_PKCS11_MODULE");
	if (env != NULL) {
		if (!ENGINE_ctrl_cmd_string(e, "MODULE_PATH", env, 0)) {
			err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
			g_set_error(
					error,
					R_SIGNATURE_ERROR,
					R_SIGNATURE_ERROR_PARSE_ERROR,
					"failed to configure PKCS11 module path: %s",
					(flags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));
			goto free;
		}
	}

	if (ENGINE_init(e) == 0) {
		err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
		g_set_error(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_LOAD_FAILED,
				"failed to initialize PKCS11 engine: %s",
				(flags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));

		goto free;
	}

	env = g_getenv("RAUC_PKCS11_PIN");
	if (env != NULL) {
		if (!ENGINE_ctrl_cmd_string(e, "PIN", env, 0)) {
			err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
			g_set_error(
					error,
					R_SIGNATURE_ERROR,
					R_SIGNATURE_ERROR_PARSE_ERROR,
					"failed to configure PKCS11 PIN: %s",
					(flags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));
			goto finish;
		}
	}

	goto out;

finish:
	ENGINE_finish(e);
free:
	ENGINE_free(e);
	e = NULL;
out:
	return e;
}
Example #27
0
ENGINE *ENGINE_by_id(const char *id)
{
    ENGINE *iterator;
    char *load_dir = NULL;
    if (id == NULL) {
        ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }
    CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
    iterator = engine_list_head;
    while (iterator && (strcmp(id, iterator->id) != 0))
        iterator = iterator->next;
    if (iterator != NULL) {
        /*
         * We need to return a structural reference. If this is an ENGINE
         * type that returns copies, make a duplicate - otherwise increment
         * the existing ENGINE's reference count.
         */
        if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) {
            ENGINE *cp = ENGINE_new();
            if (cp == NULL)
                iterator = NULL;
            else {
                engine_cpy(cp, iterator);
                iterator = cp;
            }
        } else {
            iterator->struct_ref++;
            engine_ref_debug(iterator, 0, 1);
        }
    }
    CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
    if (iterator != NULL)
        return iterator;
    /*
     * Prevent infinite recursion if we're looking for the dynamic engine.
     */
    if (strcmp(id, "dynamic")) {
# ifdef OPENSSL_SYS_VMS
        if ((load_dir = getenv("OPENSSL_ENGINES")) == 0)
            load_dir = "SSLROOT:[ENGINES]";
# else
        if ((load_dir = getenv("OPENSSL_ENGINES")) == 0)
            load_dir = ENGINESDIR;
# endif
        iterator = ENGINE_by_id("dynamic");
        if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
            !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
            !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
                                    load_dir, 0) ||
            !ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||
            !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
            goto notfound;
        return iterator;
    }
 notfound:
    ENGINE_free(iterator);
    ENGINEerr(ENGINE_F_ENGINE_BY_ID, ENGINE_R_NO_SUCH_ENGINE);
    ERR_add_error_data(2, "id=", id);
    return NULL;
    /* EEK! Experimental code ends */
}
Example #28
0
isc_result_t
dst__openssl_init(const char *engine) {
	isc_result_t result;
#ifdef USE_ENGINE
	ENGINE *re;
#else

	UNUSED(engine);
#endif

#ifdef  DNS_CRYPTO_LEAKS
	CRYPTO_malloc_debug_init();
	CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
#endif
	CRYPTO_set_mem_functions(mem_alloc, mem_realloc, mem_free);
	nlocks = CRYPTO_num_locks();
	locks = mem_alloc(sizeof(isc_mutex_t) * nlocks);
	if (locks == NULL)
		return (ISC_R_NOMEMORY);
	result = isc_mutexblock_init(locks, nlocks);
	if (result != ISC_R_SUCCESS)
		goto cleanup_mutexalloc;
	CRYPTO_set_locking_callback(lock_callback);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
	CRYPTO_set_id_callback(id_callback);
#endif

	ERR_load_crypto_strings();

	rm = mem_alloc(sizeof(RAND_METHOD));
	if (rm == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup_mutexinit;
	}
	rm->seed = NULL;
	rm->bytes = entropy_get;
	rm->cleanup = NULL;
	rm->add = entropy_add;
	rm->pseudorand = entropy_getpseudo;
	rm->status = entropy_status;

#ifdef USE_ENGINE
	OPENSSL_config(NULL);

	if (engine != NULL && *engine == '\0')
		engine = NULL;

	if (engine != NULL) {
		e = ENGINE_by_id(engine);
		if (e == NULL) {
			result = DST_R_NOENGINE;
			goto cleanup_rm;
		}
		/* This will init the engine. */
		if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
			result = DST_R_NOENGINE;
			goto cleanup_rm;
		}
	}

	re = ENGINE_get_default_RAND();
	if (re == NULL) {
		re = ENGINE_new();
		if (re == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup_rm;
		}
		ENGINE_set_RAND(re, rm);
		ENGINE_set_default_RAND(re);
		ENGINE_free(re);
	} else
		ENGINE_finish(re);
#else
	RAND_set_rand_method(rm);
#endif /* USE_ENGINE */
	return (ISC_R_SUCCESS);

#ifdef USE_ENGINE
 cleanup_rm:
	if (e != NULL)
		ENGINE_free(e);
	e = NULL;
	mem_free(rm);
	rm = NULL;
#endif
 cleanup_mutexinit:
	CRYPTO_set_locking_callback(NULL);
	DESTROYMUTEXBLOCK(locks, nlocks);
 cleanup_mutexalloc:
	mem_free(locks);
	locks = NULL;
	return (result);
}
Example #29
0
static int openssl_engine_gc(lua_State*L){
	ENGINE* eng = CHECK_OBJECT(1,ENGINE,"openssl.engine");
	ENGINE_free(eng);
	return 0;
}
Example #30
0
ret_t
http2d_init (void)
{
	if (_initialized)
		return ret_ok;

        /* Init OpenSSL
         */
        OPENSSL_config (NULL);
        SSL_library_init();
        SSL_load_error_strings();
        OpenSSL_add_all_algorithms();

        /* Ensure PRNG has been seeded with enough data
         */
        if (RAND_status() == 0) {
                LOG_WARNING_S (HTTP2D_ERROR_SSL_NO_ENTROPY);
        }

        /* Init concurrency related stuff
         */
        if ((CRYPTO_get_id_callback()      == NULL) &&
            (CRYPTO_get_locking_callback() == NULL))
        {
                cuint_t n;

                CRYPTO_set_id_callback (__get_thread_id);
                CRYPTO_set_locking_callback (__lock_thread);

                locks_num = CRYPTO_num_locks();
                locks     = malloc (locks_num * sizeof(*locks));

                for (n = 0; n < locks_num; n++) {
                        HTTP2D_MUTEX_INIT (&locks[n], NULL);
                }
        }

	/* Engines
	 */
        ENGINE_load_builtin_engines();
        OpenSSL_add_all_algorithms();

        ENGINE *e = ENGINE_by_id("pkcs11");
        while (e != NULL) {
                if(! ENGINE_init(e)) {
                        ENGINE_free (e);
                        LOG_CRITICAL_S (HTTP2D_ERROR_SSL_PKCS11);
                        break;
                }

                if(! ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
                        ENGINE_free (e);
                        LOG_CRITICAL_S (HTTP2D_ERROR_SSL_DEFAULTS);
                        break;
                }

                ENGINE_finish(e);
                ENGINE_free(e);
                break;
        }

	return ret_ok;
}