Esempio n. 1
0
int X509_verify_cert(X509_STORE_CTX *ctx)
	{
	X509 *x,*xtmp,*chain_ss=NULL;
	X509_NAME *xn;
	int bad_chain = 0;
	X509_VERIFY_PARAM *param = ctx->param;
	int depth,i,ok=0;
	int num;
	int (*cb)(int xok,X509_STORE_CTX *xctx);
	STACK_OF(X509) *sktmp=NULL;
	if (ctx->cert == NULL)
		{
		X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
		return -1;
		}

	cb=ctx->verify_cb;

	/* first we make sure the chain we are going to build is
	 * present and that the first entry is in place */
	if (ctx->chain == NULL)
		{
		if (	((ctx->chain=sk_X509_new_null()) == NULL) ||
			(!sk_X509_push(ctx->chain,ctx->cert)))
			{
			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
			goto end;
			}
		CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);
		ctx->last_untrusted=1;
		}

	/* We use a temporary STACK so we can chop and hack at it */
	if (ctx->untrusted != NULL
	    && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
		{
		X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
		goto end;
		}

	num=sk_X509_num(ctx->chain);
	x=sk_X509_value(ctx->chain,num-1);
	depth=param->depth;


	for (;;)
		{
		/* If we have enough, we break */
		if (depth < num) break; /* FIXME: If this happens, we should take
		                         * note of it and, if appropriate, use the
		                         * X509_V_ERR_CERT_CHAIN_TOO_LONG error
		                         * code later.
		                         */

		/* If we are self signed, we break */
		xn=X509_get_issuer_name(x);
		if (ctx->check_issued(ctx, x,x)) break;

		/* If we were passed a cert chain, use it first */
		if (ctx->untrusted != NULL)
			{
			xtmp=find_issuer(ctx, sktmp,x);
			if (xtmp != NULL)
				{
				if (!sk_X509_push(ctx->chain,xtmp))
					{
					X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
					goto end;
					}
				CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
				(void)sk_X509_delete_ptr(sktmp,xtmp);
				ctx->last_untrusted++;
				x=xtmp;
				num++;
				/* reparse the full chain for
				 * the next one */
				continue;
				}
			}
		break;
		}

	/* at this point, chain should contain a list of untrusted
	 * certificates.  We now need to add at least one trusted one,
	 * if possible, otherwise we complain. */

	/* Examine last certificate in chain and see if it
 	 * is self signed.
 	 */

	i=sk_X509_num(ctx->chain);
	x=sk_X509_value(ctx->chain,i-1);
	xn = X509_get_subject_name(x);
	if (ctx->check_issued(ctx, x, x))
		{
		/* we have a self signed certificate */
		if (sk_X509_num(ctx->chain) == 1)
			{
			/* We have a single self signed certificate: see if
			 * we can find it in the store. We must have an exact
			 * match to avoid possible impersonation.
			 */
			ok = ctx->get_issuer(&xtmp, ctx, x);
			if ((ok <= 0) || X509_cmp(x, xtmp)) 
				{
				ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
				ctx->current_cert=x;
				ctx->error_depth=i-1;
				if (ok == 1) X509_free(xtmp);
				bad_chain = 1;
				ok=cb(0,ctx);
				if (!ok) goto end;
				}
			else 
				{
				/* We have a match: replace certificate with store version
				 * so we get any trust settings.
				 */
				X509_free(x);
				x = xtmp;
				(void)sk_X509_set(ctx->chain, i - 1, x);
				ctx->last_untrusted=0;
				}
			}
		else
			{
			/* extract and save self signed certificate for later use */
			chain_ss=sk_X509_pop(ctx->chain);
			ctx->last_untrusted--;
			num--;
			x=sk_X509_value(ctx->chain,num-1);
			}
		}

	/* We now lookup certs from the certificate store */
	for (;;)
		{
		/* If we have enough, we break */
		if (depth < num) break;

		/* If we are self signed, we break */
		xn=X509_get_issuer_name(x);
		if (ctx->check_issued(ctx,x,x)) break;

		ok = ctx->get_issuer(&xtmp, ctx, x);

		if (ok < 0) return ok;
		if (ok == 0) break;

		x = xtmp;
		if (!sk_X509_push(ctx->chain,x))
			{
			X509_free(xtmp);
			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
			return 0;
			}
		num++;
		}

	/* we now have our chain, lets check it... */
	xn=X509_get_issuer_name(x);

	/* Is last certificate looked up self signed? */
	if (!ctx->check_issued(ctx,x,x))
		{
		if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
			{
			if (ctx->last_untrusted >= num)
				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
			else
				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
			ctx->current_cert=x;
			}
		else
			{

			sk_X509_push(ctx->chain,chain_ss);
			num++;
			ctx->last_untrusted=num;
			ctx->current_cert=chain_ss;
			ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
			chain_ss=NULL;
			}

		ctx->error_depth=num-1;
		bad_chain = 1;
		ok=cb(0,ctx);
		if (!ok) goto end;
		}

	/* We have the chain complete: now we need to check its purpose */
	ok = check_chain_extensions(ctx);

	if (!ok) goto end;

	/* The chain extensions are OK: check trust */

	if (param->trust > 0) ok = check_trust(ctx);

	if (!ok) goto end;

	/* We may as well copy down any DSA parameters that are required */
	X509_get_pubkey_parameters(NULL,ctx->chain);

	/* Check revocation status: we do this after copying parameters
	 * because they may be needed for CRL signature verification.
	 */

	ok = ctx->check_revocation(ctx);
	if(!ok) goto end;

	/* At this point, we have a chain and need to verify it */
	if (ctx->verify != NULL)
		ok=ctx->verify(ctx);
	else
		ok=internal_verify(ctx);
	if(!ok) goto end;

#ifndef OPENSSL_NO_RFC3779
	/* RFC 3779 path validation, now that CRL check has been done */
	ok = v3_asid_validate_path(ctx);
	if (!ok) goto end;
	ok = v3_addr_validate_path(ctx);
	if (!ok) goto end;
#endif

	/* If we get this far evaluate policies */
	if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
		ok = ctx->check_policy(ctx);
	if(!ok) goto end;
	if (0)
		{
end:
		X509_get_pubkey_parameters(NULL,ctx->chain);
		}
	if (sktmp != NULL) sk_X509_free(sktmp);
	if (chain_ss != NULL) X509_free(chain_ss);
	return ok;
	}
Esempio n. 2
0
/* loads in the certificate from the server */
int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data)
{
    STACK_OF(X509) *sk = NULL;
    EVP_PKEY *pkey = NULL;
    SESS_CERT *sc = NULL;
    int i;
    X509 *x509 = NULL;
    int ret = 0;

    x509 = d2i_X509(NULL, &data, (long)len);
    if (x509 == NULL) {
        SSLerr(SSL_F_SSL2_SET_CERTIFICATE, ERR_R_X509_LIB);
        goto err;
    }

    if ((sk = sk_X509_new_null()) == NULL || !sk_X509_push(sk, x509)) {
        SSLerr(SSL_F_SSL2_SET_CERTIFICATE, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    i = ssl_verify_cert_chain(s, sk);

    if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)) {
        SSLerr(SSL_F_SSL2_SET_CERTIFICATE, SSL_R_CERTIFICATE_VERIFY_FAILED);
        goto err;
    }
    ERR_clear_error();          /* but we keep s->verify_result */
    s->session->verify_result = s->verify_result;

    /* server's cert for this session */
    sc = ssl_sess_cert_new();
    if (sc == NULL) {
        ret = -1;
        goto err;
    }
    if (s->session->sess_cert)
        ssl_sess_cert_free(s->session->sess_cert);
    s->session->sess_cert = sc;

    sc->peer_pkeys[SSL_PKEY_RSA_ENC].x509 = x509;
    sc->peer_key = &(sc->peer_pkeys[SSL_PKEY_RSA_ENC]);

    pkey = X509_get_pubkey(x509);
    x509 = NULL;
    if (pkey == NULL) {
        SSLerr(SSL_F_SSL2_SET_CERTIFICATE,
               SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY);
        goto err;
    }
    if (pkey->type != EVP_PKEY_RSA) {
        SSLerr(SSL_F_SSL2_SET_CERTIFICATE, SSL_R_PUBLIC_KEY_NOT_RSA);
        goto err;
    }

    if (!ssl_set_peer_cert_type(sc, SSL2_CT_X509_CERTIFICATE))
        goto err;
    ret = 1;
 err:
    sk_X509_free(sk);
    X509_free(x509);
    EVP_PKEY_free(pkey);
    return (ret);
}
Esempio n. 3
0
int ocsp_main(int argc, char **argv)
{
    BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL;
    const EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
    CA_DB *rdb = NULL;
    EVP_PKEY *key = NULL, *rkey = NULL;
    OCSP_BASICRESP *bs = NULL;
    OCSP_REQUEST *req = NULL;
    OCSP_RESPONSE *resp = NULL;
    STACK_OF(CONF_VALUE) *headers = NULL;
    STACK_OF(OCSP_CERTID) *ids = NULL;
    STACK_OF(OPENSSL_STRING) *reqnames = NULL;
    STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
    STACK_OF(X509) *issuers = NULL;
    X509 *issuer = NULL, *cert = NULL, *rca_cert = NULL;
    X509 *signer = NULL, *rsigner = NULL;
    X509_STORE *store = NULL;
    X509_VERIFY_PARAM *vpm = NULL;
    char *CAfile = NULL, *CApath = NULL, *header, *value;
    char *host = NULL, *port = NULL, *path = "/", *outfile = NULL;
    char *rca_filename = NULL, *reqin = NULL, *respin = NULL;
    char *reqout = NULL, *respout = NULL, *ridx_filename = NULL;
    char *rsignfile = NULL, *rkeyfile = NULL;
    char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
    char *signfile = NULL, *keyfile = NULL;
    char *thost = NULL, *tport = NULL, *tpath = NULL;
    int noCAfile = 0, noCApath = 0;
    int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1;
    int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1;
    int req_text = 0, resp_text = 0, req_timeout = -1, ret = 1;
    long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
    unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
    OPTION_CHOICE o;
    char *prog;

    reqnames = sk_OPENSSL_STRING_new_null();
    if (!reqnames)
        goto end;
    ids = sk_OCSP_CERTID_new_null();
    if (!ids)
        goto end;
    if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
        return 1;

    prog = opt_init(argc, argv, ocsp_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            ret = 0;
            opt_help(ocsp_options);
            goto end;
        case OPT_OUTFILE:
            outfile = opt_arg();
            break;
        case OPT_TIMEOUT:
            req_timeout = atoi(opt_arg());
            break;
        case OPT_URL:
            OPENSSL_free(thost);
            OPENSSL_free(tport);
            OPENSSL_free(tpath);
            thost = tport = tpath = NULL;
            if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) {
                BIO_printf(bio_err, "%s Error parsing URL\n", prog);
                goto end;
            }
            thost = host;
            tport = port;
            tpath = path;
            break;
        case OPT_HOST:
            host = opt_arg();
            break;
        case OPT_PORT:
            port = opt_arg();
            break;
        case OPT_IGNORE_ERR:
            ignore_err = 1;
            break;
        case OPT_NOVERIFY:
            noverify = 1;
            break;
        case OPT_NONCE:
            add_nonce = 2;
            break;
        case OPT_NO_NONCE:
            add_nonce = 0;
            break;
        case OPT_RESP_NO_CERTS:
            rflags |= OCSP_NOCERTS;
            break;
        case OPT_RESP_KEY_ID:
            rflags |= OCSP_RESPID_KEY;
            break;
        case OPT_NO_CERTS:
            sign_flags |= OCSP_NOCERTS;
            break;
        case OPT_NO_SIGNATURE_VERIFY:
            verify_flags |= OCSP_NOSIGS;
            break;
        case OPT_NO_CERT_VERIFY:
            verify_flags |= OCSP_NOVERIFY;
            break;
        case OPT_NO_CHAIN:
            verify_flags |= OCSP_NOCHAIN;
            break;
        case OPT_NO_CERT_CHECKS:
            verify_flags |= OCSP_NOCHECKS;
            break;
        case OPT_NO_EXPLICIT:
            verify_flags |= OCSP_NOEXPLICIT;
            break;
        case OPT_TRUST_OTHER:
            verify_flags |= OCSP_TRUSTOTHER;
            break;
        case OPT_NO_INTERN:
            verify_flags |= OCSP_NOINTERN;
            break;
        case OPT_BADSIG:
            badsig = 1;
            break;
        case OPT_TEXT:
            req_text = resp_text = 1;
            break;
        case OPT_REQ_TEXT:
            req_text = 1;
            break;
        case OPT_RESP_TEXT:
            resp_text = 1;
            break;
        case OPT_REQIN:
            reqin = opt_arg();
            break;
        case OPT_RESPIN:
            respin = opt_arg();
            break;
        case OPT_SIGNER:
            signfile = opt_arg();
            break;
        case OPT_VAFILE:
            verify_certfile = opt_arg();
            verify_flags |= OCSP_TRUSTOTHER;
            break;
        case OPT_SIGN_OTHER:
            sign_certfile = opt_arg();
            break;
        case OPT_VERIFY_OTHER:
            verify_certfile = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_V_CASES:
            if (!opt_verify(o, vpm))
                goto end;
            vpmtouched++;
            break;
        case OPT_VALIDITY_PERIOD:
            opt_long(opt_arg(), &nsec);
            break;
        case OPT_STATUS_AGE:
            opt_long(opt_arg(), &maxage);
            break;
        case OPT_SIGNKEY:
            keyfile = opt_arg();
            break;
        case OPT_REQOUT:
            reqout = opt_arg();
            break;
        case OPT_RESPOUT:
            respout = opt_arg();
            break;
        case OPT_PATH:
            path = opt_arg();
            break;
        case OPT_ISSUER:
            issuer = load_cert(opt_arg(), FORMAT_PEM, "issuer certificate");
            if (issuer == NULL)
                goto end;
            if (issuers == NULL) {
                if ((issuers = sk_X509_new_null()) == NULL)
                    goto end;
            }
            sk_X509_push(issuers, issuer);
            break;
        case OPT_CERT:
            X509_free(cert);
            cert = load_cert(opt_arg(), FORMAT_PEM, "certificate");
            if (cert == NULL)
                goto end;
            if (cert_id_md == NULL)
                cert_id_md = EVP_sha1();
            if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
                goto end;
            if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
                goto end;
            break;
        case OPT_SERIAL:
            if (cert_id_md == NULL)
                cert_id_md = EVP_sha1();
            if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids))
                goto end;
            if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
                goto end;
            break;
        case OPT_INDEX:
            ridx_filename = opt_arg();
            break;
        case OPT_CA:
            rca_filename = opt_arg();
            break;
        case OPT_NMIN:
            opt_int(opt_arg(), &nmin);
            if (ndays == -1)
                ndays = 0;
            break;
        case OPT_REQUEST:
            opt_int(opt_arg(), &accept_count);
            break;
        case OPT_NDAYS:
            ndays = atoi(opt_arg());
            break;
        case OPT_RSIGNER:
            rsignfile = opt_arg();
            break;
        case OPT_RKEY:
            rkeyfile = opt_arg();
            break;
        case OPT_ROTHER:
            rcertfile = opt_arg();
            break;
        case OPT_RMD:
            if (!opt_md(opt_arg(), &rsign_md))
                goto end;
            break;
        case OPT_HEADER:
            header = opt_arg();
            value = strchr(header, '=');
            if (value == NULL) {
                BIO_printf(bio_err, "Missing = in header key=value\n");
                goto opthelp;
            }
            *value++ = '\0';
            if (!X509V3_add_value(header, value, &headers))
                goto end;
            break;
        case OPT_MD:
            if (cert_id_md != NULL) {
                BIO_printf(bio_err,
                           "%s: Digest must be before -cert or -serial\n",
                           prog);
                goto opthelp;
            }
            if (!opt_md(opt_unknown(), &cert_id_md))
                goto opthelp;
            break;
        }
    }
    argc = opt_num_rest();
    if (argc != 0)
        goto opthelp;

    /* Have we anything to do? */
    if (!req && !reqin && !respin && !(port && ridx_filename))
        goto opthelp;

    out = bio_open_default(outfile, 'w', FORMAT_TEXT);
    if (out == NULL)
        goto end;

    if (!req && (add_nonce != 2))
        add_nonce = 0;

    if (!req && reqin) {
        derbio = bio_open_default(reqin, 'r', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        req = d2i_OCSP_REQUEST_bio(derbio, NULL);
        BIO_free(derbio);
        if (!req) {
            BIO_printf(bio_err, "Error reading OCSP request\n");
            goto end;
        }
    }

    if (!req && port) {
        acbio = init_responder(port);
        if (!acbio)
            goto end;
    }

    if (rsignfile) {
        if (!rkeyfile)
            rkeyfile = rsignfile;
        rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate");
        if (!rsigner) {
            BIO_printf(bio_err, "Error loading responder certificate\n");
            goto end;
        }
        rca_cert = load_cert(rca_filename, FORMAT_PEM, "CA certificate");
        if (rcertfile) {
            if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL,
                            "responder other certificates"))
                goto end;
        }
        rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL,
                        "responder private key");
        if (!rkey)
            goto end;
    }
    if (acbio)
        BIO_printf(bio_err, "Waiting for OCSP client connections...\n");

 redo_accept:

    if (acbio) {
        if (!do_responder(&req, &cbio, acbio))
            goto end;
        if (!req) {
            resp =
                OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
                                     NULL);
            send_ocsp_response(cbio, resp);
            goto done_resp;
        }
    }

    if (!req && (signfile || reqout || host || add_nonce || ridx_filename)) {
        BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
        goto end;
    }

    if (req && add_nonce)
        OCSP_request_add1_nonce(req, NULL, -1);

    if (signfile) {
        if (!keyfile)
            keyfile = signfile;
        signer = load_cert(signfile, FORMAT_PEM, "signer certificate");
        if (!signer) {
            BIO_printf(bio_err, "Error loading signer certificate\n");
            goto end;
        }
        if (sign_certfile) {
            if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL,
                            "signer certificates"))
                goto end;
        }
        key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL,
                       "signer private key");
        if (!key)
            goto end;

        if (!OCSP_request_sign
            (req, signer, key, NULL, sign_other, sign_flags)) {
            BIO_printf(bio_err, "Error signing OCSP request\n");
            goto end;
        }
    }

    if (req_text && req)
        OCSP_REQUEST_print(out, req, 0);

    if (reqout) {
        derbio = bio_open_default(reqout, 'w', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        i2d_OCSP_REQUEST_bio(derbio, req);
        BIO_free(derbio);
    }

    if (ridx_filename && (!rkey || !rsigner || !rca_cert)) {
        BIO_printf(bio_err,
                   "Need a responder certificate, key and CA for this operation!\n");
        goto end;
    }

    if (ridx_filename && !rdb) {
        rdb = load_index(ridx_filename, NULL);
        if (!rdb)
            goto end;
        if (!index_index(rdb))
            goto end;
    }

    if (rdb) {
        make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey,
                               rsign_md, rother, rflags, nmin, ndays, badsig);
        if (cbio)
            send_ocsp_response(cbio, resp);
    } else if (host) {
# ifndef OPENSSL_NO_SOCK
        resp = process_responder(req, host, path,
                                 port, use_ssl, headers, req_timeout);
        if (!resp)
            goto end;
# else
        BIO_printf(bio_err,
                   "Error creating connect BIO - sockets not supported.\n");
        goto end;
# endif
    } else if (respin) {
        derbio = bio_open_default(respin, 'r', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
        BIO_free(derbio);
        if (!resp) {
            BIO_printf(bio_err, "Error reading OCSP response\n");
            goto end;
        }
    } else {
        ret = 0;
        goto end;
    }

 done_resp:

    if (respout) {
        derbio = bio_open_default(respout, 'w', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        i2d_OCSP_RESPONSE_bio(derbio, resp);
        BIO_free(derbio);
    }

    i = OCSP_response_status(resp);
    if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
        BIO_printf(out, "Responder Error: %s (%d)\n",
                   OCSP_response_status_str(i), i);
        if (ignore_err)
            goto redo_accept;
        ret = 0;
        goto end;
    }

    if (resp_text)
        OCSP_RESPONSE_print(out, resp, 0);

    /* If running as responder don't verify our own response */
    if (cbio) {
        /* If not unlimited, see if we took all we should. */
        if (accept_count != -1 && --accept_count <= 0) {
            ret = 0;
            goto end;
        }
        BIO_free_all(cbio);
        cbio = NULL;
        OCSP_REQUEST_free(req);
        req = NULL;
        OCSP_RESPONSE_free(resp);
        resp = NULL;
        goto redo_accept;
    }
    if (ridx_filename) {
        ret = 0;
        goto end;
    }

    if (!store) {
        store = setup_verify(CAfile, CApath, noCAfile, noCApath);
        if (!store)
            goto end;
    }
    if (vpmtouched)
        X509_STORE_set1_param(store, vpm);
    if (verify_certfile) {
        if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL,
                        "validator certificate"))
            goto end;
    }

    bs = OCSP_response_get1_basic(resp);
    if (!bs) {
        BIO_printf(bio_err, "Error parsing response\n");
        goto end;
    }

    ret = 0;

    if (!noverify) {
        if (req && ((i = OCSP_check_nonce(req, bs)) <= 0)) {
            if (i == -1)
                BIO_printf(bio_err, "WARNING: no nonce in response\n");
            else {
                BIO_printf(bio_err, "Nonce Verify error\n");
                ret = 1;
                goto end;
            }
        }

        i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
        if (i <= 0 && issuers) {
            i = OCSP_basic_verify(bs, issuers, store, OCSP_TRUSTOTHER);
            if (i > 0)
                ERR_clear_error();
        }
        if (i <= 0) {
            BIO_printf(bio_err, "Response Verify Failure\n");
            ERR_print_errors(bio_err);
            ret = 1;
        } else
            BIO_printf(bio_err, "Response verify OK\n");

    }

    print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage);

 end:
    ERR_print_errors(bio_err);
    X509_free(signer);
    X509_STORE_free(store);
    X509_VERIFY_PARAM_free(vpm);
    EVP_PKEY_free(key);
    EVP_PKEY_free(rkey);
    X509_free(cert);
    sk_X509_pop_free(issuers, X509_free);
    X509_free(rsigner);
    X509_free(rca_cert);
    free_index(rdb);
    BIO_free_all(cbio);
    BIO_free_all(acbio);
    BIO_free(out);
    OCSP_REQUEST_free(req);
    OCSP_RESPONSE_free(resp);
    OCSP_BASICRESP_free(bs);
    sk_OPENSSL_STRING_free(reqnames);
    sk_OCSP_CERTID_free(ids);
    sk_X509_pop_free(sign_other, X509_free);
    sk_X509_pop_free(verify_other, X509_free);
    sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
    OPENSSL_free(thost);
    OPENSSL_free(tport);
    OPENSSL_free(tpath);

    return (ret);
}
Esempio n. 4
0
static char *ssl_var_lookup_ssl(apr_pool_t *p, SSLConnRec *sslconn, 
                                request_rec *r, char *var)
{
    char *result;
    X509 *xs;
    STACK_OF(X509) *sk;
    SSL *ssl;

    result = NULL;

    ssl = sslconn->ssl;
    if (strlen(var) > 8 && strcEQn(var, "VERSION_", 8)) {
        result = ssl_var_lookup_ssl_version(p, var+8);
    }
    else if (ssl != NULL && strcEQ(var, "PROTOCOL")) {
        result = (char *)SSL_get_version(ssl);
    }
    else if (ssl != NULL && strcEQ(var, "SESSION_ID")) {
        char buf[MODSSL_SESSION_ID_STRING_LEN];
        SSL_SESSION *pSession = SSL_get_session(ssl);
        if (pSession) {
            IDCONST unsigned char *id;
            unsigned int idlen;

#ifdef OPENSSL_NO_SSL_INTERN
            id = (unsigned char *)SSL_SESSION_get_id(pSession, &idlen);
#else
            id = pSession->session_id;
            idlen = pSession->session_id_length;
#endif

            result = apr_pstrdup(p, modssl_SSL_SESSION_id2sz(id, idlen,
                                                             buf, sizeof(buf)));
        }
    }
    else if(ssl != NULL && strcEQ(var, "SESSION_RESUMED")) {
        if (SSL_session_reused(ssl) == 1)
            result = "Resumed";
        else
            result = "Initial";
    }
    else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) {
        result = ssl_var_lookup_ssl_cipher(p, sslconn, var+6);
    }
    else if (ssl != NULL && strlen(var) > 18 && strcEQn(var, "CLIENT_CERT_CHAIN_", 18)) {
        sk = SSL_get_peer_cert_chain(ssl);
        result = ssl_var_lookup_ssl_cert_chain(p, sk, var+18);
    }
    else if (ssl != NULL && strcEQ(var, "CLIENT_CERT_RFC4523_CEA")) {
        result = ssl_var_lookup_ssl_cert_rfc4523_cea(p, ssl);
    }
    else if (ssl != NULL && strcEQ(var, "CLIENT_VERIFY")) {
        result = ssl_var_lookup_ssl_cert_verify(p, sslconn);
    }
    else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "CLIENT_", 7)) {
        if ((xs = SSL_get_peer_certificate(ssl)) != NULL) {
            result = ssl_var_lookup_ssl_cert(p, r, xs, var+7);
            X509_free(xs);
        }
    }
    else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "SERVER_", 7)) {
        if ((xs = SSL_get_certificate(ssl)) != NULL) {
            result = ssl_var_lookup_ssl_cert(p, r, xs, var+7);
            /* SSL_get_certificate is different from SSL_get_peer_certificate.
             * No need to X509_free(xs).
             */
        }
    }
    else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) {
        result = ssl_var_lookup_ssl_compress_meth(ssl);
    }
