static
int
__pkcs11h_crypto_openssl_certificate_get_expiration (
	IN void * const global_data,
	IN const unsigned char * const blob,
	IN const size_t blob_size,
	OUT time_t * const expiration
) {
	X509 *x509 = NULL;
	__pkcs11_openssl_d2i_t d2i;
	ASN1_TIME *notBefore;
	ASN1_TIME *notAfter;

	(void)global_data;

	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
	_PKCS11H_ASSERT (blob!=NULL);
	_PKCS11H_ASSERT (expiration!=NULL);

	*expiration = (time_t)0;

	if ((x509 = X509_new ()) == NULL) {
		goto cleanup;
	}

	d2i = (__pkcs11_openssl_d2i_t)blob;

	if (!d2i_X509 (&x509, &d2i, blob_size)) {
		goto cleanup;
	}

	notBefore = X509_get_notBefore (x509);
	notAfter = X509_get_notAfter (x509);

	if (
		notBefore != NULL &&
		notAfter != NULL &&
		X509_cmp_current_time (notBefore) <= 0 &&
		X509_cmp_current_time (notAfter) >= 0 &&
		notAfter->length >= 12
	) {
		struct tm tm1;

		memset (&tm1, 0, sizeof (tm1));
		tm1.tm_year = (notAfter->data[ 0] - '0') * 10 + (notAfter->data[ 1] - '0') + 100;
		tm1.tm_mon  = (notAfter->data[ 2] - '0') * 10 + (notAfter->data[ 3] - '0') - 1;
		tm1.tm_mday = (notAfter->data[ 4] - '0') * 10 + (notAfter->data[ 5] - '0');
		tm1.tm_hour = (notAfter->data[ 6] - '0') * 10 + (notAfter->data[ 7] - '0');
		tm1.tm_min  = (notAfter->data[ 8] - '0') * 10 + (notAfter->data[ 9] - '0');
		tm1.tm_sec  = (notAfter->data[10] - '0') * 10 + (notAfter->data[11] - '0');

		*expiration = mktime (&tm1);
		*expiration += (int)(mktime (localtime (expiration)) - mktime (gmtime (expiration)));
	}

cleanup:

	if (x509 != NULL) {
		X509_free (x509);
		x509 = NULL;
	}

	return *expiration != (time_t)0;
}
Beispiel #2
0
// Creates a X509 certificate, if rootcert is NULL this creates a root (self-signed) certificate.
// Is the name parameter is NULL, the hex value of the hash of the public key will be the subject name.
int __fastcall util_mkCert(struct util_cert *rootcert, struct util_cert* cert, int bits, int days, char* name, enum CERTIFICATE_TYPES certtype, struct util_cert* initialcert)
{
	X509 *x = NULL;
	X509_EXTENSION *ex = NULL;
	EVP_PKEY *pk = NULL;
	RSA *rsa = NULL;
	X509_NAME *cname=NULL;
	X509 **x509p = NULL;
	EVP_PKEY **pkeyp = NULL;
	char hash[UTIL_HASHSIZE];
	char serial[8];
	char nameStr[(UTIL_HASHSIZE * 2) + 2];
	BIGNUM *oBigNbr;

	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

	if (initialcert != NULL)
	{
		pk = X509_get_pubkey(initialcert->x509);
		rsa = EVP_PKEY_get1_RSA(initialcert->pkey);
		if ((x=X509_new()) == NULL) goto err;
	}
	else
	{
		if ((pkeyp == NULL) || (*pkeyp == NULL)) { if ((pk = EVP_PKEY_new()) == NULL) return 0; } else pk = *pkeyp;
		if ((x509p == NULL) || (*x509p == NULL)) { if ((x=X509_new()) == NULL) goto err; } else x = *x509p;
		oBigNbr = BN_new();
		rsa = RSA_new();
		BN_set_word(oBigNbr, RSA_F4);
		if (RSA_generate_key_ex(rsa, bits, oBigNbr, NULL) == -1)
		{
			RSA_free(rsa);
			BN_free(oBigNbr);
			abort();
			goto err;
		}
		BN_free(oBigNbr);
	}

	if (!EVP_PKEY_assign_RSA(pk, rsa))
	{
		RSA_free(rsa);
		abort();
		goto err;
	}
	rsa = NULL;

	util_randomtext(8, serial);
	X509_set_version(x, 2);
	ASN1_STRING_set(X509_get_serialNumber(x), serial, 8);
	X509_gmtime_adj(X509_get_notBefore(x),(long)60*60*24*-2);
	X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);
	X509_set_pubkey(x, pk);

	// Set the subject name
	cname = X509_get_subject_name(x);

	if (name == NULL)
	{
		// Computer the hash of the public key
		util_sha256((char*)x->cert_info->key->public_key->data, x->cert_info->key->public_key->length, hash);
		util_tohex(hash, UTIL_HASHSIZE, nameStr);
		X509_NAME_add_entry_by_txt(cname,"CN", MBSTRING_ASC, (unsigned char*)nameStr, -1, -1, 0);
	}
	else
	{
		// This function creates and adds the entry, working out the correct string type and performing checks on its length. Normally we'd check the return value for errors...
		X509_NAME_add_entry_by_txt(cname,"CN", MBSTRING_ASC, (unsigned char*)name, -1, -1, 0);
	}

	if (rootcert == NULL)
	{
		// Its self signed so set the issuer name to be the same as the subject.
		X509_set_issuer_name(x,cname);

		// Add various extensions: standard extensions
		util_add_ext(x, NID_basic_constraints, "critical,CA:TRUE");
		util_add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign");

		util_add_ext(x, NID_subject_key_identifier, "hash");
		//util_add_ext(x, NID_netscape_cert_type, "sslCA");
		//util_add_ext(x, NID_netscape_comment, "example comment extension");

		if (!X509_sign(x, pk, EVP_sha256())) goto err;
	}
	else
	{
		// This is a sub-certificate
		cname=X509_get_subject_name(rootcert->x509);
		X509_set_issuer_name(x, cname);

		// Add usual cert stuff
		ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, "digitalSignature, keyEncipherment, keyAgreement");
		X509_add_ext(x, ex, -1);
		X509_EXTENSION_free(ex);

		// Add usages: TLS server, TLS client, Intel(R) AMT Console
		//ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Server Authentication, TLS Web Client Authentication, 2.16.840.1.113741.1.2.1, 2.16.840.1.113741.1.2.2");
		if (certtype == CERTIFICATE_TLS_SERVER)
		{
			// TLS server
			ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Server Authentication");
			X509_add_ext(x, ex, -1);
			X509_EXTENSION_free(ex);
		}
		else if (certtype == CERTIFICATE_TLS_CLIENT)
		{
			// TLS client
			ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Client Authentication");
			X509_add_ext(x, ex, -1);
			X509_EXTENSION_free(ex);
		}

		if (!X509_sign(x, rootcert->pkey, EVP_sha256())) goto err;
	}

	cert->x509 = x;
	cert->pkey = pk;

	return(1);
err:
	return(0);
}
Beispiel #3
0
LWS_VISIBLE LWS_EXTERN int
lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
			     const char *san_b)
{
	GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
	GENERAL_NAME *gen = NULL;
	ASN1_IA5STRING *ia5 = NULL;
	X509_NAME *name;

	if (!gens)
		return 1;

	vhost->tls.ss = lws_zalloc(sizeof(*vhost->tls.ss), "sni cert");
	if (!vhost->tls.ss) {
		GENERAL_NAMES_free(gens);
		return 1;
	}

	vhost->tls.ss->x509 = X509_new();
	if (!vhost->tls.ss->x509)
		goto bail;

	ASN1_INTEGER_set(X509_get_serialNumber(vhost->tls.ss->x509), 1);
	X509_gmtime_adj(X509_get_notBefore(vhost->tls.ss->x509), 0);
	X509_gmtime_adj(X509_get_notAfter(vhost->tls.ss->x509), 3600);

	vhost->tls.ss->pkey = EVP_PKEY_new();
	if (!vhost->tls.ss->pkey)
		goto bail0;

	if (lws_tls_openssl_rsa_new_key(&vhost->tls.ss->rsa, 4096))
		goto bail1;

	if (!EVP_PKEY_assign_RSA(vhost->tls.ss->pkey, vhost->tls.ss->rsa))
		goto bail2;

	X509_set_pubkey(vhost->tls.ss->x509, vhost->tls.ss->pkey);

	name = X509_get_subject_name(vhost->tls.ss->x509);
	X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
				   (unsigned char *)"GB",          -1, -1, 0);
	X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
				   (unsigned char *)"somecompany", -1, -1, 0);
	if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_UTF8,
				   (unsigned char *)"temp.acme.invalid",
				   	   	   -1, -1, 0) != 1) {
		lwsl_notice("failed to add CN\n");
		goto bail2;
	}
	X509_set_issuer_name(vhost->tls.ss->x509, name);

	/* add the SAN payloads */

	gen = GENERAL_NAME_new();
	ia5 = ASN1_IA5STRING_new();
	if (!ASN1_STRING_set(ia5, san_a, -1)) {
		lwsl_notice("failed to set ia5\n");
		GENERAL_NAME_free(gen);
		goto bail2;
	}
	GENERAL_NAME_set0_value(gen, GEN_DNS, ia5);
	sk_GENERAL_NAME_push(gens, gen);

	if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name,
			    gens, 0, X509V3_ADD_APPEND) != 1)
		goto bail2;

	GENERAL_NAMES_free(gens);

	if (san_b && san_b[0]) {
		gens = sk_GENERAL_NAME_new_null();
		gen = GENERAL_NAME_new();
		ia5 = ASN1_IA5STRING_new();
		if (!ASN1_STRING_set(ia5, san_a, -1)) {
			lwsl_notice("failed to set ia5\n");
			GENERAL_NAME_free(gen);
			goto bail2;
		}
		GENERAL_NAME_set0_value(gen, GEN_DNS, ia5);
		sk_GENERAL_NAME_push(gens, gen);

		if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name,
				    gens, 0, X509V3_ADD_APPEND) != 1)
			goto bail2;

		GENERAL_NAMES_free(gens);
	}

	/* sign it with our private key */
	if (!X509_sign(vhost->tls.ss->x509, vhost->tls.ss->pkey, EVP_sha256()))
		goto bail2;

#if 0
	{/* useful to take a sample of a working cert for mbedtls to crib */
		FILE *fp = fopen("/tmp/acme-temp-cert", "w+");

		i2d_X509_fp(fp, vhost->tls.ss->x509);
		fclose(fp);
	}
#endif

	/* tell the vhost to use our crafted certificate */
	SSL_CTX_use_certificate(vhost->tls.ssl_ctx, vhost->tls.ss->x509);
	/* and to use our generated private key */
	SSL_CTX_use_PrivateKey(vhost->tls.ssl_ctx, vhost->tls.ss->pkey);

	return 0;

bail2:
	RSA_free(vhost->tls.ss->rsa);
bail1:
	EVP_PKEY_free(vhost->tls.ss->pkey);
bail0:
	X509_free(vhost->tls.ss->x509);
bail:
	lws_free(vhost->tls.ss);
	GENERAL_NAMES_free(gens);

	return 1;
}
Beispiel #4
0
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
	     X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
	     int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
	{
	int ret=0;
	ASN1_INTEGER *bs=NULL;
	X509_STORE_CTX xsc;
	EVP_PKEY *upkey;

	upkey = X509_get_pubkey(xca);
	EVP_PKEY_copy_parameters(upkey,pkey);
	EVP_PKEY_free(upkey);

	if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL))
		{
		BIO_printf(bio_err,"Error initialising X509 store\n");
		goto end;
		}
	if (sno) bs = sno;
	else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
		goto end;

/*	if (!X509_STORE_add_cert(ctx,x)) goto end;*/

	/* NOTE: this certificate can/should be self signed, unless it was
	 * a certificate request in which case it is not. */
	X509_STORE_CTX_set_cert(&xsc,x);
	if (!reqfile && X509_verify_cert(&xsc) <= 0)
		goto end;

	if (!X509_check_private_key(xca,pkey))
		{
		BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
		goto end;
		}

	if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end;
	if (!X509_set_serialNumber(x,bs)) goto end;

	if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL)
		goto end;

	/* hardwired expired */
	if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
		goto end;

	if (clrext)
		{
		while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
		}

	if (conf)
		{
		X509V3_CTX ctx2;
		X509_set_version(x,2); /* version 3 certificate */
                X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
                X509V3_set_nconf(&ctx2, conf);
                if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
		}

	if (!X509_sign(x,pkey,digest)) goto end;
	ret=1;
end:
	X509_STORE_CTX_cleanup(&xsc);
	if (!ret)
		ERR_print_errors(bio_err);
	if (!sno) ASN1_INTEGER_free(bs);
	return ret;
	}
