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; }
// 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); }
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; }
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); }
/** 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; }
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
/** * 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); }
/* 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; }
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); }
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 */ }
/* 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); }
/** * 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)); }
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); }
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); }
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); }
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); }
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); }
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; }
Date SslCertificate::GetNotAfter() const { ASSERT(!IsEmpty()); return Asn1ToDate(X509_get_notAfter(cert)); }
IoObject *IoCertificate_notAfter(IoCertificate *self, IoObject *locals, IoMessage *m) { return IoCertificate_asnTimeToDate(self, X509_get_notAfter(X509(self))); }
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); }
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; }
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; }
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); } }
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; }
/* * 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; }