#ifdef HAVE_TLSEXT
    else if (ssl != NULL && strcEQ(var, "TLS_SNI")) {
        result = apr_pstrdup(p, SSL_get_servername(ssl,
                                                   TLSEXT_NAMETYPE_host_name));
    }
#endif
    else if (ssl != NULL && strcEQ(var, "SECURE_RENEG")) {
        int flag = 0;
#ifdef SSL_get_secure_renegotiation_support
        flag = SSL_get_secure_renegotiation_support(ssl);
#endif
        result = apr_pstrdup(p, flag ? "true" : "false");
    }
#ifdef HAVE_SRP
    else if (ssl != NULL && strcEQ(var, "SRP_USER")) {
        if ((result = SSL_get_srp_username(ssl)) != NULL) {
            result = apr_pstrdup(p, result);
        }
    }
    else if (ssl != NULL && strcEQ(var, "SRP_USERINFO")) {
        if ((result = SSL_get_srp_userinfo(ssl)) != NULL) {
            result = apr_pstrdup(p, result);
        }
    }
#endif

    return result;
}
Esempio n. 5
0
static int
tlso_session_chkhost( LDAP *ld, tls_session *sess, const char *name_in )
{
	tlso_session *s = (tlso_session *)sess;
	int i, ret = LDAP_LOCAL_ERROR;
	X509 *x;
	const char *name;
	char *ptr;
	int ntype = IS_DNS, nlen;
#ifdef LDAP_PF_INET6
	struct in6_addr addr;
#else
	struct in_addr addr;
#endif

	if( ldap_int_hostname &&
		( !name_in || !strcasecmp( name_in, "localhost" ) ) )
	{
		name = ldap_int_hostname;
	} else {
		name = name_in;
	}
	nlen = strlen(name);

	x = tlso_get_cert(s);
	if (!x) {
		Debug( LDAP_DEBUG_ANY,
			"TLS: unable to get peer certificate.\n",
			0, 0, 0 );
		/* If this was a fatal condition, things would have
		 * aborted long before now.
		 */
		return LDAP_SUCCESS;
	}

#ifdef LDAP_PF_INET6
	if (inet_pton(AF_INET6, name, &addr)) {
		ntype = IS_IP6;
	} else 
#endif
	if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
		if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
	}
	
	i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
	if (i >= 0) {
		X509_EXTENSION *ex;
		STACK_OF(GENERAL_NAME) *alt;

		ex = X509_get_ext(x, i);
		alt = X509V3_EXT_d2i(ex);
		if (alt) {
			int n, len2 = 0;
			char *domain = NULL;
			GENERAL_NAME *gn;

			if (ntype == IS_DNS) {
				domain = strchr(name, '.');
				if (domain) {
					len2 = nlen - (domain-name);
				}
			}
			n = sk_GENERAL_NAME_num(alt);
			for (i=0; i<n; i++) {
				char *sn;
				int sl;
				gn = sk_GENERAL_NAME_value(alt, i);
				if (gn->type == GEN_DNS) {
					if (ntype != IS_DNS) continue;

					sn = (char *) ASN1_STRING_data(gn->d.ia5);
					sl = ASN1_STRING_length(gn->d.ia5);

					/* ignore empty */
					if (sl == 0) continue;

					/* Is this an exact match? */
					if ((nlen == sl) && !strncasecmp(name, sn, nlen)) {
						break;
					}

					/* Is this a wildcard match? */
					if (domain && (sn[0] == '*') && (sn[1] == '.') &&
						(len2 == sl-1) && !strncasecmp(domain, &sn[1], len2))
					{
						break;
					}

				} else if (gn->type == GEN_IPADD) {
					if (ntype == IS_DNS) continue;

					sn = (char *) ASN1_STRING_data(gn->d.ia5);
					sl = ASN1_STRING_length(gn->d.ia5);

#ifdef LDAP_PF_INET6
					if (ntype == IS_IP6 && sl != sizeof(struct in6_addr)) {
						continue;
					} else
#endif
					if (ntype == IS_IP4 && sl != sizeof(struct in_addr)) {
						continue;
					}
					if (!memcmp(sn, &addr, sl)) {
						break;
					}
				}
			}

			GENERAL_NAMES_free(alt);
			if (i < n) {	/* Found a match */
				ret = LDAP_SUCCESS;
			}
		}
	}

	if (ret != LDAP_SUCCESS) {
		X509_NAME *xn;
		X509_NAME_ENTRY *ne;
		ASN1_OBJECT *obj;
		ASN1_STRING *cn = NULL;
		int navas;

		/* find the last CN */
		obj = OBJ_nid2obj( NID_commonName );
		if ( !obj ) goto no_cn;	/* should never happen */

		xn = X509_get_subject_name(x);
		navas = X509_NAME_entry_count( xn );
		for ( i=navas-1; i>=0; i-- ) {
			ne = X509_NAME_get_entry( xn, i );
			if ( !OBJ_cmp( X509_NAME_ENTRY_get_object(ne), obj )) {
				cn = X509_NAME_ENTRY_get_data( ne );
				break;
			}
		}

		if( !cn )
		{
no_cn:
			Debug( LDAP_DEBUG_ANY,
				"TLS: unable to get common name from peer certificate.\n",
				0, 0, 0 );
			ret = LDAP_CONNECT_ERROR;
			if ( ld->ld_error ) {
				LDAP_FREE( ld->ld_error );
			}
			ld->ld_error = LDAP_STRDUP(
				_("TLS: unable to get CN from peer certificate"));

		} else if ( cn->length == nlen &&
			strncasecmp( name, (char *) cn->data, nlen ) == 0 ) {
			ret = LDAP_SUCCESS;

		} else if (( cn->data[0] == '*' ) && ( cn->data[1] == '.' )) {
			char *domain = strchr(name, '.');
			if( domain ) {
				int dlen;

				dlen = nlen - (domain-name);

				/* Is this a wildcard match? */
				if ((dlen == cn->length-1) &&
					!strncasecmp(domain, (char *) &cn->data[1], dlen)) {
					ret = LDAP_SUCCESS;
				}
			}
		}

		if( ret == LDAP_LOCAL_ERROR ) {
			Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
				"common name in certificate (%.*s).\n", 
				name, cn->length, cn->data );
			ret = LDAP_CONNECT_ERROR;
			if ( ld->ld_error ) {
				LDAP_FREE( ld->ld_error );
			}
			ld->ld_error = LDAP_STRDUP(
				_("TLS: hostname does not match CN in peer certificate"));
		}
	}
	X509_free(x);
	return ret;
}
Esempio n. 6
0
BOOL tls_accept(rdpTls* tls, BIO* underlying, rdpSettings *settings)
{
	long options = 0;
	BIO *bio;
	RSA *rsa;
	X509 *x509;

	/**
	 * SSL_OP_NO_SSLv2:
	 *
	 * We only want SSLv3 and TLSv1, so disable SSLv2.
	 * SSLv3 is used by, eg. Microsoft RDC for Mac OS X.
	 */
	options |= SSL_OP_NO_SSLv2;

	/**
	 * SSL_OP_NO_COMPRESSION:
	 *
	 * The Microsoft RDP server does not advertise support
	 * for TLS compression, but alternative servers may support it.
	 * This was observed between early versions of the FreeRDP server
	 * and the FreeRDP client, and caused major performance issues,
	 * which is why we're disabling it.
	 */
#ifdef SSL_OP_NO_COMPRESSION
	options |= SSL_OP_NO_COMPRESSION;
#endif

	/**
	 * SSL_OP_TLS_BLOCK_PADDING_BUG:
	 *
	 * The Microsoft RDP server does *not* support TLS padding.
	 * It absolutely needs to be disabled otherwise it won't work.
	 */
	options |= SSL_OP_TLS_BLOCK_PADDING_BUG;

	/**
	 * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
	 *
	 * Just like TLS padding, the Microsoft RDP server does not
	 * support empty fragments. This needs to be disabled.
	 */
	options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;

	if (!tls_prepare(tls, underlying, SSLv23_server_method(), options, FALSE))
		return FALSE;

	if (settings->PrivateKeyFile)
	{
		bio = BIO_new_file(settings->PrivateKeyFile, "rb+");
		if (!bio)
		{
			WLog_ERR(TAG, "BIO_new_file failed for private key %s", settings->PrivateKeyFile);
			return FALSE;
		}
	}
	else if (settings->PrivateKeyContent)
	{
		bio = BIO_new_mem_buf(settings->PrivateKeyContent, strlen(settings->PrivateKeyContent));
		if (!bio)
		{
			WLog_ERR(TAG, "BIO_new_mem_buf failed for private key");
			return FALSE;
		}
	}
	else
	{
		WLog_ERR(TAG, "no private key defined");
		return FALSE;
	}

	rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
	BIO_free(bio);

	if (!rsa)
	{
		WLog_ERR(TAG, "invalid private key");
		return FALSE;
	}

	if (SSL_use_RSAPrivateKey(tls->ssl, rsa) <= 0)
	{
		WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed");
		RSA_free(rsa);
		return FALSE;
	}


	if (settings->CertificateFile)
	{
		bio = BIO_new_file(settings->CertificateFile, "rb+");
		if (!bio)
		{
			WLog_ERR(TAG, "BIO_new_file failed for certificate %s", settings->CertificateFile);
			return FALSE;
		}
	}
	else if (settings->CertificateContent)
	{
		bio = BIO_new_mem_buf(settings->CertificateContent, strlen(settings->CertificateContent));
		if (!bio)
		{
			WLog_ERR(TAG, "BIO_new_mem_buf failed for certificate");
			return FALSE;
		}
	}
	else
	{
		WLog_ERR(TAG, "no certificate defined");
		return FALSE;
	}

	x509 = PEM_read_bio_X509(bio, NULL, NULL, 0);
	BIO_free(bio);

	if (!x509)
	{
		WLog_ERR(TAG, "invalid certificate");
		return FALSE;
	}


	if (SSL_use_certificate(tls->ssl, x509) <= 0)
	{
		WLog_ERR(TAG, "SSL_use_certificate_file failed");
		X509_free(x509);
		return FALSE;
	}

#ifndef OPENSSL_NO_TLSEXT
	/**
	 * The Microsoft iOS clients eventually send a null or even double null
	 * terminated hostname in the SNI TLS extension!
	 * If the length indicator does not equal the hostname strlen OpenSSL
	 * will abort (see openssl:ssl/t1_lib.c).
	 * Here is a tcpdump segment of Microsoft Remote Desktop Client Version
	 * 8.1.7 running on an iPhone 4 with iOS 7.1.2 showing the transmitted
	 * SNI hostname TLV blob when connection to server "abcd":
	 * 00                  name_type 0x00 (host_name)
	 * 00 06               length_in_bytes 0x0006
	 * 61 62 63 64 00 00   host_name "abcd\0\0"
	 *
	 * Currently the only (runtime) workaround is setting an openssl tls
	 * extension debug callback that sets the SSL context's servername_done
	 * to 1 which effectively disables the parsing of that extension type.
	 */

	SSL_set_tlsext_debug_callback(tls->ssl, tls_openssl_tlsext_debug_callback);
#endif

	return tls_do_handshake(tls, FALSE) > 0;
}
Esempio n. 7
0
int tls13_process_certificate(SSL *ssl, int allow_anonymous) {
  CBS cbs, context;
  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
  if (!CBS_get_u8_length_prefixed(&cbs, &context) ||
      CBS_len(&context) != 0) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
    return 0;
  }

  const int retain_sha256 =
      ssl->server && ssl->ctx->retain_only_sha256_of_client_certs;
  int ret = 0;
  uint8_t alert;
  STACK_OF(X509) *chain = ssl_parse_cert_chain(
      ssl, &alert, retain_sha256 ? ssl->s3->new_session->peer_sha256 : NULL,
      &cbs);
  if (chain == NULL) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
    goto err;
  }

  if (CBS_len(&cbs) != 0) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    goto err;
  }

  if (sk_X509_num(chain) == 0) {
    if (!allow_anonymous) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED);
      goto err;
    }

    /* OpenSSL returns X509_V_OK when no certificates are requested. This is
     * classed by them as a bug, but it's assumed by at least NGINX. */
    ssl->s3->new_session->verify_result = X509_V_OK;

    /* No certificate, so nothing more to do. */
    ret = 1;
    goto err;
  }

  ssl->s3->new_session->peer_sha256_valid = retain_sha256;

  if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result,
                             chain)) {
    goto err;
  }

  X509_free(ssl->s3->new_session->peer);
  X509 *leaf = sk_X509_value(chain, 0);
  X509_up_ref(leaf);
  ssl->s3->new_session->peer = leaf;

  sk_X509_pop_free(ssl->s3->new_session->cert_chain, X509_free);
  ssl->s3->new_session->cert_chain = chain;
  chain = NULL;

  ret = 1;

