Esempio n. 1
0
static int cert_check(CLI *c, X509_STORE_CTX *callback_ctx, int preverify_ok) {
    X509_OBJECT obj;
    ASN1_BIT_STRING *local_key, *peer_key;

    if(c->opt->verify_level==SSL_VERIFY_NONE) {
        s_log(LOG_INFO, "CERT: Verification not enabled");
        return 1; /* accept connection */
    }
    if(!preverify_ok) {
        /* remote site specified a certificate, but it's not correct */
        s_log(LOG_WARNING, "CERT: Verification error: %s",
            X509_verify_cert_error_string(callback_ctx->error));
        return 0; /* reject connection */
    }
    if(c->opt->verify_use_only_my && callback_ctx->error_depth==0) {
        if(X509_STORE_get_by_subject(callback_ctx, X509_LU_X509,
                X509_get_subject_name(callback_ctx->current_cert), &obj)!=1) {
            s_log(LOG_WARNING, "CERT: Certificate not found in local repository");
            return 0; /* reject connection */
        }
        peer_key=X509_get0_pubkey_bitstr(callback_ctx->current_cert);
        local_key=X509_get0_pubkey_bitstr(obj.data.x509);
        if(!peer_key || !local_key || peer_key->length!=local_key->length ||
                memcmp(peer_key->data, local_key->data, local_key->length)) {
            s_log(LOG_WARNING, "CERT: Public keys do not match");
            return 0; /* reject connection */
        }
    }
    return 1; /* accept connection */
}
Esempio n. 2
0
NOEXPORT int cert_check_local(X509_STORE_CTX *callback_ctx) {
    X509 *cert=X509_STORE_CTX_get_current_cert(callback_ctx);
    X509_OBJECT obj;
#if OPENSSL_VERSION_NUMBER>=0x10000000L
    STACK_OF(X509) *sk;
    int i;

    sk=X509_STORE_get1_certs(callback_ctx, X509_get_subject_name(cert));
    if(sk) {
        for(i=0; i<sk_X509_num(sk); i++)
            if(compare_pubkeys(cert, sk_X509_value(sk, i))) {
                sk_X509_pop_free(sk, X509_free);
                return 1; /* accept */
            }
        sk_X509_pop_free(sk, X509_free);
    }
#endif
    /* pre-1.0.0 API only returns a single matching certificate */
    if(X509_STORE_get_by_subject(callback_ctx, X509_LU_X509,
            X509_get_subject_name(cert), &obj)==1 &&
            compare_pubkeys(cert, obj.data.x509))
        return 1; /* accept */
    s_log(LOG_WARNING,
        "CERT: Certificate not found in local repository");
    X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CERT_REJECTED);
    return 0; /* reject */
}
Esempio n. 3
0
int SSL_X509_STORE_lookup(X509_STORE *pStore, int nType,
                          X509_NAME *pName, X509_OBJECT *pObj)
{
    X509_STORE_CTX pStoreCtx;
    int rc;

    X509_STORE_CTX_init(&pStoreCtx, pStore, NULL, NULL);
    rc = X509_STORE_get_by_subject(&pStoreCtx, nType, pName, pObj);
    X509_STORE_CTX_cleanup(&pStoreCtx);
    return rc;
}
Esempio n. 4
0
/**
 * Check the transmitted client certs and a compare with client cert database
 */
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
  char subject[STRLEN];
  X509_OBJECT found_cert;

  X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), subject, STRLEN-1);

  if (!preverify_ok && !check_preverify(ctx))
    return 0;

  if (ctx->error_depth == 0 && X509_STORE_get_by_subject(ctx, X509_LU_X509, X509_get_subject_name(ctx->current_cert), &found_cert) != 1) {
    LogError("%s: SSL connection rejected. No matching certificate found -- %s\n", prog, SSLERROR);
    return 0;
  }

  return 1; 
}
Esempio n. 5
0
X509_OBJECT *X509_STORE_get_X509_by_subject(X509_STORE_CTX *vs, int type,
                                                  X509_NAME *name)
{
    X509_OBJECT *ret;

    ret = OPENSSL_malloc(sizeof (*ret));
    if (ret == NULL) {
        X509err(X509_F_X509_STORE_GET_X509_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
        return NULL;
    }
    if (!X509_STORE_get_by_subject(vs, type, name, ret)) {
        OPENSSL_free(ret);
        return NULL;
    }
    return ret;
}
Esempio n. 6
0
static int cert_check(CLI *c, X509_STORE_CTX *callback_ctx, int preverify_ok) {
    X509_OBJECT obj;
#if OPENSSL_VERSION_NUMBER>=0x0090700fL
    ASN1_BIT_STRING *local_key, *peer_key;
#endif
    X509 *cert;
    int depth;

    if(c->opt->verify_level<1) {
        s_log(LOG_INFO, "CERT: Verification not enabled");
        return 1; /* accept connection */
    }
    cert=X509_STORE_CTX_get_current_cert(callback_ctx);
    depth=X509_STORE_CTX_get_error_depth(callback_ctx);
    if(!preverify_ok) {
        /* remote site specified a certificate, but it's not correct */
        if(c->opt->verify_level>=4 && depth>0) {
            s_log(LOG_INFO, "CERT: Invalid CA certificate ignored");
            return 1; /* accept connection */
        } else {
            s_log(LOG_WARNING, "CERT: Verification error: %s",
                X509_verify_cert_error_string(
                    X509_STORE_CTX_get_error(callback_ctx)));
            return 0; /* reject connection */
        }
    }
    if(c->opt->verify_level>=3 && depth==0) {
        if(X509_STORE_get_by_subject(callback_ctx, X509_LU_X509,
                X509_get_subject_name(cert), &obj)!=1) {
            s_log(LOG_WARNING,
                "CERT: Certificate not found in local repository");
            return 0; /* reject connection */
        }
#if OPENSSL_VERSION_NUMBER>=0x0090700fL
        peer_key=X509_get0_pubkey_bitstr(cert);
        local_key=X509_get0_pubkey_bitstr(obj.data.x509);
        if(!peer_key || !local_key || peer_key->length!=local_key->length ||
                memcmp(peer_key->data, local_key->data, local_key->length)) {
            s_log(LOG_WARNING, "CERT: Public keys do not match");
            return 0; /* reject connection */
        }
#endif
        s_log(LOG_INFO, "CERT: Locally installed certificate matched");
    }
    return 1; /* accept connection */
}
Esempio n. 7
0
/*****************************************************************************
 *
 * Low-level x509 functions
 *
 *****************************************************************************/
static int
xmlSecOpenSSLX509VerifyCRL(X509_STORE* xst, X509_CRL *crl ) {
    X509_STORE_CTX xsc;
    X509_OBJECT xobj;
    EVP_PKEY *pkey;
    int ret;

    xmlSecAssert2(xst != NULL, -1);
    xmlSecAssert2(crl != NULL, -1);

    X509_STORE_CTX_init(&xsc, xst, NULL, NULL);
    ret = X509_STORE_get_by_subject(&xsc, X509_LU_X509,
                                    X509_CRL_get_issuer(crl), &xobj);
    if(ret <= 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    NULL,
                    "X509_STORE_get_by_subject",
                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
                    XMLSEC_ERRORS_NO_MESSAGE);
        return(-1);
    }
    pkey = X509_get_pubkey(xobj.data.x509);
    X509_OBJECT_free_contents(&xobj);
    if(pkey == NULL) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    NULL,
                    "X509_get_pubkey",
                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
                    XMLSEC_ERRORS_NO_MESSAGE);
        return(-1);
    }
    ret = X509_CRL_verify(crl, pkey);
    EVP_PKEY_free(pkey);
    if(ret != 1) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    NULL,
                    "X509_CRL_verify",
                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
                    XMLSEC_ERRORS_NO_MESSAGE);
    }
    X509_STORE_CTX_cleanup (&xsc);
    return((ret == 1) ? 1 : 0);
}
Esempio n. 8
0
static int cert_check(CLI *c, X509_STORE_CTX *callback_ctx, int preverify_ok) {
    X509_OBJECT ret;

    if(c->opt->verify_level==SSL_VERIFY_NONE) {
        s_log(LOG_INFO, "CERT: Verification not enabled");
        return 1; /* accept connection */
    }
    if(!preverify_ok) {
        /* remote site specified a certificate, but it's not correct */
        s_log(LOG_WARNING, "CERT: Verification error: %s",
            X509_verify_cert_error_string(callback_ctx->error));
        return 0; /* reject connection */
    }
    if(c->opt->verify_use_only_my && callback_ctx->error_depth==0 &&
            X509_STORE_get_by_subject(callback_ctx, X509_LU_X509,
                X509_get_subject_name(callback_ctx->current_cert), &ret)!=1) {
        s_log(LOG_WARNING, "CERT: Certificate not found in local repository");
        return 0; /* reject connection */
    }
    return 1; /* accept connection */
}
Esempio n. 9
0
/**
 * Check the transmitted client certs and a compare with client cert database
 */
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {

    char subject[STRLEN];
    X509_OBJECT found_cert;

    /* RATS: ignore */ /* buffer size is limited by STRLEN */
    X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), subject,
                      STRLEN-1);

    if(!preverify_ok) {

        if (!check_preverify(ctx)) {

            goto reject;

        }

    }

    if(ctx->error_depth==0 &&
            X509_STORE_get_by_subject(ctx, X509_LU_X509,
                                      X509_get_subject_name(ctx->current_cert),
                                      &found_cert)!=1) {

        handle_ssl_error("verify_callback()");
        log("%s: verify_callback(): SSL connection rejected. No matching "
            "certificate found.", prog);

        goto reject;

    }

    return 1;