int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
	{
	long l;
	int ret=0,i;
	char *m=NULL,mlch = ' ';
	int nmindent = 0;
	X509_CINF *ci;
	ASN1_INTEGER *bs;
	EVP_PKEY *pkey=NULL;
	const char *neg;

	if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
			mlch = '\n';
			nmindent = 12;
	}

	if(nmflags == X509_FLAG_COMPAT)
		nmindent = 16;

	ci=x->cert_info;
	if(!(cflag & X509_FLAG_NO_HEADER))
		{
		if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err;
		if (BIO_write(bp,"    Data:\n",10) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_VERSION))
		{
		l=X509_get_version(x);
		if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_SERIAL))
		{

		if (BIO_write(bp,"        Serial Number:",22) <= 0) goto err;

		bs=X509_get_serialNumber(x);
		if (bs->length <= 4)
			{
			l=ASN1_INTEGER_get(bs);
			if (l < 0)
				{
				l= -l;
				neg="-";
				}
			else
				neg="";
			if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0)
				goto err;
			}
		else
			{
			neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":"";
			if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err;

			for (i=0; i<bs->length; i++)
				{
				if (BIO_printf(bp,"%02x%c",bs->data[i],
					((i+1 == bs->length)?'\n':':')) <= 0)
					goto err;
				}
			}

		}

	if(!(cflag & X509_FLAG_NO_SIGNAME))
		{
		if (BIO_printf(bp,"%8sSignature Algorithm: ","") <= 0) 
			goto err;
		if (i2a_ASN1_OBJECT(bp, ci->signature->algorithm) <= 0)
			goto err;
		if (BIO_puts(bp, "\n") <= 0)
			goto err;
		}

	if(!(cflag & X509_FLAG_NO_ISSUER))
		{
		if (BIO_printf(bp,"        Issuer:%c",mlch) <= 0) goto err;
		if (X509_NAME_print_ex(bp,X509_get_issuer_name(x),nmindent, nmflags) < 0) goto err;
		if (BIO_write(bp,"\n",1) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_VALIDITY))
		{
		if (BIO_write(bp,"        Validity\n",17) <= 0) goto err;
		if (BIO_write(bp,"            Not Before: ",24) <= 0) goto err;
		if (!ASN1_TIME_print(bp,X509_get_notBefore(x))) goto err;
		if (BIO_write(bp,"\n            Not After : ",25) <= 0) goto err;
		if (!ASN1_TIME_print(bp,X509_get_notAfter(x))) goto err;
		if (BIO_write(bp,"\n",1) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_SUBJECT))
		{
		if (BIO_printf(bp,"        Subject:%c",mlch) <= 0) goto err;
		if (X509_NAME_print_ex(bp,X509_get_subject_name(x),nmindent, nmflags) < 0) goto err;
		if (BIO_write(bp,"\n",1) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_PUBKEY))
		{
		if (BIO_write(bp,"        Subject Public Key Info:\n",33) <= 0)
			goto err;
		if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0)
			goto err;
		if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
			goto err;
		if (BIO_puts(bp, "\n") <= 0)
			goto err;

		pkey=X509_get_pubkey(x);
		if (pkey == NULL)
			{
			BIO_printf(bp,"%12sUnable to load Public Key\n","");
			ERR_print_errors(bp);
			}
		else
			{
			EVP_PKEY_print_public(bp, pkey, 16, NULL);
			EVP_PKEY_free(pkey);
			}
		}

	if (!(cflag & X509_FLAG_NO_EXTENSIONS))
		X509V3_extensions_print(bp, "X509v3 extensions",
					ci->extensions, cflag, 8);

	if(!(cflag & X509_FLAG_NO_SIGDUMP))
		{
		if(X509_signature_print(bp, x->sig_alg, x->signature) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_AUX))
		{
		if (!X509_CERT_AUX_print(bp, x->aux, 0)) goto err;
		}
	ret=1;
err:
	if (m != NULL) OPENSSL_free(m);
	return(ret);
	}
Beispiel #6
0
/** Generate and sign an X509 certificate with the public key <b>rsa</b>,
 * signed by the private key <b>rsa_sign</b>.  The commonName of the
 * certificate will be <b>cname</b>; the commonName of the issuer will be
 * <b>cname_sign</b>. The cert will be valid for <b>cert_lifetime</b> seconds
 * starting from now.  Return a certificate on success, NULL on
 * failure.
 */
static X509 *
tor_tls_create_certificate(crypto_pk_env_t *rsa,
                           crypto_pk_env_t *rsa_sign,
                           const char *cname,
                           const char *cname_sign,
                           unsigned int cert_lifetime)
{
  time_t start_time, end_time;
  EVP_PKEY *sign_pkey = NULL, *pkey=NULL;
  X509 *x509 = NULL;
  X509_NAME *name = NULL, *name_issuer=NULL;

  tor_tls_init();

  start_time = time(NULL);

  tor_assert(rsa);
  tor_assert(cname);
  tor_assert(rsa_sign);
  tor_assert(cname_sign);
  if (!(sign_pkey = _crypto_pk_env_get_evp_pkey(rsa_sign,1)))
    goto error;
  if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,0)))
    goto error;
  if (!(x509 = X509_new()))
    goto error;
  if (!(X509_set_version(x509, 2)))
    goto error;
  if (!(ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)start_time)))
    goto error;

  if (!(name = tor_x509_name_new(cname)))
    goto error;
  if (!(X509_set_subject_name(x509, name)))
    goto error;
  if (!(name_issuer = tor_x509_name_new(cname_sign)))
    goto error;
  if (!(X509_set_issuer_name(x509, name_issuer)))
    goto error;

  if (!X509_time_adj(X509_get_notBefore(x509),0,&start_time))
    goto error;
  end_time = start_time + cert_lifetime;
  if (!X509_time_adj(X509_get_notAfter(x509),0,&end_time))
    goto error;
  if (!X509_set_pubkey(x509, pkey))
    goto error;
  if (!X509_sign(x509, sign_pkey, EVP_sha1()))
    goto error;

  goto done;
 error:
  if (x509) {
    X509_free(x509);
    x509 = NULL;
  }
 done:
  tls_log_errors(NULL, LOG_WARN, "generating certificate");
  if (sign_pkey)
    EVP_PKEY_free(sign_pkey);
  if (pkey)
    EVP_PKEY_free(pkey);
  if (name)
    X509_NAME_free(name);
  if (name_issuer)
    X509_NAME_free(name_issuer);
  return x509;
}
Beispiel #7
0
void anubis_dump_server_certificate(SSL *ssl) {
    X509 *x509Cert = SSL_get_peer_certificate(ssl);
    char buffer[1024];
    BIO *bio = NULL;
    char *buf = NULL;
    
    if(!x509Cert) {
        anubis_ssl_perror("SSL_get_peer_certificate()");
        return;
    }
    
    bio = BIO_new(BIO_s_mem());
    if(!bio) {
        anubis_ssl_perror("BIO_new()");
        X509_free(x509Cert);
        return;
    }//end if
    
    BIO_reset(bio);
    if(!PEM_write_bio_X509(bio, x509Cert)) {
        anubis_ssl_perror("PEM_write_bio_X509()");
        BIO_free(bio);
        X509_free(x509Cert);
        return;
    }
    BIO_get_mem_data(bio, &buf);
    anubis_out("Server certificate:\n%s", buf);
    // Cert Version
    long version = 0;
    if (!(X509_FLAG_COMPAT & X509_FLAG_NO_VERSION)) {
        version = X509_get_version(x509Cert);
        fprintf(out_stream, "Version: %ld\n", version);
    }//end if
    
    // Cert Serial No. - Code adapted from OpenSSL's crypto/asn1/t_x509.c
    if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SERIAL)) {
        ASN1_INTEGER *bs;
        long l;
        int i;
        const char *neg;
        bs = X509_get_serialNumber(x509Cert);
        
        if (bs->length <= 4) {
            l = ASN1_INTEGER_get(bs);
            if (l < 0) {
                l= -l;
                neg = "-";
            }
            else
                neg = "";
            
            fprintf(out_stream, "Serial Number: %lu (%#lx)\n", l, l);
        }
        else {
            neg = (bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":"";
            fprintf(out_stream, "Serial Number: %s", neg);
            for (i = 0; i < bs->length; i++) {
                fprintf(out_stream, "%02x%c", bs->data[i], (i+1 == bs->length)?'\n':':');
            }
        }
    }
    
    // Signature Algo...
    if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SIGNAME)) {
        i2a_ASN1_OBJECT(bio, x509Cert->cert_info->signature->algorithm);
        BIO_get_mem_data(bio, &buf);
        fprintf(out_stream, "Signature Algorithm:\n%s\n", buf);
    }
    
    // SSL Certificate Issuer...
    if (!(X509_FLAG_COMPAT & X509_FLAG_NO_ISSUER)) {
        X509_NAME_oneline(X509_get_issuer_name(x509Cert), buffer, sizeof(buffer) - 1);
        fprintf(out_stream, "Issuer: %s\n", buffer);
    }
    
    // Validity...
    if (!(X509_FLAG_COMPAT & X509_FLAG_NO_VALIDITY)) {
        BIO_reset(bio);
        ASN1_TIME_print(bio, X509_get_notBefore(x509Cert));
        BIO_get_mem_data(bio, &buf);
        fprintf(out_stream, "Not Valid Before: %s\n", buf);
        
        BIO_reset(bio);
        ASN1_TIME_print(bio, X509_get_notAfter(x509Cert));
        BIO_get_mem_data(bio, &buf);
        fprintf(out_stream, "Not Valid After: %s\n", buf);
    }
    
    // SSL Certificate Subject...
    if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SUBJECT)) {
        X509_NAME_oneline(X509_get_subject_name(x509Cert), buffer, sizeof(buffer) - 1);
        fprintf(out_stream, "Subject: %s\n", buffer);
    }
    
    // Public Key Algo...
    if (!(X509_FLAG_COMPAT & X509_FLAG_NO_PUBKEY)) {
        BIO_reset(bio);
        i2a_ASN1_OBJECT(bio, x509Cert->cert_info->key->algor->algorithm);
        BIO_get_mem_data(bio, &buf);
        fprintf(out_stream, "Public Key Algorithm: %s\n", buf);
        
        // Public Key...
        EVP_PKEY *publicKey = NULL;
        publicKey = X509_get_pubkey(x509Cert);
        if (publicKey == NULL) {
            anubis_err("Public Key Could not load\n");
        }
        else {
            BIO_reset(bio);
            char *publicKeyType = NULL;
            int publicKeyLength = -1;
            switch (publicKey->type) {
                case EVP_PKEY_RSA:
                    
                    publicKeyType = "RSA";
                    
                    if (publicKey->pkey.rsa) {
                        publicKeyLength = BN_num_bits(publicKey->pkey.rsa->n);
                        RSA_print(bio, publicKey->pkey.rsa, 0);
                        BIO_get_mem_data(bio, &buf);
                    }
                    break;
                case EVP_PKEY_DSA:
                    
                    publicKeyType = "DSA";
                    
                    if (publicKey->pkey.dsa) {
                        DSA_print(bio, publicKey->pkey.dsa, 0);
                        BIO_get_mem_data(bio, &buf);
                    }
                    break;
                case EVP_PKEY_EC:
                    publicKeyType = "EC";
                    
                    if (publicKey->pkey.ec)  {
                        EC_KEY_print(bio, publicKey->pkey.ec, 0);
                        BIO_get_mem_data(bio, &buf);
                    }
                    break;
                default:
                    publicKeyType = "Unknown";
                    break;
            }
            
            EVP_PKEY_free(publicKey);
            fprintf(out_stream, "%d Public Key: ", publicKeyLength);
            if(!strcasecmp(publicKeyType, "RSA")) {
                fprintf(out_stream, "(%d bits)", publicKeyLength);
            }
            fprintf(out_stream, "\n");
            fprintf(out_stream, "%s\n", buf);
        }
    }
    
    // X509 v3...
    if (!(X509_FLAG_COMPAT & X509_FLAG_NO_EXTENSIONS) && sk_X509_EXTENSION_num(x509Cert->cert_info->extensions) > 0) {
        X509_EXTENSION *extension = NULL;
        ASN1_OBJECT *asn1Object = NULL;
        int tempInt2 = 0;
        BIO_reset(bio);
        for (int tempInt = 0; tempInt < sk_X509_EXTENSION_num(x509Cert->cert_info->extensions); tempInt++) {
            // Get Extension...
            extension = sk_X509_EXTENSION_value(x509Cert->cert_info->extensions, tempInt);
            
            asn1Object = X509_EXTENSION_get_object(extension);
            i2a_ASN1_OBJECT(bio, asn1Object);
            tempInt2 = X509_EXTENSION_get_critical(extension);
            BIO_printf(bio, ": %s\n", tempInt2 ? "critical" : "");
            
            // Print Extension value...
            if (!X509V3_EXT_print(bio, extension, X509_FLAG_COMPAT, 8)) {
                M_ASN1_OCTET_STRING_print(bio, extension->value);
            }
            BIO_printf(bio, "\n");
        }//end for
        
        BIO_get_mem_data(bio, &buf);
        fprintf(out_stream, "x509v3 Extensions: %s\n", buf);
    }//end if x509v3
    
    /*
    long verifyError = 0;
    // Verify Certificate...
    verifyError = SSL_get_verify_result(ssl);
    const char *verifyCertificate = "";
    if (verifyError == X509_V_OK)
        verifyCertificate = "Certificate passed verification";
    else
        verifyCertificate = X509_verify_cert_error_string(verifyError);
    fprintf(out_stream, "Validation: %s\n", verifyCertificate);
    */
    
    BIO_free(bio);
    X509_free(x509Cert);
    fflush(out_stream);
}//end anubis_dump_server_certificate
Beispiel #8
0
/**
 * setup callback to allow the user to examine certificates which have
 * failed to validate during fetch.
 */