err:
  sk_X509_pop_free(chain, X509_free);
  return ret;
}
Esempio n. 8
0
int MAIN(int argc, char **argv)
{
    ENGINE *e = NULL;
    BIO *in = NULL, *out = NULL;
    char *infile = NULL, *outfile = NULL;
# ifndef OPENSSL_NO_ENGINE
    char *engine = NULL;
# endif
    char *keyfile = NULL;
    char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
    int keyform = FORMAT_PEM;
    char need_priv = 0, badarg = 0, rev = 0;
    char hexdump = 0, asn1parse = 0;
    X509 *x;
    EVP_PKEY *pkey = NULL;
    RSA *rsa = NULL;
    unsigned char *rsa_in = NULL, *rsa_out = NULL, pad;
    char *passargin = NULL, *passin = NULL;
    int rsa_inlen, rsa_outlen = 0;
    int keysize;

    int ret = 1;

    argc--;
    argv++;

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

    if (!load_config(bio_err, NULL))
        goto end;
    ERR_load_crypto_strings();
    OpenSSL_add_all_algorithms();
    pad = RSA_PKCS1_PADDING;

    while (argc >= 1) {
        if (!strcmp(*argv, "-in")) {
            if (--argc < 1)
                badarg = 1;
            else
                infile = *(++argv);
        } else if (!strcmp(*argv, "-out")) {
            if (--argc < 1)
                badarg = 1;
            else
                outfile = *(++argv);
        } else if (!strcmp(*argv, "-inkey")) {
            if (--argc < 1)
                badarg = 1;
            else
                keyfile = *(++argv);
        } else if (!strcmp(*argv, "-passin")) {
            if (--argc < 1)
                badarg = 1;
            else
                passargin = *(++argv);
        } else if (strcmp(*argv, "-keyform") == 0) {
            if (--argc < 1)
                badarg = 1;
            else
                keyform = str2fmt(*(++argv));
# ifndef OPENSSL_NO_ENGINE
        } else if (!strcmp(*argv, "-engine")) {
            if (--argc < 1)
                badarg = 1;
            else
                engine = *(++argv);
# endif
        } else if (!strcmp(*argv, "-pubin")) {
            key_type = KEY_PUBKEY;
        } else if (!strcmp(*argv, "-certin")) {
            key_type = KEY_CERT;
        } else if (!strcmp(*argv, "-asn1parse"))
            asn1parse = 1;
        else if (!strcmp(*argv, "-hexdump"))
            hexdump = 1;
        else if (!strcmp(*argv, "-raw"))
            pad = RSA_NO_PADDING;
        else if (!strcmp(*argv, "-oaep"))
            pad = RSA_PKCS1_OAEP_PADDING;
        else if (!strcmp(*argv, "-ssl"))
            pad = RSA_SSLV23_PADDING;
        else if (!strcmp(*argv, "-pkcs"))
            pad = RSA_PKCS1_PADDING;
        else if (!strcmp(*argv, "-x931"))
            pad = RSA_X931_PADDING;
        else if (!strcmp(*argv, "-sign")) {
            rsa_mode = RSA_SIGN;
            need_priv = 1;
        } else if (!strcmp(*argv, "-verify"))
            rsa_mode = RSA_VERIFY;
        else if (!strcmp(*argv, "-rev"))
            rev = 1;
        else if (!strcmp(*argv, "-encrypt"))
            rsa_mode = RSA_ENCRYPT;
        else if (!strcmp(*argv, "-decrypt")) {
            rsa_mode = RSA_DECRYPT;
            need_priv = 1;
        } else
            badarg = 1;
        if (badarg) {
            usage();
            goto end;
        }
        argc--;
        argv++;
    }

    if (need_priv && (key_type != KEY_PRIVKEY)) {
        BIO_printf(bio_err, "A private key is needed for this operation\n");
        goto end;
    }
# ifndef OPENSSL_NO_ENGINE
    e = setup_engine(bio_err, engine, 0);
# endif
    if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

/* FIXME: seed PRNG only if needed */
    app_RAND_load_file(NULL, bio_err, 0);

    switch (key_type) {
    case KEY_PRIVKEY:
        pkey = load_key(bio_err, keyfile, keyform, 0,
                        passin, e, "Private Key");
        break;

    case KEY_PUBKEY:
        pkey = load_pubkey(bio_err, keyfile, keyform, 0,
                           NULL, e, "Public Key");
        break;

    case KEY_CERT:
        x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate");
        if (x) {
            pkey = X509_get_pubkey(x);
            X509_free(x);
        }
        break;
    }

    if (!pkey) {
        return 1;
    }

    rsa = EVP_PKEY_get1_RSA(pkey);
    EVP_PKEY_free(pkey);

    if (!rsa) {
        BIO_printf(bio_err, "Error getting RSA key\n");
        ERR_print_errors(bio_err);
        goto end;
    }

    if (infile) {
        if (!(in = BIO_new_file(infile, "rb"))) {
            BIO_printf(bio_err, "Error Reading Input File\n");
            ERR_print_errors(bio_err);
            goto end;
        }
    } else
        in = BIO_new_fp(stdin, BIO_NOCLOSE);

    if (outfile) {
        if (!(out = BIO_new_file(outfile, "wb"))) {
            BIO_printf(bio_err, "Error Reading Output File\n");
            ERR_print_errors(bio_err);
            goto end;
        }
    } else {
        out = BIO_new_fp(stdout, BIO_NOCLOSE);
# ifdef OPENSSL_SYS_VMS
        {
            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
            out = BIO_push(tmpbio, out);
        }
# endif
    }

    keysize = RSA_size(rsa);

    rsa_in = OPENSSL_malloc(keysize * 2);
    rsa_out = OPENSSL_malloc(keysize);

    /* Read the input data */
    rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
    if (rsa_inlen <= 0) {
        BIO_printf(bio_err, "Error reading input Data\n");
        exit(1);
    }
    if (rev) {
        int i;
        unsigned char ctmp;
        for (i = 0; i < rsa_inlen / 2; i++) {
            ctmp = rsa_in[i];
            rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
            rsa_in[rsa_inlen - 1 - i] = ctmp;
        }
    }
    switch (rsa_mode) {

    case RSA_VERIFY:
        rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
        break;

    case RSA_SIGN:
        rsa_outlen =
            RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
        break;

    case RSA_ENCRYPT:
        rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
        break;

    case RSA_DECRYPT:
        rsa_outlen =
            RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
        break;

    }

    if (rsa_outlen <= 0) {
        BIO_printf(bio_err, "RSA operation error\n");
        ERR_print_errors(bio_err);
        goto end;
    }
    ret = 0;
    if (asn1parse) {
        if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) {
            ERR_print_errors(bio_err);
        }
    } else if (hexdump)
        BIO_dump(out, (char *)rsa_out, rsa_outlen);
    else
        BIO_write(out, rsa_out, rsa_outlen);
 end:
    RSA_free(rsa);
    BIO_free(in);
    BIO_free_all(out);
    if (rsa_in)
        OPENSSL_free(rsa_in);
    if (rsa_out)
        OPENSSL_free(rsa_out);
    if (passin)
        OPENSSL_free(passin);
    return ret;
}
Esempio n. 9
0
static ngx_int_t
ngx_stream_ssl_handler(ngx_stream_session_t *s)
{
    long                    rc;
    X509                   *cert;
    ngx_int_t               rv;
    ngx_connection_t       *c;
    ngx_stream_ssl_conf_t  *sslcf;

    if (!s->ssl) {
        return NGX_OK;
    }

    c = s->connection;

    sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);

    if (c->ssl == NULL) {
        c->log->action = "SSL handshaking";

        if (sslcf->ssl.ctx == NULL) {
            ngx_log_error(NGX_LOG_ERR, c->log, 0,
                          "no \"ssl_certificate\" is defined "
                          "in server listening on SSL port");
            return NGX_ERROR;
        }

        rv = ngx_stream_ssl_init_connection(&sslcf->ssl, c);

        if (rv != NGX_OK) {
            return rv;
        }
    }

    if (sslcf->verify) {
        rc = SSL_get_verify_result(c->ssl->connection);

        if (rc != X509_V_OK
            && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
        {
            ngx_log_error(NGX_LOG_INFO, c->log, 0,
                          "client SSL certificate verify error: (%l:%s)",
                          rc, X509_verify_cert_error_string(rc));

            ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
                                       (SSL_get0_session(c->ssl->connection)));
            return NGX_ERROR;
        }

        if (sslcf->verify == 1) {
            cert = SSL_get_peer_certificate(c->ssl->connection);

            if (cert == NULL) {
                ngx_log_error(NGX_LOG_INFO, c->log, 0,
                              "client sent no required SSL certificate");

                ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
                                       (SSL_get0_session(c->ssl->connection)));
                return NGX_ERROR;
            }

            X509_free(cert);
        }
    }

    return NGX_OK;
}
Esempio n. 10
0
int MAIN(int argc, char **argv)
	{
	ENGINE *e = NULL;
	int operation = 0;
	int ret = 0;
	char **args;
	const char *inmode = "r", *outmode = "w";
	char *infile = NULL, *outfile = NULL;
	char *signerfile = NULL, *recipfile = NULL;
	char *certfile = NULL, *keyfile = NULL, *contfile=NULL;
	const EVP_CIPHER *cipher = NULL;
	PKCS7 *p7 = NULL;
	X509_STORE *store = NULL;
	X509 *cert = NULL, *recip = NULL, *signer = NULL;
	EVP_PKEY *key = NULL;
	STACK_OF(X509) *encerts = NULL, *other = NULL;
	BIO *in = NULL, *out = NULL, *indata = NULL;
	int badarg = 0;
	int flags = PKCS7_DETACHED;
	char *to = NULL, *from = NULL, *subject = NULL;
	char *CAfile = NULL, *CApath = NULL;
	char *passargin = NULL, *passin = NULL;
	char *inrand = NULL;
	int need_rand = 0;
	int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
        int keyform = FORMAT_PEM;
#ifndef OPENSSL_NO_ENGINE
	char *engine=NULL;
#endif

	X509_VERIFY_PARAM *vpm = NULL;

	args = argv + 1;
	ret = 1;

	apps_startup();

	if (bio_err == NULL)
		{
		if ((bio_err = BIO_new(BIO_s_file())) != NULL)
			BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
		}

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

	while (!badarg && *args && *args[0] == '-')
		{
		if (!strcmp (*args, "-encrypt"))
			operation = SMIME_ENCRYPT;
		else if (!strcmp (*args, "-decrypt"))
			operation = SMIME_DECRYPT;
		else if (!strcmp (*args, "-sign"))
			operation = SMIME_SIGN;
		else if (!strcmp (*args, "-verify"))
			operation = SMIME_VERIFY;
		else if (!strcmp (*args, "-pk7out"))
			operation = SMIME_PK7OUT;
#ifndef OPENSSL_NO_DES
		else if (!strcmp (*args, "-des3")) 
				cipher = EVP_des_ede3_cbc();
		else if (!strcmp (*args, "-des")) 
				cipher = EVP_des_cbc();
#endif
#ifndef OPENSSL_NO_RC2
		else if (!strcmp (*args, "-rc2-40")) 
				cipher = EVP_rc2_40_cbc();
		else if (!strcmp (*args, "-rc2-128")) 
				cipher = EVP_rc2_cbc();
		else if (!strcmp (*args, "-rc2-64")) 
				cipher = EVP_rc2_64_cbc();
#endif
#ifndef OPENSSL_NO_AES
		else if (!strcmp(*args,"-aes128"))
				cipher = EVP_aes_128_cbc();
		else if (!strcmp(*args,"-aes192"))
				cipher = EVP_aes_192_cbc();
		else if (!strcmp(*args,"-aes256"))
				cipher = EVP_aes_256_cbc();
#endif
		else if (!strcmp (*args, "-text")) 
				flags |= PKCS7_TEXT;
		else if (!strcmp (*args, "-nointern")) 
				flags |= PKCS7_NOINTERN;
		else if (!strcmp (*args, "-noverify")) 
				flags |= PKCS7_NOVERIFY;
		else if (!strcmp (*args, "-nochain")) 
				flags |= PKCS7_NOCHAIN;
		else if (!strcmp (*args, "-nocerts")) 
				flags |= PKCS7_NOCERTS;
		else if (!strcmp (*args, "-noattr")) 
				flags |= PKCS7_NOATTR;
		else if (!strcmp (*args, "-nodetach")) 
				flags &= ~PKCS7_DETACHED;
		else if (!strcmp (*args, "-nosmimecap"))
				flags |= PKCS7_NOSMIMECAP;
		else if (!strcmp (*args, "-binary"))
				flags |= PKCS7_BINARY;
		else if (!strcmp (*args, "-nosigs"))
				flags |= PKCS7_NOSIGS;
		else if (!strcmp (*args, "-nooldmime"))
				flags |= PKCS7_NOOLDMIMETYPE;
		else if (!strcmp (*args, "-crlfeol"))
				flags |= PKCS7_CRLFEOL;
		else if (!strcmp(*args,"-rand"))
			{
			if (args[1])
				{
				args++;
				inrand = *args;
				}
			else
				badarg = 1;
			need_rand = 1;
			}
#ifndef OPENSSL_NO_ENGINE
		else if (!strcmp(*args,"-engine"))
			{
			if (args[1])
				{
				args++;
				engine = *args;
				}
			else badarg = 1;
			}
#endif
		else if (!strcmp(*args,"-passin"))
			{
			if (args[1])
				{
				args++;
				passargin = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-to"))
			{
			if (args[1])
				{
				args++;
				to = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-from"))
			{
			if (args[1])
				{
				args++;
				from = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-subject"))
			{
			if (args[1])
				{
				args++;
				subject = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-signer"))
			{
			if (args[1])
				{
				args++;
				signerfile = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-recip"))
			{
			if (args[1])
				{
				args++;
				recipfile = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-inkey"))
			{
			if (args[1])
				{
				args++;
				keyfile = *args;
				}
			else
				badarg = 1;
		}
		else if (!strcmp (*args, "-keyform"))
			{
			if (args[1])
				{
				args++;
				keyform = str2fmt(*args);
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-certfile"))
			{
			if (args[1])
				{
				args++;
				certfile = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-CAfile"))
			{
			if (args[1])
				{
				args++;
				CAfile = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-CApath"))
			{
			if (args[1])
				{
				args++;
				CApath = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-in"))
			{
			if (args[1])
				{
				args++;
				infile = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-inform"))
			{
			if (args[1])
				{
				args++;
				informat = str2fmt(*args);
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-outform"))
			{
			if (args[1])
				{
				args++;
				outformat = str2fmt(*args);
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-out"))
			{
			if (args[1])
				{
				args++;
				outfile = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-content"))
			{
			if (args[1])
				{
				args++;
				contfile = *args;
				}
			else
				badarg = 1;
			}
		else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
			continue;
		else
			badarg = 1;
		args++;
		}


	if (operation == SMIME_SIGN)
		{
		if (!signerfile)
			{
			BIO_printf(bio_err, "No signer certificate specified\n");
			badarg = 1;
			}
		need_rand = 1;
		}
	else if (operation == SMIME_DECRYPT)
		{
		if (!recipfile)
			{
			BIO_printf(bio_err, "No recipient certificate and key specified\n");
			badarg = 1;
			}
		}
	else if (operation == SMIME_ENCRYPT)
		{
		if (!*args)
			{
			BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
			badarg = 1;
			}
		need_rand = 1;
		}
	else if (!operation)
		badarg = 1;

	if (badarg)
		{
		BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n");
		BIO_printf (bio_err, "where options are\n");
		BIO_printf (bio_err, "-encrypt       encrypt message\n");
		BIO_printf (bio_err, "-decrypt       decrypt encrypted message\n");
		BIO_printf (bio_err, "-sign          sign message\n");
		BIO_printf (bio_err, "-verify        verify signed message\n");
		BIO_printf (bio_err, "-pk7out        output PKCS#7 structure\n");
#ifndef OPENSSL_NO_DES
		BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
		BIO_printf (bio_err, "-des           encrypt with DES\n");
#endif
#ifndef OPENSSL_NO_RC2
		BIO_printf (bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
		BIO_printf (bio_err, "-rc2-64        encrypt with RC2-64\n");
		BIO_printf (bio_err, "-rc2-128       encrypt with RC2-128\n");
#endif
#ifndef OPENSSL_NO_AES
		BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
		BIO_printf (bio_err, "               encrypt PEM output with cbc aes\n");
#endif
		BIO_printf (bio_err, "-nointern      don't search certificates in message for signer\n");
		BIO_printf (bio_err, "-nosigs        don't verify message signature\n");
		BIO_printf (bio_err, "-noverify      don't verify signers certificate\n");
		BIO_printf (bio_err, "-nocerts       don't include signers certificate when signing\n");
		BIO_printf (bio_err, "-nodetach      use opaque signing\n");
		BIO_printf (bio_err, "-noattr        don't include any signed attributes\n");
		BIO_printf (bio_err, "-binary        don't translate message to text\n");
		BIO_printf (bio_err, "-certfile file other certificates file\n");
		BIO_printf (bio_err, "-signer file   signer certificate file\n");
		BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
		BIO_printf (bio_err, "-in file       input file\n");
		BIO_printf (bio_err, "-inform arg    input format SMIME (default), PEM or DER\n");
		BIO_printf (bio_err, "-inkey file    input private key (if not signer or recipient)\n");
		BIO_printf (bio_err, "-keyform arg   input private key format (PEM or ENGINE)\n");
		BIO_printf (bio_err, "-out file      output file\n");
		BIO_printf (bio_err, "-outform arg   output format SMIME (default), PEM or DER\n");
		BIO_printf (bio_err, "-content file  supply or override content for detached signature\n");
		BIO_printf (bio_err, "-to addr       to address\n");
		BIO_printf (bio_err, "-from ad       from address\n");
		BIO_printf (bio_err, "-subject s     subject\n");
		BIO_printf (bio_err, "-text          include or delete text MIME headers\n");
		BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
		BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
		BIO_printf (bio_err, "-crl_check     check revocation status of signer's certificate using CRLs\n");
		BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
#ifndef OPENSSL_NO_ENGINE
		BIO_printf (bio_err, "-engine e      use engine e, possibly a hardware device.\n");
#endif
		BIO_printf (bio_err, "-passin arg    input file pass phrase source\n");
		BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
		BIO_printf(bio_err,  "               load the file (or the files in the directory) into\n");
		BIO_printf(bio_err,  "               the random number generator\n");
		BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
		goto end;
		}

#ifndef OPENSSL_NO_ENGINE
        e = setup_engine(bio_err, engine, 0);
#endif

	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
		{
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
		}

	if (need_rand)
		{
		app_RAND_load_file(NULL, bio_err, (inrand != NULL));
		if (inrand != NULL)
			BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
				app_RAND_load_files(inrand));
		}

	ret = 2;

	if (operation != SMIME_SIGN)
		flags &= ~PKCS7_DETACHED;

	if (operation & SMIME_OP)
		{
		if (flags & PKCS7_BINARY)
			inmode = "rb";
		if (outformat == FORMAT_ASN1)
			outmode = "wb";
		}
	else
		{
		if (flags & PKCS7_BINARY)
			outmode = "wb";
		if (informat == FORMAT_ASN1)
			inmode = "rb";
		}

	if (operation == SMIME_ENCRYPT)
		{
		if (!cipher)
			{
#ifndef OPENSSL_NO_RC2			
			cipher = EVP_rc2_40_cbc();
#else
			BIO_printf(bio_err, "No cipher selected\n");
			goto end;
#endif
			}
		encerts = sk_X509_new_null();
		while (*args)
			{
			if (!(cert = load_cert(bio_err,*args,FORMAT_PEM,
				NULL, e, "recipient certificate file")))
				{
#if 0				/* An appropriate message is already printed */
				BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args);
#endif
				goto end;
				}
			sk_X509_push(encerts, cert);
			cert = NULL;
			args++;
			}
		}

	if (signerfile && (operation == SMIME_SIGN))
		{
		if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM, NULL,
			e, "signer certificate")))
			{
#if 0			/* An appropri message has already been printed */
			BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile);
#endif
			goto end;
			}
		}

	if (certfile)
		{
		if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL,
			e, "certificate file")))
			{
#if 0			/* An appropriate message has already been printed */
			BIO_printf(bio_err, "Can't read certificate file %s\n", certfile);
#endif
			ERR_print_errors(bio_err);
			goto end;
			}
		}

	if (recipfile && (operation == SMIME_DECRYPT))
		{
		if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL,
			e, "recipient certificate file")))
			{
#if 0			/* An appropriate message has alrady been printed */
			BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile);
#endif
			ERR_print_errors(bio_err);
			goto end;
			}
		}

	if (operation == SMIME_DECRYPT)
		{
		if (!keyfile)
			keyfile = recipfile;
		}
	else if (operation == SMIME_SIGN)
		{
		if (!keyfile)
			keyfile = signerfile;
		}
	else keyfile = NULL;

	if (keyfile)
		{
		key = load_key(bio_err, keyfile, keyform, 0, passin, e,
			       "signing key file");
		if (!key)
			goto end;
		}

	if (infile)
		{
		if (!(in = BIO_new_file(infile, inmode)))
			{
			BIO_printf (bio_err,
				 "Can't open input file %s\n", infile);
			goto end;
			}
		}
	else
		in = BIO_new_fp(stdin, BIO_NOCLOSE);

	if (outfile)
		{
		if (!(out = BIO_new_file(outfile, outmode)))
			{
			BIO_printf (bio_err,
				 "Can't open output file %s\n", outfile);
			goto end;
			}
		}
	else
		{
		out = BIO_new_fp(stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
		{
		    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		    out = BIO_push(tmpbio, out);
		}
#endif
		}

	if (operation == SMIME_VERIFY)
		{
		if (!(store = setup_verify(bio_err, CAfile, CApath)))
			goto end;
		X509_STORE_set_verify_cb_func(store, smime_cb);
		if (vpm)
			X509_STORE_set1_param(store, vpm);
		}


	ret = 3;

	if (operation == SMIME_ENCRYPT)
		p7 = PKCS7_encrypt(encerts, in, cipher, flags);
	else if (operation == SMIME_SIGN)
		{
		/* If detached data and SMIME output enable partial
		 * signing.
		 */
		if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME))
			flags |= PKCS7_STREAM;
		p7 = PKCS7_sign(signer, key, other, in, flags);
		/* Don't need to rewind for partial signing */
		if (!(flags & PKCS7_STREAM) && (BIO_reset(in) != 0))
			{
			BIO_printf(bio_err, "Can't rewind input file\n");
			goto end;
			}
		}
	else
		{
		if (informat == FORMAT_SMIME) 
			p7 = SMIME_read_PKCS7(in, &indata);
		else if (informat == FORMAT_PEM) 
			p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
		else if (informat == FORMAT_ASN1) 
			p7 = d2i_PKCS7_bio(in, NULL);
		else
			{
			BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
			goto end;
			}

		if (!p7)
			{
			BIO_printf(bio_err, "Error reading S/MIME message\n");
			goto end;
			}
		if (contfile)
			{
			BIO_free(indata);
			if (!(indata = BIO_new_file(contfile, "rb")))
				{
				BIO_printf(bio_err, "Can't read content file %s\n", contfile);
				goto end;
				}
			}
		}

	if (!p7)
		{
		BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
		goto end;
		}

	ret = 4;
	if (operation == SMIME_DECRYPT)
		{
		if (!PKCS7_decrypt(p7, key, recip, out, flags))
			{
			BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
			goto end;
			}
		}
	else if (operation == SMIME_VERIFY)
		{
		STACK_OF(X509) *signers;
		if (PKCS7_verify(p7, other, store, indata, out, flags))
			BIO_printf(bio_err, "Verification successful\n");
		else
			{
			BIO_printf(bio_err, "Verification failure\n");
			goto end;
			}
		signers = PKCS7_get0_signers(p7, other, flags);
		if (!save_certs(signerfile, signers))
			{
			BIO_printf(bio_err, "Error writing signers to %s\n",
								signerfile);
			ret = 5;
			goto end;
			}
		sk_X509_free(signers);
		}
	else if (operation == SMIME_PK7OUT)
		PEM_write_bio_PKCS7(out, p7);
	else
		{
		if (to)
			BIO_printf(out, "To: %s\n", to);
		if (from)
			BIO_printf(out, "From: %s\n", from);
		if (subject)
			BIO_printf(out, "Subject: %s\n", subject);
		if (outformat == FORMAT_SMIME) 
			SMIME_write_PKCS7(out, p7, in, flags);
		else if (outformat == FORMAT_PEM) 
			PEM_write_bio_PKCS7(out,p7);
		else if (outformat == FORMAT_ASN1) 
			i2d_PKCS7_bio(out,p7);
		else
			{
			BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
			goto end;
			}
		}
	ret = 0;
end:
	if (need_rand)
		app_RAND_write_file(NULL, bio_err);
	if (ret) ERR_print_errors(bio_err);
	sk_X509_pop_free(encerts, X509_free);
	sk_X509_pop_free(other, X509_free);
	if (vpm)
		X509_VERIFY_PARAM_free(vpm);
	X509_STORE_free(store);
	X509_free(cert);
	X509_free(recip);
	X509_free(signer);
	EVP_PKEY_free(key);
	PKCS7_free(p7);
	BIO_free(in);
	BIO_free(indata);
	BIO_free_all(out);
	if (passin) OPENSSL_free(passin);
	return (ret);
}
Esempio n. 11
0
 /*
  * This is the actual startup routine for the connection. We expect that the
  * buffers are flushed and the "220 Ready to start TLS" was received by us,
  * so that we can immediately start the TLS handshake process.
  */
TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
{
    int     sts;
    int     protomask;
    const char *cipher_list;
    SSL_SESSION *session;
    const SSL_CIPHER *cipher;
    X509   *peercert;
    TLS_SESS_STATE *TLScontext;
    TLS_APPL_STATE *app_ctx = props->ctx;
    VSTRING *myserverid;
    int     log_mask = app_ctx->log_mask;

    /*
     * When certificate verification is required, log trust chain validation
     * errors even when disabled by default for opportunistic sessions.
     */
    if (props->tls_level >= TLS_LEV_VERIFY)
	log_mask |= TLS_LOG_UNTRUSTED;

    if (log_mask & TLS_LOG_VERBOSE)
	msg_info("setting up TLS connection to %s", props->namaddr);

    /*
     * First make sure we have valid protocol and cipher parameters
     * 
     * The cipherlist will be applied to the global SSL context, where it can be
     * repeatedly reset if necessary, but the protocol restrictions will be
     * is applied to the SSL connection, because protocol restrictions in the
     * global context cannot be cleared.
     */

    /*
     * OpenSSL will ignore cached sessions that use the wrong protocol. So we
     * do not need to filter out cached sessions with the "wrong" protocol,
     * rather OpenSSL will simply negotiate a new session.
     * 
     * Still, we salt the session lookup key with the protocol list, so that
     * sessions found in the cache are always acceptable.
     */
    protomask = tls_protocol_mask(props->protocols);
    if (protomask == TLS_PROTOCOL_INVALID) {
	/* tls_protocol_mask() logs no warning. */
	msg_warn("%s: Invalid TLS protocol list \"%s\": aborting TLS session",
		 props->namaddr, props->protocols);
	return (0);
    }
    myserverid = vstring_alloc(100);
    vstring_sprintf_append(myserverid, "%s&p=%d", props->serverid, protomask);

    /*
     * Per session cipher selection for sessions with mandatory encryption
     * 
     * By the time a TLS client is negotiating ciphers it has already offered to
     * re-use a session, it is too late to renege on the offer. So we must
     * not attempt to re-use sessions whose ciphers are too weak. We salt the
     * session lookup key with the cipher list, so that sessions found in the
     * cache are always acceptable.
     */
    cipher_list = tls_set_ciphers(app_ctx, "TLS", props->cipher_grade,
				  props->cipher_exclusions);
    if (cipher_list == 0) {
	msg_warn("%s: %s: aborting TLS session",
		 props->namaddr, vstring_str(app_ctx->why));
	vstring_free(myserverid);
	return (0);
    }
    if (log_mask & TLS_LOG_VERBOSE)
	msg_info("%s: TLS cipher list \"%s\"", props->namaddr, cipher_list);
    vstring_sprintf_append(myserverid, "&c=%s", cipher_list);

    /*
     * Allocate a new TLScontext for the new connection and get an SSL
     * structure. Add the location of TLScontext to the SSL to later retrieve
     * the information inside the tls_verify_certificate_callback().
     * 
     * If session caching was enabled when TLS was initialized, the cache type
     * is stored in the client SSL context.
     */
    TLScontext = tls_alloc_sess_context(log_mask, props->namaddr);
    TLScontext->cache_type = app_ctx->cache_type;

    TLScontext->serverid = vstring_export(myserverid);
    TLScontext->stream = props->stream;

    if ((TLScontext->con = SSL_new(app_ctx->ssl_ctx)) == NULL) {
	msg_warn("Could not allocate 'TLScontext->con' with SSL_new()");
	tls_print_errors();
	tls_free_context(TLScontext);
	return (0);
    }
    if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
	msg_warn("Could not set application data for 'TLScontext->con'");
	tls_print_errors();
	tls_free_context(TLScontext);
	return (0);
    }

    /*
     * Apply session protocol restrictions.
     */
    if (protomask != 0)
	SSL_set_options(TLScontext->con,
		   ((protomask & TLS_PROTOCOL_TLSv1) ? SSL_OP_NO_TLSv1 : 0L)
#ifdef SSL_OP_NO_TLSv1_1
	     | ((protomask & TLS_PROTOCOL_TLSv1_1) ? SSL_OP_NO_TLSv1_1 : 0L)
#endif
#ifdef SSL_OP_NO_TLSv1_2
	     | ((protomask & TLS_PROTOCOL_TLSv1_2) ? SSL_OP_NO_TLSv1_2 : 0L)
#endif
		 | ((protomask & TLS_PROTOCOL_SSLv3) ? SSL_OP_NO_SSLv3 : 0L)
	       | ((protomask & TLS_PROTOCOL_SSLv2) ? SSL_OP_NO_SSLv2 : 0L));

    /*
     * XXX To avoid memory leaks we must always call SSL_SESSION_free() after
     * calling SSL_set_session(), regardless of whether or not the session
     * will be reused.
     */
    if (TLScontext->cache_type) {
	session = load_clnt_session(TLScontext);
	if (session) {
	    SSL_set_session(TLScontext->con, session);
	    SSL_SESSION_free(session);		/* 200411 */
#if (OPENSSL_VERSION_NUMBER < 0x00906011L) || (OPENSSL_VERSION_NUMBER == 0x00907000L)

	    /*
	     * Ugly Hack: OpenSSL before 0.9.6a does not store the verify
	     * result in sessions for the client side. We modify the session
	     * directly which is version specific, but this bug is version
	     * specific, too.
	     * 
	     * READ: 0-09-06-01-1 = 0-9-6-a-beta1: all versions before beta1
	     * have this bug, it has been fixed during development of 0.9.6a.
	     * The development version of 0.9.7 can have this bug, too. It
	     * has been fixed on 2000/11/29.
	     */
	    SSL_set_verify_result(TLScontext->con, session->verify_result);
#endif

	}
    }

    /*
     * Before really starting anything, try to seed the PRNG a little bit
     * more.
     */
    tls_int_seed();
    (void) tls_ext_seed(var_tls_daemon_rand_bytes);

    /*
     * Initialize the SSL connection to connect state. This should not be
     * necessary anymore since 0.9.3, but the call is still in the library
     * and maintaining compatibility never hurts.
     */
    SSL_set_connect_state(TLScontext->con);

    /*
     * Connect the SSL connection with the network socket.
     */
    if (SSL_set_fd(TLScontext->con, vstream_fileno(props->stream)) != 1) {
	msg_info("SSL_set_fd error to %s", props->namaddr);
	tls_print_errors();
	uncache_session(app_ctx->ssl_ctx, TLScontext);
	tls_free_context(TLScontext);
	return (0);
    }

    /*
     * Turn on non-blocking I/O so that we can enforce timeouts on network
     * I/O.
     */
    non_blocking(vstream_fileno(props->stream), NON_BLOCKING);

    /*
     * If the debug level selected is high enough, all of the data is dumped:
     * TLS_LOG_TLSPKTS will dump the SSL negotiation, TLS_LOG_ALLPKTS will
     * dump everything.
     * 
     * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
     * Well there is a BIO below the SSL routines that is automatically
     * created for us, so we can use it for debugging purposes.
     */
    if (log_mask & TLS_LOG_TLSPKTS)
	BIO_set_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);

    /*
     * Start TLS negotiations. This process is a black box that invokes our
     * call-backs for certificate verification.
     * 
     * Error handling: If the SSL handhake fails, we print out an error message
     * and remove all TLS state concerning this session.
     */
    sts = tls_bio_connect(vstream_fileno(props->stream), props->timeout,
			  TLScontext);
    if (sts <= 0) {
	if (ERR_peek_error() != 0) {
	    msg_info("SSL_connect error to %s: %d", props->namaddr, sts);
	    tls_print_errors();
	} else if (errno != 0) {
	    msg_info("SSL_connect error to %s: %m", props->namaddr);
	} else {
	    msg_info("SSL_connect error to %s: lost connection",
		     props->namaddr);
	}
	uncache_session(app_ctx->ssl_ctx, TLScontext);
	tls_free_context(TLScontext);
	return (0);
    }
    /* Turn off packet dump if only dumping the handshake */
    if ((log_mask & TLS_LOG_ALLPKTS) == 0)
	BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);

    /*
     * The caller may want to know if this session was reused or if a new
     * session was negotiated.
     */
    TLScontext->session_reused = SSL_session_reused(TLScontext->con);
    if ((log_mask & TLS_LOG_CACHE) && TLScontext->session_reused)
	msg_info("%s: Reusing old session", TLScontext->namaddr);

    /*
     * Do peername verification if requested and extract useful information
     * from the certificate for later use.
     */
    if ((peercert = SSL_get_peer_certificate(TLScontext->con)) != 0) {
	TLScontext->peer_status |= TLS_CERT_FLAG_PRESENT;

	/*
	 * Peer name or fingerprint verification as requested.
	 * Unconditionally set peer_CN, issuer_CN and peer_fingerprint.
	 */
	verify_extract_name(TLScontext, peercert, props);
	verify_extract_print(TLScontext, peercert, props);

	if (TLScontext->log_mask &
	    (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT))
	    msg_info("%s: subject_CN=%s, issuer_CN=%s, "
		     "fingerprint %s, pkey_fingerprint=%s", props->namaddr,
		     TLScontext->peer_CN, TLScontext->issuer_CN,
		     TLScontext->peer_fingerprint,
		     TLScontext->peer_pkey_fprint);
	X509_free(peercert);
    } else {
	TLScontext->issuer_CN = mystrdup("");
	TLScontext->peer_CN = mystrdup("");
	TLScontext->peer_fingerprint = mystrdup("");
	TLScontext->peer_pkey_fprint = mystrdup("");
    }

    /*
     * Finally, collect information about protocol and cipher for logging
     */
    TLScontext->protocol = SSL_get_version(TLScontext->con);
    cipher = SSL_get_current_cipher(TLScontext->con);
    TLScontext->cipher_name = SSL_CIPHER_get_name(cipher);
    TLScontext->cipher_usebits = SSL_CIPHER_get_bits(cipher,
					     &(TLScontext->cipher_algbits));

    /*
     * The TLS engine is active. Switch to the tls_timed_read/write()
     * functions and make the TLScontext available to those functions.
     */
    tls_stream_start(props->stream, TLScontext);

    /*
     * All the key facts in a single log entry.
     */
    if (log_mask & TLS_LOG_SUMMARY)
	msg_info("%s TLS connection established to %s: %s with cipher %s "
	      "(%d/%d bits)", TLS_CERT_IS_MATCHED(TLScontext) ? "Verified" :
		 TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted",
	      props->namaddr, TLScontext->protocol, TLScontext->cipher_name,
		 TLScontext->cipher_usebits, TLScontext->cipher_algbits);

    tls_int_seed();

    return (TLScontext);
}
Esempio n. 12
0
int
x509_main(int argc, char **argv)
{
	ENGINE *e = NULL;
	int ret = 1;
	X509_REQ *req = NULL;
	X509 *x = NULL, *xca = NULL;
	ASN1_OBJECT *objtmp;
	STACK_OF(OPENSSL_STRING) *sigopts = NULL;
	EVP_PKEY *Upkey = NULL, *CApkey = NULL;
	ASN1_INTEGER *sno = NULL;
	int i, num, badops = 0;
	BIO *out = NULL;
	BIO *STDout = NULL;
	STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
	int informat, outformat, keyformat, CAformat, CAkeyformat;
	char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
	char *CAkeyfile = NULL, *CAserial = NULL;
	char *alias = NULL;
	int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0,
	    enddate = 0;
	int next_serial = 0;
	int subject_hash = 0, issuer_hash = 0, ocspid = 0;
#ifndef OPENSSL_NO_MD5
	int subject_hash_old = 0, issuer_hash_old = 0;
#endif
	int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0,
	    email = 0;
	int ocsp_uri = 0;
	int trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0, clrext = 0;
	int C = 0;
	int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0;
	int pprint = 0;
	const char **pp;
	X509_STORE *ctx = NULL;
	X509_REQ *rq = NULL;
	int fingerprint = 0;
	char buf[256];
	const EVP_MD *md_alg, *digest = NULL;
	CONF *extconf = NULL;
	char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
	int checkend = 0, checkoffset = 0;
	unsigned long nmflag = 0, certflag = 0;
#ifndef OPENSSL_NO_ENGINE
	char *engine = NULL;
#endif
	const char *errstr = NULL;

	reqfile = 0;

	STDout = BIO_new_fp(stdout, BIO_NOCLOSE);

	informat = FORMAT_PEM;
	outformat = FORMAT_PEM;
	keyformat = FORMAT_PEM;
	CAformat = FORMAT_PEM;
	CAkeyformat = FORMAT_PEM;

	ctx = X509_STORE_new();
	if (ctx == NULL)
		goto end;
	X509_STORE_set_verify_cb(ctx, callb);

	argc--;
	argv++;
	num = 0;
	while (argc >= 1) {
		if (strcmp(*argv, "-inform") == 0) {
			if (--argc < 1)
				goto bad;
			informat = str2fmt(*(++argv));
		} else if (strcmp(*argv, "-outform") == 0) {
			if (--argc < 1)
				goto bad;
			outformat = str2fmt(*(++argv));
		} else if (strcmp(*argv, "-keyform") == 0) {
			if (--argc < 1)
				goto bad;
			keyformat = str2fmt(*(++argv));
		} else if (strcmp(*argv, "-req") == 0) {
			reqfile = 1;
		} else if (strcmp(*argv, "-CAform") == 0) {
			if (--argc < 1)
				goto bad;
			CAformat = str2fmt(*(++argv));
		} else if (strcmp(*argv, "-CAkeyform") == 0) {
			if (--argc < 1)
				goto bad;
			CAkeyformat = str2fmt(*(++argv));
		} else if (strcmp(*argv, "-sigopt") == 0) {
			if (--argc < 1)
				goto bad;
			if (!sigopts)
				sigopts = sk_OPENSSL_STRING_new_null();
			if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
				goto bad;
		} else if (strcmp(*argv, "-days") == 0) {
			if (--argc < 1)
				goto bad;
			days = strtonum(*(++argv), 1, INT_MAX, &errstr);
			if (errstr) {
				BIO_printf(bio_err, "bad number of days: %s\n", errstr);
				goto bad;
			}
		} else if (strcmp(*argv, "-passin") == 0) {
			if (--argc < 1)
				goto bad;
			passargin = *(++argv);
		} else if (strcmp(*argv, "-extfile") == 0) {
			if (--argc < 1)
				goto bad;
			extfile = *(++argv);
		} else if (strcmp(*argv, "-extensions") == 0) {
			if (--argc < 1)
				goto bad;
			extsect = *(++argv);
		} else if (strcmp(*argv, "-in") == 0) {
			if (--argc < 1)
				goto bad;
			infile = *(++argv);
		} else if (strcmp(*argv, "-out") == 0) {
			if (--argc < 1)
				goto bad;
			outfile = *(++argv);
		} else if (strcmp(*argv, "-signkey") == 0) {
			if (--argc < 1)
				goto bad;
			keyfile = *(++argv);
			sign_flag = ++num;
		} else if (strcmp(*argv, "-CA") == 0) {
			if (--argc < 1)
				goto bad;
			CAfile = *(++argv);
			CA_flag = ++num;
		} else if (strcmp(*argv, "-CAkey") == 0) {
			if (--argc < 1)
				goto bad;
			CAkeyfile = *(++argv);
		} else if (strcmp(*argv, "-CAserial") == 0) {
			if (--argc < 1)
				goto bad;
			CAserial = *(++argv);
		} else if (strcmp(*argv, "-set_serial") == 0) {
			if (--argc < 1)
				goto bad;
			M_ASN1_INTEGER_free(sno);
			if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
				goto bad;
		} else if (strcmp(*argv, "-addtrust") == 0) {
			if (--argc < 1)
				goto bad;
			if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
				BIO_printf(bio_err,
				    "Invalid trust object value %s\n", *argv);
				goto bad;
			}
			if (!trust)
				trust = sk_ASN1_OBJECT_new_null();
			sk_ASN1_OBJECT_push(trust, objtmp);
			trustout = 1;
		} else if (strcmp(*argv, "-addreject") == 0) {
			if (--argc < 1)
				goto bad;
			if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
				BIO_printf(bio_err,
				    "Invalid reject object value %s\n", *argv);
				goto bad;
			}
			if (!reject)
				reject = sk_ASN1_OBJECT_new_null();
			sk_ASN1_OBJECT_push(reject, objtmp);
			trustout = 1;
		} else if (strcmp(*argv, "-setalias") == 0) {
			if (--argc < 1)
				goto bad;
			alias = *(++argv);
			trustout = 1;
		} else if (strcmp(*argv, "-certopt") == 0) {
			if (--argc < 1)
				goto bad;
			if (!set_cert_ex(&certflag, *(++argv)))
				goto bad;
		} else if (strcmp(*argv, "-nameopt") == 0) {
			if (--argc < 1)
				goto bad;
			if (!set_name_ex(&nmflag, *(++argv)))
				goto bad;
		}
#ifndef OPENSSL_NO_ENGINE
		else if (strcmp(*argv, "-engine") == 0) {
			if (--argc < 1)
				goto bad;
			engine = *(++argv);
		}
#endif
		else if (strcmp(*argv, "-C") == 0)
			C = ++num;
		else if (strcmp(*argv, "-email") == 0)
			email = ++num;
		else if (strcmp(*argv, "-ocsp_uri") == 0)
			ocsp_uri = ++num;
		else if (strcmp(*argv, "-serial") == 0)
			serial = ++num;
		else if (strcmp(*argv, "-next_serial") == 0)
			next_serial = ++num;
		else if (strcmp(*argv, "-modulus") == 0)
			modulus = ++num;
		else if (strcmp(*argv, "-pubkey") == 0)
			pubkey = ++num;
		else if (strcmp(*argv, "-x509toreq") == 0)
			x509req = ++num;
		else if (strcmp(*argv, "-text") == 0)
			text = ++num;
		else if (strcmp(*argv, "-hash") == 0 ||
		    strcmp(*argv, "-subject_hash") == 0)
			subject_hash = ++num;
#ifndef OPENSSL_NO_MD5
		else if (strcmp(*argv, "-subject_hash_old") == 0)
			subject_hash_old = ++num;
#endif
		else if (strcmp(*argv, "-issuer_hash") == 0)
			issuer_hash = ++num;
#ifndef OPENSSL_NO_MD5
		else if (strcmp(*argv, "-issuer_hash_old") == 0)
			issuer_hash_old = ++num;
#endif
		else if (strcmp(*argv, "-subject") == 0)
			subject = ++num;
		else if (strcmp(*argv, "-issuer") == 0)
			issuer = ++num;
		else if (strcmp(*argv, "-fingerprint") == 0)
			fingerprint = ++num;
		else if (strcmp(*argv, "-dates") == 0) {
			startdate = ++num;
			enddate = ++num;
		} else if (strcmp(*argv, "-purpose") == 0)
			pprint = ++num;
		else if (strcmp(*argv, "-startdate") == 0)
			startdate = ++num;
		else if (strcmp(*argv, "-enddate") == 0)
			enddate = ++num;
		else if (strcmp(*argv, "-checkend") == 0) {
			if (--argc < 1)
				goto bad;
			checkoffset = strtonum(*(++argv), 0, INT_MAX, &errstr);
			if (errstr) {
				BIO_printf(bio_err, "checkend unusable: %s\n", errstr);
				goto bad;
			}
			checkend = 1;
		} else if (strcmp(*argv, "-noout") == 0)
			noout = ++num;
		else if (strcmp(*argv, "-trustout") == 0)
			trustout = 1;
		else if (strcmp(*argv, "-clrtrust") == 0)
			clrtrust = ++num;
		else if (strcmp(*argv, "-clrreject") == 0)
			clrreject = ++num;
		else if (strcmp(*argv, "-alias") == 0)
			aliasout = ++num;
		else if (strcmp(*argv, "-CAcreateserial") == 0)
			CA_createserial = ++num;
		else if (strcmp(*argv, "-clrext") == 0)
			clrext = 1;
		else if (strcmp(*argv, "-ocspid") == 0)
			ocspid = ++num;
		else if ((md_alg = EVP_get_digestbyname(*argv + 1))) {
			/* ok */
			digest = md_alg;
		} else {
			BIO_printf(bio_err, "unknown option %s\n", *argv);
			badops = 1;
			break;
		}
		argc--;
		argv++;
	}

	if (badops) {
bad:
		for (pp = x509_usage; (*pp != NULL); pp++)
			BIO_printf(bio_err, "%s", *pp);
		goto end;
	}
#ifndef OPENSSL_NO_ENGINE
	e = setup_engine(bio_err, engine, 0);
#endif

	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
	}
	if (!X509_STORE_set_default_paths(ctx)) {
		ERR_print_errors(bio_err);
		goto end;
	}
	if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
		CAkeyfile = CAfile;
	} else if ((CA_flag) && (CAkeyfile == NULL)) {
		BIO_printf(bio_err,
		    "need to specify a CAkey if using the CA command\n");
		goto end;
	}
	if (extfile) {
		long errorline = -1;
		X509V3_CTX ctx2;
		extconf = NCONF_new(NULL);
		if (!NCONF_load(extconf, extfile, &errorline)) {
			if (errorline <= 0)
				BIO_printf(bio_err,
				    "error loading the config file '%s'\n",
				    extfile);
			else
				BIO_printf(bio_err,
				    "error on line %ld of config file '%s'\n",
				    errorline, extfile);
			goto end;
		}
		if (!extsect) {
			extsect = NCONF_get_string(extconf, "default",
			    "extensions");
			if (!extsect) {
				ERR_clear_error();
				extsect = "default";
			}
		}
		X509V3_set_ctx_test(&ctx2);
		X509V3_set_nconf(&ctx2, extconf);
		if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
			BIO_printf(bio_err,
			    "Error Loading extension section %s\n",
			    extsect);
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (reqfile) {
		EVP_PKEY *pkey;
		BIO *in;

		if (!sign_flag && !CA_flag) {
			BIO_printf(bio_err, "We need a private key to sign with\n");
			goto end;
		}
		in = BIO_new(BIO_s_file());
		if (in == NULL) {
			ERR_print_errors(bio_err);
			goto end;
		}
		if (infile == NULL)
			BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT);
		else {
			if (BIO_read_filename(in, infile) <= 0) {
				perror(infile);
				BIO_free(in);
				goto end;
			}
		}
		req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
		BIO_free(in);

		if (req == NULL) {
			ERR_print_errors(bio_err);
			goto end;
		}
		if ((req->req_info == NULL) ||
		    (req->req_info->pubkey == NULL) ||
		    (req->req_info->pubkey->public_key == NULL) ||
		    (req->req_info->pubkey->public_key->data == NULL)) {
			BIO_printf(bio_err, "The certificate request appears to corrupted\n");
			BIO_printf(bio_err, "It does not contain a public key\n");
			goto end;
		}
		if ((pkey = X509_REQ_get_pubkey(req)) == NULL) {
			BIO_printf(bio_err, "error unpacking public key\n");
			goto end;
		}
		i = X509_REQ_verify(req, pkey);
		EVP_PKEY_free(pkey);
		if (i < 0) {
			BIO_printf(bio_err, "Signature verification error\n");
			ERR_print_errors(bio_err);
			goto end;
		}
		if (i == 0) {
			BIO_printf(bio_err, "Signature did not match the certificate request\n");
			goto end;
		} else
			BIO_printf(bio_err, "Signature ok\n");

		print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);

		if ((x = X509_new()) == NULL)
			goto end;

		if (sno == NULL) {
			sno = ASN1_INTEGER_new();
			if (!sno || !rand_serial(NULL, sno))
				goto end;
			if (!X509_set_serialNumber(x, sno))
				goto end;
			ASN1_INTEGER_free(sno);
			sno = NULL;
		} else if (!X509_set_serialNumber(x, sno))
			goto end;

		if (!X509_set_issuer_name(x, req->req_info->subject))
			goto end;
		if (!X509_set_subject_name(x, req->req_info->subject))
			goto end;

		X509_gmtime_adj(X509_get_notBefore(x), 0);
		X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL);

		pkey = X509_REQ_get_pubkey(req);
		X509_set_pubkey(x, pkey);
		EVP_PKEY_free(pkey);
	} else
		x = load_cert(bio_err, infile, informat, NULL, e, "Certificate");

	if (x == NULL)
		goto end;
	if (CA_flag) {
		xca = load_cert(bio_err, CAfile, CAformat, NULL, e, "CA Certificate");
		if (xca == NULL)
			goto end;
	}
	if (!noout || text || next_serial) {
		OBJ_create("2.99999.3",
		    "SET.ex3", "SET x509v3 extension 3");

		out = BIO_new(BIO_s_file());
		if (out == NULL) {
			ERR_print_errors(bio_err);
			goto end;
		}
		if (outfile == NULL) {
			BIO_set_fp(out, stdout, BIO_NOCLOSE);
		} else {
			if (BIO_write_filename(out, outfile) <= 0) {
				perror(outfile);
				goto end;
			}
		}
	}
	if (alias)
		X509_alias_set1(x, (unsigned char *) alias, -1);

	if (clrtrust)
		X509_trust_clear(x);
	if (clrreject)
		X509_reject_clear(x);

	if (trust) {
		for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
			objtmp = sk_ASN1_OBJECT_value(trust, i);
			X509_add1_trust_object(x, objtmp);
		}
	}
	if (reject) {
		for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
			objtmp = sk_ASN1_OBJECT_value(reject, i);
			X509_add1_reject_object(x, objtmp);
		}
	}
	if (num) {
		for (i = 1; i <= num; i++) {
			if (issuer == i) {
				print_name(STDout, "issuer= ",
				    X509_get_issuer_name(x), nmflag);
			} else if (subject == i) {
				print_name(STDout, "subject= ",
				    X509_get_subject_name(x), nmflag);
			} else if (serial == i) {
				BIO_printf(STDout, "serial=");
				i2a_ASN1_INTEGER(STDout,
				    X509_get_serialNumber(x));
				BIO_printf(STDout, "\n");
			} else if (next_serial == i) {
				BIGNUM *bnser;
				ASN1_INTEGER *ser;
				ser = X509_get_serialNumber(x);
				bnser = ASN1_INTEGER_to_BN(ser, NULL);
				if (!bnser)
					goto end;
				if (!BN_add_word(bnser, 1))
					goto end;
				ser = BN_to_ASN1_INTEGER(bnser, NULL);
				if (!ser)
					goto end;
				BN_free(bnser);
				i2a_ASN1_INTEGER(out, ser);
				ASN1_INTEGER_free(ser);
				BIO_puts(out, "\n");
			} else if ((email == i) || (ocsp_uri == i)) {
				int j;
				STACK_OF(OPENSSL_STRING) *emlst;
				if (email == i)
					emlst = X509_get1_email(x);
				else
					emlst = X509_get1_ocsp(x);
				for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
					BIO_printf(STDout, "%s\n",
					    sk_OPENSSL_STRING_value(emlst, j));
				X509_email_free(emlst);
			} else if (aliasout == i) {
				unsigned char *alstr;
				alstr = X509_alias_get0(x, NULL);
				if (alstr)
					BIO_printf(STDout, "%s\n", alstr);
				else
					BIO_puts(STDout, "<No Alias>\n");
			} else if (subject_hash == i) {
				BIO_printf(STDout, "%08lx\n", X509_subject_name_hash(x));
			}
#ifndef OPENSSL_NO_MD5
			else if (subject_hash_old == i) {
				BIO_printf(STDout, "%08lx\n", X509_subject_name_hash_old(x));
			}
#endif
			else if (issuer_hash == i) {
				BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash(x));
			}
#ifndef OPENSSL_NO_MD5
			else if (issuer_hash_old == i) {
				BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash_old(x));
			}
#endif
			else if (pprint == i) {
				X509_PURPOSE *ptmp;
				int j;
				BIO_printf(STDout, "Certificate purposes:\n");
				for (j = 0; j < X509_PURPOSE_get_count(); j++) {
					ptmp = X509_PURPOSE_get0(j);
					purpose_print(STDout, x, ptmp);
				}
			} else if (modulus == i) {
				EVP_PKEY *pkey;

				pkey = X509_get_pubkey(x);
				if (pkey == NULL) {
					BIO_printf(bio_err, "Modulus=unavailable\n");
					ERR_print_errors(bio_err);
					goto end;
				}
				BIO_printf(STDout, "Modulus=");
				if (pkey->type == EVP_PKEY_RSA)
					BN_print(STDout, pkey->pkey.rsa->n);
				else
						if (pkey->type == EVP_PKEY_DSA)
							BN_print(STDout, pkey->pkey.dsa->pub_key);
				else
						BIO_printf(STDout, "Wrong Algorithm type");
				BIO_printf(STDout, "\n");
				EVP_PKEY_free(pkey);
			} else if (pubkey == i) {
				EVP_PKEY *pkey;

				pkey = X509_get_pubkey(x);
				if (pkey == NULL) {
					BIO_printf(bio_err, "Error getting public key\n");
					ERR_print_errors(bio_err);
					goto end;
				}
				PEM_write_bio_PUBKEY(STDout, pkey);
				EVP_PKEY_free(pkey);
			} else if (C == i) {
				unsigned char *d;
				char *m;
				int y, z;

				X509_NAME_oneline(X509_get_subject_name(x),
				    buf, sizeof buf);
				BIO_printf(STDout, "/* subject:%s */\n", buf);
				m = X509_NAME_oneline(
				    X509_get_issuer_name(x), buf,
				    sizeof buf);
				BIO_printf(STDout, "/* issuer :%s */\n", buf);

				z = i2d_X509(x, NULL);
				m = malloc(z);

				d = (unsigned char *) m;
				z = i2d_X509_NAME(X509_get_subject_name(x), &d);
				BIO_printf(STDout, "unsigned char XXX_subject_name[%d]={\n", z);
				d = (unsigned char *) m;
				for (y = 0; y < z; y++) {
					BIO_printf(STDout, "0x%02X,", d[y]);
					if ((y & 0x0f) == 0x0f)
						BIO_printf(STDout, "\n");
				}
				if (y % 16 != 0)
					BIO_printf(STDout, "\n");
				BIO_printf(STDout, "};\n");

				z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
				BIO_printf(STDout, "unsigned char XXX_public_key[%d]={\n", z);
				d = (unsigned char *) m;
				for (y = 0; y < z; y++) {
					BIO_printf(STDout, "0x%02X,", d[y]);
					if ((y & 0x0f) == 0x0f)
						BIO_printf(STDout, "\n");
				}
				if (y % 16 != 0)
					BIO_printf(STDout, "\n");
				BIO_printf(STDout, "};\n");

				z = i2d_X509(x, &d);
				BIO_printf(STDout, "unsigned char XXX_certificate[%d]={\n", z);
				d = (unsigned char *) m;
				for (y = 0; y < z; y++) {
					BIO_printf(STDout, "0x%02X,", d[y]);
					if ((y & 0x0f) == 0x0f)
						BIO_printf(STDout, "\n");
				}
				if (y % 16 != 0)
					BIO_printf(STDout, "\n");
				BIO_printf(STDout, "};\n");

				free(m);
			} else if (text == i) {
				X509_print_ex(STDout, x, nmflag, certflag);
			} else if (startdate == i) {
				BIO_puts(STDout, "notBefore=");
				ASN1_TIME_print(STDout, X509_get_notBefore(x));
				BIO_puts(STDout, "\n");
			} else if (enddate == i) {
				BIO_puts(STDout, "notAfter=");
				ASN1_TIME_print(STDout, X509_get_notAfter(x));
				BIO_puts(STDout, "\n");
			} else if (fingerprint == i) {
				int j;
				unsigned int n;
				unsigned char md[EVP_MAX_MD_SIZE];
				const EVP_MD *fdig = digest;

				if (!fdig)
					fdig = EVP_sha1();

				if (!X509_digest(x, fdig, md, &n)) {
					BIO_printf(bio_err, "out of memory\n");
					goto end;
				}
				BIO_printf(STDout, "%s Fingerprint=",
				    OBJ_nid2sn(EVP_MD_type(fdig)));
				for (j = 0; j < (int) n; j++) {
					BIO_printf(STDout, "%02X%c", md[j],
					    (j + 1 == (int)n) ? '\n' : ':');
				}
			}
			/* should be in the library */
			else if ((sign_flag == i) && (x509req == 0)) {
				BIO_printf(bio_err, "Getting Private key\n");
				if (Upkey == NULL) {
					Upkey = load_key(bio_err,
					    keyfile, keyformat, 0,
					    passin, e, "Private key");
					if (Upkey == NULL)
						goto end;
				}
				if (!sign(x, Upkey, days, clrext, digest,
				    extconf, extsect))
					goto end;
			} else if (CA_flag == i) {
				BIO_printf(bio_err, "Getting CA Private Key\n");
				if (CAkeyfile != NULL) {
					CApkey = load_key(bio_err,
					    CAkeyfile, CAkeyformat,
					    0, passin, e,
					    "CA Private Key");
					if (CApkey == NULL)
						goto end;
				}
				if (!x509_certify(ctx, CAfile, digest, x, xca,
				    CApkey, sigopts,
				    CAserial, CA_createserial, days, clrext,
				    extconf, extsect, sno))
					goto end;
			} else if (x509req == i) {
				EVP_PKEY *pk;

				BIO_printf(bio_err, "Getting request Private Key\n");
				if (keyfile == NULL) {
					BIO_printf(bio_err, "no request key file specified\n");
					goto end;
				} else {
					pk = load_key(bio_err,
					    keyfile, keyformat, 0,
					    passin, e, "request key");
					if (pk == NULL)
						goto end;
				}

				BIO_printf(bio_err, "Generating certificate request\n");

				rq = X509_to_X509_REQ(x, pk, digest);
				EVP_PKEY_free(pk);
				if (rq == NULL) {
					ERR_print_errors(bio_err);
					goto end;
				}
				if (!noout) {
					X509_REQ_print(out, rq);
					PEM_write_bio_X509_REQ(out, rq);
				}
				noout = 1;
			} else if (ocspid == i) {
				X509_ocspid_print(out, x);
			}
		}
	}
	if (checkend) {
		time_t tcheck = time(NULL) + checkoffset;

		if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) {
			BIO_printf(out, "Certificate will expire\n");
			ret = 1;
		} else {
			BIO_printf(out, "Certificate will not expire\n");
			ret = 0;
		}
		goto end;
	}
	if (noout) {
		ret = 0;
		goto end;
	}
	if (outformat == FORMAT_ASN1)
		i = i2d_X509_bio(out, x);
	else if (outformat == FORMAT_PEM) {
		if (trustout)
			i = PEM_write_bio_X509_AUX(out, x);
		else
			i = PEM_write_bio_X509(out, x);
	} else if (outformat == FORMAT_NETSCAPE) {
		NETSCAPE_X509 nx;
		ASN1_OCTET_STRING hdr;

		hdr.data = (unsigned char *) NETSCAPE_CERT_HDR;
		hdr.length = strlen(NETSCAPE_CERT_HDR);
		nx.header = &hdr;
		nx.cert = x;

		i = ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509), out, &nx);
	} else {
		BIO_printf(bio_err, "bad output format specified for outfile\n");
		goto end;
	}
	if (!i) {
		BIO_printf(bio_err, "unable to write certificate\n");
		ERR_print_errors(bio_err);
		goto end;
	}
	ret = 0;