reject:
    return 0;

}
int MAIN(int argc, char **argv)
{
    X509_CRL *x=NULL;
    char *CAfile = NULL, *CApath = NULL;
    int ret=1,i,num,badops=0;
    BIO *out=NULL;
    int informat,outformat;
    char *infile=NULL,*outfile=NULL;
    int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0;
    int fingerprint = 0;
    char **pp,buf[256];
    X509_STORE *store = NULL;
    X509_STORE_CTX ctx;
    X509_LOOKUP *lookup = NULL;
    X509_OBJECT xobj;
    EVP_PKEY *pkey;
    int do_ver = 0;
    const EVP_MD *md_alg,*digest=EVP_md5();

    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 (bio_out == NULL)
        if ((bio_out=BIO_new(BIO_s_file())) != NULL)
        {
            BIO_set_fp(bio_out,stdout,BIO_NOCLOSE);
#ifdef VMS
            {
                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
                bio_out = BIO_push(tmpbio, bio_out);
            }
#endif
        }

    informat=FORMAT_PEM;
    outformat=FORMAT_PEM;

    argc--;
    argv++;
    num=0;
    while (argc >= 1)
    {
#ifdef undef
        if	(strcmp(*argv,"-p") == 0)
        {
            if (--argc < 1) goto bad;
            if (!args_from_file(++argv,Nargc,Nargv)) {
                goto end;
            }*/
        }
#endif
        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,"-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,"-CApath") == 0)
        {
            if (--argc < 1) goto bad;
            CApath = *(++argv);
            do_ver = 1;
        }
        else if (strcmp(*argv,"-CAfile") == 0)
        {
            if (--argc < 1) goto bad;
            CAfile = *(++argv);
            do_ver = 1;
        }
        else if (strcmp(*argv,"-verify") == 0)
            do_ver = 1;
        else if (strcmp(*argv,"-text") == 0)
            text = 1;
        else if (strcmp(*argv,"-hash") == 0)
            hash= ++num;
        else if (strcmp(*argv,"-issuer") == 0)
            issuer= ++num;
        else if (strcmp(*argv,"-lastupdate") == 0)
            lastupdate= ++num;
        else if (strcmp(*argv,"-nextupdate") == 0)
            nextupdate= ++num;
        else if (strcmp(*argv,"-noout") == 0)
            noout= ++num;
        else if (strcmp(*argv,"-fingerprint") == 0)
            fingerprint= ++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=crl_usage; (*pp != NULL); pp++)
            BIO_printf(bio_err,*pp);
        goto end;
    }

    ERR_load_crypto_strings();
    x=load_crl(infile,informat);
    if (x == NULL) {
        goto end;
    }

    if(do_ver) {
        store = X509_STORE_new();
        lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
        if (lookup == NULL) goto end;
        if (!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM))
            X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);

        lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
        if (lookup == NULL) goto end;
        if (!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM))
            X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
        ERR_clear_error();

        X509_STORE_CTX_init(&ctx, store, NULL, NULL);

        i = X509_STORE_get_by_subject(&ctx, X509_LU_X509,
                                      X509_CRL_get_issuer(x), &xobj);
        if(i <= 0) {
            BIO_printf(bio_err,
                       "Error getting CRL issuer certificate\n");
            goto end;
        }
        pkey = X509_get_pubkey(xobj.data.x509);
        X509_OBJECT_free_contents(&xobj);
        if(!pkey) {
            BIO_printf(bio_err,
                       "Error getting CRL issuer public key\n");
            goto end;
        }
        i = X509_CRL_verify(x, pkey);
        EVP_PKEY_free(pkey);
        if(i < 0) goto end;
        if(i == 0) BIO_printf(bio_err, "verify failure\n");
        else BIO_printf(bio_err, "verify OK\n");
    }

    if (num)
    {
        for (i=1; i<=num; i++)
        {
            if (issuer == i)
            {
                X509_NAME_oneline(X509_CRL_get_issuer(x),
                                  buf,256);
                BIO_printf(bio_out,"issuer= %s\n",buf);
            }

            if (hash == i)
            {
                BIO_printf(bio_out,"%08lx\n",
                           X509_NAME_hash(X509_CRL_get_issuer(x)));
            }
            if (lastupdate == i)
            {
                BIO_printf(bio_out,"lastUpdate=");
                ASN1_TIME_print(bio_out,
                                X509_CRL_get_lastUpdate(x));
                BIO_printf(bio_out,"\n");
            }
            if (nextupdate == i)
            {
                BIO_printf(bio_out,"nextUpdate=");
                if (X509_CRL_get_nextUpdate(x))
                    ASN1_TIME_print(bio_out,
                                    X509_CRL_get_nextUpdate(x));
                else
                    BIO_printf(bio_out,"NONE");
                BIO_printf(bio_out,"\n");
            }
            if (fingerprint == i)
            {
                int j;
                unsigned int n;
                unsigned char md[EVP_MAX_MD_SIZE];

                if (!X509_CRL_digest(x,digest,md,&n))
                {
                    BIO_printf(bio_err,"out of memory\n");
                    goto end;
                }
                BIO_printf(bio_out,"%s Fingerprint=",
                           OBJ_nid2sn(EVP_MD_type(digest)));
                for (j=0; j<(int)n; j++)
                {
                    BIO_printf(bio_out,"%02X%c",md[j],
                               (j+1 == (int)n)
                               ?'\n':':');
                }
            }
        }
    }

    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);