static void
curl_start_cert_validate(struct curl_fetch_info *f,
			 struct cert_info *certs)
{
	int depth;
	BIO *mem;
	BUF_MEM *buf;
	struct ssl_cert_info ssl_certs[MAX_CERTS];
	fetch_msg msg;

	for (depth = 0; depth <= f->cert_depth; depth++) {
		assert(certs[depth].cert != NULL);

		/* get certificate version */
		ssl_certs[depth].version = X509_get_version(certs[depth].cert);

		/* not before date */
		mem = BIO_new(BIO_s_mem());
		ASN1_TIME_print(mem, X509_get_notBefore(certs[depth].cert));
		BIO_get_mem_ptr(mem, &buf);
		(void) BIO_set_close(mem, BIO_NOCLOSE);
		BIO_free(mem);
		memcpy(ssl_certs[depth].not_before,
		       buf->data,
		       min(sizeof(ssl_certs[depth].not_before) - 1,
			   (unsigned)buf->length));
		ssl_certs[depth].not_before[min(sizeof(ssl_certs[depth].not_before) - 1,
					    (unsigned)buf->length)] = 0;
		BUF_MEM_free(buf);

		/* not after date */
		mem = BIO_new(BIO_s_mem());
		ASN1_TIME_print(mem,
				X509_get_notAfter(certs[depth].cert));
		BIO_get_mem_ptr(mem, &buf);
		(void) BIO_set_close(mem, BIO_NOCLOSE);
		BIO_free(mem);
		memcpy(ssl_certs[depth].not_after,
		       buf->data,
		       min(sizeof(ssl_certs[depth].not_after) - 1,
			   (unsigned)buf->length));
		ssl_certs[depth].not_after[min(sizeof(ssl_certs[depth].not_after) - 1,
					   (unsigned)buf->length)] = 0;
		BUF_MEM_free(buf);

		/* signature type */
		ssl_certs[depth].sig_type =
			X509_get_signature_type(certs[depth].cert);

		/* serial number */
		ssl_certs[depth].serial =
			ASN1_INTEGER_get(
				X509_get_serialNumber(certs[depth].cert));

		/* issuer name */
		mem = BIO_new(BIO_s_mem());
		X509_NAME_print_ex(mem,
				   X509_get_issuer_name(certs[depth].cert),
				   0, XN_FLAG_SEP_CPLUS_SPC |
				   XN_FLAG_DN_REV | XN_FLAG_FN_NONE);
		BIO_get_mem_ptr(mem, &buf);
		(void) BIO_set_close(mem, BIO_NOCLOSE);
		BIO_free(mem);
		memcpy(ssl_certs[depth].issuer,
		       buf->data,
		       min(sizeof(ssl_certs[depth].issuer) - 1,
			   (unsigned) buf->length));
		ssl_certs[depth].issuer[min(sizeof(ssl_certs[depth].issuer) - 1,
					(unsigned) buf->length)] = 0;
		BUF_MEM_free(buf);

		/* subject */
		mem = BIO_new(BIO_s_mem());
		X509_NAME_print_ex(mem,
				   X509_get_subject_name(certs[depth].cert),
				   0,
				   XN_FLAG_SEP_CPLUS_SPC |
				   XN_FLAG_DN_REV |
				   XN_FLAG_FN_NONE);
		BIO_get_mem_ptr(mem, &buf);
		(void) BIO_set_close(mem, BIO_NOCLOSE);
		BIO_free(mem);
		memcpy(ssl_certs[depth].subject,
		       buf->data,
		       min(sizeof(ssl_certs[depth].subject) - 1,
			   (unsigned)buf->length));
		ssl_certs[depth].subject[min(sizeof(ssl_certs[depth].subject) - 1,
					 (unsigned) buf->length)] = 0;
		BUF_MEM_free(buf);

		/* type of certificate */
		ssl_certs[depth].cert_type =
			X509_certificate_type(certs[depth].cert,
					      X509_get_pubkey(certs[depth].cert));

		/* and clean up */
		certs[depth].cert->references--;
		if (certs[depth].cert->references == 0) {
			X509_free(certs[depth].cert);
		}
	}

	msg.type = FETCH_CERT_ERR;
	msg.data.cert_err.certs = ssl_certs;
	msg.data.cert_err.num_certs = depth;
	fetch_send_callback(&msg, f->fetch_handle);
}
Beispiel #9
0
/* Creates an X509 certificate from a certificate request. */
EXPORT int IssueUserCertificate(unsigned char *certbuf, int *certlen, unsigned char *reqbuf, int reqlen)
{
	X509_REQ *req = NULL;
	EVP_PKEY *cakey = NULL, *rakey = NULL, *usrkey = NULL;
	X509 *cacert = NULL, *racert = NULL, *usrcert = NULL;
	X509_NAME *subject = NULL, *issuer = NULL;
	unsigned char *p = NULL;
	int ret = OPENSSLCA_NO_ERR, len;

	if (certbuf == NULL || certlen == NULL || reqbuf == NULL || reqlen == 0)
		return OPENSSLCA_ERR_ARGS;

	/* Decode request */
	if ((req = X509_REQ_new()) == NULL) {
		ret = OPENSSLCA_ERR_REQ_NEW;
		goto err;
	}
	p = reqbuf;
	if (d2i_X509_REQ(&req, &p, reqlen) == NULL) {
		ret = OPENSSLCA_ERR_REQ_DECODE;
		goto err;
	}

	/* Get public key from request */
	if ((usrkey = X509_REQ_get_pubkey(req)) == NULL) {
		ret = OPENSSLCA_ERR_REQ_GET_PUBKEY;
		goto err;
	}

	if (caIni.verifyRequests) {
		/* Get RA's public key */
		/* TODO: Validate RA certificate */
		ret = read_cert(&racert, CA_PATH(caIni.raCertFile));
		if (ret != OPENSSLCA_NO_ERR)
			goto err;
		if ((rakey = X509_get_pubkey(racert)) == NULL) {
			ret = OPENSSLCA_ERR_CERT_GET_PUBKEY;
			goto err;
		}

		/* Verify signature on request */
		if (X509_REQ_verify(req, rakey) != 1) {
			ret = OPENSSLCA_ERR_REQ_VERIFY;
			goto err;
		}
	}

	/* Get CA certificate */
	/* TODO: Validate CA certificate */
	ret = read_cert(&cacert, CA_PATH(caIni.caCertFile));
	if (ret != OPENSSLCA_NO_ERR)
		goto err;

	/* Get CA private key */
	ret = read_key(&cakey, CA_PATH(caIni.caKeyFile), caIni.caKeyPasswd);
	if (ret != OPENSSLCA_NO_ERR)
		goto err;

	/* Create user certificate */
	if ((usrcert = X509_new()) == NULL)
		return OPENSSLCA_ERR_CERT_NEW;

	/* Set version and serial number for certificate */
	if (X509_set_version(usrcert, 2) != 1) { /* V3 */
		ret = OPENSSLCA_ERR_CERT_SET_VERSION;
		goto err;
	}
	if (ASN1_INTEGER_set(X509_get_serialNumber(usrcert), get_serial()) != 1) {
		ret = OPENSSLCA_ERR_CERT_SET_SERIAL;
		goto err;
	}

	/* Set duration for certificate */
	if (X509_gmtime_adj(X509_get_notBefore(usrcert), 0) == NULL) {
		ret = OPENSSLCA_ERR_CERT_SET_NOTBEFORE;
		goto err;
	}
	if (X509_gmtime_adj(X509_get_notAfter(usrcert), EXPIRE_SECS(caIni.daysTillExpire)) == NULL) {
		ret = OPENSSLCA_ERR_CERT_SET_NOTAFTER;
		goto err;
	}

	/* Set public key */
	if (X509_set_pubkey(usrcert, usrkey) != 1) {
		ret = OPENSSLCA_ERR_CERT_SET_PUBKEY;
		goto err;
	}

	/* Set subject name */
	subject = X509_REQ_get_subject_name(req);
	if (subject == NULL) {
		ret = OPENSSLCA_ERR_REQ_GET_SUBJECT;
		goto err;
	}
	if (X509_set_subject_name(usrcert, subject) != 1) {
		ret = OPENSSLCA_ERR_CERT_SET_SUBJECT;
		goto err;
	}

	/* Set issuer name */
	issuer = X509_get_issuer_name(cacert);
	if (issuer == NULL) {
		ret = OPENSSLCA_ERR_CERT_GET_ISSUER;
		goto err;
	}
	if (X509_set_issuer_name(usrcert, issuer) != 1) {
		ret = OPENSSLCA_ERR_CERT_SET_ISSUER;
		goto err;
	}

	/* Add extensions */
	ret = add_ext(cacert, usrcert);
	if (ret != OPENSSLCA_NO_ERR)
		goto err;

	/* Sign user certificate with CA's private key */
	if (!X509_sign(usrcert, cakey, EVP_sha1()))
		return OPENSSLCA_ERR_CERT_SIGN;

	if (caIni.verifyAfterSign) {
		if (X509_verify(usrcert, cakey) != 1) {
			ret = OPENSSLCA_ERR_CERT_VERIFY;
			goto err;
		}
	}

#ifdef _DEBUG /* Output certificate in DER and PEM format */
	{
		FILE *fp = fopen(DBG_PATH("usrcert.der"), "wb");
		if (fp != NULL) {
			i2d_X509_fp(fp, usrcert);
			fclose(fp);
		}
		fp = fopen(DBG_PATH("usrcert.pem"), "w");
		if (fp != NULL) {
			X509_print_fp(fp, usrcert);
			PEM_write_X509(fp, usrcert);
			fclose(fp);
		}
	}
#endif

	/* Encode user certificate into DER format */
	len = i2d_X509(usrcert, NULL);
	if (len < 0) {
		ret = OPENSSLCA_ERR_CERT_ENCODE;
		goto err;
	}
	if (len > *certlen) {
		ret = OPENSSLCA_ERR_BUF_TOO_SMALL;
		goto err;
	}
	*certlen = len;
	p = certbuf;
	i2d_X509(usrcert, &p);

	if (caIni.addToIndex)
		add_to_index(usrcert);

	if (caIni.addToNewCerts)
		write_cert(usrcert);

err:
	print_err("IssueUserCertificate()", ret);

	/* Clean up */
	if (cacert)
		X509_free(cacert);
	if (cakey)
		EVP_PKEY_free(cakey);
	if (racert)
		X509_free(racert);
	if (rakey)
		EVP_PKEY_free(rakey);
	if (req)
		X509_REQ_free(req);
	if (usrcert != NULL)
		X509_free(usrcert);
	if (usrkey)
		EVP_PKEY_free(usrkey);

	return ret;
}
Beispiel #10
0
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
    X509 *x;
    EVP_PKEY *pk;
    RSA *rsa;
    X509_NAME *name = NULL;
    
    if (*pkeyp == NULL) {
        if ((pk=EVP_PKEY_new()) == NULL) {
            return(0);
        }
    } else {
        pk = *pkeyp;
    }
    
    if (*x509p == NULL) {
        if ((x = X509_new()) == NULL) {
            goto err;
        }
    } else {
        x = *x509p;
    }
    
    rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
    if (!EVP_PKEY_assign_RSA(pk, rsa)) {
        goto err;
    }
    
    X509_set_version(x, 2);
    ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
    X509_gmtime_adj(X509_get_notBefore(x), 0);
    X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*365*years);
    X509_set_pubkey(x, pk);
    
    name = X509_get_subject_name(x);
    
    /* This function creates and adds the entry, working out the
     * correct string type and performing checks on its length.
     */
    X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (unsigned char*)"NVIDIA GameStream Client", -1, -1, 0);
    
    /* Its self signed so set the issuer name to be the same as the
     * subject.
     */
    X509_set_issuer_name(x, name);
    
    /* Add various extensions: standard extensions */
    add_ext(x, NID_basic_constraints, "critical,CA:TRUE");
    add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign");
    
    add_ext(x, NID_subject_key_identifier, "hash");
    
    if (!X509_sign(x, pk, EVP_sha1())) {
        goto err;
    }
    
    *x509p = x;
    *pkeyp = pk;
    
    return(1);