end:
	OBJ_cleanup();
	NCONF_free(extconf);
	BIO_free_all(out);
	BIO_free_all(STDout);
	X509_STORE_free(ctx);
	X509_REQ_free(req);
	X509_free(x);
	X509_free(xca);
	EVP_PKEY_free(Upkey);
	EVP_PKEY_free(CApkey);
	if (sigopts)
		sk_OPENSSL_STRING_free(sigopts);
	X509_REQ_free(rq);
	ASN1_INTEGER_free(sno);
	sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
	sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
	free(passin);

	return (ret);
}
static int ssl_set_cert(CERT *c, X509 *x)
	{
	EVP_PKEY *pkey;
	int i,ok=0,bad=0;

	pkey=X509_get_pubkey(x);
	if (pkey == NULL)
		{
		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_X509_LIB);
		return(0);
		}

	i=ssl_cert_type(x,pkey);
	if (i < 0)
		{
		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
		EVP_PKEY_free(pkey);
		return(0);
		}

	if (c->pkeys[i].privatekey != NULL)
		{
		EVP_PKEY_copy_parameters(pkey,c->pkeys[i].privatekey);
		ERR_clear_error();

#ifndef OPENSSL_NO_RSA
		/* Don't check the public/private key, this is mostly
		 * for smart cards. */
		if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) &&
			(RSA_flags(c->pkeys[i].privatekey->pkey.rsa) &
			 RSA_METHOD_FLAG_NO_CHECK))
			 ok=1;
		else