#ifdef VMS
        {
            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
            out = BIO_push(tmpbio, out);
        }
#endif
    }
    else
    {
        if (BIO_write_filename(out,outfile) <= 0)
        {
            perror(outfile);
            goto end;
        }
    }

    if (text) X509_CRL_print(out, x);

    if (noout) goto end;

    if 	(outformat == FORMAT_ASN1)
        i=(int)i2d_X509_CRL_bio(out,x);
    else if (outformat == FORMAT_PEM)
        i=PEM_write_bio_X509_CRL(out,x);
    else
    {
        BIO_printf(bio_err,"bad output format specified for outfile\n");
        goto end;
    }
    if (!i) {
        BIO_printf(bio_err,"unable to write CRL\n");
        goto end;
    }
    ret=0;
end:
    BIO_free_all(out);
    BIO_free_all(bio_out);
    bio_out=NULL;
    X509_CRL_free(x);
    if(store) {
        X509_STORE_CTX_cleanup(&ctx);
        X509_STORE_free(store);
    }
    EXIT(ret);
}
Esempio n. 11
0
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. 12
0
int crl_main(int argc, char **argv)
{
    X509_CRL *x = NULL;
    BIO *out = NULL;
    X509_STORE *store = NULL;
    X509_STORE_CTX ctx;
    X509_LOOKUP *lookup = NULL;
    X509_OBJECT xobj;
    EVP_PKEY *pkey;
    const EVP_MD *digest = EVP_sha1();
    unsigned long nmflag = 0;
    char nmflag_set = 0;
    char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL;
    char *CAfile = NULL, *CApath = NULL, *prog;
    OPTION_CHOICE o;
    int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0;
    int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
    int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0;
    int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0;
    int i;
#ifndef OPENSSL_NO_MD5
    int hash_old = 0;
#endif

    prog = opt_init(argc, argv, crl_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(crl_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
                goto opthelp;
            break;
        case OPT_KEY:
            keyfile = opt_arg();
            break;
        case OPT_GENDELTA:
            crldiff = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            do_ver = 1;
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            do_ver = 1;
            break;
        case OPT_NOCAPATH:
            noCApath =  1;
            break;
        case OPT_NOCAFILE:
            noCAfile =  1;
            break;
        case OPT_HASH_OLD:
#ifndef OPENSSL_NO_MD5
            hash_old = ++num;
#endif
            break;
        case OPT_VERIFY:
            do_ver = 1;
            break;
        case OPT_TEXT:
            text = 1;
            break;
        case OPT_HASH:
            hash = ++num;
            break;
        case OPT_ISSUER:
            issuer = ++num;
            break;
        case OPT_LASTUPDATE:
            lastupdate = ++num;
            break;
        case OPT_NEXTUPDATE:
            nextupdate = ++num;
            break;
        case OPT_NOOUT:
            noout = ++num;
            break;
        case OPT_FINGERPRINT:
            fingerprint = ++num;
            break;
        case OPT_CRLNUMBER:
            crlnumber = ++num;
            break;
        case OPT_BADSIG:
            badsig = 1;
            break;
        case OPT_NAMEOPT:
            nmflag_set = 1;
            if (!set_name_ex(&nmflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_MD:
            if (!opt_md(opt_unknown(), &digest))
                goto opthelp;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (!nmflag_set)
        nmflag = XN_FLAG_ONELINE;

    x = load_crl(infile, informat);
    if (x == NULL)
        goto end;

    if (do_ver) {
        if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
            goto end;
        lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
        if (lookup == NULL)
            goto end;
        if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) {
            BIO_printf(bio_err, "Error initialising X509 store\n");
            goto end;
        }

        i = X509_STORE_get_by_subject(&ctx, X509_LU_X509,
                                      X509_CRL_get_issuer(x), &xobj);
        if (i <= 0) {
            BIO_printf(bio_err, "Error getting CRL issuer certificate\n");
            goto end;
        }
        pkey = X509_get0_pubkey(xobj.data.x509);
        X509_OBJECT_free_contents(&xobj);
        if (!pkey) {
            BIO_printf(bio_err, "Error getting CRL issuer public key\n");
            goto end;
        }
        i = X509_CRL_verify(x, pkey);
        if (i < 0)
            goto end;
        if (i == 0)
            BIO_printf(bio_err, "verify failure\n");
        else
            BIO_printf(bio_err, "verify OK\n");
    }

    if (crldiff) {
        X509_CRL *newcrl, *delta;
        if (!keyfile) {
            BIO_puts(bio_err, "Missing CRL signing key\n");
            goto end;
        }
        newcrl = load_crl(crldiff, informat);
        if (!newcrl)
            goto end;
        pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key");
        if (!pkey) {
            X509_CRL_free(newcrl);
            goto end;
        }
        delta = X509_CRL_diff(x, newcrl, pkey, digest, 0);
        X509_CRL_free(newcrl);
        EVP_PKEY_free(pkey);
        if (delta) {
            X509_CRL_free(x);
            x = delta;
        } else {
            BIO_puts(bio_err, "Error creating delta CRL\n");
            goto end;
        }
    }

    if (num) {
        for (i = 1; i <= num; i++) {
            if (issuer == i) {
                print_name(bio_out, "issuer=", X509_CRL_get_issuer(x),
                           nmflag);
            }
            if (crlnumber == i) {
                ASN1_INTEGER *crlnum;
                crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL);
                BIO_printf(bio_out, "crlNumber=");
                if (crlnum) {
                    i2a_ASN1_INTEGER(bio_out, crlnum);
                    ASN1_INTEGER_free(crlnum);
                } else
                    BIO_puts(bio_out, "<NONE>");
                BIO_printf(bio_out, "\n");
            }
            if (hash == i) {
                BIO_printf(bio_out, "%08lx\n",
                           X509_NAME_hash(X509_CRL_get_issuer(x)));
            }
#ifndef OPENSSL_NO_MD5
            if (hash_old == i) {
                BIO_printf(bio_out, "%08lx\n",
                           X509_NAME_hash_old(X509_CRL_get_issuer(x)));
            }
#endif
            if (lastupdate == i) {
                BIO_printf(bio_out, "lastUpdate=");
                ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x));
                BIO_printf(bio_out, "\n");
            }
            if (nextupdate == i) {
                BIO_printf(bio_out, "nextUpdate=");
                if (X509_CRL_get_nextUpdate(x))
                    ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x));
                else
                    BIO_printf(bio_out, "NONE");
                BIO_printf(bio_out, "\n");
            }
            if (fingerprint == i) {
                int j;
                unsigned int n;
                unsigned char md[EVP_MAX_MD_SIZE];

                if (!X509_CRL_digest(x, digest, md, &n)) {
                    BIO_printf(bio_err, "out of memory\n");
                    goto end;
                }
                BIO_printf(bio_out, "%s Fingerprint=",
                           OBJ_nid2sn(EVP_MD_type(digest)));
                for (j = 0; j < (int)n; j++) {
                    BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n)
                               ? '\n' : ':');
                }
            }
        }
    }
    out = bio_open_default(outfile, 'w', outformat);
    if (out == NULL)
        goto end;

    if (text)
        X509_CRL_print(out, x);

    if (noout) {
        ret = 0;
        goto end;
    }

    if (badsig) {
        ASN1_BIT_STRING *sig;
        unsigned char *psig;
        X509_CRL_get0_signature(&sig, NULL, x);
        psig = ASN1_STRING_data(sig);
        psig[ASN1_STRING_length(sig) - 1] ^= 0x1;
    }

    if (outformat == FORMAT_ASN1)
        i = (int)i2d_X509_CRL_bio(out, x);
    else
        i = PEM_write_bio_X509_CRL(out, x);
    if (!i) {
        BIO_printf(bio_err, "unable to write CRL\n");
        goto end;
    }
    ret = 0;

 end:
    if (ret != 0)
        ERR_print_errors(bio_err);
    BIO_free_all(out);
    X509_CRL_free(x);
    if (store) {
        X509_STORE_CTX_cleanup(&ctx);
        X509_STORE_free(store);
    }
    return (ret);
}
Esempio n. 13
0
/* based on BSD-style licensed code of mod_ssl */
static int crl_check(CLI *c, X509_STORE_CTX *callback_ctx) {
    X509_STORE_CTX store_ctx;
    X509_OBJECT obj;
    X509_NAME *subject;
    X509_NAME *issuer;
    X509 *cert;
    X509_CRL *crl;
    X509_REVOKED *revoked;
    EVP_PKEY *pubkey;
    long serial;
    int i, n, rc;
    char *cp;
    ASN1_TIME *last_update=NULL, *next_update=NULL;

    /* determine certificate ingredients in advance */
    cert=X509_STORE_CTX_get_current_cert(callback_ctx);
    subject=X509_get_subject_name(cert);
    issuer=X509_get_issuer_name(cert);

    /* try to retrieve a CRL corresponding to the _subject_ of
     * the current certificate in order to verify it's integrity */
    memset((char *)&obj, 0, sizeof obj);
    X509_STORE_CTX_init(&store_ctx, c->opt->revocation_store, NULL, NULL);
    rc=X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, subject, &obj);
    X509_STORE_CTX_cleanup(&store_ctx);
    crl=obj.data.crl;
    if(rc>0 && crl) {
        cp=X509_NAME_oneline(subject, NULL, 0);
        s_log(LOG_INFO, "CRL: issuer: %s", cp);
        OPENSSL_free(cp);
        last_update=X509_CRL_get_lastUpdate(crl);
        next_update=X509_CRL_get_nextUpdate(crl);
        log_time(LOG_INFO, "CRL: last update", last_update);
        log_time(LOG_INFO, "CRL: next update", next_update);

        /* verify the signature on this CRL */
        pubkey=X509_get_pubkey(cert);
        if(X509_CRL_verify(crl, pubkey)<=0) {
            s_log(LOG_WARNING, "CRL: Invalid signature");
            X509_STORE_CTX_set_error(callback_ctx,
                X509_V_ERR_CRL_SIGNATURE_FAILURE);
            X509_OBJECT_free_contents(&obj);
            if(pubkey)
                EVP_PKEY_free(pubkey);
            return 0; /* reject connection */
        }
        if(pubkey)
            EVP_PKEY_free(pubkey);

        /* check date of CRL to make sure it's not expired */
        if(!next_update) {
            s_log(LOG_WARNING, "CRL: Invalid nextUpdate field");
            X509_STORE_CTX_set_error(callback_ctx,
                X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
            X509_OBJECT_free_contents(&obj);
            return 0; /* reject connection */
        }
        if(X509_cmp_current_time(next_update)<0) {
            s_log(LOG_WARNING, "CRL: CRL Expired - revoking all certificates");
            X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CRL_HAS_EXPIRED);
            X509_OBJECT_free_contents(&obj);
            return 0; /* reject connection */
        }
        X509_OBJECT_free_contents(&obj);
    }

    /* try to retrieve a CRL corresponding to the _issuer_ of
     * the current certificate in order to check for revocation */
    memset((char *)&obj, 0, sizeof obj);
    X509_STORE_CTX_init(&store_ctx, c->opt->revocation_store, NULL, NULL);
    rc=X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, issuer, &obj);
    X509_STORE_CTX_cleanup(&store_ctx);
    crl=obj.data.crl;
    if(rc>0 && crl) {
        /* check if the current certificate is revoked by this CRL */
        n=sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
        for(i=0; i<n; i++) {
            revoked=sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
            if(ASN1_INTEGER_cmp(revoked->serialNumber,
                    X509_get_serialNumber(cert)) == 0) {
                serial=ASN1_INTEGER_get(revoked->serialNumber);
                cp=X509_NAME_oneline(issuer, NULL, 0);
                s_log(LOG_WARNING, "CRL: Certificate with serial %ld (0x%lX) "
                    "revoked per CRL from issuer %s", serial, serial, cp);
                OPENSSL_free(cp);
                X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CERT_REVOKED);
                X509_OBJECT_free_contents(&obj);
                return 0; /* reject connection */
            }
        }
        X509_OBJECT_free_contents(&obj);
    }
    return 1; /* accept connection */
}
Esempio n. 14
0
int MAIN(int argc, char **argv)
{
    unsigned long nmflag = 0;
    X509_CRL *x = NULL;
    char *CAfile = NULL, *CApath = NULL;
    int ret = 1, i, num, badops = 0, badsig = 0;
    BIO *out = NULL;
    int informat, outformat, keyformat;
    char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL;
    int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout =
        0, text = 0;
#ifndef OPENSSL_NO_MD5
    int hash_old = 0;
#endif
    int fingerprint = 0, crlnumber = 0;
    const char **pp;
    X509_STORE *store = NULL;
    X509_STORE_CTX ctx;
    X509_LOOKUP *lookup = NULL;
    X509_OBJECT xobj;
    EVP_PKEY *pkey;
    int do_ver = 0;
    const EVP_MD *md_alg, *digest = EVP_sha1();

    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;

    if (bio_out == NULL)
        if ((bio_out = BIO_new(BIO_s_file())) != NULL) {
            BIO_set_fp(bio_out, stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
            {
                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
                bio_out = BIO_push(tmpbio, bio_out);
            }
#endif
        }

    informat = FORMAT_PEM;
    outformat = FORMAT_PEM;
    keyformat = FORMAT_PEM;

    argc--;
    argv++;
    num = 0;
    while (argc >= 1) {
#ifdef undef
        if (sgx_strcmp(*argv, "-p") == 0) {
            if (--argc < 1)
                goto bad;
            if (!args_from_file(++argv, Nargc, Nargv)) {
                goto end;
            }
        */}
#endif
        if (sgx_strcmp(*argv, "-inform") == 0) {
            if (--argc < 1)
                goto bad;
            informat = str2fmt(*(++argv));
        } else if (sgx_strcmp(*argv, "-outform") == 0) {
            if (--argc < 1)
                goto bad;
            outformat = str2fmt(*(++argv));
        } else if (sgx_strcmp(*argv, "-in") == 0) {
            if (--argc < 1)
                goto bad;
            infile = *(++argv);
        } else if (sgx_strcmp(*argv, "-gendelta") == 0) {
            if (--argc < 1)
                goto bad;
            crldiff = *(++argv);
        } else if (sgx_strcmp(*argv, "-key") == 0) {
            if (--argc < 1)
                goto bad;
            keyfile = *(++argv);
        } else if (sgx_strcmp(*argv, "-keyform") == 0) {
            if (--argc < 1)
                goto bad;
            keyformat = str2fmt(*(++argv));
        } else if (sgx_strcmp(*argv, "-out") == 0) {
            if (--argc < 1)
                goto bad;
            outfile = *(++argv);
        } else if (sgx_strcmp(*argv, "-CApath") == 0) {
            if (--argc < 1)
                goto bad;
            CApath = *(++argv);
            do_ver = 1;
        } else if (sgx_strcmp(*argv, "-CAfile") == 0) {
            if (--argc < 1)
                goto bad;
            CAfile = *(++argv);
            do_ver = 1;
        } else if (sgx_strcmp(*argv, "-verify") == 0)
            do_ver = 1;
        else if (sgx_strcmp(*argv, "-text") == 0)
            text = 1;
        else if (sgx_strcmp(*argv, "-hash") == 0)
            hash = ++num;
#ifndef OPENSSL_NO_MD5
        else if (sgx_strcmp(*argv, "-hash_old") == 0)
            hash_old = ++num;
#endif
        else if (sgx_strcmp(*argv, "-nameopt") == 0) {
            if (--argc < 1)
                goto bad;
            if (!set_name_ex(&nmflag, *(++argv)))
                goto bad;
        } else if (sgx_strcmp(*argv, "-issuer") == 0)
            issuer = ++num;
        else if (sgx_strcmp(*argv, "-lastupdate") == 0)
            lastupdate = ++num;
        else if (sgx_strcmp(*argv, "-nextupdate") == 0)
            nextupdate = ++num;
        else if (sgx_strcmp(*argv, "-noout") == 0)
            noout = ++num;
        else if (sgx_strcmp(*argv, "-fingerprint") == 0)
            fingerprint = ++num;
        else if (sgx_strcmp(*argv, "-crlnumber") == 0)
            crlnumber = ++num;
        else if (sgx_strcmp(*argv, "-badsig") == 0)
            badsig = 1;
        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 = crl_usage; (*pp != NULL); pp++)
            BIO_printf(bio_err, "%s", *pp);
        goto end;
    }

    ERR_load_crypto_strings();
    x = load_crl(infile, informat);
    if (x == NULL) {
        goto end;
    }

    if (do_ver) {
        store = X509_STORE_new();
        lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
        if (lookup == NULL)
            goto end;
        if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM))
            X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);

        lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
        if (lookup == NULL)
            goto end;
        if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM))
            X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
        ERR_clear_error();

        if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) {
            BIO_printf(bio_err, "Error initialising X509 store\n");
            goto end;
        }

        i = X509_STORE_get_by_subject(&ctx, X509_LU_X509,
                                      X509_CRL_get_issuer(x), &xobj);
        if (i <= 0) {
            BIO_printf(bio_err, "Error getting CRL issuer certificate\n");
            goto end;
        }
        pkey = X509_get_pubkey(xobj.data.x509);
        X509_OBJECT_free_contents(&xobj);
        if (!pkey) {
            BIO_printf(bio_err, "Error getting CRL issuer public key\n");
            goto end;
        }
        i = X509_CRL_verify(x, pkey);
        EVP_PKEY_free(pkey);
        if (i < 0)
            goto end;
        if (i == 0)
            BIO_printf(bio_err, "verify failure\n");
        else
            BIO_printf(bio_err, "verify OK\n");
    }

    if (crldiff) {
        X509_CRL *newcrl, *delta;
        if (!keyfile) {
            BIO_puts(bio_err, "Missing CRL signing key\n");
            goto end;
        }
        newcrl = load_crl(crldiff, informat);
        if (!newcrl)
            goto end;
        pkey = load_key(bio_err, keyfile, keyformat, 0, NULL, NULL,
                        "CRL signing key");
        if (!pkey) {
            X509_CRL_free(newcrl);
            goto end;
        }
        delta = X509_CRL_diff(x, newcrl, pkey, digest, 0);
        X509_CRL_free(newcrl);
        EVP_PKEY_free(pkey);
        if (delta) {
            X509_CRL_free(x);
            x = delta;
        } else {
            BIO_puts(bio_err, "Error creating delta CRL\n");
            goto end;
        }
    }

    if (num) {
        for (i = 1; i <= num; i++) {
            if (issuer == i) {
                print_name(bio_out, "issuer=", X509_CRL_get_issuer(x),
                           nmflag);
            }
            if (crlnumber == i) {
                ASN1_INTEGER *crlnum;
                crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL);
                BIO_printf(bio_out, "crlNumber=");
                if (crlnum) {
                    i2a_ASN1_INTEGER(bio_out, crlnum);
                    ASN1_INTEGER_free(crlnum);
                } else
                    BIO_puts(bio_out, "<NONE>");
                BIO_printf(bio_out, "\n");
            }
            if (hash == i) {
                BIO_printf(bio_out, "%08lx\n",
                           X509_NAME_hash(X509_CRL_get_issuer(x)));
            }
#ifndef OPENSSL_NO_MD5
            if (hash_old == i) {
                BIO_printf(bio_out, "%08lx\n",
                           X509_NAME_hash_old(X509_CRL_get_issuer(x)));
            }
#endif
            if (lastupdate == i) {
                BIO_printf(bio_out, "lastUpdate=");
                ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x));
                BIO_printf(bio_out, "\n");
            }
            if (nextupdate == i) {
                BIO_printf(bio_out, "nextUpdate=");
                if (X509_CRL_get_nextUpdate(x))
                    ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x));
                else
                    BIO_printf(bio_out, "NONE");
                BIO_printf(bio_out, "\n");
            }
            if (fingerprint == i) {
                int j;
                unsigned int n;
                unsigned char md[EVP_MAX_MD_SIZE];

                if (!X509_CRL_digest(x, digest, md, &n)) {
                    BIO_printf(bio_err, "out of memory\n");
                    goto end;
                }
                BIO_printf(bio_out, "%s Fingerprint=",
                           OBJ_nid2sn(EVP_MD_type(digest)));
                for (j = 0; j < (int)n; j++) {
                    BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n)
                               ? '\n' : ':');
                }
            }
        }
    }

    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);