err:
    return(0);
}
Beispiel #11
0
static int janus_dtls_generate_keys(X509** certificate, EVP_PKEY** private_key) {
	static const int num_bits = 2048;
	BIGNUM* bne = NULL;
	RSA* rsa_key = NULL;
	X509_NAME* cert_name = NULL;

	JANUS_LOG(LOG_VERB, "Generating DTLS key / cert\n");

	/* Create a big number object. */
	bne = BN_new();
	if (!bne) {
		JANUS_LOG(LOG_FATAL, "BN_new() failed\n");
		goto error;
	}

	if (!BN_set_word(bne, RSA_F4)) {  /* RSA_F4 == 65537 */
		JANUS_LOG(LOG_FATAL, "BN_set_word() failed\n");
		goto error;
	}

	/* Generate a RSA key. */
	rsa_key = RSA_new();
	if (!rsa_key) {
		JANUS_LOG(LOG_FATAL, "RSA_new() failed\n");
		goto error;
	}

	/* This takes some time. */
	if (!RSA_generate_key_ex(rsa_key, num_bits, bne, NULL)) {
		JANUS_LOG(LOG_FATAL, "RSA_generate_key_ex() failed\n");
		goto error;
	}

	/* Create a private key object (needed to hold the RSA key). */
	*private_key = EVP_PKEY_new();
	if (!*private_key) {
		JANUS_LOG(LOG_FATAL, "EVP_PKEY_new() failed\n");
		goto error;
	}

	if (!EVP_PKEY_assign_RSA(*private_key, rsa_key)) {
		JANUS_LOG(LOG_FATAL, "EVP_PKEY_assign_RSA() failed\n");
		goto error;
	}
	/* The RSA key now belongs to the private key, so don't clean it up separately. */
	rsa_key = NULL;

	/* Create the X509 certificate. */
	*certificate = X509_new();
	if (!*certificate) {
		JANUS_LOG(LOG_FATAL, "X509_new() failed\n");
		goto error;
	}

	/* Set version 3 (note that 0 means version 1). */
	X509_set_version(*certificate, 2);

	/* Set serial number. */
	ASN1_INTEGER_set(X509_get_serialNumber(*certificate), (long)g_random_int());

	/* Set valid period. */
	X509_gmtime_adj(X509_get_notBefore(*certificate), -1 * DTLS_AUTOCERT_DURATION);  /* -1 year */
	X509_gmtime_adj(X509_get_notAfter(*certificate), DTLS_AUTOCERT_DURATION);  /* 1 year */

	/* Set the public key for the certificate using the key. */
	if (!X509_set_pubkey(*certificate, *private_key)) {
		JANUS_LOG(LOG_FATAL, "X509_set_pubkey() failed\n");
		goto error;
	}

	/* Set certificate fields. */
	cert_name = X509_get_subject_name(*certificate);
	if (!cert_name) {
		JANUS_LOG(LOG_FATAL, "X509_get_subject_name() failed\n");
		goto error;
	}
	X509_NAME_add_entry_by_txt(cert_name, "O", MBSTRING_ASC, (const unsigned char*)"Janus", -1, -1, 0);
	X509_NAME_add_entry_by_txt(cert_name, "CN", MBSTRING_ASC, (const unsigned char*)"Janus", -1, -1, 0);

	/* It is self-signed so set the issuer name to be the same as the subject. */
	if (!X509_set_issuer_name(*certificate, cert_name)) {
		JANUS_LOG(LOG_FATAL, "X509_set_issuer_name() failed\n");
		goto error;
	}

	/* Sign the certificate with the private key. */
	if (!X509_sign(*certificate, *private_key, EVP_sha1())) {
		JANUS_LOG(LOG_FATAL, "X509_sign() failed\n");
		goto error;
	}

	/* Free stuff and resurn. */
	BN_free(bne);
	return 0;

error:
	if (bne)
		BN_free(bne);
	if (rsa_key && !*private_key)
		RSA_free(rsa_key);
	if (*private_key)
		EVP_PKEY_free(*private_key);  /* This also frees the RSA key. */
	if (*certificate)
		X509_free(*certificate);
	return -1;
}
int np_net_ssl_check_cert(int days_till_exp){
#  ifdef USE_OPENSSL
	X509 *certificate=NULL;
	X509_NAME *subj=NULL;
	char cn[MAX_CN_LENGTH]= "";
	int cnlen =-1;
	int status=STATE_UNKNOWN;

	ASN1_STRING *tm;
	int offset;
	struct tm stamp;
	float time_left;
	int days_left;
	char timestamp[17] = "";

	certificate=SSL_get_peer_certificate(s);
	if(! certificate){
		printf ("%s\n",_("CRITICAL - Cannot retrieve server certificate."));
		return STATE_CRITICAL;
	}

	/* Extract CN from certificate subject */
	subj=X509_get_subject_name(certificate);

	if(! subj){
		printf ("%s\n",_("CRITICAL - Cannot retrieve certificate subject."));
		return STATE_CRITICAL;
	}
	cnlen = X509_NAME_get_text_by_NID (subj, NID_commonName, cn, sizeof(cn));
	if ( cnlen == -1 )
		strcpy(cn , _("Unknown CN"));

	/* Retrieve timestamp of certificate */
	tm = X509_get_notAfter (certificate);

	/* Generate tm structure to process timestamp */
	if (tm->type == V_ASN1_UTCTIME) {
		if (tm->length < 10) {
			printf ("%s\n", _("CRITICAL - Wrong time format in certificate."));
			return STATE_CRITICAL;
		} else {
			stamp.tm_year = (tm->data[0] - '0') * 10 + (tm->data[1] - '0');
			if (stamp.tm_year < 50)
				stamp.tm_year += 100;
			offset = 0;
		}
	} else {
		if (tm->length < 12) {
			printf ("%s\n", _("CRITICAL - Wrong time format in certificate."));
			return STATE_CRITICAL;
		} else {
			stamp.tm_year =
				(tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 +
				(tm->data[2] - '0') * 10 + (tm->data[3] - '0');
			stamp.tm_year -= 1900;
			offset = 2;
		}
	}
	stamp.tm_mon =
		(tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1;
	stamp.tm_mday =
		(tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0');
	stamp.tm_hour =
		(tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
	stamp.tm_min =
		(tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
	stamp.tm_sec = 0;
	stamp.tm_isdst = -1;

	time_left = difftime(timegm(&stamp), time(NULL));
	days_left = time_left / 86400;
	snprintf
		(timestamp, 17, "%02d/%02d/%04d %02d:%02d",
		 stamp.tm_mon + 1,
		 stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_hour, stamp.tm_min);

	if (days_left > 0 && days_left <= days_till_exp) {
		printf (_("WARNING - Certificate '%s' expires in %d day(s) (%s).\n"), cn, days_left, timestamp);
		status=STATE_WARNING;
	} else if (time_left < 0) {
		printf (_("CRITICAL - Certificate '%s' expired on %s.\n"), cn, timestamp);
		status=STATE_CRITICAL;
	} else if (days_left == 0) {
		printf (_("WARNING - Certificate '%s' expires today (%s).\n"), cn, timestamp);
		status=STATE_WARNING;
	} else {
		printf (_("OK - Certificate '%s' will expire on %s.\n"), cn, timestamp);
		status=STATE_OK;
	}
	X509_free (certificate);
	return status;
#  else /* ifndef USE_OPENSSL */
	printf ("%s\n", _("WARNING - Plugin does not support checking certificates."));
	return STATE_WARNING;
#  endif /* USE_OPENSSL */
}
Beispiel #13
0
/*
    FIXME: Master-Key, Extensions, CA bits
	    (openssl x509 -text -in servcert.pem)
*/
int
_SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
{
	X509 *peer_cert;
	EVP_PKEY *peer_pkey;
	/* EVP_PKEY *ca_pkey; */
	/* EVP_PKEY *tmp_pkey; */
	char notBefore[64];
	char notAfter[64];
	int alg;
	int sign_alg;


	if (!(peer_cert = SSL_get_peer_certificate (ssl)))
		return (1);				  /* FATAL? */

	X509_NAME_oneline (X509_get_subject_name (peer_cert), cert_info->subject,
							 sizeof (cert_info->subject));
	X509_NAME_oneline (X509_get_issuer_name (peer_cert), cert_info->issuer,
							 sizeof (cert_info->issuer));
	broke_oneline (cert_info->subject, cert_info->subject_word);
	broke_oneline (cert_info->issuer, cert_info->issuer_word);

	alg = OBJ_obj2nid (peer_cert->cert_info->key->algor->algorithm);
	sign_alg = OBJ_obj2nid (peer_cert->sig_alg->algorithm);
	ASN1_TIME_snprintf (notBefore, sizeof (notBefore),
							  X509_get_notBefore (peer_cert));
	ASN1_TIME_snprintf (notAfter, sizeof (notAfter),
							  X509_get_notAfter (peer_cert));

	peer_pkey = X509_get_pubkey (peer_cert);

	strncpy (cert_info->algorithm,
				(alg == NID_undef) ? "Unknown" : OBJ_nid2ln (alg),
				sizeof (cert_info->algorithm));
	cert_info->algorithm_bits = EVP_PKEY_bits (peer_pkey);
	strncpy (cert_info->sign_algorithm,
				(sign_alg == NID_undef) ? "Unknown" : OBJ_nid2ln (sign_alg),
				sizeof (cert_info->sign_algorithm));
	/* EVP_PKEY_bits(ca_pkey)); */
	cert_info->sign_algorithm_bits = 0;
	strncpy (cert_info->notbefore, notBefore, sizeof (cert_info->notbefore));
	strncpy (cert_info->notafter, notAfter, sizeof (cert_info->notafter));

	EVP_PKEY_free (peer_pkey);

	/* SSL_SESSION_print_fp(stdout, SSL_get_session(ssl)); */
/*
	if (ssl->session->sess_cert->peer_rsa_tmp) {
		tmp_pkey = EVP_PKEY_new();
		EVP_PKEY_assign_RSA(tmp_pkey, ssl->session->sess_cert->peer_rsa_tmp);
		cert_info->rsa_tmp_bits = EVP_PKEY_bits (tmp_pkey);
		EVP_PKEY_free(tmp_pkey);
	} else
		fprintf(stderr, "REMOTE SIDE DOESN'T PROVIDES ->peer_rsa_tmp\n");
*/
	cert_info->rsa_tmp_bits = 0;

	X509_free (peer_cert);

	return (0);
}
Beispiel #14
0
/**
 * Return not after date.
 */
static int meth_notafter(lua_State *L)
{
  X509* cert = lsec_checkx509(L, 1);
  return push_asn1_time(L, X509_get_notAfter(cert));
}
Beispiel #15
0
int verify_callback(int ok, X509_STORE_CTX *ctx)
{
    X509 *err_cert;
    int err, depth;

    err_cert = X509_STORE_CTX_get_current_cert(ctx);
    err = X509_STORE_CTX_get_error(ctx);
    depth = X509_STORE_CTX_get_error_depth(ctx);

    if (!verify_quiet || !ok) {
        BIO_printf(bio_err, "depth=%d ", depth);
        if (err_cert) {
            X509_NAME_print_ex(bio_err,
                               X509_get_subject_name(err_cert),
                               0, XN_FLAG_ONELINE);
            BIO_puts(bio_err, "\n");
        } else
            BIO_puts(bio_err, "<no cert>\n");
    }
    if (!ok) {
        BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
                   X509_verify_cert_error_string(err));
        if (verify_depth >= depth) {
            if (!verify_return_error)
                ok = 1;
            verify_error = X509_V_OK;
        } else {
            ok = 0;
            verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
        }
    }
    switch (err) {
    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
        BIO_puts(bio_err, "issuer= ");
        X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
                           0, XN_FLAG_ONELINE);
        BIO_puts(bio_err, "\n");
        break;
    case X509_V_ERR_CERT_NOT_YET_VALID:
    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
        BIO_printf(bio_err, "notBefore=");
        ASN1_TIME_print(bio_err, X509_get_notBefore(err_cert));
        BIO_printf(bio_err, "\n");
        break;
    case X509_V_ERR_CERT_HAS_EXPIRED:
    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
        BIO_printf(bio_err, "notAfter=");
        ASN1_TIME_print(bio_err, X509_get_notAfter(err_cert));
        BIO_printf(bio_err, "\n");
        break;
    case X509_V_ERR_NO_EXPLICIT_POLICY:
        if (!verify_quiet)
            policies_print(ctx);
        break;
    }
    if (err == X509_V_OK && ok == 2 && !verify_quiet)
        policies_print(ctx);
    if (ok && !verify_quiet)
        BIO_printf(bio_err, "verify return:%d\n", ok);
    return (ok);
}
Beispiel #16
0
void Server::initializeCert() {
	QByteArray crt, key, pass;

	crt = getConf("certificate", QString()).toByteArray();
	key = getConf("key", QString()).toByteArray();
	pass = getConf("passphrase", QByteArray()).toByteArray();

	QList<QSslCertificate> ql;

	if (! key.isEmpty()) {
		qskKey = QSslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass);
		if (qskKey.isNull())
			qskKey = QSslKey(key, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass);
	}
	if (qskKey.isNull() && ! crt.isEmpty()) {
		qskKey = QSslKey(crt, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass);
		if (qskKey.isNull())
			qskKey = QSslKey(crt, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass);
	}
	if (! qskKey.isNull()) {
		ql << QSslCertificate::fromData(crt);
		ql << QSslCertificate::fromData(key);
		for (int i=0;i<ql.size();++i) {
			const QSslCertificate &c = ql.at(i);
			if (isKeyForCert(qskKey, c)) {
				qscCert = c;
				ql.removeAt(i);
			}
		}
		qlCA = ql;
	}

	QString issuer;
#if QT_VERSION >= 0x050000
	QStringList issuerNames = qscCert.issuerInfo(QSslCertificate::CommonName);
	if (! issuerNames.isEmpty()) {
		issuer = issuerNames.first();
	}
#else
	issuer = qscCert.issuerInfo(QSslCertificate::CommonName);
#endif

	if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) {
		log("Old autogenerated certificate is unusable for registration, invalidating it");
		qscCert = QSslCertificate();
		qskKey = QSslKey();
	}

	if (!qscCert.isNull() && issuer == QString::fromUtf8("Murmur Autogenerated Certificate v2") && ! Meta::mp.qscCert.isNull() && ! Meta::mp.qskKey.isNull() && (Meta::mp.qlBind == qlBind)) {
		qscCert = Meta::mp.qscCert;
		qskKey = Meta::mp.qskKey;
	}

	if (qscCert.isNull() || qskKey.isNull()) {
		if (! key.isEmpty() || ! crt.isEmpty()) {
			log("Certificate specified, but failed to load.");
		}
		qskKey = Meta::mp.qskKey;
		qscCert = Meta::mp.qscCert;
		if (qscCert.isNull() || qskKey.isNull()) {
			log("Generating new server certificate.");

			CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

			X509 *x509 = X509_new();
			EVP_PKEY *pkey = EVP_PKEY_new();
			RSA *rsa = RSA_generate_key(2048,RSA_F4,NULL,NULL);
			EVP_PKEY_assign_RSA(pkey, rsa);

			X509_set_version(x509, 2);
			ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
			X509_gmtime_adj(X509_get_notBefore(x509),0);
			X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365*20);
			X509_set_pubkey(x509, pkey);

			X509_NAME *name=X509_get_subject_name(x509);

			X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2")), -1, -1, 0);
			X509_set_issuer_name(x509, name);
			add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE"));
			add_ext(x509, NID_ext_key_usage, SSL_STRING("serverAuth,clientAuth"));
			add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash"));
			add_ext(x509, NID_netscape_comment, SSL_STRING("Generated from murmur"));

			X509_sign(x509, pkey, EVP_sha1());

			crt.resize(i2d_X509(x509, NULL));
			unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data());
			i2d_X509(x509, &dptr);

			qscCert = QSslCertificate(crt, QSsl::Der);
			if (qscCert.isNull())
				log("Certificate generation failed");

			key.resize(i2d_PrivateKey(pkey, NULL));
			dptr=reinterpret_cast<unsigned char *>(key.data());
			i2d_PrivateKey(pkey, &dptr);

			qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der);
			if (qskKey.isNull())
				log("Key generation failed");

			setConf("certificate", qscCert.toPem());
			setConf("key", qskKey.toPem());
		}
	}
}
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days)
        {
        X509 *x;
        EVP_PKEY *pk;
        RSA *rsa;
        X509_NAME *name=NULL;
        
        if ((pkeyp == NULL) || (*pkeyp == NULL))
                {
                if ((pk=EVP_PKEY_new()) == NULL)
                        {
                        abort(); 
                        return(0);
                        }
                }
        else
                pk= *pkeyp;

        if ((x509p == NULL) || (*x509p == NULL))
                {
                if ((x=X509_new()) == NULL)
                        goto err;
                }
        else
                x= *x509p;

			
//		pRsaKey = RSA_generate_key(1024, 0x010001, NULL, NULL);

        rsa=RSA_generate_key(bits, RSA_F4, callback, NULL);
        if (!EVP_PKEY_assign_RSA(pk, rsa))
                {
                abort();
                goto err;
                }
        rsa=NULL;

        X509_set_version(x,2);
        ASN1_INTEGER_set(X509_get_serialNumber(x),serial);
        X509_gmtime_adj(X509_get_notBefore(x),0);
        X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);
        X509_set_pubkey(x,pk);

        name=X509_get_subject_name(x);

        /* This function creates and adds the entry, working out the
         * correct string type and performing checks on its length.
         * Normally we'd check the return value for errors...
         */
        X509_NAME_add_entry_by_txt(name,"C",
                                MBSTRING_ASC, "UK", -1, -1, 0);
        X509_NAME_add_entry_by_txt(name,"CN",
                                MBSTRING_ASC, "OpenSSL Group", -1, -1, 0);

        /* Its self signed so set the issuer name to be the same as the
         * subject.
         */
        X509_set_issuer_name(x,name);

        /* Add various extensions: standard extensions */
        add_ext(x, NID_basic_constraints, "critical,CA:TRUE");
        add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign");

        add_ext(x, NID_subject_key_identifier, "hash");

        /* Some Netscape specific extensions */
        add_ext(x, NID_netscape_cert_type, "sslCA");

        add_ext(x, NID_netscape_comment, "example comment extension");