#endif
		{
		if (!X509_check_private_key(x,c->pkeys[i].privatekey))
			{
			if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA))
				{
				i=(i == SSL_PKEY_DH_RSA)?
					SSL_PKEY_DH_DSA:SSL_PKEY_DH_RSA;

				if (c->pkeys[i].privatekey == NULL)
					ok=1;
				else
					{
					if (!X509_check_private_key(x,
						c->pkeys[i].privatekey))
						bad=1;
					else
						ok=1;
					}
				}
			else
				bad=1;
			}
		else
			ok=1;
		} /* OPENSSL_NO_RSA */
		}
	else
		ok=1;

	EVP_PKEY_free(pkey);
	if (bad)
		{
		EVP_PKEY_free(c->pkeys[i].privatekey);
		c->pkeys[i].privatekey=NULL;
		}

	if (c->pkeys[i].x509 != NULL)
		X509_free(c->pkeys[i].x509);
	CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
	c->pkeys[i].x509=x;
	c->key= &(c->pkeys[i]);

	c->valid=0;
	return(1);
	}
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
	{
	int i,ok=0,bad=0;

	i=ssl_cert_type(NULL,pkey);
	if (i < 0)
		{
		SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
		return(0);
		}

	if (c->pkeys[i].x509 != NULL)
		{
		EVP_PKEY *pktmp;
		pktmp =	X509_get_pubkey(c->pkeys[i].x509);
		EVP_PKEY_copy_parameters(pktmp,pkey);
		EVP_PKEY_free(pktmp);
		ERR_clear_error();

#ifndef OPENSSL_NO_RSA
		/* Don't check the public/private key, this is mostly
		 * for smart cards. */
		if ((pkey->type == EVP_PKEY_RSA) &&
			(RSA_flags(pkey->pkey.rsa) &
			 RSA_METHOD_FLAG_NO_CHECK))
			 ok=1;
		else
#endif
		     if (!X509_check_private_key(c->pkeys[i].x509,pkey))
			{
			if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA))
				{
				i=(i == SSL_PKEY_DH_RSA)?
					SSL_PKEY_DH_DSA:SSL_PKEY_DH_RSA;

				if (c->pkeys[i].x509 == NULL)
					ok=1;
				else
					{
					if (!X509_check_private_key(
						c->pkeys[i].x509,pkey))
						bad=1;
					else
						ok=1;
					}
				}
			else
				bad=1;
			}
		else
			ok=1;
		}
	else
		ok=1;

	if (bad)
		{
		X509_free(c->pkeys[i].x509);
		c->pkeys[i].x509=NULL;
		return(0);
		}

	ERR_clear_error(); /* make sure no error from X509_check_private_key()
	                    * is left if we have chosen to ignore it */
	if (c->pkeys[i].privatekey != NULL)
		EVP_PKEY_free(c->pkeys[i].privatekey);
	CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
	c->pkeys[i].privatekey=pkey;
	c->key= &(c->pkeys[i]);

	c->valid=0;
	return(1);
	}