#ifdef OPENSSL_SYS_VMS
        {
            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
            out = BIO_push(tmpbio, out);
        }
#endif
    } else {
        if (BIO_write_filename(out, outfile) <= 0) {
            perror(outfile);
            goto end;
        }
    }

    if (text)
        X509_CRL_print(out, x);

    if (noout) {
        ret = 0;
        goto end;
    }

    if (badsig)
        x->signature->data[x->signature->length - 1] ^= 0x1;

    if (outformat == FORMAT_ASN1)
        i = (int)i2d_X509_CRL_bio(out, x);
    else if (outformat == FORMAT_PEM)
        i = PEM_write_bio_X509_CRL(out, x);
    else {
        BIO_printf(bio_err, "bad output format specified for outfile\n");
        goto end;
    }
    if (!i) {
        BIO_printf(bio_err, "unable to write CRL\n");
        goto end;
    }
    ret = 0;
 end:
    if (ret != 0)
        ERR_print_errors(bio_err);
    BIO_free_all(out);
    BIO_free_all(bio_out);
    bio_out = NULL;
    X509_CRL_free(x);
    if (store) {
        X509_STORE_CTX_cleanup(&ctx);
        X509_STORE_free(store);
    }
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
Esempio n. 15
0
int
crl_main(int argc, char **argv)
{
	unsigned long nmflag = 0;
	X509_CRL *x = NULL;
	int ret = 1, i;
	BIO *out = NULL;
	X509_STORE *store = NULL;
	X509_STORE_CTX ctx;
	X509_LOOKUP *lookup = NULL;
	X509_OBJECT xobj;
	EVP_PKEY *pkey;
	const EVP_MD *digest;
	char *digest_name = NULL;

	if (single_execution) {
		if (pledge("stdio cpath wpath rpath", NULL) == -1) {
			perror("pledge");
			exit(1);
		}
	}

	if (bio_out == NULL) {
		if ((bio_out = BIO_new(BIO_s_file())) != NULL) {
			BIO_set_fp(bio_out, stdout, BIO_NOCLOSE);
		}
	}

	digest = EVP_sha256();

	memset(&crl_config, 0, sizeof(crl_config));
	crl_config.informat = FORMAT_PEM;
	crl_config.outformat = FORMAT_PEM;

	if (options_parse(argc, argv, crl_options, &digest_name, NULL) != 0) {
		crl_usage();
		goto end;
	}

	if (crl_config.cafile != NULL || crl_config.capath != NULL)
		crl_config.verify = 1;

	if (crl_config.nameopt != NULL) {
		if (set_name_ex(&nmflag, crl_config.nameopt) != 1) {
			fprintf(stderr,
			    "Invalid -nameopt argument '%s'\n",
			    crl_config.nameopt);
			goto end;
		}
	}

	if (digest_name != NULL) {
		if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
			fprintf(stderr,
			    "Unknown message digest algorithm '%s'\n",
			    digest_name);
			goto end;
		}
	}

	x = load_crl(crl_config.infile, crl_config.informat);
	if (x == NULL)
		goto end;

	if (crl_config.verify) {
		store = X509_STORE_new();
		lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
		if (lookup == NULL)
			goto end;
		if (!X509_LOOKUP_load_file(lookup, crl_config.cafile,
		    X509_FILETYPE_PEM))
			X509_LOOKUP_load_file(lookup, NULL,
			    X509_FILETYPE_DEFAULT);

		lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
		if (lookup == NULL)
			goto end;
		if (!X509_LOOKUP_add_dir(lookup, crl_config.capath,
		    X509_FILETYPE_PEM))
			X509_LOOKUP_add_dir(lookup, NULL,
			    X509_FILETYPE_DEFAULT);
		ERR_clear_error();

		if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) {
			BIO_printf(bio_err,
			    "Error initialising X509 store\n");
			goto end;
		}
		i = X509_STORE_get_by_subject(&ctx, X509_LU_X509,
		    X509_CRL_get_issuer(x), &xobj);
		if (i <= 0) {
			BIO_printf(bio_err,
			    "Error getting CRL issuer certificate\n");
			goto end;
		}
		pkey = X509_get_pubkey(xobj.data.x509);
		X509_OBJECT_free_contents(&xobj);
		if (!pkey) {
			BIO_printf(bio_err,
			    "Error getting CRL issuer public key\n");
			goto end;
		}
		i = X509_CRL_verify(x, pkey);
		EVP_PKEY_free(pkey);
		if (i < 0)
			goto end;
		if (i == 0)
			BIO_printf(bio_err, "verify failure\n");
		else
			BIO_printf(bio_err, "verify OK\n");
	}

	/* Print requested information the order that the flags were given. */
	for (i = 1; i <= argc; i++) {
		if (crl_config.issuer == i) {
			print_name(bio_out, "issuer=",
			    X509_CRL_get_issuer(x), nmflag);
		}
		if (crl_config.crlnumber == i) {
			ASN1_INTEGER *crlnum;
			crlnum = X509_CRL_get_ext_d2i(x,
			    NID_crl_number, NULL, NULL);
			BIO_printf(bio_out, "crlNumber=");
			if (crlnum) {
				i2a_ASN1_INTEGER(bio_out, crlnum);
				ASN1_INTEGER_free(crlnum);
			} else
				BIO_puts(bio_out, "<NONE>");
			BIO_printf(bio_out, "\n");
		}
		if (crl_config.hash == i) {
			BIO_printf(bio_out, "%08lx\n",
			    X509_NAME_hash(X509_CRL_get_issuer(x)));
		}
#ifndef OPENSSL_NO_MD5
		if (crl_config.hash_old == i) {
			BIO_printf(bio_out, "%08lx\n",
			    X509_NAME_hash_old(X509_CRL_get_issuer(x)));
		}
#endif
		if (crl_config.lastupdate == i) {
			BIO_printf(bio_out, "lastUpdate=");
			ASN1_TIME_print(bio_out,
			    X509_CRL_get_lastUpdate(x));
			BIO_printf(bio_out, "\n");
		}
		if (crl_config.nextupdate == i) {
			BIO_printf(bio_out, "nextUpdate=");
			if (X509_CRL_get_nextUpdate(x))
				ASN1_TIME_print(bio_out,
				    X509_CRL_get_nextUpdate(x));
			else
				BIO_printf(bio_out, "NONE");
			BIO_printf(bio_out, "\n");
		}
		if (crl_config.fingerprint == i) {
			int j;
			unsigned int n;
			unsigned char md[EVP_MAX_MD_SIZE];

			if (!X509_CRL_digest(x, digest, md, &n)) {
				BIO_printf(bio_err, "out of memory\n");
				goto end;
			}
			BIO_printf(bio_out, "%s Fingerprint=",
			    OBJ_nid2sn(EVP_MD_type(digest)));
			for (j = 0; j < (int) n; j++) {
				BIO_printf(bio_out, "%02X%c", md[j],
				    (j + 1 == (int)n) ? '\n' : ':');
			}
		}
	}

	out = BIO_new(BIO_s_file());
	if (out == NULL) {
		ERR_print_errors(bio_err);
		goto end;
	}
	if (crl_config.outfile == NULL) {
		BIO_set_fp(out, stdout, BIO_NOCLOSE);
	} else {
		if (BIO_write_filename(out, crl_config.outfile) <= 0) {
			perror(crl_config.outfile);
			goto end;
		}
	}

	if (crl_config.text)
		X509_CRL_print(out, x);

	if (crl_config.noout) {
		ret = 0;
		goto end;
	}
	if (crl_config.outformat == FORMAT_ASN1)
		i = (int) i2d_X509_CRL_bio(out, x);
	else if (crl_config.outformat == FORMAT_PEM)
		i = PEM_write_bio_X509_CRL(out, x);
	else {
		BIO_printf(bio_err,
		    "bad output format specified for outfile\n");
		goto end;
	}
	if (!i) {
		BIO_printf(bio_err, "unable to write CRL\n");
		goto end;
	}
	ret = 0;

 end:
	BIO_free_all(out);
	BIO_free_all(bio_out);
	bio_out = NULL;
	X509_CRL_free(x);
	if (store) {
		X509_STORE_CTX_cleanup(&ctx);
		X509_STORE_free(store);
	}

	return (ret);
}
Esempio n. 16
0
/* based on the code of stunnel utility */
int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) {
	X509_STORE* store;
	X509_STORE_CTX store_ctx;
	X509_OBJECT obj;
	X509_NAME* subject;
	X509_NAME* issuer;
	X509* cert;
	X509_CRL* crl;
	X509_REVOKED* revoked;
	EVP_PKEY* pubkey;
	int i, n, rc;
	ASN1_TIME* next_update = NULL;

	if (!preverify_ok) {
		return 0;
	}

	if ((store = pthread_getspecific(tls_store_key)) == NULL) {
		ERROR("Failed to get thread-specific X509 store");
		return 1; /* fail */
	}

	cert = X509_STORE_CTX_get_current_cert(x509_ctx);
	subject = X509_get_subject_name(cert);
	issuer = X509_get_issuer_name(cert);

	/* try to retrieve a CRL corresponding to the _subject_ of
	 * the current certificate in order to verify it's integrity */
	memset((char *)&obj, 0, sizeof obj);
	X509_STORE_CTX_init(&store_ctx, store, NULL, NULL);
	rc = X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, subject, &obj);
	X509_STORE_CTX_cleanup(&store_ctx);
	crl = obj.data.crl;
	if (rc > 0 && crl) {
		next_update = X509_CRL_get_nextUpdate(crl);

		/* verify the signature on this CRL */
		pubkey = X509_get_pubkey(cert);
		if (X509_CRL_verify(crl, pubkey) <= 0) {
			X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE);
			X509_OBJECT_free_contents(&obj);
			if (pubkey) {
				EVP_PKEY_free(pubkey);
			}
			return 0; /* fail */
		}
		if (pubkey) {
			EVP_PKEY_free(pubkey);
		}

		/* check date of CRL to make sure it's not expired */
		if (!next_update) {
			X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
			X509_OBJECT_free_contents(&obj);
			return 0; /* fail */
		}
		if (X509_cmp_current_time(next_update) < 0) {
			X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_CRL_HAS_EXPIRED);
			X509_OBJECT_free_contents(&obj);
			return 0; /* fail */
		}
		X509_OBJECT_free_contents(&obj);
	}

	/* try to retrieve a CRL corresponding to the _issuer_ of
	 * the current certificate in order to check for revocation */
	memset((char *)&obj, 0, sizeof obj);
	X509_STORE_CTX_init(&store_ctx, store, NULL, NULL);
	rc = X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, issuer, &obj);
	X509_STORE_CTX_cleanup(&store_ctx);
	crl = obj.data.crl;
	if (rc > 0 && crl) {
		/* check if the current certificate is revoked by this CRL */
		n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
		for (i = 0; i < n; i++) {
			revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
			if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(cert)) == 0) {
				ERROR("Certificate revoked");
				X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_CERT_REVOKED);
				X509_OBJECT_free_contents(&obj);
				return 0; /* fail */
			}
		}
		X509_OBJECT_free_contents(&obj);
	}
	return 1; /* success */
}
Esempio n. 17
0
/*
 * Given an X509 certificate, create a KeyNote assertion where
 * Issuer/Subject -> Authorizer/Licensees.
 * XXX RSA-specific.
 */