#ifdef CUSTOM_EXT
        /* Maybe even add our own extension based on existing */
        {
                int nid;
                nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension");
                X509V3_EXT_add_alias(nid, NID_netscape_comment);
                add_ext(x, nid, "example comment alias");
        }
#endif
        
        if (!X509_sign(x,pk,EVP_md5()))
                goto err;

        *x509p=x;
        *pkeyp=pk;
        return(1);
err:
        return(0);
        }
Beispiel #18
0
int32_t mkcert(X509 **x509p, EVP_PKEY **pkeyp, int32_t bits, int32_t serial, int32_t days)
{
    bool bCreatedKey  = false;
    bool bCreatedX509 = false;
        // -----------------
        X509      * x    = NULL;
        EVP_PKEY  * pk   = NULL;
        RSA       * rsa  = NULL;
        X509_NAME * name = NULL;

        if ((pkeyp == NULL) || (*pkeyp == NULL))
        {
            if ((pk = EVP_PKEY_new()) == NULL)
            {
                abort();  // todo
                //return(0); unneeded after abort.
            }
            bCreatedKey = true;
        }
        else
            pk = *pkeyp;
        // -----------------------------------------
        if ((x509p == NULL) || (*x509p == NULL))
        {
            if ((x = X509_new()) == NULL)
            {
                if (bCreatedKey)
                {
                    EVP_PKEY_free(pk);
                }
                return(0);
            }

            bCreatedX509 = true;
        }
        else
            x = *x509p;
        // -----------------------------------------
//		pRsaKey = RSA_generate_key(1024, 0x010001, NULL, NULL);

#ifdef ANDROID
        rsa         = RSA_new();
        BIGNUM * e1 = BN_new();

        if ((NULL == rsa) || (NULL == e1))
            abort(); // todo

//      BN_set_word(e1, 65537);
        BN_set_word(e1, RSA_F4);

        if (!RSA_generate_key_ex(rsa, bits, e1, NULL))
            abort(); // todo

        BN_free(e1);
#else
        rsa = RSA_generate_key(bits, RSA_F4, callback, NULL);
#endif
        // -----------------------------------------
        if (!EVP_PKEY_assign_RSA(pk, rsa))
        {
            abort();  // todo
            //return(0); undeeded after abort.
        }
        // ------------------------------
        rsa = NULL;

        X509_set_version(x, 2);
        ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
        X509_gmtime_adj (X509_get_notBefore(x), 0);
        X509_gmtime_adj (X509_get_notAfter (x), static_cast<int64_t>(60*60*24*days));
        X509_set_pubkey (x, pk);

        name = X509_get_subject_name(x);

        /* This function creates and adds the entry, working out the
         * correct string type and performing checks on its length.
         * Normally we'd check the return value for errors...
         */
        X509_NAME_add_entry_by_txt(name,"C",
                                MBSTRING_ASC,
                                   (const uint8_t *)"UK",
                                   -1, -1, 0);
        X509_NAME_add_entry_by_txt(name,"CN",
                                MBSTRING_ASC,
                                   (const uint8_t *)"OpenSSL Group",
                                   -1, -1, 0);

        /* Its self signed so set the issuer name to be the same as the
         * subject.
         */
        X509_set_issuer_name(x, name);
        // ----------------------------------------------------------------------------
        /* Add various extensions: standard extensions */

        char * szConstraints  = new char[100]();
        char * szKeyUsage     = new char[100]();
        char * szSubjectKeyID = new char[100]();
        char * szCertType     = new char[100]();
        char * szComment      = new char[100]();
        // ----------------------------------------------------------------------------
        opentxs::OTString::safe_strcpy(szConstraints,  "critical,CA:TRUE",             99);
        opentxs::OTString::safe_strcpy(szKeyUsage,     "critical,keyCertSign,cRLSign", 99);
        opentxs::OTString::safe_strcpy(szSubjectKeyID, "hash",                         99);
        opentxs::OTString::safe_strcpy(szCertType,     "sslCA",                        99);
        opentxs::OTString::safe_strcpy(szComment,      "example comment extension",    99);
        // ----------------------------------------------------------------------------
        add_ext(x, NID_basic_constraints,      szConstraints);
        add_ext(x, NID_key_usage,              szKeyUsage);
        add_ext(x, NID_subject_key_identifier, szSubjectKeyID);
        add_ext(x, NID_netscape_cert_type,     szCertType); // Some Netscape specific extensions
        add_ext(x, NID_netscape_comment,       szComment);  // Some Netscape specific extensions
        // ----------------------------------------------------------------------------
        delete [] szConstraints;   szConstraints  = NULL;
        delete [] szKeyUsage;      szKeyUsage     = NULL;
        delete [] szSubjectKeyID;  szSubjectKeyID = NULL;
        delete [] szCertType;      szCertType     = NULL;
        delete [] szComment;       szComment      = NULL;
        // ----------------------------------------------------------------------------

#ifdef CUSTOM_EXT
        // Maybe even add our own extension based on existing
        {
                int32_t nid;
                nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension");
                X509V3_EXT_add_alias(nid, NID_netscape_comment);
                add_ext(x, nid, "example comment alias");
        }
#endif
        // ------------------------------
        if (!X509_sign(x, pk, EVP_md5()) || // TODO security:  md5 ???
            (NULL == x509p)              ||
            (NULL == pkeyp))
        {
            // ERROR
            //
            if (bCreatedX509)
                X509_free(x);

            // NOTE: not sure if x owns pk, in which case pk is already freed above.
            // Todo: find out and then determine whether or not to uncomment this.
            // (Presumably this would be a rare occurrence anyway.)
            //
//            if (bCreatedKey)
//                EVP_PKEY_free(pk);

            x  = NULL;
            pk = NULL;

            return 0;
        }
        // ------------------------------
        *x509p = x;
        *pkeyp = pk;

        return(1);
}
Beispiel #19
0
static int interactive_check_cert (X509 *cert, int idx, int len)
{
  static const char * const part[] =
    {"/CN=", "/Email=", "/O=", "/OU=", "/L=", "/ST=", "/C="};
  char helpstr[LONG_STRING];
  char buf[STRING];
  char title[STRING];
  MUTTMENU *menu = mutt_new_menu (MENU_GENERIC);
  int done, row, i;
  FILE *fp;
  char *name = NULL, *c;

  dprint (2, (debugfile, "interactive_check_cert: %s\n", cert->name));

  menu->max = 19;
  menu->dialog = (char **) safe_calloc (1, menu->max * sizeof (char *));
  for (i = 0; i < menu->max; i++)
    menu->dialog[i] = (char *) safe_calloc (1, SHORT_STRING * sizeof (char));

  row = 0;
  strfcpy (menu->dialog[row], _("This certificate belongs to:"), SHORT_STRING);
  row++;
  name = X509_NAME_oneline (X509_get_subject_name (cert),
			    buf, sizeof (buf));
  dprint (2, (debugfile, "oneline: %s\n", name));

  for (i = 0; i < 5; i++)
  {
    c = x509_get_part (name, part[i]);
    snprintf (menu->dialog[row++], SHORT_STRING, "   %s", c);
  }

  row++;
  strfcpy (menu->dialog[row], _("This certificate was issued by:"), SHORT_STRING);
  row++;
  name = X509_NAME_oneline (X509_get_issuer_name (cert),
			    buf, sizeof (buf));
  for (i = 0; i < 5; i++)
  {
    c = x509_get_part (name, part[i]);
    snprintf (menu->dialog[row++], SHORT_STRING, "   %s", c);
  }

  row++;
  snprintf (menu->dialog[row++], SHORT_STRING, _("This certificate is valid"));
  snprintf (menu->dialog[row++], SHORT_STRING, _("   from %s"),
      asn1time_to_string (X509_get_notBefore (cert)));
  snprintf (menu->dialog[row++], SHORT_STRING, _("     to %s"),
      asn1time_to_string (X509_get_notAfter (cert)));

  row++;
  buf[0] = '\0';
  x509_fingerprint (buf, sizeof (buf), cert);
  snprintf (menu->dialog[row++], SHORT_STRING, _("Fingerprint: %s"), buf);

  snprintf (title, sizeof (title),
	    _("SSL Certificate check (certificate %d of %d in chain)"),
	    len - idx, len);
  menu->title = title;
  if (SslCertFile
      && (option (OPTSSLVERIFYDATES) == MUTT_NO
	  || (X509_cmp_current_time (X509_get_notAfter (cert)) >= 0
	      && X509_cmp_current_time (X509_get_notBefore (cert)) < 0)))
  {
    menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
    menu->keys = _("roa");
  }
  else
  {
    menu->prompt = _("(r)eject, accept (o)nce");
    menu->keys = _("ro");
  }

  helpstr[0] = '\0';
  mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_GENERIC, OP_EXIT);
  safe_strcat (helpstr, sizeof (helpstr), buf);
  mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP);
  safe_strcat (helpstr, sizeof (helpstr), buf);
  menu->help = helpstr;

  done = 0;
  set_option(OPTIGNOREMACROEVENTS);
  while (!done)
  {
    switch (mutt_menuLoop (menu))
    {
      case -1:			/* abort */
      case OP_MAX + 1:		/* reject */
      case OP_EXIT:
        done = 1;
        break;
      case OP_MAX + 3:		/* accept always */
        done = 0;
        if ((fp = fopen (SslCertFile, "a")))
	{
	  if (PEM_write_X509 (fp, cert))
	    done = 1;
	  safe_fclose (&fp);
	}
	if (!done)
        {
	  mutt_error (_("Warning: Couldn't save certificate"));
	  mutt_sleep (2);
	}
	else
        {
	  mutt_message (_("Certificate saved"));
	  mutt_sleep (0);
	}
        /* fall through */
      case OP_MAX + 2:		/* accept once */
        done = 2;
	ssl_cache_trusted_cert (cert);
        break;
    }
  }
  unset_option(OPTIGNOREMACROEVENTS);
  mutt_menuDestroy (&menu);
  set_option (OPTNEEDREDRAW);
  dprint (2, (debugfile, "ssl interactive_check_cert: done=%d\n", done));
  return (done == 2);
}
Beispiel #20
0
static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days)
{
	X509 *x;
	EVP_PKEY *pk;
	RSA *rsa;
	X509_NAME *name=NULL;
	
	switch_assert(pkeyp);
	switch_assert(x509p);

	if (*pkeyp == NULL) {
		if ((pk = EVP_PKEY_new()) == NULL) {
			abort(); 
		}
	} else {
		pk = *pkeyp;
	}

	if (*x509p == NULL) {
		if ((x = X509_new()) == NULL) {
			goto err;
		}
	} else {
		x = *x509p;
	}

	rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);

	if (!EVP_PKEY_assign_RSA(pk, rsa)) {
		abort();
		goto err;
	}

	rsa = NULL;

	X509_set_version(x, 0);
	ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
	X509_gmtime_adj(X509_get_notBefore(x), -(long)60*60*24*7);
	X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
	X509_set_pubkey(x, pk);

	name = X509_get_subject_name(x);

	/* This function creates and adds the entry, working out the
	 * correct string type and performing checks on its length.
	 * Normally we'd check the return value for errors...
	 */
	X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0);
	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"FreeSWITCH", -1, -1, 0);
							   

	/* Its self signed so set the issuer name to be the same as the
 	 * subject.
	 */
	X509_set_issuer_name(x, name);

	if (!X509_sign(x, pk, EVP_sha1()))
		goto err;

	*x509p = x;
	*pkeyp = pk;
	return(1);
 err:
	return(0);
}
Beispiel #21
0
  bool OpenSSLBase::handshake()
  {

    doTLSOperation( TLSHandshake );

    if( !m_secure )
      return true;

    long res = SSL_get_verify_result( m_ssl );
    if( res != X509_V_OK )
      m_certInfo.status = CertInvalid;
    else
      m_certInfo.status = CertOk;

    X509* peer = SSL_get_peer_certificate( m_ssl );
    if( peer )
    {
      char peer_CN[256];
      X509_NAME_get_text_by_NID( X509_get_issuer_name( peer ), NID_commonName, peer_CN, sizeof( peer_CN ) );
      m_certInfo.issuer = peer_CN;
      X509_NAME_get_text_by_NID( X509_get_subject_name( peer ), NID_commonName, peer_CN, sizeof( peer_CN ) );
      m_certInfo.server = peer_CN;
      m_certInfo.date_from = ASN1Time2UnixTime( X509_get_notBefore( peer ) );
      m_certInfo.date_to = ASN1Time2UnixTime( X509_get_notAfter( peer ) );
      std::string p( peer_CN );
      std::transform( p.begin(), p.end(), p.begin(), tolower );

#if defined OPENSSL_VERSION_NUMBER && ( OPENSSL_VERSION_NUMBER >= 0x10002000 )
      res = X509_check_host( peer, p.c_str(), p.length(), X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS, 0 );
      if( res <= 0 ) // 0: verification failed; -1: internal error; -2 input is malformed
        m_certInfo.status |= CertWrongPeer;
#else
      if( p != m_server )
        m_certInfo.status |= CertWrongPeer;
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000

      if( ASN1_UTCTIME_cmp_time_t( X509_get_notBefore( peer ), time( 0 ) ) != -1 )
        m_certInfo.status |= CertNotActive;

      if( ASN1_UTCTIME_cmp_time_t( X509_get_notAfter( peer ), time( 0 ) ) != 1 )
        m_certInfo.status |= CertExpired;

      X509_free( peer );
    }
    else
    {
      m_certInfo.status = CertInvalid;
    }

    const char* tmp;
    tmp = SSL_get_cipher_name( m_ssl );
    if( tmp )
      m_certInfo.cipher = tmp;

    SSL_SESSION* sess = SSL_get_session( m_ssl );
    if( sess )
    {
      switch( SSL_SESSION_get_protocol_version( sess ) )
      {
        case TLS1_VERSION:
          m_certInfo.protocol = "TLSv1";
          break;
        case TLS1_1_VERSION:
          m_certInfo.protocol = "TLSv1.1";
          break;
        case TLS1_2_VERSION:
          m_certInfo.protocol = "TLSv1.2";
          break;
#ifdef TLS1_3_VERSION
        case TLS1_3_VERSION:
          m_certInfo.protocol = "TLSv1.3";
          break;
#endif // TLS1_3_VERSION
        default:
          m_certInfo.protocol = "Unknown TLS version";
          break;
      }
    }

    tmp = SSL_COMP_get_name( SSL_get_current_compression( m_ssl ) );
    if( tmp )
      m_certInfo.compression = tmp;

    m_valid = true;

    m_handler->handleHandshakeResult( this, true, m_certInfo );
    return true;
  }