Esempio n. 15
0
static void finalize_cert(value block)
{
  X509 *cert = Cert_val(block);
  X509_free(cert);
}
Esempio n. 16
0
int MAIN(int argc, char **argv)
	{
	ENGINE *e = NULL;
	int operation = 0;
	int ret = 0;
	char **args;
	const char *inmode = "r", *outmode = "w";
	char *infile = NULL, *outfile = NULL, *rctfile = NULL;
	char *signerfile = NULL, *recipfile = NULL;
	STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
	char *certfile = NULL, *keyfile = NULL, *contfile=NULL;
	char *certsoutfile = NULL;
	const EVP_CIPHER *cipher = NULL;
	CMS_ContentInfo *cms = NULL, *rcms = NULL;
	X509_STORE *store = NULL;
	X509 *cert = NULL, *recip = NULL, *signer = NULL;
	EVP_PKEY *key = NULL;
	STACK_OF(X509) *encerts = NULL, *other = NULL;
	BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
	int badarg = 0;
	int flags = CMS_DETACHED, noout = 0, print = 0;
	int verify_retcode = 0;
	int rr_print = 0, rr_allorfirst = -1;
	STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
	CMS_ReceiptRequest *rr = NULL;
	char *to = NULL, *from = NULL, *subject = NULL;
	char *CAfile = NULL, *CApath = NULL;
	char *passargin = NULL, *passin = NULL;
	char *inrand = NULL;
	int need_rand = 0;
	const EVP_MD *sign_md = NULL;
	int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
        int rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
#ifndef OPENSSL_NO_ENGINE
	char *engine=NULL;
#endif
	unsigned char *secret_key = NULL, *secret_keyid = NULL;
	size_t secret_keylen = 0, secret_keyidlen = 0;

	ASN1_OBJECT *econtent_type = NULL;

	X509_VERIFY_PARAM *vpm = NULL;

	args = argv + 1;
	ret = 1;

	apps_startup();

	if (bio_err == NULL)
		{
		if ((bio_err = BIO_new(BIO_s_file())) != NULL)
			BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
		}

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

	while (!badarg && *args && *args[0] == '-')
		{
		if (!strcmp (*args, "-encrypt"))
			operation = SMIME_ENCRYPT;
		else if (!strcmp (*args, "-decrypt"))
			operation = SMIME_DECRYPT;
		else if (!strcmp (*args, "-sign"))
			operation = SMIME_SIGN;
		else if (!strcmp (*args, "-sign_receipt"))
			operation = SMIME_SIGN_RECEIPT;
		else if (!strcmp (*args, "-resign"))
			operation = SMIME_RESIGN;
		else if (!strcmp (*args, "-verify"))
			operation = SMIME_VERIFY;
		else if (!strcmp (*args, "-verify_retcode"))
			verify_retcode = 1;
		else if (!strcmp(*args,"-verify_receipt"))
			{
			operation = SMIME_VERIFY_RECEIPT;
			if (!args[1])
				goto argerr;
			args++;
			rctfile = *args;
			}
		else if (!strcmp (*args, "-cmsout"))
			operation = SMIME_CMSOUT;
		else if (!strcmp (*args, "-data_out"))
			operation = SMIME_DATAOUT;
		else if (!strcmp (*args, "-data_create"))
			operation = SMIME_DATA_CREATE;
		else if (!strcmp (*args, "-digest_verify"))
			operation = SMIME_DIGEST_VERIFY;
		else if (!strcmp (*args, "-digest_create"))
			operation = SMIME_DIGEST_CREATE;
		else if (!strcmp (*args, "-compress"))
			operation = SMIME_COMPRESS;
		else if (!strcmp (*args, "-uncompress"))
			operation = SMIME_UNCOMPRESS;
		else if (!strcmp (*args, "-EncryptedData_decrypt"))
			operation = SMIME_ENCRYPTED_DECRYPT;
		else if (!strcmp (*args, "-EncryptedData_encrypt"))
			operation = SMIME_ENCRYPTED_ENCRYPT;
#ifndef OPENSSL_NO_DES
		else if (!strcmp (*args, "-des3")) 
				cipher = EVP_des_ede3_cbc();
		else if (!strcmp (*args, "-des")) 
				cipher = EVP_des_cbc();
#endif
#ifndef OPENSSL_NO_SEED
		else if (!strcmp (*args, "-seed")) 
				cipher = EVP_seed_cbc();
#endif
#ifndef OPENSSL_NO_RC2
		else if (!strcmp (*args, "-rc2-40")) 
				cipher = EVP_rc2_40_cbc();
		else if (!strcmp (*args, "-rc2-128")) 
				cipher = EVP_rc2_cbc();
		else if (!strcmp (*args, "-rc2-64")) 
				cipher = EVP_rc2_64_cbc();
#endif
#ifndef OPENSSL_NO_AES
		else if (!strcmp(*args,"-aes128"))
				cipher = EVP_aes_128_cbc();
		else if (!strcmp(*args,"-aes192"))
				cipher = EVP_aes_192_cbc();
		else if (!strcmp(*args,"-aes256"))
				cipher = EVP_aes_256_cbc();
#endif
#ifndef OPENSSL_NO_CAMELLIA
		else if (!strcmp(*args,"-camellia128"))
				cipher = EVP_camellia_128_cbc();
		else if (!strcmp(*args,"-camellia192"))
				cipher = EVP_camellia_192_cbc();
		else if (!strcmp(*args,"-camellia256"))
				cipher = EVP_camellia_256_cbc();
#endif
		else if (!strcmp (*args, "-debug_decrypt")) 
				flags |= CMS_DEBUG_DECRYPT;
		else if (!strcmp (*args, "-text")) 
				flags |= CMS_TEXT;
		else if (!strcmp (*args, "-nointern")) 
				flags |= CMS_NOINTERN;
		else if (!strcmp (*args, "-noverify") 
			|| !strcmp (*args, "-no_signer_cert_verify")) 
				flags |= CMS_NO_SIGNER_CERT_VERIFY;
		else if (!strcmp (*args, "-nocerts")) 
				flags |= CMS_NOCERTS;
		else if (!strcmp (*args, "-noattr")) 
				flags |= CMS_NOATTR;
		else if (!strcmp (*args, "-nodetach")) 
				flags &= ~CMS_DETACHED;
		else if (!strcmp (*args, "-nosmimecap"))
				flags |= CMS_NOSMIMECAP;
		else if (!strcmp (*args, "-binary"))
				flags |= CMS_BINARY;
		else if (!strcmp (*args, "-keyid"))
				flags |= CMS_USE_KEYID;
		else if (!strcmp (*args, "-nosigs"))
				flags |= CMS_NOSIGS;
		else if (!strcmp (*args, "-no_content_verify"))
				flags |= CMS_NO_CONTENT_VERIFY;
		else if (!strcmp (*args, "-no_attr_verify"))
				flags |= CMS_NO_ATTR_VERIFY;
		else if (!strcmp (*args, "-stream"))
				flags |= CMS_STREAM;
		else if (!strcmp (*args, "-indef"))
				flags |= CMS_STREAM;
		else if (!strcmp (*args, "-noindef"))
				flags &= ~CMS_STREAM;
		else if (!strcmp (*args, "-nooldmime"))
				flags |= CMS_NOOLDMIMETYPE;
		else if (!strcmp (*args, "-crlfeol"))
				flags |= CMS_CRLFEOL;
		else if (!strcmp (*args, "-noout"))
				noout = 1;
		else if (!strcmp (*args, "-receipt_request_print"))
				rr_print = 1;
		else if (!strcmp (*args, "-receipt_request_all"))
				rr_allorfirst = 0;
		else if (!strcmp (*args, "-receipt_request_first"))
				rr_allorfirst = 1;
		else if (!strcmp(*args,"-receipt_request_from"))
			{
			if (!args[1])
				goto argerr;
			args++;
			if (!rr_from)
				rr_from = sk_OPENSSL_STRING_new_null();
			sk_OPENSSL_STRING_push(rr_from, *args);
			}
		else if (!strcmp(*args,"-receipt_request_to"))
			{
			if (!args[1])
				goto argerr;
			args++;
			if (!rr_to)
				rr_to = sk_OPENSSL_STRING_new_null();
			sk_OPENSSL_STRING_push(rr_to, *args);
			}
		else if (!strcmp (*args, "-print"))
				{
				noout = 1;
				print = 1;
				}
		else if (!strcmp(*args,"-secretkey"))
			{
			long ltmp;
			if (!args[1])
				goto argerr;
			args++;
			secret_key = string_to_hex(*args, &ltmp);
			if (!secret_key)
				{
				BIO_printf(bio_err, "Invalid key %s\n", *args);
				goto argerr;
				}
			secret_keylen = (size_t)ltmp;
			}
		else if (!strcmp(*args,"-secretkeyid"))
			{
			long ltmp;
			if (!args[1])
				goto argerr;
			args++;
			secret_keyid = string_to_hex(*args, &ltmp);
			if (!secret_keyid)
				{
				BIO_printf(bio_err, "Invalid id %s\n", *args);
				goto argerr;
				}
			secret_keyidlen = (size_t)ltmp;
			}
		else if (!strcmp(*args,"-econtent_type"))
			{
			if (!args[1])
				goto argerr;
			args++;
			econtent_type = OBJ_txt2obj(*args, 0);
			if (!econtent_type)
				{
				BIO_printf(bio_err, "Invalid OID %s\n", *args);
				goto argerr;
				}
			}
		else if (!strcmp(*args,"-rand"))
			{
			if (!args[1])
				goto argerr;
			args++;
			inrand = *args;
			need_rand = 1;
			}
#ifndef OPENSSL_NO_ENGINE
		else if (!strcmp(*args,"-engine"))
			{
			if (!args[1])
				goto argerr;
			engine = *++args;
			}
#endif
		else if (!strcmp(*args,"-passin"))
			{
			if (!args[1])
				goto argerr;
			passargin = *++args;
			}
		else if (!strcmp (*args, "-to"))
			{
			if (!args[1])
				goto argerr;
			to = *++args;
			}
		else if (!strcmp (*args, "-from"))
			{
			if (!args[1])
				goto argerr;
			from = *++args;
			}
		else if (!strcmp (*args, "-subject"))
			{
			if (!args[1])
				goto argerr;
			subject = *++args;
			}
		else if (!strcmp (*args, "-signer"))
			{
			if (!args[1])
				goto argerr;
			/* If previous -signer argument add signer to list */

			if (signerfile)
				{
				if (!sksigners)
					sksigners = sk_OPENSSL_STRING_new_null();
				sk_OPENSSL_STRING_push(sksigners, signerfile);
				if (!keyfile)
					keyfile = signerfile;
				if (!skkeys)
					skkeys = sk_OPENSSL_STRING_new_null();
				sk_OPENSSL_STRING_push(skkeys, keyfile);
				keyfile = NULL;
				}
			signerfile = *++args;
			}
		else if (!strcmp (*args, "-recip"))
			{
			if (!args[1])
				goto argerr;
			recipfile = *++args;
			}
		else if (!strcmp (*args, "-certsout"))
			{
			if (!args[1])
				goto argerr;
			certsoutfile = *++args;
			}
		else if (!strcmp (*args, "-md"))
			{
			if (!args[1])
				goto argerr;
			sign_md = EVP_get_digestbyname(*++args);
			if (sign_md == NULL)
				{
				BIO_printf(bio_err, "Unknown digest %s\n",
							*args);
				goto argerr;
				}
			}
		else if (!strcmp (*args, "-inkey"))
			{
			if (!args[1])	
				goto argerr;
			/* If previous -inkey arument add signer to list */
			if (keyfile)
				{
				if (!signerfile)
					{
					BIO_puts(bio_err, "Illegal -inkey without -signer\n");
					goto argerr;
					}
				if (!sksigners)
					sksigners = sk_OPENSSL_STRING_new_null();
				sk_OPENSSL_STRING_push(sksigners, signerfile);
				signerfile = NULL;
				if (!skkeys)
					skkeys = sk_OPENSSL_STRING_new_null();
				sk_OPENSSL_STRING_push(skkeys, keyfile);
				}
			keyfile = *++args;
			}
		else if (!strcmp (*args, "-keyform"))
			{
			if (!args[1])
				goto argerr;
			keyform = str2fmt(*++args);
			}
		else if (!strcmp (*args, "-rctform"))
			{
			if (!args[1])
				goto argerr;
			rctformat = str2fmt(*++args);
			}
		else if (!strcmp (*args, "-certfile"))
			{
			if (!args[1])
				goto argerr;
			certfile = *++args;
			}
		else if (!strcmp (*args, "-CAfile"))
			{
			if (!args[1])
				goto argerr;
			CAfile = *++args;
			}
		else if (!strcmp (*args, "-CApath"))
			{
			if (!args[1])
				goto argerr;
			CApath = *++args;
			}
		else if (!strcmp (*args, "-in"))
			{
			if (!args[1])
				goto argerr;
			infile = *++args;
			}
		else if (!strcmp (*args, "-inform"))
			{
			if (!args[1])
				goto argerr;
			informat = str2fmt(*++args);
			}
		else if (!strcmp (*args, "-outform"))
			{
			if (!args[1])
				goto argerr;
			outformat = str2fmt(*++args);
			}
		else if (!strcmp (*args, "-out"))
			{
			if (!args[1])
				goto argerr;
			outfile = *++args;
			}
		else if (!strcmp (*args, "-content"))
			{
			if (!args[1])
				goto argerr;
			contfile = *++args;
			}
		else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
			continue;
		else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL)
			badarg = 1;
		args++;
		}

	if (((rr_allorfirst != -1) || rr_from) && !rr_to)
		{
		BIO_puts(bio_err, "No Signed Receipts Recipients\n");
		goto argerr;
		}

	if (!(operation & SMIME_SIGNERS)  && (rr_to || rr_from))
		{
		BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
		goto argerr;
		}
	if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners))
		{
		BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
		goto argerr;
		}

	if (operation & SMIME_SIGNERS)
		{
		if (keyfile && !signerfile)
			{
			BIO_puts(bio_err, "Illegal -inkey without -signer\n");
			goto argerr;
			}
		/* Check to see if any final signer needs to be appended */
		if (signerfile)
			{
			if (!sksigners)
				sksigners = sk_OPENSSL_STRING_new_null();
			sk_OPENSSL_STRING_push(sksigners, signerfile);
			if (!skkeys)
				skkeys = sk_OPENSSL_STRING_new_null();
			if (!keyfile)
				keyfile = signerfile;
			sk_OPENSSL_STRING_push(skkeys, keyfile);
			}
		if (!sksigners)
			{
			BIO_printf(bio_err, "No signer certificate specified\n");
			badarg = 1;
			}
		signerfile = NULL;
		keyfile = NULL;
		need_rand = 1;
		}

	else if (operation == SMIME_DECRYPT)
		{
		if (!recipfile && !keyfile && !secret_key)
			{
			BIO_printf(bio_err, "No recipient certificate or key specified\n");
			badarg = 1;
			}
		}
	else if (operation == SMIME_ENCRYPT)
		{
		if (!*args && !secret_key)
			{
			BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
			badarg = 1;
			}
		need_rand = 1;
		}
	else if (!operation)
		badarg = 1;

	if (badarg)
		{
		argerr:
		BIO_printf (bio_err, "Usage cms [options] cert.pem ...\n");
		BIO_printf (bio_err, "where options are\n");
		BIO_printf (bio_err, "-encrypt       encrypt message\n");
		BIO_printf (bio_err, "-decrypt       decrypt encrypted message\n");
		BIO_printf (bio_err, "-sign          sign message\n");
		BIO_printf (bio_err, "-verify        verify signed message\n");
		BIO_printf (bio_err, "-cmsout        output CMS structure\n");
#ifndef OPENSSL_NO_DES
		BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
		BIO_printf (bio_err, "-des           encrypt with DES\n");
#endif
#ifndef OPENSSL_NO_SEED
		BIO_printf (bio_err, "-seed          encrypt with SEED\n");
#endif
#ifndef OPENSSL_NO_RC2
		BIO_printf (bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
		BIO_printf (bio_err, "-rc2-64        encrypt with RC2-64\n");
		BIO_printf (bio_err, "-rc2-128       encrypt with RC2-128\n");
#endif
#ifndef OPENSSL_NO_AES
		BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
		BIO_printf (bio_err, "               encrypt PEM output with cbc aes\n");
#endif
#ifndef OPENSSL_NO_CAMELLIA
		BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n");
		BIO_printf (bio_err, "               encrypt PEM output with cbc camellia\n");
#endif
		BIO_printf (bio_err, "-nointern      don't search certificates in message for signer\n");
		BIO_printf (bio_err, "-nosigs        don't verify message signature\n");
		BIO_printf (bio_err, "-noverify      don't verify signers certificate\n");
		BIO_printf (bio_err, "-nocerts       don't include signers certificate when signing\n");
		BIO_printf (bio_err, "-nodetach      use opaque signing\n");
		BIO_printf (bio_err, "-noattr        don't include any signed attributes\n");
		BIO_printf (bio_err, "-binary        don't translate message to text\n");
		BIO_printf (bio_err, "-certfile file other certificates file\n");
		BIO_printf (bio_err, "-certsout file certificate output file\n");
		BIO_printf (bio_err, "-signer file   signer certificate file\n");
		BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
		BIO_printf (bio_err, "-keyid         use subject key identifier\n");
		BIO_printf (bio_err, "-in file       input file\n");
		BIO_printf (bio_err, "-inform arg    input format SMIME (default), PEM or DER\n");
		BIO_printf (bio_err, "-inkey file    input private key (if not signer or recipient)\n");
		BIO_printf (bio_err, "-keyform arg   input private key format (PEM or ENGINE)\n");
		BIO_printf (bio_err, "-out file      output file\n");
		BIO_printf (bio_err, "-outform arg   output format SMIME (default), PEM or DER\n");
		BIO_printf (bio_err, "-content file  supply or override content for detached signature\n");
		BIO_printf (bio_err, "-to addr       to address\n");
		BIO_printf (bio_err, "-from ad       from address\n");
		BIO_printf (bio_err, "-subject s     subject\n");
		BIO_printf (bio_err, "-text          include or delete text MIME headers\n");
		BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
		BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
		BIO_printf (bio_err, "-crl_check     check revocation status of signer's certificate using CRLs\n");
		BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
#ifndef OPENSSL_NO_ENGINE
		BIO_printf (bio_err, "-engine e      use engine e, possibly a hardware device.\n");
#endif
		BIO_printf (bio_err, "-passin arg    input file pass phrase source\n");
		BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
		BIO_printf(bio_err,  "               load the file (or the files in the directory) into\n");
		BIO_printf(bio_err,  "               the random number generator\n");
		BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
		goto end;
		}

#ifndef OPENSSL_NO_ENGINE
        e = setup_engine(bio_err, engine, 0);
#endif

	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
		{
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
		}

	if (need_rand)
		{
		app_RAND_load_file(NULL, bio_err, (inrand != NULL));
		if (inrand != NULL)
			BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
				app_RAND_load_files(inrand));
		}

	ret = 2;

	if (!(operation & SMIME_SIGNERS))
		flags &= ~CMS_DETACHED;

	if (operation & SMIME_OP)
		{
		if (outformat == FORMAT_ASN1)
			outmode = "wb";
		}
	else
		{
		if (flags & CMS_BINARY)
			outmode = "wb";
		}

	if (operation & SMIME_IP)
		{
		if (informat == FORMAT_ASN1)
			inmode = "rb";
		}
	else
		{
		if (flags & CMS_BINARY)
			inmode = "rb";
		}

	if (operation == SMIME_ENCRYPT)
		{
		if (!cipher)
			{
#ifndef OPENSSL_NO_DES			
			cipher = EVP_des_ede3_cbc();
#else
			BIO_printf(bio_err, "No cipher selected\n");
			goto end;
#endif
			}

		if (secret_key && !secret_keyid)
			{
			BIO_printf(bio_err, "No secret key id\n");
			goto end;
			}

		if (*args)
			encerts = sk_X509_new_null();
		while (*args)
			{
			if (!(cert = load_cert(bio_err,*args,FORMAT_PEM,
				NULL, e, "recipient certificate file")))
				goto end;
			sk_X509_push(encerts, cert);
			cert = NULL;
			args++;
			}
		}

	if (certfile)
		{
		if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL,
			e, "certificate file")))
			{
			ERR_print_errors(bio_err);
			goto end;
			}
		}

	if (recipfile && (operation == SMIME_DECRYPT))
		{
		if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL,
			e, "recipient certificate file")))
			{
			ERR_print_errors(bio_err);
			goto end;
			}
		}

	if (operation == SMIME_SIGN_RECEIPT)
		{
		if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM,NULL,
			e, "receipt signer certificate file")))
			{
			ERR_print_errors(bio_err);
			goto end;
			}
		}

	if (operation == SMIME_DECRYPT)
		{
		if (!keyfile)
			keyfile = recipfile;
		}
	else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT))
		{
		if (!keyfile)
			keyfile = signerfile;
		}
	else keyfile = NULL;

	if (keyfile)
		{
		key = load_key(bio_err, keyfile, keyform, 0, passin, e,
			       "signing key file");
		if (!key)
			goto end;
		}

	if (infile)
		{
		if (!(in = BIO_new_file(infile, inmode)))
			{
			BIO_printf (bio_err,
				 "Can't open input file %s\n", infile);
			goto end;
			}
		}
	else
		in = BIO_new_fp(stdin, BIO_NOCLOSE);

	if (operation & SMIME_IP)
		{
		if (informat == FORMAT_SMIME) 
			cms = SMIME_read_CMS(in, &indata);
		else if (informat == FORMAT_PEM) 
			cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
		else if (informat == FORMAT_ASN1) 
			cms = d2i_CMS_bio(in, NULL);
		else
			{
			BIO_printf(bio_err, "Bad input format for CMS file\n");
			goto end;
			}

		if (!cms)
			{
			BIO_printf(bio_err, "Error reading S/MIME message\n");
			goto end;
			}
		if (contfile)
			{
			BIO_free(indata);
			if (!(indata = BIO_new_file(contfile, "rb")))
				{
				BIO_printf(bio_err, "Can't read content file %s\n", contfile);
				goto end;
				}
			}
		if (certsoutfile)
			{
			STACK_OF(X509) *allcerts;
			allcerts = CMS_get1_certs(cms);
			if (!save_certs(certsoutfile, allcerts))
				{
				BIO_printf(bio_err,
						"Error writing certs to %s\n",
								certsoutfile);
				ret = 5;
				goto end;
				}
			sk_X509_pop_free(allcerts, X509_free);
			}
		}

	if (rctfile)
		{
		char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
		if (!(rctin = BIO_new_file(rctfile, rctmode)))
			{
			BIO_printf (bio_err,
				 "Can't open receipt file %s\n", rctfile);
			goto end;
			}
		
		if (rctformat == FORMAT_SMIME) 
			rcms = SMIME_read_CMS(rctin, NULL);
		else if (rctformat == FORMAT_PEM) 
			rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
		else if (rctformat == FORMAT_ASN1) 
			rcms = d2i_CMS_bio(rctin, NULL);
		else
			{
			BIO_printf(bio_err, "Bad input format for receipt\n");
			goto end;
			}

		if (!rcms)
			{
			BIO_printf(bio_err, "Error reading receipt\n");
			goto end;
			}
		}

	if (outfile)
		{
		if (!(out = BIO_new_file(outfile, outmode)))
			{
			BIO_printf (bio_err,
				 "Can't open output file %s\n", outfile);
			goto end;
			}
		}
	else
		{
		out = BIO_new_fp(stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
		{
		    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		    out = BIO_push(tmpbio, out);
		}
#endif
		}

	if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT))
		{
		if (!(store = setup_verify(bio_err, CAfile, CApath)))
			goto end;
		X509_STORE_set_verify_cb(store, cms_cb);
		if (vpm)
			X509_STORE_set1_param(store, vpm);
		}


	ret = 3;

	if (operation == SMIME_DATA_CREATE)
		{
		cms = CMS_data_create(in, flags);
		}
	else if (operation == SMIME_DIGEST_CREATE)
		{
		cms = CMS_digest_create(in, sign_md, flags);
		}
	else if (operation == SMIME_COMPRESS)
		{
		cms = CMS_compress(in, -1, flags);
		}
	else if (operation == SMIME_ENCRYPT)
		{
		flags |= CMS_PARTIAL;
		cms = CMS_encrypt(encerts, in, cipher, flags);
		if (!cms)
			goto end;
		if (secret_key)
			{
			if (!CMS_add0_recipient_key(cms, NID_undef, 
						secret_key, secret_keylen,
						secret_keyid, secret_keyidlen,
						NULL, NULL, NULL))
				goto end;
			/* NULL these because call absorbs them */
			secret_key = NULL;
			secret_keyid = NULL;
			}
		if (!(flags & CMS_STREAM))
			{
			if (!CMS_final(cms, in, NULL, flags))
				goto end;
			}
		}
	else if (operation == SMIME_ENCRYPTED_ENCRYPT)
		{
		cms = CMS_EncryptedData_encrypt(in, cipher,
						secret_key, secret_keylen,
						flags);

		}
	else if (operation == SMIME_SIGN_RECEIPT)
		{
		CMS_ContentInfo *srcms = NULL;
		STACK_OF(CMS_SignerInfo) *sis;
		CMS_SignerInfo *si;
		sis = CMS_get0_SignerInfos(cms);
		if (!sis)
			goto end;
		si = sk_CMS_SignerInfo_value(sis, 0);
		srcms = CMS_sign_receipt(si, signer, key, other, flags);
		if (!srcms)
			goto end;
		CMS_ContentInfo_free(cms);
		cms = srcms;
		}
	else if (operation & SMIME_SIGNERS)
		{
		int i;
		/* If detached data content we enable streaming if
		 * S/MIME output format.
		 */
		if (operation == SMIME_SIGN)
			{
				
			if (flags & CMS_DETACHED)
				{
				if (outformat == FORMAT_SMIME)
					flags |= CMS_STREAM;
				}
			flags |= CMS_PARTIAL;
			cms = CMS_sign(NULL, NULL, other, in, flags);
			if (!cms)
				goto end;
			if (econtent_type)
				CMS_set1_eContentType(cms, econtent_type);

			if (rr_to)
				{
				rr = make_receipt_request(rr_to, rr_allorfirst,
								rr_from);
				if (!rr)
					{
					BIO_puts(bio_err,
				"Signed Receipt Request Creation Error\n");
					goto end;
					}
				}
			}
		else
			flags |= CMS_REUSE_DIGEST;
		for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++)
			{
			CMS_SignerInfo *si;
			signerfile = sk_OPENSSL_STRING_value(sksigners, i);
			keyfile = sk_OPENSSL_STRING_value(skkeys, i);
			signer = load_cert(bio_err, signerfile,FORMAT_PEM, NULL,
					e, "signer certificate");
			if (!signer)
				goto end;
			key = load_key(bio_err, keyfile, keyform, 0, passin, e,
			       "signing key file");
			if (!key)
				goto end;
			si = CMS_add1_signer(cms, signer, key, sign_md, flags);
			if (!si)
				goto end;
			if (rr && !CMS_add1_ReceiptRequest(si, rr))
				goto end;
			X509_free(signer);
			signer = NULL;
			EVP_PKEY_free(key);
			key = NULL;
			}
		/* If not streaming or resigning finalize structure */
		if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM))
			{
			if (!CMS_final(cms, in, NULL, flags))
				goto end;
			}
		}

	if (!cms)
		{
		BIO_printf(bio_err, "Error creating CMS structure\n");
		goto end;
		}

	ret = 4;
	if (operation == SMIME_DECRYPT)
		{
		if (flags & CMS_DEBUG_DECRYPT)
			CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags);

		if (secret_key)
			{
			if (!CMS_decrypt_set1_key(cms,
						secret_key, secret_keylen,
						secret_keyid, secret_keyidlen))
				{
				BIO_puts(bio_err,
					"Error decrypting CMS using secret key\n");
				goto end;
				}
			}

		if (key)
			{
			if (!CMS_decrypt_set1_pkey(cms, key, recip))
				{
				BIO_puts(bio_err,
					"Error decrypting CMS using private key\n");
				goto end;
				}
			}

		if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags))
			{
			BIO_printf(bio_err, "Error decrypting CMS structure\n");
			goto end;
			}
		}
	else if (operation == SMIME_DATAOUT)
		{
		if (!CMS_data(cms, out, flags))
			goto end;
		}
	else if (operation == SMIME_UNCOMPRESS)
		{
		if (!CMS_uncompress(cms, indata, out, flags))
			goto end;
		}
	else if (operation == SMIME_DIGEST_VERIFY)
		{
		if (CMS_digest_verify(cms, indata, out, flags) > 0)
			BIO_printf(bio_err, "Verification successful\n");
		else
			{
			BIO_printf(bio_err, "Verification failure\n");
			goto end;
			}
		}
	else if (operation == SMIME_ENCRYPTED_DECRYPT)
		{
		if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
						indata, out, flags))
			goto end;
		}
	else if (operation == SMIME_VERIFY)
		{
		if (CMS_verify(cms, other, store, indata, out, flags) > 0)
			BIO_printf(bio_err, "Verification successful\n");
		else
			{
			BIO_printf(bio_err, "Verification failure\n");
			if (verify_retcode)
				ret = verify_err + 32;
			goto end;
			}
		if (signerfile)
			{
			STACK_OF(X509) *signers;
			signers = CMS_get0_signers(cms);
			if (!save_certs(signerfile, signers))
				{
				BIO_printf(bio_err,
						"Error writing signers to %s\n",
								signerfile);
				ret = 5;
				goto end;
				}
			sk_X509_free(signers);
			}
		if (rr_print)
			receipt_request_print(bio_err, cms);
					
		}
	else if (operation == SMIME_VERIFY_RECEIPT)
		{
		if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0)
			BIO_printf(bio_err, "Verification successful\n");
		else
			{
			BIO_printf(bio_err, "Verification failure\n");
			goto end;
			}
		}
	else
		{
		if (noout)
			{
			if (print)
				CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
			}
		else if (outformat == FORMAT_SMIME)
			{
			if (to)
				BIO_printf(out, "To: %s\n", to);
			if (from)
				BIO_printf(out, "From: %s\n", from);
			if (subject)
				BIO_printf(out, "Subject: %s\n", subject);
			if (operation == SMIME_RESIGN)
				ret = SMIME_write_CMS(out, cms, indata, flags);
			else
				ret = SMIME_write_CMS(out, cms, in, flags);
			}
		else if (outformat == FORMAT_PEM) 
			ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
		else if (outformat == FORMAT_ASN1) 
			ret = i2d_CMS_bio_stream(out,cms, in, flags);
		else
			{
			BIO_printf(bio_err, "Bad output format for CMS file\n");
			goto end;
			}
		if (ret <= 0)
			{
			ret = 6;
			goto end;
			}
		}
	ret = 0;
end:
	if (ret)
		ERR_print_errors(bio_err);
	if (need_rand)
		app_RAND_write_file(NULL, bio_err);
	sk_X509_pop_free(encerts, X509_free);
	sk_X509_pop_free(other, X509_free);
	if (vpm)
		X509_VERIFY_PARAM_free(vpm);
	if (sksigners)
		sk_OPENSSL_STRING_free(sksigners);
	if (skkeys)
		sk_OPENSSL_STRING_free(skkeys);
	if (secret_key)
		OPENSSL_free(secret_key);
	if (secret_keyid)
		OPENSSL_free(secret_keyid);
	if (econtent_type)
		ASN1_OBJECT_free(econtent_type);
	if (rr)
		CMS_ReceiptRequest_free(rr);
	if (rr_to)
		sk_OPENSSL_STRING_free(rr_to);
	if (rr_from)
		sk_OPENSSL_STRING_free(rr_from);
	X509_STORE_free(store);
	X509_free(cert);
	X509_free(recip);
	X509_free(signer);
	EVP_PKEY_free(key);
	CMS_ContentInfo_free(cms);
	CMS_ContentInfo_free(rcms);
	BIO_free(rctin);
	BIO_free(in);
	BIO_free(indata);
	BIO_free_all(out);
	if (passin) OPENSSL_free(passin);
	return (ret);
}
Esempio n. 17
0
static EVP_PKEY_CTX *init_ctx(int *pkeysize,
				char *keyfile, int keyform, int key_type,
				char *passargin, int pkey_op, ENGINE *e)
	{
	EVP_PKEY *pkey = NULL;
	EVP_PKEY_CTX *ctx = NULL;
	char *passin = NULL;
	int rv = -1;
	X509 *x;
	if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) 
		|| (pkey_op == EVP_PKEY_OP_DERIVE))
		&& (key_type != KEY_PRIVKEY))
		{
		BIO_printf(bio_err, "A private key is needed for this operation\n");
		goto end;
		}
	if(!app_passwd(bio_err, passargin, NULL, &passin, NULL))
		{
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
		}
	switch(key_type)
		{
		case KEY_PRIVKEY:
		pkey = load_key(bio_err, keyfile, keyform, 0,
			passin, e, "Private Key");
		break;

		case KEY_PUBKEY:
		pkey = load_pubkey(bio_err, keyfile, keyform, 0,
			NULL, e, "Public Key");
		break;

		case KEY_CERT:
		x = load_cert(bio_err, keyfile, keyform,
			NULL, e, "Certificate");
		if(x)
			{
			pkey = X509_get_pubkey(x);
			X509_free(x);
			}
		break;

		}

	*pkeysize = EVP_PKEY_size(pkey);

	if (!pkey)
		goto end;

	ctx = EVP_PKEY_CTX_new(pkey, e);

	EVP_PKEY_free(pkey);

	if (!ctx)
		goto end;

	switch(pkey_op)
		{
		case EVP_PKEY_OP_SIGN:
		rv = EVP_PKEY_sign_init(ctx);
		break;

		case EVP_PKEY_OP_VERIFY:
		rv = EVP_PKEY_verify_init(ctx);
		break;

		case EVP_PKEY_OP_VERIFYRECOVER:
		rv = EVP_PKEY_verify_recover_init(ctx);
		break;

		case EVP_PKEY_OP_ENCRYPT:
		rv = EVP_PKEY_encrypt_init(ctx);
		break;

		case EVP_PKEY_OP_DECRYPT:
		rv = EVP_PKEY_decrypt_init(ctx);
		break;

		case EVP_PKEY_OP_DERIVE:
		rv = EVP_PKEY_derive_init(ctx);
		break;
		}

	if (rv <= 0)
		{
		EVP_PKEY_CTX_free(ctx);
		ctx = NULL;
		}

	end:

	if (passin)
		OPENSSL_free(passin);

	return ctx;


	}