int
x509_generate_kn(int id, X509 *cert)
{
	static const char fmt[] = "Authorizer: \"rsa-hex:%s\"\nLicensees: \"rsa-hex:%s"
		    "\"\nConditions: %s >= \"%s\" && %s <= \"%s\";\n";
	char	*ikey = NULL, *skey = NULL, *buf = NULL;
	char	isname[256], subname[256];
	static const char fmt2[] = "Authorizer: \"DN:%s\"\nLicensees: \"DN:%s\"\n"
		    "Conditions: %s >= \"%s\" && %s <= \"%s\";\n";
	X509_NAME *issuer, *subject;
	struct keynote_deckey dc;
	X509_STORE_CTX csc;
	X509_OBJECT obj;
	X509	*icert;
	RSA	*key = NULL;
	time_t	tt;
	char	before[15], after[15], *timecomp, *timecomp2;
	ASN1_TIME *tm;
	int	i;

	LOG_DBG((LOG_POLICY, 90,
	    "x509_generate_kn: generating KeyNote policy for certificate %p",
	    cert));

	issuer = X509_get_issuer_name(cert);
	subject = X509_get_subject_name(cert);

	/* Missing or self-signed, ignore cert but don't report failure.  */
	if (!issuer || !subject || !X509_name_cmp(issuer, subject))
		return 1;

	if (!x509_cert_get_key(cert, &key)) {
		LOG_DBG((LOG_POLICY, 30,
		    "x509_generate_kn: failed to get public key from cert"));
		return 0;
	}
	dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA;
	dc.dec_key = key;
	ikey = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX,
	    KEYNOTE_PUBLIC_KEY);
	if (keynote_errno == ERROR_MEMORY) {
		log_print("x509_generate_kn: failed to get memory for "
		    "public key");
		LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get "
		    "subject key"));
		goto fail;
	}
	if (!ikey) {
		LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get "
		    "subject key"));
		goto fail;
	}

	RSA_free(key);
	key = NULL;

	/* Now find issuer's certificate so we can get the public key.  */
	X509_STORE_CTX_init(&csc, x509_cas, cert, NULL);
	if (X509_STORE_get_by_subject(&csc, X509_LU_X509, issuer, &obj) !=
	    X509_LU_X509) {
		X509_STORE_CTX_cleanup(&csc);
		X509_STORE_CTX_init(&csc, x509_certs, cert, NULL);
		if (X509_STORE_get_by_subject(&csc, X509_LU_X509, issuer, &obj)
		    != X509_LU_X509) {
			X509_STORE_CTX_cleanup(&csc);
			LOG_DBG((LOG_POLICY, 30,
			    "x509_generate_kn: no certificate found for "
			    "issuer"));
			goto fail;
		}
	}
	X509_STORE_CTX_cleanup(&csc);
	icert = obj.data.x509;

	if (icert == NULL) {
		LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: "
		    "missing certificates, cannot construct X509 chain"));
		goto fail;
	}
	if (!x509_cert_get_key(icert, &key)) {
		LOG_DBG((LOG_POLICY, 30,
		    "x509_generate_kn: failed to get public key from cert"));
		goto fail;
	}
	X509_OBJECT_free_contents(&obj);

	dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA;
	dc.dec_key = key;
	skey = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX,
	    KEYNOTE_PUBLIC_KEY);
	if (keynote_errno == ERROR_MEMORY) {
		log_error("x509_generate_kn: failed to get memory for public "
		    "key");
		LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer "
		    "key"));
		goto fail;
	}
	if (!skey) {
		LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer "
		    "key"));
		goto fail;
	}

	RSA_free(key);
	key = NULL;

	if (((tm = X509_get_notBefore(cert)) == NULL) ||
	    (tm->type != V_ASN1_UTCTIME &&
		tm->type != V_ASN1_GENERALIZEDTIME)) {
		tt = time(0);
		strftime(before, 14, "%Y%m%d%H%M%S", localtime(&tt));
		timecomp = "LocalTimeOfDay";
	} else {
		if (tm->data[tm->length - 1] == 'Z') {
			timecomp = "GMTTimeOfDay";
			i = tm->length - 2;
		} else {
			timecomp = "LocalTimeOfDay";
			i = tm->length - 1;
		}

		for (; i >= 0; i--) {
			if (tm->data[i] < '0' || tm->data[i] > '9') {
				LOG_DBG((LOG_POLICY, 30,
				    "x509_generate_kn: invalid data in "
				    "NotValidBefore time field"));
				goto fail;
			}
		}

		if (tm->type == V_ASN1_UTCTIME) {
			if ((tm->length < 10) || (tm->length > 13)) {
				LOG_DBG((LOG_POLICY, 30,
				    "x509_generate_kn: invalid length "
				    "of NotValidBefore time field (%d)",
				    tm->length));
				goto fail;
			}
			/* Validity checks.  */
			if ((tm->data[2] != '0' && tm->data[2] != '1') ||
			    (tm->data[2] == '0' && tm->data[3] == '0') ||
			    (tm->data[2] == '1' && tm->data[3] > '2') ||
			    (tm->data[4] > '3') ||
			    (tm->data[4] == '0' && tm->data[5] == '0') ||
			    (tm->data[4] == '3' && tm->data[5] > '1') ||
			    (tm->data[6] > '2') ||
			    (tm->data[6] == '2' && tm->data[7] > '3') ||
			    (tm->data[8] > '5')) {
				LOG_DBG((LOG_POLICY, 30,
				    "x509_generate_kn: invalid value in "
				    "NotValidBefore time field"));
				goto fail;
			}
			/* Stupid UTC tricks.  */
			if (tm->data[0] < '5')
				snprintf(before, sizeof before, "20%s",
				    tm->data);
			else
				snprintf(before, sizeof before, "19%s",
				    tm->data);
		} else {	/* V_ASN1_GENERICTIME */
			if ((tm->length < 12) || (tm->length > 15)) {
				LOG_DBG((LOG_POLICY, 30,
				    "x509_generate_kn: invalid length of "
				    "NotValidBefore time field (%d)",
				    tm->length));
				goto fail;
			}
			/* Validity checks.  */
			if ((tm->data[4] != '0' && tm->data[4] != '1') ||
			    (tm->data[4] == '0' && tm->data[5] == '0') ||
			    (tm->data[4] == '1' && tm->data[5] > '2') ||
			    (tm->data[6] > '3') ||
			    (tm->data[6] == '0' && tm->data[7] == '0') ||
			    (tm->data[6] == '3' && tm->data[7] > '1') ||
			    (tm->data[8] > '2') ||
			    (tm->data[8] == '2' && tm->data[9] > '3') ||
			    (tm->data[10] > '5')) {
				LOG_DBG((LOG_POLICY, 30,
				    "x509_generate_kn: invalid value in "
				    "NotValidBefore time field"));
				goto fail;
			}
			snprintf(before, sizeof before, "%s", tm->data);
		}

		/* Fix missing seconds.  */
		if (tm->length < 12) {
			before[12] = '0';
			before[13] = '0';
		}
		/* This will overwrite trailing 'Z'.  */
		before[14] = '\0';
	}

	tm = X509_get_notAfter(cert);
	if (tm == NULL &&
	    (tm->type != V_ASN1_UTCTIME &&
		tm->type != V_ASN1_GENERALIZEDTIME)) {
		tt = time(0);
		strftime(after, 14, "%Y%m%d%H%M%S", localtime(&tt));
		timecomp2 = "LocalTimeOfDay";
	} else {
		if (tm->data[tm->length - 1] == 'Z') {
			timecomp2 = "GMTTimeOfDay";
			i = tm->length - 2;
		} else {
			timecomp2 = "LocalTimeOfDay";
			i = tm->length - 1;
		}

		for (; i >= 0; i--) {
			if (tm->data[i] < '0' || tm->data[i] > '9') {
				LOG_DBG((LOG_POLICY, 30,
				    "x509_generate_kn: invalid data in "
				    "NotValidAfter time field"));
				goto fail;
			}
		}

		if (tm->type == V_ASN1_UTCTIME) {
			if ((tm->length < 10) || (tm->length > 13)) {
				LOG_DBG((LOG_POLICY, 30,
				    "x509_generate_kn: invalid length of "
				    "NotValidAfter time field (%d)",
				    tm->length));
				goto fail;
			}
			/* Validity checks. */
			if ((tm->data[2] != '0' && tm->data[2] != '1') ||
			    (tm->data[2] == '0' && tm->data[3] == '0') ||
			    (tm->data[2] == '1' && tm->data[3] > '2') ||
			    (tm->data[4] > '3') ||
			    (tm->data[4] == '0' && tm->data[5] == '0') ||
			    (tm->data[4] == '3' && tm->data[5] > '1') ||
			    (tm->data[6] > '2') ||
			    (tm->data[6] == '2' && tm->data[7] > '3') ||
			    (tm->data[8] > '5')) {
				LOG_DBG((LOG_POLICY, 30,
				    "x509_generate_kn: invalid value in "
				    "NotValidAfter time field"));
				goto fail;
			}
			/* Stupid UTC tricks.  */
			if (tm->data[0] < '5')
				snprintf(after, sizeof after, "20%s",
				    tm->data);
			else
				snprintf(after, sizeof after, "19%s",
				    tm->data);
		} else {	/* V_ASN1_GENERICTIME */
			if ((tm->length < 12) || (tm->length > 15)) {
				LOG_DBG((LOG_POLICY, 30,
				    "x509_generate_kn: invalid length of "
				    "NotValidAfter time field (%d)",
				    tm->length));
				goto fail;
			}
			/* Validity checks.  */
			if ((tm->data[4] != '0' && tm->data[4] != '1') ||
			    (tm->data[4] == '0' && tm->data[5] == '0') ||
			    (tm->data[4] == '1' && tm->data[5] > '2') ||
			    (tm->data[6] > '3') ||
			    (tm->data[6] == '0' && tm->data[7] == '0') ||
			    (tm->data[6] == '3' && tm->data[7] > '1') ||
			    (tm->data[8] > '2') ||
			    (tm->data[8] == '2' && tm->data[9] > '3') ||
			    (tm->data[10] > '5')) {
				LOG_DBG((LOG_POLICY, 30,
				    "x509_generate_kn: invalid value in "
				    "NotValidAfter time field"));
				goto fail;
			}
			snprintf(after, sizeof after, "%s", tm->data);
		}

		/* Fix missing seconds.  */
		if (tm->length < 12) {
			after[12] = '0';
			after[13] = '0';
		}
		after[14] = '\0';	/* This will overwrite trailing 'Z' */
	}

	if (asprintf(&buf, fmt, skey, ikey, timecomp, before, timecomp2,
	    after) == -1) {
		log_error("x509_generate_kn: "
		    "failed to allocate memory for KeyNote credential");
		goto fail;
	}
	
	free(ikey);
	ikey = NULL;
	free(skey);
	skey = NULL;

	if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL) == -1) {
		LOG_DBG((LOG_POLICY, 30,
		    "x509_generate_kn: failed to add new KeyNote credential"));
		goto fail;
	}
	/* We could print the assertion here, but log_print() truncates...  */
	LOG_DBG((LOG_POLICY, 60, "x509_generate_kn: added credential"));

	free(buf);
	buf = NULL;

	if (!X509_NAME_oneline(issuer, isname, 256)) {
		LOG_DBG((LOG_POLICY, 50,
		    "x509_generate_kn: "
		    "X509_NAME_oneline (issuer, ...) failed"));
		goto fail;
	}
	if (!X509_NAME_oneline(subject, subname, 256)) {
		LOG_DBG((LOG_POLICY, 50,
		    "x509_generate_kn: "
		    "X509_NAME_oneline (subject, ...) failed"));
		goto fail;
	}
	if (asprintf(&buf, fmt2, isname, subname, timecomp, before,
	    timecomp2, after) == -1) {
		log_error("x509_generate_kn: malloc failed");
		return 0;
	}

	if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL) == -1) {
		LOG_DBG((LOG_POLICY, 30,
		    "x509_generate_kn: failed to add new KeyNote credential"));
		goto fail;
	}
	LOG_DBG((LOG_POLICY, 80, "x509_generate_kn: added credential:\n%s",
	    buf));

	free(buf);
	return 1;

fail:
	free(buf);
	free(skey);
	free(ikey);
	if (key)
		RSA_free(key);

	return 0;
}
unsigned long ssl3_output_cert_chain(SSL *s, X509 *x)
	{
	unsigned char *p;
	int n,i;
	unsigned long l=7;
	BUF_MEM *buf;
	X509_STORE_CTX xs_ctx;
	X509_OBJECT obj;

	int no_chain;

	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
		no_chain = 1;
	else
		no_chain = 0;

	/* 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_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
		return(0);
		}
	if (x != NULL)
		{
		if(!no_chain && !X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL))
			{
			SSLerr(SSL_F_SSL3_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_SSL3_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 (no_chain)
				break;

			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);
			}
		if (!no_chain)
			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_SSL3_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-=7;
	p=(unsigned char *)&(buf->data[4]);
	l2n3(l,p);
	l+=3;
	p=(unsigned char *)&(buf->data[0]);
	*(p++)=SSL3_MT_CERTIFICATE;
	l2n3(l,p);
	l+=4;
	return(l);
	}