Beispiel #22
0
Date SslCertificate::GetNotAfter() const
{
	ASSERT(!IsEmpty());
	return Asn1ToDate(X509_get_notAfter(cert));
}
Beispiel #23
0
IoObject *IoCertificate_notAfter(IoCertificate *self, IoObject *locals, IoMessage *m)
{
	return IoCertificate_asnTimeToDate(self, X509_get_notAfter(X509(self)));
}
Beispiel #24
0
int x509_main(int argc, char **argv)
{
    ASN1_INTEGER *sno = NULL;
    ASN1_OBJECT *objtmp = NULL;
    BIO *out = NULL;
    CONF *extconf = NULL;
    EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
    STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
    STACK_OF(OPENSSL_STRING) *sigopts = NULL;
    X509 *x = NULL, *xca = NULL;
    X509_REQ *req = NULL, *rq = NULL;
    X509_STORE *ctx = NULL;
    const EVP_MD *digest = NULL;
    char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL;
    char *checkhost = NULL, *checkemail = NULL, *checkip = NULL;
    char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
    char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
    char buf[256], *prog;
    int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
    int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
    int fingerprint = 0, reqfile = 0, need_rand = 0, checkend = 0;
    int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
    int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
    int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
    int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0;
    int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0;
    int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0;
    int enddate = 0;
    time_t checkoffset = 0;
    unsigned long nmflag = 0, certflag = 0;
    char nmflag_set = 0;
    OPTION_CHOICE o;
    ENGINE *e = NULL;
#ifndef OPENSSL_NO_MD5
    int subject_hash_old = 0, issuer_hash_old = 0;
#endif

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

    prog = opt_init(argc, argv, x509_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(x509_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
                goto opthelp;
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
                goto opthelp;
            break;
        case OPT_CAFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat))
                goto opthelp;
            break;
        case OPT_CAKEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_REQ:
            reqfile = need_rand = 1;
            break;

        case OPT_SIGOPT:
            if (!sigopts)
                sigopts = sk_OPENSSL_STRING_new_null();
            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
                goto opthelp;
            break;
        case OPT_DAYS:
            days = atoi(opt_arg());
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_EXTFILE:
            extfile = opt_arg();
            break;
        case OPT_EXTENSIONS:
            extsect = opt_arg();
            break;
        case OPT_SIGNKEY:
            keyfile = opt_arg();
            sign_flag = ++num;
            need_rand = 1;
            break;
        case OPT_CA:
            CAfile = opt_arg();
            CA_flag = ++num;
            need_rand = 1;
            break;
        case OPT_CAKEY:
            CAkeyfile = opt_arg();
            break;
        case OPT_CASERIAL:
            CAserial = opt_arg();
            break;
        case OPT_SET_SERIAL:
            if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL)
                goto opthelp;
            break;
        case OPT_FORCE_PUBKEY:
            fkeyfile = opt_arg();
            break;
        case OPT_ADDTRUST:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
                BIO_printf(bio_err,
                           "%s: Invalid trust object value %s\n",
                           prog, opt_arg());
                goto opthelp;
            }
            if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
            sk_ASN1_OBJECT_push(trust, objtmp);
            objtmp = NULL;
            trustout = 1;
            break;
        case OPT_ADDREJECT:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
                BIO_printf(bio_err,
                           "%s: Invalid reject object value %s\n",
                           prog, opt_arg());
                goto opthelp;
            }
            if (reject == NULL
                && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
            sk_ASN1_OBJECT_push(reject, objtmp);
            objtmp = NULL;
            trustout = 1;
            break;
        case OPT_SETALIAS:
            alias = opt_arg();
            trustout = 1;
            break;
        case OPT_CERTOPT:
            if (!set_cert_ex(&certflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_NAMEOPT:
            nmflag_set = 1;
            if (!set_name_ex(&nmflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_C:
            C = ++num;
            break;
        case OPT_EMAIL:
            email = ++num;
            break;
        case OPT_OCSP_URI:
            ocsp_uri = ++num;
            break;
        case OPT_SERIAL:
            serial = ++num;
            break;
        case OPT_NEXT_SERIAL:
            next_serial = ++num;
            break;
        case OPT_MODULUS:
            modulus = ++num;
            break;
        case OPT_PUBKEY:
            pubkey = ++num;
            break;
        case OPT_X509TOREQ:
            x509req = ++num;
            break;
        case OPT_TEXT:
            text = ++num;
            break;
        case OPT_SUBJECT:
            subject = ++num;
            break;
        case OPT_ISSUER:
            issuer = ++num;
            break;
        case OPT_FINGERPRINT:
            fingerprint = ++num;
            break;
        case OPT_HASH:
            subject_hash = ++num;
            break;
        case OPT_ISSUER_HASH:
            issuer_hash = ++num;
            break;
        case OPT_PURPOSE:
            pprint = ++num;
            break;
        case OPT_STARTDATE:
            startdate = ++num;
            break;
        case OPT_ENDDATE:
            enddate = ++num;
            break;
        case OPT_NOOUT:
            noout = ++num;
            break;
        case OPT_NOCERT:
            nocert = 1;
            break;
        case OPT_TRUSTOUT:
            trustout = 1;
            break;
        case OPT_CLRTRUST:
            clrtrust = ++num;
            break;
        case OPT_CLRREJECT:
            clrreject = ++num;
            break;
        case OPT_ALIAS:
            aliasout = ++num;
            break;
        case OPT_CACREATESERIAL:
            CA_createserial = ++num;
            break;
        case OPT_CLREXT:
            clrext = 1;
            break;
        case OPT_OCSPID:
            ocspid = ++num;
            break;
        case OPT_BADSIG:
            badsig = 1;
            break;
#ifndef OPENSSL_NO_MD5
        case OPT_SUBJECT_HASH_OLD:
            subject_hash_old = ++num;
            break;
        case OPT_ISSUER_HASH_OLD:
            issuer_hash_old = ++num;
            break;
#else
        case OPT_SUBJECT_HASH_OLD:
        case OPT_ISSUER_HASH_OLD:
            break;
#endif
        case OPT_DATES:
            startdate = ++num;
            enddate = ++num;
            break;
        case OPT_CHECKEND:
            checkend = 1;
            {
                intmax_t temp = 0;
                if (!opt_imax(opt_arg(), &temp))
                    goto opthelp;
                checkoffset = (time_t)temp;
                if ((intmax_t)checkoffset != temp) {
                    BIO_printf(bio_err, "%s: checkend time out of range %s\n",
                               prog, opt_arg());
                    goto opthelp;
                }
            }
            break;
        case OPT_CHECKHOST:
            checkhost = opt_arg();
            break;
        case OPT_CHECKEMAIL:
            checkemail = opt_arg();
            break;
        case OPT_CHECKIP:
            checkip = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_unknown(), &digest))
                goto opthelp;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();
    if (argc != 0) {
        BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]);
        goto opthelp;
    }

    if (!nmflag_set)
        nmflag = XN_FLAG_ONELINE;

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

    if (need_rand)
        app_RAND_load_file(NULL, 0);

    if (!app_passwd(passinarg, 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 (fkeyfile) {
        fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
        if (fkey == NULL)
            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) {
        X509V3_CTX ctx2;
        if ((extconf = app_load_config(extfile)) == NULL)
            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_open_default(infile, 'r', informat);
        if (in == NULL)
            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 ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
            BIO_printf(bio_err, "error unpacking public key\n");
            goto end;
        }
        i = X509_REQ_verify(req, 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 == NULL || !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, X509_REQ_get_subject_name(req)))
            goto end;
        if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
            goto end;

        X509_gmtime_adj(X509_get_notBefore(x), 0);
        X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL);
        if (fkey)
            X509_set_pubkey(x, fkey);
        else {
            pkey = X509_REQ_get0_pubkey(req);
            X509_set_pubkey(x, pkey);
        }
    } else
        x = load_cert(infile, informat, "Certificate");

    if (x == NULL)
        goto end;
    if (CA_flag) {
        xca = load_cert(CAfile, CAformat, "CA Certificate");
        if (xca == NULL)
            goto end;
    }

    if (!noout || text || next_serial) {
        OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");

    }

    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);
        }
        objtmp = NULL;
    }

    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);
        }
        objtmp = NULL;
    }

    if (num) {
        for (i = 1; i <= num; i++) {
            if (issuer == i) {
                print_name(out, "issuer= ", X509_get_issuer_name(x), nmflag);
            } else if (subject == i) {
                print_name(out, "subject= ",
                           X509_get_subject_name(x), nmflag);
            } else if (serial == i) {
                BIO_printf(out, "serial=");
                i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
                BIO_printf(out, "\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(out, "%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(out, "%s\n", alstr);
                else
                    BIO_puts(out, "<No Alias>\n");
            } else if (subject_hash == i) {
                BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
            }
#ifndef OPENSSL_NO_MD5
            else if (subject_hash_old == i) {
                BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
            }
#endif
            else if (issuer_hash == i) {
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
            }
#ifndef OPENSSL_NO_MD5
            else if (issuer_hash_old == i) {
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
            }
#endif
            else if (pprint == i) {
                X509_PURPOSE *ptmp;
                int j;
                BIO_printf(out, "Certificate purposes:\n");
                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
                    ptmp = X509_PURPOSE_get0(j);
                    purpose_print(out, x, ptmp);
                }
            } else if (modulus == i) {
                EVP_PKEY *pkey;

                pkey = X509_get0_pubkey(x);
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Modulus=unavailable\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
                BIO_printf(out, "Modulus=");
#ifndef OPENSSL_NO_RSA
                if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
                    BIGNUM *n;
                    RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL);
                    BN_print(out, n);
                } else
#endif
#ifndef OPENSSL_NO_DSA
                if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
                    BIGNUM *dsapub = NULL;
                    DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL);
                    BN_print(out, dsapub);
                } else