Esempio n. 18
0
long post_connection_check(SSL *ssl, char *host)
{
    X509      *cert;
    X509_NAME *subj;
    char      data[256];
    int       extcount;
    int       ok = 0;
 
    /* Checking the return from SSL_get_peer_certificate here is not strictly
     * necessary.  With our example programs, it is not possible for it to return
     * NULL.  However, it is good form to check the return since it can return NULL
     * if the examples are modified to enable anonymous ciphers or for the server
     * to not require a client certificate.
     */
    if (!(cert = SSL_get_peer_certificate(ssl)) || !host)
        goto err_occured;
    if ((extcount = X509_get_ext_count(cert)) > 0)
    {
        int i;
 
        for (i = 0;  i < extcount;  i++)
        {
            char              *extstr;
            X509_EXTENSION    *ext;
 
            ext = X509_get_ext(cert, i);
            extstr = (char*) OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
 
            if (!strcmp(extstr, "subjectAltName"))
            {
                int                  j;
                unsigned char        *data;
                STACK_OF(CONF_VALUE) *val;
                CONF_VALUE           *nval;
                X509V3_EXT_METHOD    *meth;
                void                 *ext_str = NULL;
 
                if (!(meth = X509V3_EXT_get(ext)))
                    break;
                data = ext->value->data;

#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
                if (meth->it)
                  ext_str = ASN1_item_d2i(NULL, &data, ext->value->length,
                                          ASN1_ITEM_ptr(meth->it));
                else
                  ext_str = meth->d2i(NULL, &data, ext->value->length);
#else
                ext_str = meth->d2i(NULL, &data, ext->value->length);
#endif
                val = meth->i2v(meth, ext_str, NULL);
                for (j = 0;  j < sk_CONF_VALUE_num(val);  j++)
                {
                    nval = sk_CONF_VALUE_value(val, j);
                    if (!strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
                    {
                        ok = 1;
                        break;
                    }
                }
            }
            if (ok)
                break;
        }
    }
 
    if (!ok && (subj = X509_get_subject_name(cert)) &&
        X509_NAME_get_text_by_NID(subj, NID_commonName, data, 256) > 0)
    {
        data[255] = 0;
        if (strcasecmp(data, host) != 0)
            goto err_occured;
    }
 
    X509_free(cert);
    return SSL_get_verify_result(ssl);
 
err_occured:
    if (cert)
        X509_free(cert);
    return X509_V_ERR_APPLICATION_VERIFICATION;
}
Esempio n. 19
0
bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const
{
    merchant.clear();

    if (!IsInitialized())
        return false;

    // One day we'll support more PKI types, but just
    // x509 for now:
    const EVP_MD* digestAlgorithm = NULL;
    if (paymentRequest.pki_type() == "x509+sha256") {
        digestAlgorithm = EVP_sha256();
    }
    else if (paymentRequest.pki_type() == "x509+sha1") {
        digestAlgorithm = EVP_sha1();
    }
    else if (paymentRequest.pki_type() == "none") {
        if (fDebug) qDebug() << "PaymentRequest: pki_type == none";
        return false;
    }
    else {
        qDebug() << "PaymentRequest: unknown pki_type " << paymentRequest.pki_type().c_str();
        return false;
    }

    payments::X509Certificates certChain;
    if (!certChain.ParseFromString(paymentRequest.pki_data())) {
        qDebug() << "PaymentRequest: error parsing pki_data";
        return false;
    }

    std::vector<X509*> certs;
    const QDateTime currentTime = QDateTime::currentDateTime();
    for (int i = 0; i < certChain.certificate_size(); i++) {
        QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size());
        QSslCertificate qCert(certData, QSsl::Der);
        if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) {
            qDebug() << "PaymentRequest: certificate expired or not yet active: " << qCert;
            return false;
        }
#if QT_VERSION >= 0x050000
        if (qCert.isBlacklisted()) {
            qDebug() << "PaymentRequest: certificate blacklisted: " << qCert;
            return false;
        }
#endif
        const unsigned char *data = (const unsigned char *)certChain.certificate(i).data();
        X509 *cert = d2i_X509(NULL, &data, certChain.certificate(i).size());
        if (cert)
            certs.push_back(cert);
    }
    if (certs.empty()) {
        qDebug() << "PaymentRequest: empty certificate chain";
        return false;
    }

    // The first cert is the signing cert, the rest are untrusted certs that chain
    // to a valid root authority. OpenSSL needs them separately.
    STACK_OF(X509) *chain = sk_X509_new_null();
    for (int i = certs.size()-1; i > 0; i--) {
        sk_X509_push(chain, certs[i]);
    }
    X509 *signing_cert = certs[0];

    // Now create a "store context", which is a single use object for checking,
    // load the signing cert into it and verify.
    X509_STORE_CTX *store_ctx = X509_STORE_CTX_new();
    if (!store_ctx) {
        qDebug() << "PaymentRequest: error creating X509_STORE_CTX";
        return false;
    }

    char *website = NULL;
    bool fResult = true;
    try
    {
        if (!X509_STORE_CTX_init(store_ctx, certStore, signing_cert, chain))
        {
            int error = X509_STORE_CTX_get_error(store_ctx);
            throw SSLVerifyError(X509_verify_cert_error_string(error));
        }

        // Now do the verification!
        int result = X509_verify_cert(store_ctx);
        if (result != 1) {
            int error = X509_STORE_CTX_get_error(store_ctx);
            throw SSLVerifyError(X509_verify_cert_error_string(error));
        }
        X509_NAME *certname = X509_get_subject_name(signing_cert);

        // Valid cert; check signature:
        payments::PaymentRequest rcopy(paymentRequest); // Copy
        rcopy.set_signature(std::string(""));
        std::string data_to_verify;                 // Everything but the signature
        rcopy.SerializeToString(&data_to_verify);

        EVP_MD_CTX ctx;
        EVP_PKEY *pubkey = X509_get_pubkey(signing_cert);
        EVP_MD_CTX_init(&ctx);
        if (!EVP_VerifyInit_ex(&ctx, digestAlgorithm, NULL) ||
            !EVP_VerifyUpdate(&ctx, data_to_verify.data(), data_to_verify.size()) ||
            !EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), paymentRequest.signature().size(), pubkey)) {

            throw SSLVerifyError("Bad signature, invalid PaymentRequest.");
        }

        // OpenSSL API for getting human printable strings from certs is baroque.
        int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, NULL, 0);
        website = new char[textlen + 1];
        if (X509_NAME_get_text_by_NID(certname, NID_commonName, website, textlen + 1) == textlen && textlen > 0) {
            merchant = website;
        }
        else {
            throw SSLVerifyError("Bad certificate, missing common name");
        }
        // TODO: detect EV certificates and set merchant = business name instead of unfriendly NID_commonName ?
    }
    catch (SSLVerifyError& err)
    {
        fResult = false;
        qDebug() << "PaymentRequestPlus::getMerchant SSL err: " << err.what();
    }

    if (website)
        delete[] website;
    X509_STORE_CTX_free(store_ctx);
    for (unsigned int i = 0; i < certs.size(); i++)
        X509_free(certs[i]);

    return fResult;
}
Esempio n. 20
0
/**
 * Collect X509 objects.
 */
static int meth_destroy(lua_State* L)
{
  X509_free(lsec_checkx509(L, 1));
  return 0;
}
Esempio n. 21
0
File: kloxo.c Progetto: BHWD/kloxo
char* ssl_sock_read(int sock, SSL_CTX *ctx)
{
	int err;
	int verify_client = OFF; /* To verify a client certificate, set ON */
	int pid;
	struct sockaddr_in sa_serv;
	struct sockaddr_in sa_cli;
	size_t client_len;
	char *str;
	char buf[4096];
	SSL *ssl;
	SSL_METHOD *meth;
	X509 *client_cert = NULL;

	/* ----------------------------------------------- */
	/* TCP connection is ready. */
	/* A SSL structure is created */
	ssl = SSL_new(ctx);

	RETURN_NULL(ssl);

	/* Assign the socket into the SSL structure (SSL and socket without BIO) */
	SSL_set_fd(ssl, sock);

	/* Perform SSL Handshake on the SSL server */
	err = SSL_accept(ssl);

	RETURN_SSL(err);

	/* Informational output (optional) */
	//printf("SSL connection using %s\n", SSL_get_cipher (ssl));

	if (verify_client == ON) {
		/* Get the client's certificate (optional) */
		client_cert = SSL_get_peer_certificate(ssl);
		if (client_cert != NULL) {
			//printf ("Client certificate:\n");
			str = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0);
			RETURN_NULL(str);
			//printf ("\t subject: %s\n", str);
			free(str);
			str = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0);
			RETURN_NULL(str);
			//printf ("\t issuer: %s\n", str);
			free(str);
			X509_free(client_cert);
		} else {
			printf("The SSL client does not have certificate.\n");
		}
	}

	/*------- DATA EXCHANGE - Receive message and send reply. -------*/
	/* Receive data from the SSL client */
	/* Send data to the SSL client */

	run_php_prog_ssl(ssl, 0);

	/*--------------- SSL closure ---------------*/
	/* Shutdown this side (server) of the connection. */
	err = SSL_shutdown(ssl);
	RETURN_SSL(err);
	/* Terminate communication on a socket */
	err = close(sock);
	RETURN_ERR(err, "close");
	/* Free the SSL structure */
	//SSL_free(ssl);
	/* Free the SSL_CTX structure */
	//SSL_CTX_free(ctx);
	exit(0);
}
Esempio n. 22
0
/* Read a file that contains our certificate in "PEM" format,
 * possibly followed by a sequence of CA certificates that should be
 * sent to the peer in the Certificate message.
 */
int SSL_CTX_use_certificate_chain_file (SSL_CTX * ctx, const char *file)
{
    BIO *in;

    int ret = 0;

    X509 *x = NULL;

    ERR_clear_error ();            /* clear error stack for SSL_CTX_use_certificate() */

    in = BIO_new (BIO_s_file_internal ());
    if (in == NULL)
    {
        SSLerr (SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
        goto end;
    }

    if (BIO_read_filename (in, file) <= 0)
    {
        SSLerr (SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB);
        goto end;
    }

    x = PEM_read_bio_X509_AUX (in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
    if (x == NULL)
    {
        SSLerr (SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
        goto end;
    }

    ret = SSL_CTX_use_certificate (ctx, x);

    if (ERR_peek_error () != 0)
        ret = 0;                /* Key/certificate mismatch doesn't imply ret==0 ... */
    if (ret)
    {
        /* If we could set up our certificate, now proceed to
         * the CA certificates.
         */
        X509 *ca;

        int r;

        unsigned long err;

        if (ctx->extra_certs != NULL)
        {
            sk_X509_pop_free (ctx->extra_certs, X509_free);
            ctx->extra_certs = NULL;
        }

        while ((ca = PEM_read_bio_X509 (in, NULL,
                                        ctx->default_passwd_callback, ctx->default_passwd_callback_userdata)) != NULL)
        {
            r = SSL_CTX_add_extra_chain_cert (ctx, ca);
            if (!r)
            {
                X509_free (ca);
                ret = 0;
                goto end;
            }
            /* Note that we must not free r if it was successfully
             * added to the chain (while we must free the main
             * certificate, since its reference count is increased
             * by SSL_CTX_use_certificate). */
        }
        /* When the while loop ends, it's usually just EOF. */
        err = ERR_peek_last_error ();
        if (ERR_GET_LIB (err) == ERR_LIB_PEM && ERR_GET_REASON (err) == PEM_R_NO_START_LINE)
            ERR_clear_error ();
        else
            ret = 0;            /* some real error */
    }

  end:
    if (x != NULL)
        X509_free (x);
    if (in != NULL)
        BIO_free (in);
    return (ret);
}
Esempio n. 23
0
/*
 * initialize a new TLS context
 */
static int
tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
{
	tlso_ctx *ctx = (tlso_ctx *)lo->ldo_tls_ctx;
	int i;

	if ( is_server ) {
		SSL_CTX_set_session_id_context( ctx,
			(const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 );
	}

#ifdef SSL_OP_NO_TLSv1
#ifdef SSL_OP_NO_TLSv1_1
#ifdef SSL_OP_NO_TLSv1_2
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_2)
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
			SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 |
			SSL_OP_NO_TLSv1_2 );
	else
#endif
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_1)
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
			SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 );
	else
#endif
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_0)
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
			SSL_OP_NO_TLSv1);
	else
#endif
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 )
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 );
	else if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 )
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 );

	if ( lo->ldo_tls_ciphersuite &&
		!SSL_CTX_set_cipher_list( ctx, lt->lt_ciphersuite ) )
	{
		Debug( LDAP_DEBUG_ANY,
			   "TLS: could not set cipher list %s.\n",
			   lo->ldo_tls_ciphersuite, 0, 0 );
		tlso_report_error();
		return -1;
	}

	if ( lo->ldo_tls_cacertfile == NULL && lo->ldo_tls_cacertdir == NULL &&
		lo->ldo_tls_cacert.bv_val == NULL ) {
		if ( !SSL_CTX_set_default_verify_paths( ctx ) ) {
			Debug( LDAP_DEBUG_ANY, "TLS: "
				"could not use default certificate paths", 0, 0, 0 );
			tlso_report_error();
			return -1;
		}
	} else {
		X509 *cert = NULL;
		if ( lo->ldo_tls_cacert.bv_val ) {
			const unsigned char *pp = lo->ldo_tls_cacert.bv_val;
			cert = d2i_X509( NULL, &pp, lo->ldo_tls_cacert.bv_len );
			X509_STORE *store = SSL_CTX_get_cert_store( ctx );
			if ( !X509_STORE_add_cert( store, cert )) {
				Debug( LDAP_DEBUG_ANY, "TLS: "
					"could not use CA certificate", 0, 0, 0 );
				tlso_report_error();
				return -1;
			}
		}
		if (( lt->lt_cacertfile || lt->lt_cacertdir ) && !SSL_CTX_load_verify_locations( ctx,
				lt->lt_cacertfile, lt->lt_cacertdir ) )
		{
			Debug( LDAP_DEBUG_ANY, "TLS: "
				"could not load verify locations (file:`%s',dir:`%s').\n",
				lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
				lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "",
				0 );
			tlso_report_error();
			return -1;
		}

		if ( is_server ) {
			STACK_OF(X509_NAME) *calist;
			/* List of CA names to send to a client */
			calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir, cert );
			if ( !calist ) {
				Debug( LDAP_DEBUG_ANY, "TLS: "
					"could not load client CA list (file:`%s',dir:`%s').\n",
					lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
					lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "",
					0 );
				tlso_report_error();
				return -1;
			}

			SSL_CTX_set_client_CA_list( ctx, calist );
		}
		if ( cert )
			X509_free( cert );
	}

	if ( lo->ldo_tls_cert.bv_val )
	{
		const unsigned char *pp = lo->ldo_tls_cert.bv_val;
		X509 *cert = d2i_X509( NULL, &pp, lo->ldo_tls_cert.bv_len );
		if ( !SSL_CTX_use_certificate( ctx, cert )) {
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not use certificate.\n", 0,0,0);
			tlso_report_error();
			return -1;
		}
		X509_free( cert );
	} else
	if ( lo->ldo_tls_certfile &&
		!SSL_CTX_use_certificate_file( ctx,
			lt->lt_certfile, SSL_FILETYPE_PEM ) )
	{
		Debug( LDAP_DEBUG_ANY,
			"TLS: could not use certificate file `%s'.\n",
			lo->ldo_tls_certfile,0,0);
		tlso_report_error();
		return -1;
	}

	/* Key validity is checked automatically if cert has already been set */
	if ( lo->ldo_tls_key.bv_val )
	{
		const unsigned char *pp = lo->ldo_tls_key.bv_val;
		EVP_PKEY *pkey = d2i_AutoPrivateKey( NULL, &pp, lo->ldo_tls_key.bv_len );
		if ( !SSL_CTX_use_PrivateKey( ctx, pkey ))
		{
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not use private key.\n", 0,0,0);
			tlso_report_error();
			return -1;
		}
		EVP_PKEY_free( pkey );
	} else
	if ( lo->ldo_tls_keyfile &&
		!SSL_CTX_use_PrivateKey_file( ctx,
			lt->lt_keyfile, SSL_FILETYPE_PEM ) )
	{
		Debug( LDAP_DEBUG_ANY,
			"TLS: could not use key file `%s'.\n",
			lo->ldo_tls_keyfile,0,0);
		tlso_report_error();
		return -1;
	}

	if ( is_server && lo->ldo_tls_dhfile ) {
		DH *dh;
		BIO *bio;

		if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) {
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not use DH parameters file `%s'.\n",
				lo->ldo_tls_dhfile,0,0);
			tlso_report_error();
			return -1;
		}
		if (!( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) {
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not read DH parameters file `%s'.\n",
				lo->ldo_tls_dhfile,0,0);
			tlso_report_error();
			BIO_free( bio );
			return -1;
		}
		BIO_free( bio );
		SSL_CTX_set_tmp_dh( ctx, dh );
		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE );
		DH_free( dh );
	}

	if ( is_server && lo->ldo_tls_ecname ) {
#ifdef OPENSSL_NO_EC
		Debug( LDAP_DEBUG_ANY,
			"TLS: Elliptic Curves not supported.\n", 0,0,0 );
		return -1;
#else
		EC_KEY *ecdh;

		int nid = OBJ_sn2nid( lt->lt_ecname );
		if ( nid == NID_undef ) {
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not use EC name `%s'.\n",
				lo->ldo_tls_ecname,0,0);
			tlso_report_error();
			return -1;
		}
		ecdh = EC_KEY_new_by_curve_name( nid );
		if ( ecdh == NULL ) {
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not generate key for EC name `%s'.\n",
				lo->ldo_tls_ecname,0,0);
			tlso_report_error();
			return -1;
		}
		SSL_CTX_set_tmp_ecdh( ctx, ecdh );
		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_ECDH_USE );
		EC_KEY_free( ecdh );
#endif
	}

	if ( tlso_opt_trace ) {
		SSL_CTX_set_info_callback( ctx, tlso_info_cb );
	}

	i = SSL_VERIFY_NONE;
	if ( lo->ldo_tls_require_cert ) {
		i = SSL_VERIFY_PEER;
		if ( lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND ||
			 lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD ) {
			i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
		}
	}

	SSL_CTX_set_verify( ctx, i,
		lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_ALLOW ?
		tlso_verify_ok : tlso_verify_cb );
#if OPENSSL_VERSION_NUMBER < 0x10100000
	SSL_CTX_set_tmp_rsa_callback( ctx, tlso_tmp_rsa_cb );
#endif
#ifdef HAVE_OPENSSL_CRL
	if ( lo->ldo_tls_crlcheck ) {
		X509_STORE *x509_s = SSL_CTX_get_cert_store( ctx );
		if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_PEER ) {
			X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK );
		} else if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_ALL ) {
			X509_STORE_set_flags( x509_s, 
					X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL  );
		}
	}
#endif
	return 0;
}
Esempio n. 24
0
/*
 * ChangePasswordPKCS12() returns:
 *   -1  Wrong password
 *    0  Changing password failed for unknown reason
 *    1  Password changed successfully
 */