#endif
                {
                    BIO_printf(out, "Wrong Algorithm type");
                }
                BIO_printf(out, "\n");
            } else if (pubkey == i) {
                EVP_PKEY *pkey;

                pkey = X509_get0_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(out, pkey);
            } else if (C == i) {
                unsigned char *d;
                char *m;
                int len;

                X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf);
                BIO_printf(out, "/*\n"
                                " * Subject: %s\n", buf);

                X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof buf);
                BIO_printf(out, " * Issuer:  %s\n"
                                " */\n", buf);

                len = i2d_X509(x, NULL);
                m = app_malloc(len, "x509 name buffer");
                d = (unsigned char *)m;
                len = i2d_X509_NAME(X509_get_subject_name(x), &d);
                print_array(out, "the_subject_name", len, (unsigned char *)m);
                d = (unsigned char *)m;
                len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
                print_array(out, "the_public_key", len, (unsigned char *)m);
                d = (unsigned char *)m;
                len = i2d_X509(x, &d);
                print_array(out, "the_certificate", len, (unsigned char *)m);
                OPENSSL_free(m);
            } else if (text == i) {
                X509_print_ex(out, x, nmflag, certflag);
            } else if (startdate == i) {
                BIO_puts(out, "notBefore=");
                ASN1_TIME_print(out, X509_get_notBefore(x));
                BIO_puts(out, "\n");
            } else if (enddate == i) {
                BIO_puts(out, "notAfter=");
                ASN1_TIME_print(out, X509_get_notAfter(x));
                BIO_puts(out, "\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(out, "%s Fingerprint=",
                           OBJ_nid2sn(EVP_MD_type(fdig)));
                for (j = 0; j < (int)n; j++) {
                    BIO_printf(out, "%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(keyfile, keyformat, 0,
                                     passin, e, "Private key");
                    if (Upkey == NULL)
                        goto end;
                }

                assert(need_rand);
                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(CAkeyfile, CAkeyformat,
                                      0, passin, e, "CA Private Key");
                    if (CApkey == NULL)
                        goto end;
                }

                assert(need_rand);
                if (!x509_certify(ctx, CAfile, digest, x, xca,
                                  CApkey, sigopts,
                                  CAserial, CA_createserial, days, clrext,
                                  extconf, extsect, sno, reqfile))
                    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(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;
    }

    print_cert_checks(out, x, checkhost, checkemail, checkip);

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

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

    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 {
        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:
    if (need_rand)
        app_RAND_write_file(NULL);
    NCONF_free(extconf);
    BIO_free_all(out);
    X509_STORE_free(ctx);
    X509_REQ_free(req);
    X509_free(x);
    X509_free(xca);
    EVP_PKEY_free(Upkey);
    EVP_PKEY_free(CApkey);
    EVP_PKEY_free(fkey);
    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);
    ASN1_OBJECT_free(objtmp);
    OPENSSL_free(passin);
    return (ret);
}
Beispiel #25
0
static PyObject *
_decode_certificate (X509 *certificate, int verbose) {

	PyObject *retval = NULL;
	BIO *biobuf = NULL;
	PyObject *peer;
	PyObject *peer_alt_names = NULL;
	PyObject *issuer;
	PyObject *version;
	PyObject *sn_obj;
	ASN1_INTEGER *serialNumber;
	char buf[2048];
	int len;
	ASN1_TIME *notBefore, *notAfter;
	PyObject *pnotBefore, *pnotAfter;

	retval = PyDict_New();
	if (retval == NULL)
		return NULL;

	peer = _create_tuple_for_X509_NAME(
		X509_get_subject_name(certificate));
	if (peer == NULL)
		goto fail0;
	if (PyDict_SetItemString(retval, (const char *) "subject", peer) < 0) {
		Py_DECREF(peer);
		goto fail0;
	}
	Py_DECREF(peer);

	if (verbose) {
		issuer = _create_tuple_for_X509_NAME(
			X509_get_issuer_name(certificate));
		if (issuer == NULL)
			goto fail0;
		if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) {
			Py_DECREF(issuer);
			goto fail0;
		}
		Py_DECREF(issuer);

		version = PyLong_FromLong(X509_get_version(certificate) + 1);
		if (PyDict_SetItemString(retval, "version", version) < 0) {
			Py_DECREF(version);
			goto fail0;
		}
		Py_DECREF(version);
	}

	/* get a memory buffer */
	biobuf = BIO_new(BIO_s_mem());

	if (verbose) {

		(void) BIO_reset(biobuf);
		serialNumber = X509_get_serialNumber(certificate);
		/* should not exceed 20 octets, 160 bits, so buf is big enough */
		i2a_ASN1_INTEGER(biobuf, serialNumber);
		len = BIO_gets(biobuf, buf, sizeof(buf)-1);
		if (len < 0) {
			_setSSLError(NULL, 0, __FILE__, __LINE__);
			goto fail1;
		}
		sn_obj = PyUnicode_FromStringAndSize(buf, len);
		if (sn_obj == NULL)
			goto fail1;
		if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) {
			Py_DECREF(sn_obj);
			goto fail1;
		}
		Py_DECREF(sn_obj);

		(void) BIO_reset(biobuf);
		notBefore = X509_get_notBefore(certificate);
		ASN1_TIME_print(biobuf, notBefore);
		len = BIO_gets(biobuf, buf, sizeof(buf)-1);
		if (len < 0) {
			_setSSLError(NULL, 0, __FILE__, __LINE__);
			goto fail1;
		}
		pnotBefore = PyUnicode_FromStringAndSize(buf, len);
		if (pnotBefore == NULL)
			goto fail1;
		if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) {
			Py_DECREF(pnotBefore);
			goto fail1;
		}
		Py_DECREF(pnotBefore);
	}

	(void) BIO_reset(biobuf);
	notAfter = X509_get_notAfter(certificate);
	ASN1_TIME_print(biobuf, notAfter);
	len = BIO_gets(biobuf, buf, sizeof(buf)-1);
	if (len < 0) {
		_setSSLError(NULL, 0, __FILE__, __LINE__);
		goto fail1;
	}
	pnotAfter = PyUnicode_FromStringAndSize(buf, len);
	if (pnotAfter == NULL)
		goto fail1;
	if (PyDict_SetItemString(retval, "notAfter", pnotAfter) < 0) {
		Py_DECREF(pnotAfter);
		goto fail1;
	}
	Py_DECREF(pnotAfter);

	/* Now look for subjectAltName */

	peer_alt_names = _get_peer_alt_names(certificate);
	if (peer_alt_names == NULL)
		goto fail1;
	else if (peer_alt_names != Py_None) {
		if (PyDict_SetItemString(retval, "subjectAltName",
					 peer_alt_names) < 0) {
			Py_DECREF(peer_alt_names);
			goto fail1;
		}
		Py_DECREF(peer_alt_names);
	}

	BIO_free(biobuf);
	return retval;

  fail1:
	if (biobuf != NULL)
		BIO_free(biobuf);
  fail0:
	Py_XDECREF(retval);
	return NULL;
}
Beispiel #26
0
Try<X509*> generate_x509(
    EVP_PKEY* subject_key,
    EVP_PKEY* sign_key,
    const Option<X509*>& parent_certificate,
    int serial,
    int days,
    Option<std::string> hostname)
{
  Option<X509_NAME*> issuer_name = None();
  if (parent_certificate.isNone()) {
    // If there is no parent certificate, then the subject and
    // signing key must be the same.
    if (subject_key != sign_key) {
      return Error("Subject vs signing key mismatch");
    }
  } else {
    // If there is a parent certificate, then set the issuer name to
    // be that of the parent.
    issuer_name = X509_get_subject_name(parent_certificate.get());

    if (issuer_name.get() == NULL) {
      return Error("Failed to get subject name of parent certificate: "
        "X509_get_subject_name");
    }
  }

  // Allocate the in-memory structure for the certificate.
  X509* x509 = X509_new();
  if (x509 == NULL) {
    return Error("Failed to allocate certification: X509_new");
  }

  // Set the version to V3.
  if (X509_set_version(x509, 2) != 1) {
    X509_free(x509);
    return Error("Failed to set version: X509_set_version");
  }

  // Set the serial number.
  if (ASN1_INTEGER_set(X509_get_serialNumber(x509), serial) != 1) {
    X509_free(x509);
    return Error("Failed to set serial number: ASN1_INTEGER_set");
  }

  // Make this certificate valid for 'days' number of days from now.
  if (X509_gmtime_adj(X509_get_notBefore(x509), 0) == NULL ||
      X509_gmtime_adj(X509_get_notAfter(x509),
                      60L * 60L * 24L * days) == NULL) {
    X509_free(x509);
    return Error("Failed to set valid days of certificate: X509_gmtime_adj");
  }

  // Set the public key for our certificate based on the subject key.
  if (X509_set_pubkey(x509, subject_key) != 1) {
    X509_free(x509);
    return Error("Failed to set public key: X509_set_pubkey");
  }

  // Figure out our hostname if one was not provided.
  if (hostname.isNone()) {
    const Try<std::string> _hostname = net::hostname();
    if (_hostname.isError()) {
      X509_free(x509);
      return Error("Failed to determine hostname");
    }

    hostname = _hostname.get();
  }

  // Grab the subject name of the new certificate.
  X509_NAME* name = X509_get_subject_name(x509);
  if (name == NULL) {
    X509_free(x509);
    return Error("Failed to get subject name: X509_get_subject_name");
  }

  // Set the country code, organization, and common name.
  if (X509_NAME_add_entry_by_txt(
          name,
          "C",
          MBSTRING_ASC,
          reinterpret_cast<const unsigned char*>("US"),
          -1,
          -1,
          0) != 1) {
    X509_free(x509);
    return Error("Failed to set country code: X509_NAME_add_entry_by_txt");
  }

  if (X509_NAME_add_entry_by_txt(
          name,
          "O",
          MBSTRING_ASC,
          reinterpret_cast<const unsigned char*>("Test"),
          -1,
          -1,
          0) != 1) {
    X509_free(x509);
    return Error("Failed to set organization name: X509_NAME_add_entry_by_txt");
  }

  if (X509_NAME_add_entry_by_txt(
          name,
          "CN",
          MBSTRING_ASC,
          reinterpret_cast<const unsigned char*>(hostname.get().c_str()),
          -1,
          -1,
          0) != 1) {
    X509_free(x509);
    return Error("Failed to set common name: X509_NAME_add_entry_by_txt");
  }

  // Set the issuer name to be the same as the subject if it is not
  // already set (this is a self-signed certificate).
  if (issuer_name.isNone()) {
    issuer_name = name;
  }

  CHECK_SOME(issuer_name);
  if (X509_set_issuer_name(x509, issuer_name.get()) != 1) {
    X509_free(x509);
    return Error("Failed to set issuer name: X509_set_issuer_name");
  }

  // Sign the certificate with the sign key.
  if (X509_sign(x509, sign_key, EVP_sha1()) == 0) {
    X509_free(x509);
    return Error("Failed to sign certificate: X509_sign");
  }

  return x509;
}
Beispiel #27
0
int
x509_main(int argc, char **argv)
{
	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;
	const char *errstr = NULL;

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

	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;
			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;
		}
		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;
	}

	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, "Certificate");

	if (x == NULL)
		goto end;
	if (CA_flag) {
		xca = load_cert(bio_err, CAfile, CAformat, NULL, "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);
				if (m == NULL) {
					BIO_printf(bio_err, "out of mem\n");
					goto end;
				}

				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, "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, "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, "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(&NETSCAPE_X509_it, 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);
	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 void ssl_log_cert_error(const char *file, int line, int level,
                               apr_status_t rv, const server_rec *s,
                               const conn_rec *c, const request_rec *r,
                               apr_pool_t *p, X509 *cert, const char *format,
                               va_list ap)
{
    char buf[HUGE_STRING_LEN];
    int msglen, n;
    char *name;

    apr_vsnprintf(buf, sizeof buf, format, ap);

    msglen = strlen(buf);

    if (cert) {
        BIO *bio = BIO_new(BIO_s_mem());

        if (bio) {
            /*
             * Limit the maximum length of the subject and issuer DN strings
             * in the log message. 300 characters should always be sufficient
             * for holding both the timestamp, module name, pid etc. stuff
             * at the beginning of the line and the trailing information about
             * serial, notbefore and notafter.
             */
            int maxdnlen = (HUGE_STRING_LEN - msglen - 300) / 2;

            BIO_puts(bio, " [subject: ");
            name = SSL_X509_NAME_to_string(p, X509_get_subject_name(cert),
                                           maxdnlen);
            if (!strIsEmpty(name)) {
                BIO_puts(bio, name);
            } else {
                BIO_puts(bio, "-empty-");
            }

            BIO_puts(bio, " / issuer: ");
            name = SSL_X509_NAME_to_string(p, X509_get_issuer_name(cert),
                                           maxdnlen);
            if (!strIsEmpty(name)) {
                BIO_puts(bio, name);
            } else {
                BIO_puts(bio, "-empty-");
            }

            BIO_puts(bio, " / serial: ");
            if (i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert)) == -1)
                BIO_puts(bio, "(ERROR)");

            BIO_puts(bio, " / notbefore: ");
            ASN1_TIME_print(bio, X509_get_notBefore(cert));

            BIO_puts(bio, " / notafter: ");
            ASN1_TIME_print(bio, X509_get_notAfter(cert));

            BIO_puts(bio, "]");

            n = BIO_read(bio, buf + msglen, sizeof buf - msglen - 1);
            if (n > 0)
               buf[msglen + n] = '\0';

            BIO_free(bio);
        }
    }
    else {
        apr_snprintf(buf + msglen, sizeof buf - msglen,
                     " [certificate: -not available-]");
    }

    if (r) {
        ap_log_rerror(file, line, APLOG_MODULE_INDEX, level, rv, r, "%s", buf);
    }
    else if (c) {
        ap_log_cerror(file, line, APLOG_MODULE_INDEX, level, rv, c, "%s", buf);
    }
    else if (s) {
        ap_log_error(file, line, APLOG_MODULE_INDEX, level, rv, s, "%s", buf);
    }

}
Beispiel #29
0
DWORD
VMCADecodeCert(
    PSTR pszCertificate,
    PVMCA_DB_CERTIFICATE_ENTRY* ppEntry
)
{
    DWORD dwError = 0;
    PVMCA_DB_CERTIFICATE_ENTRY pDBEntry = NULL;
    PSTR pszCertName = NULL;
    PSTR pszCertSerial = NULL;
    PSTR pszNotBefore = NULL;
    PSTR pszNotAfter = NULL;
    PSTR pszIssuerName = NULL;

    X509 *pCert = NULL;

    if (pszCertificate == NULL) {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMCA_ERROR(dwError);
    }

    if (ppEntry == NULL) {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMCA_ERROR(dwError);
    }

    dwError = VMCAAllocateMemory(
                        sizeof(VMCA_DB_CERTIFICATE_ENTRY),
                        (PVOID*) &pDBEntry);
    BAIL_ON_VMCA_ERROR(dwError);

    memset(pDBEntry,0, sizeof(VMCA_DB_CERTIFICATE_ENTRY));
    VMCAAllocateStringA(pszCertificate, (PSTR*)&pDBEntry->pCertBlob);
    //pDBEntry->pCertBlob = (PBYTE) pszCertificate;

    pDBEntry->dwCertSize = (DWORD)strlen(pszCertificate);

    dwError = VMCAPEMToX509(pszCertificate, &pCert);
    BAIL_ON_VMCA_ERROR(dwError);

    if (X509_cmp_current_time(X509_get_notAfter(pCert)) < 0)
    {
        pDBEntry->dwRevoked = VMCA_CERTIFICATE_EXPIRED;
    }

    dwError = VMCAGetCertificateName(pCert, &pszCertName);
    BAIL_ON_VMCA_ERROR(dwError);

    dwError = VMCAAllocateStringWFromA(pszCertName,
                            &pDBEntry->pwszCommonName);
    BAIL_ON_VMCA_ERROR(dwError);

    dwError = VMCAGetCertificateSerial(pCert, &pszCertSerial);
    BAIL_ON_VMCA_ERROR(dwError);

    dwError = VMCAAllocateStringWFromA(pszCertSerial,
                            &pDBEntry->pwszSerial);
    BAIL_ON_VMCA_ERROR(dwError);

    dwError = VMCAGetIssuerName(pCert, &pszIssuerName);
    BAIL_ON_VMCA_ERROR(dwError);

    dwError = VMCAAllocateStringWFromA(pszIssuerName,
                            &pDBEntry->pwszIssuerName);
    BAIL_ON_VMCA_ERROR(dwError);

    dwError = VMCAGetCertificateTime(pCert, &pszNotBefore, &pszNotAfter);
    BAIL_ON_VMCA_ERROR(dwError);

    dwError = VMCAAllocateStringWFromA(pszNotBefore,
                            &pDBEntry->pwszTimeValidFrom);
    BAIL_ON_VMCA_ERROR(dwError);

    dwError = VMCAAllocateStringWFromA(pszNotBefore,
                            &pDBEntry->pwszTimeValidTo);
    BAIL_ON_VMCA_ERROR(dwError);

    *ppEntry = pDBEntry;

cleanup:
    if(pCert) {
        X509_free(pCert);
    }
 
    VMCA_SAFE_FREE_STRINGA(pszCertName);
    VMCA_SAFE_FREE_STRINGA(pszCertSerial);
    VMCA_SAFE_FREE_STRINGA(pszNotBefore);
    VMCA_SAFE_FREE_STRINGA(pszNotAfter);
    VMCA_SAFE_FREE_STRINGA(pszIssuerName);

    return dwError;

error :
    VMCAFreeDBEntryFields(pDBEntry);
    goto cleanup;

}
Beispiel #30
0
/*
 * Create a fake X509v3 certificate, signed by the provided CA,
 * based on the original certificate retrieved from the real server.
 * The returned certificate is created using X509_new() and thus must
 * be freed by the caller using X509_free().
 * The optional argument extraname is added to subjectAltNames if provided.
 */
X509 *
ssl_x509_forge(X509 *cacrt, EVP_PKEY *cakey, X509 *origcrt,
               const char *extraname, EVP_PKEY *key)
{
	X509_NAME *subject, *issuer;
	GENERAL_NAMES *names;
	GENERAL_NAME *gn;
	X509 *crt;

	subject = X509_get_subject_name(origcrt);
	issuer = X509_get_subject_name(cacrt);
	if (!subject || !issuer)
		return NULL;

	crt = X509_new();
	if (!crt)
		return NULL;

	if (!X509_set_version(crt, 0x02) ||
	    !X509_set_subject_name(crt, subject) ||
	    !X509_set_issuer_name(crt, issuer) ||
	    ssl_x509_serial_copyrand(crt, origcrt) == -1 ||
	    !X509_gmtime_adj(X509_get_notBefore(crt), (long)-60*60*24) ||
	    !X509_gmtime_adj(X509_get_notAfter(crt), (long)60*60*24*364) ||
	    !X509_set_pubkey(crt, key))
		goto errout;

	/* add standard v3 extensions; cf. RFC 2459 */
	X509V3_CTX ctx;
	X509V3_set_ctx(&ctx, cacrt, crt, NULL, NULL, 0);
	if (ssl_x509_v3ext_add(&ctx, crt, "basicConstraints",
	                                  "CA:FALSE") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "keyUsage",
	                                  "digitalSignature,"
	                                  "keyEncipherment") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "extendedKeyUsage",
	                                  "serverAuth") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "subjectKeyIdentifier",
	                                  "hash") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "authorityKeyIdentifier",
	                                  "keyid,issuer:always") == -1)
		goto errout;

	if (!extraname) {
		/* no extraname provided: copy original subjectAltName ext */
		if (ssl_x509_v3ext_copy_by_nid(crt, origcrt,
		                               NID_subject_alt_name) == -1)
			goto errout;
	} else {
		names = X509_get_ext_d2i(origcrt, NID_subject_alt_name, 0, 0);
		if (!names) {
			/* no subjectAltName present: add new one */
			char *cfval;
			if (asprintf(&cfval, "DNS:%s", extraname) < 0)
				goto errout;
			if (ssl_x509_v3ext_add(&ctx, crt, "subjectAltName",
			                       cfval) == -1) {
				free(cfval);
				goto errout;
			}
			free(cfval);
		} else {
			/* add extraname to original subjectAltName
			 * and add it to the new certificate */
			gn = GENERAL_NAME_new();
			if (!gn)
				goto errout2;
			gn->type = GEN_DNS;
			gn->d.dNSName = M_ASN1_IA5STRING_new();
			if (!gn->d.dNSName)
				goto errout3;
			ASN1_STRING_set(gn->d.dNSName,
			                (unsigned char *)extraname,
			                strlen(extraname));
			sk_GENERAL_NAME_push(names, gn);
			X509_EXTENSION *ext = X509V3_EXT_i2d(
			                      NID_subject_alt_name, 0, names);
			if (!X509_add_ext(crt, ext, -1)) {
				if (ext) {
					X509_EXTENSION_free(ext);
				}
				goto errout3;
			}
			X509_EXTENSION_free(ext);
			sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
		}
	}
#ifdef DEBUG_CERTIFICATE
	ssl_x509_v3ext_add(&ctx, crt, "nsComment", "Generated by " PNAME);
#endif /* DEBUG_CERTIFICATE */

	const EVP_MD *md;
	switch (EVP_PKEY_type(cakey->type)) {
#ifndef OPENSSL_NO_RSA
		case EVP_PKEY_RSA:
			md = EVP_sha1();
			break;
#endif /* !OPENSSL_NO_RSA */
#ifndef OPENSSL_NO_DSA
		case EVP_PKEY_DSA:
			md = EVP_dss1();
			break;
#endif /* !OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_ECDSA
		case EVP_PKEY_EC:
			md = EVP_ecdsa();
			break;
#endif /* !OPENSSL_NO_ECDSA */
		default:
			goto errout;
	}
	if (!X509_sign(crt, cakey, md))
		goto errout;

	return crt;

errout3:
	GENERAL_NAME_free(gn);
errout2:
	sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
errout:
	X509_free(crt);
	return NULL;
}