static int
ChangePasswordPKCS12(HWND hwndDlg)
{
  TCHAR keyfile[MAX_PATH];
  char oldpsw[50];
  char newpsw[50];
  WCHAR oldpsw_unicode[50];
  WCHAR newpsw_unicode[50];
  FILE *fp;

  EVP_PKEY *privkey;
  X509 *cert;
  STACK_OF(X509) *ca = NULL;
  PKCS12 *p12;
  char *alias;

  /* Get filename, old_psw and new_psw from Dialog */
  GetDlgItemText(hwndDlg, ID_TXT_KEYFILE, keyfile, _countof(keyfile) - 1);
  GetDlgItemTextW(hwndDlg, ID_EDT_PASS_CUR, oldpsw_unicode, sizeof(oldpsw_unicode)/2 - 1);
  GetDlgItemTextW(hwndDlg, ID_EDT_PASS_NEW, newpsw_unicode, sizeof(newpsw_unicode)/2 - 1);

  /* Convert Unicode to ASCII (CP850) */
  ConvertUnicode2Ascii(oldpsw_unicode, oldpsw, sizeof(oldpsw));
  if (!ConvertUnicode2Ascii(newpsw_unicode, newpsw, sizeof(newpsw)))
    {
      ShowLocalizedMsg(IDS_ERR_INVALID_CHARS_IN_PSW);
      return(-1);
    }

  /* Load the PKCS #12 file */
  if (!(fp = _tfopen(keyfile, _T("rb"))))
    {
      /* error opening file */
      ShowLocalizedMsg(IDS_ERR_OPEN_PRIVATE_KEY_FILE, keyfile);
      return(0);
    }
  p12 = d2i_PKCS12_fp(fp, NULL);
  fclose (fp);
  if (!p12)
    {
      /* error reading PKCS #12 */
      ShowLocalizedMsg(IDS_ERR_READ_PKCS12, keyfile);
      return(0);
    }

  /* Parse the PKCS #12 file */
  if (!PKCS12_parse(p12, oldpsw, &privkey, &cert, &ca))
    {
      /* old password incorrect */
      ShowLocalizedMsg(IDS_ERR_OLD_PWD_INCORRECT);
      PKCS12_free(p12);
      return(-1);
    }

  /* Free old PKCS12 object */
  PKCS12_free(p12);

  /* Get FriendlyName of old cert */
  alias = (char*) X509_alias_get0(cert, NULL);

  /* Create new PKCS12 object */
  p12 = PKCS12_create(newpsw, alias, privkey, cert, ca, 0,0,0,0,0);
  if (!p12)
    {
      /* create failed */
      ShowLocalizedMsg(IDS_ERR_CREATE_PKCS12);
      return(0);
    }

  /* Free old key, cert and ca */
  EVP_PKEY_free(privkey);
  X509_free(cert);
  sk_X509_pop_free(ca, X509_free);

  /* Open keyfile for writing */
  if (!(fp = _tfopen(keyfile, _T("wb"))))
    {
      ShowLocalizedMsg(IDS_ERR_OPEN_WRITE_KEY, keyfile);
      PKCS12_free(p12);
      return(0);
    }

  /* Write new key to file */
  i2d_PKCS12_fp(fp, p12);

  PKCS12_free(p12);
  fclose(fp);
  /* signal success to user */
  ShowLocalizedMsg(IDS_NFO_PWD_CHANGED);

  return(1);
}
Esempio n. 25
0
/* read the data and then respond */
static int client_certificate(SSL *s)
{
    unsigned char *buf;
    unsigned char *p, *d;
    int i;
    unsigned int n;
    int cert_ch_len;
    unsigned char *cert_ch;

    buf = (unsigned char *)s->init_buf->data;

    /*
     * We have a cert associated with the SSL, so attach it to the session if
     * it does not have one
     */

    if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_A) {
        i = ssl2_read(s, (char *)&(buf[s->init_num]),
                      SSL2_MAX_CERT_CHALLENGE_LENGTH + 2 - s->init_num);
        if (i < (SSL2_MIN_CERT_CHALLENGE_LENGTH + 2 - s->init_num))
            return (ssl2_part_read(s, SSL_F_CLIENT_CERTIFICATE, i));
        s->init_num += i;
        if (s->msg_callback) {
            /* REQUEST-CERTIFICATE */
            s->msg_callback(0, s->version, 0, buf, (size_t)s->init_num, s,
                            s->msg_callback_arg);
        }

        /* type=buf[0]; */
        /* type eq x509 */
        if (buf[1] != SSL2_AT_MD5_WITH_RSA_ENCRYPTION) {
            ssl2_return_error(s, SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE);
            SSLerr(SSL_F_CLIENT_CERTIFICATE, SSL_R_BAD_AUTHENTICATION_TYPE);
            return (-1);
        }

        if ((s->cert == NULL) ||
            (s->cert->key->x509 == NULL) ||
            (s->cert->key->privatekey == NULL)) {
            s->state = SSL2_ST_X509_GET_CLIENT_CERTIFICATE;
        } else
            s->state = SSL2_ST_SEND_CLIENT_CERTIFICATE_C;
    }

    cert_ch = buf + 2;
    cert_ch_len = s->init_num - 2;

    if (s->state == SSL2_ST_X509_GET_CLIENT_CERTIFICATE) {
        X509 *x509 = NULL;
        EVP_PKEY *pkey = NULL;

        /*
         * If we get an error we need to ssl->rwstate=SSL_X509_LOOKUP;
         * return(error); We should then be retried when things are ok and we
         * can get a cert or not
         */

        i = 0;
        if (s->ctx->client_cert_cb != NULL) {
            i = s->ctx->client_cert_cb(s, &(x509), &(pkey));
        }

        if (i < 0) {
            s->rwstate = SSL_X509_LOOKUP;
            return (-1);
        }
        s->rwstate = SSL_NOTHING;

        if ((i == 1) && (pkey != NULL) && (x509 != NULL)) {
            s->state = SSL2_ST_SEND_CLIENT_CERTIFICATE_C;
            if (!SSL_use_certificate(s, x509) || !SSL_use_PrivateKey(s, pkey)) {
                i = 0;
            }
            X509_free(x509);
            EVP_PKEY_free(pkey);
        } else if (i == 1) {
            if (x509 != NULL)
                X509_free(x509);
            if (pkey != NULL)
                EVP_PKEY_free(pkey);
            SSLerr(SSL_F_CLIENT_CERTIFICATE,
                   SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
            i = 0;
        }

        if (i == 0) {
            /*
             * We have no client certificate to respond with so send the
             * correct error message back
             */
            s->state = SSL2_ST_SEND_CLIENT_CERTIFICATE_B;
            p = buf;
            *(p++) = SSL2_MT_ERROR;
            s2n(SSL2_PE_NO_CERTIFICATE, p);
            s->init_off = 0;
            s->init_num = 3;
            /* Write is done at the end */
        }
    }

    if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_B) {
        return (ssl2_do_write(s));
    }

    if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_C) {
        EVP_MD_CTX ctx;

        /*
         * ok, now we calculate the checksum do it first so we can reuse buf
         * :-)
         */
        p = buf;
        EVP_MD_CTX_init(&ctx);
        EVP_SignInit_ex(&ctx, s->ctx->rsa_md5, NULL);
        EVP_SignUpdate(&ctx, s->s2->key_material, s->s2->key_material_length);
        EVP_SignUpdate(&ctx, cert_ch, (unsigned int)cert_ch_len);
        i = i2d_X509(s->session->sess_cert->peer_key->x509, &p);
        /*
         * Don't update the signature if it fails - FIXME: probably should
         * handle this better
         */
        if (i > 0)
            EVP_SignUpdate(&ctx, buf, (unsigned int)i);

        p = buf;
        d = p + 6;
        *(p++) = SSL2_MT_CLIENT_CERTIFICATE;
        *(p++) = SSL2_CT_X509_CERTIFICATE;
        n = i2d_X509(s->cert->key->x509, &d);
        s2n(n, p);

        if (!EVP_SignFinal(&ctx, d, &n, s->cert->key->privatekey)) {
            /*
             * this is not good.  If things have failed it means there so
             * something wrong with the key. We will continue with a 0 length
             * signature
             */
        }
        EVP_MD_CTX_cleanup(&ctx);
        s2n(n, p);
        d += n;

        s->state = SSL2_ST_SEND_CLIENT_CERTIFICATE_D;
        s->init_num = d - buf;
        s->init_off = 0;
    }
    /* if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_D) */
    return (ssl2_do_write(s));
}
Esempio n. 26
0
void pki_embassy_free(embassy_t *embassy)
{
	X509_free(embassy->certificate);
	EVP_PKEY_free(embassy->keyring);
	free(embassy);
}
Esempio n. 27
0
int smime_main(int argc, char **argv)
{
    BIO *in = NULL, *out = NULL, *indata = NULL;
    EVP_PKEY *key = NULL;
    PKCS7 *p7 = NULL;
    STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
    STACK_OF(X509) *encerts = NULL, *other = NULL;
    X509 *cert = NULL, *recip = NULL, *signer = NULL;
    X509_STORE *store = NULL;
    X509_VERIFY_PARAM *vpm = NULL;
    const EVP_CIPHER *cipher = NULL;
    const EVP_MD *sign_md = NULL;
    char *CAfile = NULL, *CApath = NULL, *inrand = NULL;
    char *certfile = NULL, *keyfile = NULL, *contfile = NULL, *prog;
    char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile =
        NULL;
    char *passinarg = NULL, *passin = NULL, *to = NULL, *from =
        NULL, *subject = NULL;
    OPTION_CHOICE o;
    int noCApath = 0, noCAfile = 0;
    int flags = PKCS7_DETACHED, operation = 0, ret = 0, need_rand = 0, indef =
        0;
    int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform =
        FORMAT_PEM;
    int vpmtouched = 0, rv = 0;
    ENGINE *e = NULL;
    const char *mime_eol = "\n";

    if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
        return 1;

    prog = opt_init(argc, argv, smime_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(smime_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENCRYPT:
            operation = SMIME_ENCRYPT;
            break;
        case OPT_DECRYPT:
            operation = SMIME_DECRYPT;
            break;
        case OPT_SIGN:
            operation = SMIME_SIGN;
            break;
        case OPT_RESIGN:
            operation = SMIME_RESIGN;
            break;
        case OPT_VERIFY:
            operation = SMIME_VERIFY;
            break;
        case OPT_PK7OUT:
            operation = SMIME_PK7OUT;
            break;
        case OPT_TEXT:
            flags |= PKCS7_TEXT;
            break;
        case OPT_NOINTERN:
            flags |= PKCS7_NOINTERN;
            break;
        case OPT_NOVERIFY:
            flags |= PKCS7_NOVERIFY;
            break;
        case OPT_NOCHAIN:
            flags |= PKCS7_NOCHAIN;
            break;
        case OPT_NOCERTS:
            flags |= PKCS7_NOCERTS;
            break;
        case OPT_NOATTR:
            flags |= PKCS7_NOATTR;
            break;
        case OPT_NODETACH:
            flags &= ~PKCS7_DETACHED;
            break;
        case OPT_NOSMIMECAP:
            flags |= PKCS7_NOSMIMECAP;
            break;
        case OPT_BINARY:
            flags |= PKCS7_BINARY;
            break;
        case OPT_NOSIGS:
            flags |= PKCS7_NOSIGS;
            break;
        case OPT_STREAM:
        case OPT_INDEF:
            indef = 1;
            break;
        case OPT_NOINDEF:
            indef = 0;
            break;
        case OPT_NOOLDMIME:
            flags |= PKCS7_NOOLDMIMETYPE;
            break;
        case OPT_CRLFEOL:
            flags |= PKCS7_CRLFEOL;
            mime_eol = "\r\n";
            break;
        case OPT_RAND:
            inrand = opt_arg();
            need_rand = 1;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_TO:
            to = opt_arg();
            break;
        case OPT_FROM:
            from = opt_arg();
            break;
        case OPT_SUBJECT:
            subject = opt_arg();
            break;
        case OPT_SIGNER:
            /* If previous -signer argument add signer to list */
            if (signerfile) {
                if (sksigners == NULL
                    && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                if (keyfile == NULL)
                    keyfile = signerfile;
                if (skkeys == NULL
                    && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(skkeys, keyfile);
                keyfile = NULL;
            }
            signerfile = opt_arg();
            break;
        case OPT_RECIP:
            recipfile = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_arg(), &sign_md))
                goto opthelp;
            break;
        case OPT_CIPHER:
            if (!opt_cipher(opt_unknown(), &cipher))
                goto opthelp;
            break;
        case OPT_INKEY:
            /* If previous -inkey arument add signer to list */
            if (keyfile) {
                if (signerfile == NULL) {
                    BIO_printf(bio_err,
                               "%s: Must have -signer before -inkey\n", prog);
                    goto opthelp;
                }
                if (sksigners == NULL
                    && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                signerfile = NULL;
                if (skkeys == NULL
                    && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(skkeys, keyfile);
            }
            keyfile = opt_arg();
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
                goto opthelp;
            break;
        case OPT_CERTFILE:
            certfile = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_CONTENT:
            contfile = opt_arg();
            break;
        case OPT_V_CASES:
            if (!opt_verify(o, vpm))
                goto opthelp;
            vpmtouched++;
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) {
        BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
        goto opthelp;
    }

    if (operation & SMIME_SIGNERS) {
        /* Check to see if any final signer needs to be appended */
        if (keyfile && !signerfile) {
            BIO_puts(bio_err, "Illegal -inkey without -signer\n");
            goto opthelp;
        }
        if (signerfile) {
            if (!sksigners
                && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(sksigners, signerfile);
            if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            if (!keyfile)
                keyfile = signerfile;
            sk_OPENSSL_STRING_push(skkeys, keyfile);
        }
        if (!sksigners) {
            BIO_printf(bio_err, "No signer certificate specified\n");
            goto opthelp;
        }
        signerfile = NULL;
        keyfile = NULL;
        need_rand = 1;
    } else if (operation == SMIME_DECRYPT) {
        if (!recipfile && !keyfile) {
            BIO_printf(bio_err,
                       "No recipient certificate or key specified\n");
            goto opthelp;
        }
    } else if (operation == SMIME_ENCRYPT) {
        if (argc == 0) {
            BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
            goto opthelp;
        }
        need_rand = 1;
    } else if (!operation)
        goto opthelp;

    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (need_rand) {
        app_RAND_load_file(NULL, (inrand != NULL));
        if (inrand != NULL)
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(inrand));
    }

    ret = 2;

    if (!(operation & SMIME_SIGNERS))
        flags &= ~PKCS7_DETACHED;

    if (!(operation & SMIME_OP)) {
        if (flags & PKCS7_BINARY)
            outformat = FORMAT_BINARY;
    }

    if (!(operation & SMIME_IP)) {
        if (flags & PKCS7_BINARY)
            informat = FORMAT_BINARY;
    }

    if (operation == SMIME_ENCRYPT) {
        if (!cipher) {
#ifndef OPENSSL_NO_DES
            cipher = EVP_des_ede3_cbc();
#else
            BIO_printf(bio_err, "No cipher selected\n");
            goto end;
#endif
        }
        encerts = sk_X509_new_null();
        if (!encerts)
            goto end;
        while (*argv) {
            cert = load_cert(*argv, FORMAT_PEM,
                             "recipient certificate file");
            if (cert == NULL)
                goto end;
            sk_X509_push(encerts, cert);
            cert = NULL;
            argv++;
        }
    }

    if (certfile) {
        if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
                        "certificate file")) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (recipfile && (operation == SMIME_DECRYPT)) {
        if ((recip = load_cert(recipfile, FORMAT_PEM,
                               "recipient certificate file")) == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (operation == SMIME_DECRYPT) {
        if (!keyfile)
            keyfile = recipfile;
    } else if (operation == SMIME_SIGN) {
        if (!keyfile)
            keyfile = signerfile;
    } else
        keyfile = NULL;

    if (keyfile) {
        key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
        if (!key)
            goto end;
    }

    in = bio_open_default(infile, 'r', informat);
    if (in == NULL)
        goto end;

    if (operation & SMIME_IP) {
        if (informat == FORMAT_SMIME)
            p7 = SMIME_read_PKCS7(in, &indata);
        else if (informat == FORMAT_PEM)
            p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
        else if (informat == FORMAT_ASN1)
            p7 = d2i_PKCS7_bio(in, NULL);
        else {
            BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
            goto end;
        }

        if (!p7) {
            BIO_printf(bio_err, "Error reading S/MIME message\n");
            goto end;
        }
        if (contfile) {
            BIO_free(indata);
            if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
                BIO_printf(bio_err, "Can't read content file %s\n", contfile);
                goto end;
            }
        }
    }

    out = bio_open_default(outfile, 'w', outformat);
    if (out == NULL)
        goto end;

    if (operation == SMIME_VERIFY) {
        if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
            goto end;
        X509_STORE_set_verify_cb(store, smime_cb);
        if (vpmtouched)
            X509_STORE_set1_param(store, vpm);
    }

    ret = 3;

    if (operation == SMIME_ENCRYPT) {
        if (indef)
            flags |= PKCS7_STREAM;
        p7 = PKCS7_encrypt(encerts, in, cipher, flags);
    } else if (operation & SMIME_SIGNERS) {
        int i;
        /*
         * If detached data content we only enable streaming if S/MIME output
         * format.
         */
        if (operation == SMIME_SIGN) {
            if (flags & PKCS7_DETACHED) {
                if (outformat == FORMAT_SMIME)
                    flags |= PKCS7_STREAM;
            } else if (indef)
                flags |= PKCS7_STREAM;
            flags |= PKCS7_PARTIAL;
            p7 = PKCS7_sign(NULL, NULL, other, in, flags);
            if (!p7)
                goto end;
            if (flags & PKCS7_NOCERTS) {
                for (i = 0; i < sk_X509_num(other); i++) {
                    X509 *x = sk_X509_value(other, i);
                    PKCS7_add_certificate(p7, x);
                }
            }
        } else
            flags |= PKCS7_REUSE_DIGEST;
        for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
            signerfile = sk_OPENSSL_STRING_value(sksigners, i);
            keyfile = sk_OPENSSL_STRING_value(skkeys, i);
            signer = load_cert(signerfile, FORMAT_PEM,
                               "signer certificate");
            if (!signer)
                goto end;
            key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
            if (!key)
                goto end;
            if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags))
                goto end;
            X509_free(signer);
            signer = NULL;
            EVP_PKEY_free(key);
            key = NULL;
        }
        /* If not streaming or resigning finalize structure */
        if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) {
            if (!PKCS7_final(p7, in, flags))
                goto end;
        }
    }

    if (!p7) {
        BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
        goto end;
    }

    ret = 4;
    if (operation == SMIME_DECRYPT) {
        if (!PKCS7_decrypt(p7, key, recip, out, flags)) {
            BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
            goto end;
        }
    } else if (operation == SMIME_VERIFY) {
        STACK_OF(X509) *signers;
        if (PKCS7_verify(p7, other, store, indata, out, flags))
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            goto end;
        }
        signers = PKCS7_get0_signers(p7, other, flags);
        if (!save_certs(signerfile, signers)) {
            BIO_printf(bio_err, "Error writing signers to %s\n", signerfile);
            ret = 5;
            goto end;
        }
        sk_X509_free(signers);
    } else if (operation == SMIME_PK7OUT)
        PEM_write_bio_PKCS7(out, p7);
    else {
        if (to)
            BIO_printf(out, "To: %s%s", to, mime_eol);
        if (from)
            BIO_printf(out, "From: %s%s", from, mime_eol);
        if (subject)
            BIO_printf(out, "Subject: %s%s", subject, mime_eol);
        if (outformat == FORMAT_SMIME) {
            if (operation == SMIME_RESIGN)
                rv = SMIME_write_PKCS7(out, p7, indata, flags);
            else
                rv = SMIME_write_PKCS7(out, p7, in, flags);
        } else if (outformat == FORMAT_PEM)
            rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags);
        else if (outformat == FORMAT_ASN1)
            rv = i2d_PKCS7_bio_stream(out, p7, in, flags);
        else {
            BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
            goto end;
        }
        if (rv == 0) {
            BIO_printf(bio_err, "Error writing output\n");
            ret = 3;
            goto end;
        }
    }
    ret = 0;
 end:
    if (need_rand)
        app_RAND_write_file(NULL);
    if (ret)
        ERR_print_errors(bio_err);
    sk_X509_pop_free(encerts, X509_free);
    sk_X509_pop_free(other, X509_free);
    X509_VERIFY_PARAM_free(vpm);
    sk_OPENSSL_STRING_free(sksigners);
    sk_OPENSSL_STRING_free(skkeys);
    X509_STORE_free(store);
    X509_free(cert);
    X509_free(recip);
    X509_free(signer);
    EVP_PKEY_free(key);
    PKCS7_free(p7);
    BIO_free(in);
    BIO_free(indata);
    BIO_free_all(out);
    OPENSSL_free(passin);
    return (ret);
}
unsigned long dtls1_output_cert_chain(SSL *s, X509 *x)
	{
	unsigned char *p;
	int n,i;
	unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH;
	BUF_MEM *buf;
	X509_STORE_CTX xs_ctx;
	X509_OBJECT obj;

	/* TLSv1 sends a chain with nothing in it, instead of an alert */
	buf=s->init_buf;
	if (!BUF_MEM_grow_clean(buf,10))
		{
		SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
		return(0);
		}
	if (x != NULL)
		{
		if(!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL))
			{
			SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
			return(0);
			}

		for (;;)
			{
			n=i2d_X509(x,NULL);
			if (!BUF_MEM_grow_clean(buf,(int)(n+l+3)))
				{
				SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
				return(0);
				}
			p=(unsigned char *)&(buf->data[l]);
			l2n3(n,p);
			i2d_X509(x,&p);
			l+=n+3;
			if (X509_NAME_cmp(X509_get_subject_name(x),
				X509_get_issuer_name(x)) == 0) break;

			i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509,
				X509_get_issuer_name(x),&obj);
			if (i <= 0) break;
			x=obj.data.x509;
			/* Count is one too high since the X509_STORE_get uped the
			 * ref count */
			X509_free(x);
			}

		X509_STORE_CTX_cleanup(&xs_ctx);
		}

	/* Thawte special :-) */
	if (s->ctx->extra_certs != NULL)
	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
		{
		x=sk_X509_value(s->ctx->extra_certs,i);
		n=i2d_X509(x,NULL);
		if (!BUF_MEM_grow_clean(buf,(int)(n+l+3)))
			{
			SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
			return(0);
			}
		p=(unsigned char *)&(buf->data[l]);
		l2n3(n,p);
		i2d_X509(x,&p);
		l+=n+3;
		}

	l-= (3 + DTLS1_HM_HEADER_LENGTH);

	p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]);
	l2n3(l,p);
	l+=3;
	p=(unsigned char *)&(buf->data[0]);
	p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l);

	l+=DTLS1_HM_HEADER_LENGTH;
	return(l);
	}
Esempio n. 29
0
static void tls_free_certificate(CryptoCert cert)
{
	X509_free(cert->px509);
	free(cert);
}
Esempio n. 30
0
CERT *
ssl_cert_dup(CERT *cert)
{
	CERT *ret;
	int i;

	ret = calloc(1, sizeof(CERT));
	if (ret == NULL) {
		SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
		return (NULL);
	}

	/*
	 * same as ret->key = ret->pkeys + (cert->key - cert->pkeys),
	 * if you find that more readable
	 */
	ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];

	ret->valid = cert->valid;
	ret->mask_k = cert->mask_k;
	ret->mask_a = cert->mask_a;

	if (cert->rsa_tmp != NULL) {
		RSA_up_ref(cert->rsa_tmp);
		ret->rsa_tmp = cert->rsa_tmp;
	}
	ret->rsa_tmp_cb = cert->rsa_tmp_cb;

	if (cert->dh_tmp != NULL) {
		ret->dh_tmp = DHparams_dup(cert->dh_tmp);
		if (ret->dh_tmp == NULL) {
			SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB);
			goto err;
		}
		if (cert->dh_tmp->priv_key) {
			BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
			if (!b) {
				SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
				goto err;
			}
			ret->dh_tmp->priv_key = b;
		}
		if (cert->dh_tmp->pub_key) {
			BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
			if (!b) {
				SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
				goto err;
			}
			ret->dh_tmp->pub_key = b;
		}
	}
	ret->dh_tmp_cb = cert->dh_tmp_cb;

	if (cert->ecdh_tmp) {
		ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
		if (ret->ecdh_tmp == NULL) {
			SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB);
			goto err;
		}
	}
	ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
	ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;

	for (i = 0; i < SSL_PKEY_NUM; i++) {
		if (cert->pkeys[i].x509 != NULL) {
			ret->pkeys[i].x509 = cert->pkeys[i].x509;
			CRYPTO_add(&ret->pkeys[i].x509->references, 1,
			CRYPTO_LOCK_X509);
		}

		if (cert->pkeys[i].privatekey != NULL) {
			ret->pkeys[i].privatekey = cert->pkeys[i].privatekey;
			CRYPTO_add(&ret->pkeys[i].privatekey->references, 1,
			CRYPTO_LOCK_EVP_PKEY);

			switch (i) {
				/*
				 * If there was anything special to do for
				 * certain types of keys, we'd do it here.
				 * (Nothing at the moment, I think.)
				 */

			case SSL_PKEY_RSA_ENC:
			case SSL_PKEY_RSA_SIGN:
				/* We have an RSA key. */
				break;

			case SSL_PKEY_DSA_SIGN:
				/* We have a DSA key. */
				break;

			case SSL_PKEY_DH_RSA:
			case SSL_PKEY_DH_DSA:
				/* We have a DH key. */
				break;

			case SSL_PKEY_ECC:
				/* We have an ECC key */
				break;

			default:
				/* Can't happen. */
				SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG);
			}
		}
	}

	/*
	 * ret->extra_certs *should* exist, but currently the own certificate
	 * chain is held inside SSL_CTX
	 */

	ret->references = 1;
	/*
	 * Set digests to defaults. NB: we don't copy existing values
	 * as they will be set during handshake.
	 */
	ssl_cert_set_default_md(ret);

	return (ret);

err:
	RSA_free(ret->rsa_tmp);
	DH_free(ret->dh_tmp);
	EC_KEY_free(ret->ecdh_tmp);

	for (i = 0; i < SSL_PKEY_NUM; i++) {
		if (ret->pkeys[i].x509 != NULL)
			X509_free(ret->pkeys[i].x509);
		EVP_PKEY_free(ret->pkeys[i].privatekey);
	}
	free (ret);
	return NULL;
}