struct X509_flat * flatten_X509(X509 *x) { struct X509_flat *out = NULL; int ret; BUF_MEM *bptr = NULL; BIO *mem = NULL; if (x == NULL) { return NULL; } mem = BIO_new(BIO_s_mem()); if (mem == NULL) { return NULL; } ret = PEM_write_bio_X509(mem, x); if (ret == 0) { BIO_free(mem); return NULL; } out = new_X509_flat(); if (out == NULL) { BIO_free(mem); return NULL; } BIO_get_mem_ptr(mem, &bptr); assert(BIO_set_close(mem, BIO_NOCLOSE) == 1); BIO_free(mem); out->len = bptr->length; if (bptr->length != 0 && (size_t) bptr->length <= SIZE_MAX/sizeof(*(out->data))) { out->data = malloc(bptr->length*sizeof(*(out->data))); } if (out->data == NULL) { BUF_MEM_free(bptr); return NULL; } memcpy(out->data, bptr->data, bptr->length); BUF_MEM_free(bptr); return out; }
static void print_certificate(BIO *out, cert_format_e format, X509 *cert) { if (out == NULL) return; switch (format) { default: case CERT_FORMAT_TEXT: X509_print(out, cert); break; case CERT_FORMAT_PEM: PEM_write_bio_X509(out, cert); break; case CERT_FORMAT_DER: EXIT_ERROR("DER format is not yet supported for output"); break; } }
void capi_dump_cert(CAPI_CTX *ctx, BIO *out, PCCERT_CONTEXT cert) { X509 *x; unsigned char *p; unsigned long flags = ctx->dump_flags; if (flags & CAPI_DMP_FNAME) { char *fname; fname = capi_cert_get_fname(ctx, cert); if (fname) { BIO_printf(out, " Friendly Name \"%s\"\n", fname); OPENSSL_free(fname); } else BIO_printf(out, " <No Friendly Name>\n"); } p = cert->pbCertEncoded; x = d2i_X509(NULL, &p, cert->cbCertEncoded); if (!x) BIO_printf(out, " <Can't parse certificate>\n"); if (flags & CAPI_DMP_SUMMARY) { BIO_printf(out, " Subject: "); X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE); BIO_printf(out, "\n Issuer: "); X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE); BIO_printf(out, "\n"); } if (flags & CAPI_DMP_FULL) X509_print_ex(out, x, XN_FLAG_ONELINE,0); if (flags & CAPI_DMP_PKEYINFO) { CRYPT_KEY_PROV_INFO *pinfo; pinfo = capi_get_prov_info(ctx, cert); capi_dump_prov_info(ctx, out, pinfo); if (pinfo) OPENSSL_free(pinfo); } if (flags & CAPI_DMP_PEM) PEM_write_bio_X509(out, x); X509_free(x); }
static PyObject * z_py_zorp_certificate_getattr(PyObject *o, char *name) { ZorpCertificate *self = (ZorpCertificate *) o; PyObject *res = NULL; BIO *bio; guint len; gchar *mem; gchar buf[512]; if (strcmp(name, "blob") == 0) { bio = BIO_new(BIO_s_mem()); PEM_write_bio_X509(bio, self->cert); len = BIO_get_mem_data(bio, &mem); res = PyString_FromStringAndSize(mem, len); BIO_free(bio); } else if (strcmp(name, "issuer") == 0) { X509_NAME_oneline(X509_get_issuer_name(self->cert), buf, sizeof(buf)); res = PyString_FromString(buf); } else if (strcmp(name, "subject") == 0) { X509_NAME_oneline(X509_get_subject_name(self->cert), buf, sizeof(buf)); res = PyString_FromString(buf); } else if (strcmp(name, "serial") == 0) { ASN1_INTEGER *cert_serial; cert_serial = X509_get_serialNumber(self->cert); if (cert_serial) { res = PyInt_FromLong(ASN1_INTEGER_get(cert_serial)); } } else { PyErr_SetString(PyExc_AttributeError, "Attribute not found"); } return res; }
unsigned char* pemCert(X509* cert) { BIO * bio_out = BIO_new(BIO_s_mem()); PEM_write_bio_X509(bio_out, cert); BUF_MEM *bio_buf; BIO_get_mem_ptr(bio_out, &bio_buf); string pemStr = string(bio_buf->data, bio_buf->length); unsigned char* pem; char* cstr = const_cast<char*>(pemStr.c_str()); pem = reinterpret_cast<unsigned char*>(cstr); BIO_free(bio_out); unsigned char* retPem = new unsigned char[pemStr.length()]; memcpy(retPem, cstr, pemStr.length()); return retPem; }
int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* o, unsigned long flags) { int i; long l; OCSP_CERTID* cid = NULL; OCSP_ONEREQ *one = NULL; OCSP_REQINFO *inf = o->tbsRequest; OCSP_SIGNATURE *sig = o->optionalSignature; if (BIO_write(bp,"OCSP Request Data:\n",19) <= 0) goto err; l=ASN1_INTEGER_get(inf->version); if (BIO_printf(bp," Version: %lu (0x%lx)",l+1,l) <= 0) goto err; if (inf->requestorName != NULL) { if (BIO_write(bp,"\n Requestor Name: ",21) <= 0) goto err; GENERAL_NAME_print(bp, inf->requestorName); } if (BIO_write(bp,"\n Requestor List:\n",21) <= 0) goto err; for (i = 0; i < sk_OCSP_ONEREQ_num(inf->requestList); i++) { one = sk_OCSP_ONEREQ_value(inf->requestList, i); cid = one->reqCert; ocsp_certid_print(bp, cid, 8); if (!X509V3_extensions_print(bp, "Request Single Extensions", one->singleRequestExtensions, flags, 8)) goto err; } if (!X509V3_extensions_print(bp, "Request Extensions", inf->requestExtensions, flags, 4)) goto err; if (sig) { X509_signature_print(bp, sig->signatureAlgorithm, sig->signature); for (i=0; i<sk_X509_num(sig->certs); i++) { X509_print(bp, sk_X509_value(sig->certs,i)); PEM_write_bio_X509(bp,sk_X509_value(sig->certs,i)); } } return 1; err: return 0; }
int pki_write_certificate(X509 *certificate, const char *filename) { int ret = 0; BIO *bio_file = NULL; bio_file = BIO_new_file(filename, "w"); if (bio_file == NULL) { ret = -1; goto out; } ret = PEM_write_bio_X509(bio_file, certificate); if (ret != 1) { ret = -1; } BIO_free(bio_file); out: return ret; }
/** * Convert the certificate to PEM format. */ static int meth_pem(lua_State* L) { char* data; long bytes; X509* cert = lsec_checkx509(L, 1); BIO *bio = BIO_new(BIO_s_mem()); if (!PEM_write_bio_X509(bio, cert)) { lua_pushnil(L); return 1; } bytes = BIO_get_mem_data(bio, &data); if (bytes > 0) lua_pushlstring(L, data, bytes); else lua_pushnil(L); BIO_free(bio); return 1; }
// // retrieve the pem using the openssl functionality std::string LLBasicCertificate::getPem() const { char * pem_bio_chars = NULL; // a BIO is the equivalent of a 'std::stream', and // can be a file, mem stream, whatever. Grab a memory based // BIO for the result BIO *pem_bio = BIO_new(BIO_s_mem()); if (!pem_bio) { LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL; return std::string(); } PEM_write_bio_X509(pem_bio, mCert); int length = BIO_get_mem_data(pem_bio, &pem_bio_chars); std::string result = std::string(pem_bio_chars, length); BIO_free(pem_bio); return result; }
std::string exportToPem(X509 *x509) { std::string bio; if (!x509) return bio; BIO *bioMem = BIO_new(BIO_s_mem()); if (!PEM_write_bio_X509(bioMem, x509)) { // error } else { char *thePem; int pemLength = BIO_get_mem_data(bioMem, &thePem); bio = std::string(thePem, thePem + pemLength); } BIO_free_all(bioMem); return bio; }
static PyObject * as_pem (certificate_x509 *self, PyObject *args) { if (!PyArg_ParseTuple (args, "")) { return NULL; } BIO *bio = BIO_new (BIO_s_mem ()); PEM_write_bio_X509 (bio, self->x509); size_t size = BIO_ctrl_pending (bio); char *buf = malloc (sizeof (char) * size); BIO_read (bio, buf, size); BIO_free (bio); PyObject *pem = PyString_FromStringAndSize (buf, size); free (buf); return pem; }
void print_peer_certificate(SSL *ssl) { X509* cert= NULL; X509_NAME *name=NULL; char buf[8192]={0}; BIO *bio_cert = NULL; cert = SSL_get_peer_certificate(ssl); name = X509_get_subject_name(cert); X509_NAME_oneline(name,buf,8191); printf("Verified Peer Name:%s\n",buf); memset(buf,0,sizeof(buf)); bio_cert = BIO_new(BIO_s_mem()); PEM_write_bio_X509(bio_cert, cert); BIO_read( bio_cert, buf, 8191); printf("SERVER CERT:\n%s\n",buf); if(bio_cert)BIO_free(bio_cert); if(cert)X509_free(cert); }
bool write_pem(char *path, uint8_t *passwd, size_t len, EVP_PKEY *key, EC_GROUP *group, size_t certs, ...) { const EVP_CIPHER *cipher = passwd ? EVP_aes_256_cbc() : NULL; va_list ap; BIO *out = NULL; int fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd >= 0 && (out = BIO_new_fd(fd, BIO_CLOSE))) { PEM_write_bio_ECPKParameters(out, group); PEM_write_bio_PKCS8PrivateKey(out, key, cipher, (char *) passwd, len, NULL, NULL); va_start(ap, certs); for (size_t i = 0; i < certs; i++) { X509 *cert = va_arg(ap, X509 *); PEM_write_bio_X509(out, cert); } va_end(ap); BIO_free(out); }
/* * Convert X509 to string. */ static char * x509_to_string(const X509 *cert) { BIO *bio; int len; char *ptr, *result; // write X509 into buffer bio = BIO_new(BIO_s_mem()); PEM_write_bio_X509(bio, (X509 *) cert); // create results. len = BIO_number_written(bio); BIO_get_mem_data(bio, &ptr); result = palloc(len + 1); strncpy(result, ptr, len); result[len] = '\0'; BIO_free(bio); return result; }
static VALUE t_get_peer_cert (VALUE self UNUSED, VALUE signature) { VALUE ret = Qnil; X509 *cert = NULL; BUF_MEM *buf; BIO *out; cert = evma_get_peer_cert (NUM2BSIG (signature)); if (cert != NULL) { out = BIO_new(BIO_s_mem()); PEM_write_bio_X509(out, cert); BIO_get_mem_ptr(out, &buf); ret = rb_str_new(buf->data, buf->length); X509_free(cert); BIO_free(out); } return ret; }
/* * Convert an X509 certificate to a buffer of "sz". * We don't guarantee that it's nil-terminated. * Returns NULL on failure. */ static char * x509buf(X509 *x, size_t *sz) { BIO *bio; char *p; int ssz; /* Convert X509 to PEM in BIO. */ if (NULL == (bio = BIO_new(BIO_s_mem()))) { warnx("BIO_new"); return(NULL); } else if ( ! PEM_write_bio_X509(bio, x)) { warnx("PEM_write_bio_X509"); BIO_free(bio); return(NULL); } /* * Now convert bio to string. * Make into nil-terminated, just in case. */ if (NULL == (p = calloc(1, bio->num_write + 1))) { warn("calloc"); BIO_free(bio); return(NULL); } ssz = BIO_read(bio, p, bio->num_write); if (ssz < 0 || (unsigned)ssz != bio->num_write) { warnx("BIO_read"); BIO_free(bio); return(NULL); } *sz = ssz; BIO_free(bio); return(p); }
int SocketClient::pinCertCallback(int pok, X509_STORE_CTX *ctx) { std::cout << "Checking pinned certificate" << std::endl; X509 *cert = NULL; BIO *b64 = NULL; BUF_MEM *bptr = NULL; char *szCert = NULL; cert = ctx->current_cert; assert(cert != NULL); b64 = BIO_new(BIO_s_mem()); assert(b64 != NULL); assert(1 == PEM_write_bio_X509(b64, cert)); BIO_get_mem_ptr(b64, &bptr); assert(NULL != (szCert = (char*)malloc(bptr->length + 1))); assert(0 < BIO_read(b64, szCert, bptr->length)); int ret = strncmp(szCert, AUTH_CERTIFICATE, strlen(AUTH_CERTIFICATE)); free(szCert); if (b64) { BIO_free(b64); } if(ret == 0) { std::cout << "pinned certificate verification passed..." << std::endl; return 1; } else { std::cout << "pinned certificate verification failed..." << std::endl; return 0; } }
std::string render_pem() const { if (x509_) { BIO *bio = BIO_new(BIO_s_mem()); const int ret = PEM_write_bio_X509(bio, x509_); if (ret == 0) { BIO_free(bio); throw OpenSSLException("X509::render_pem"); } { char *temp; const int buf_len = BIO_get_mem_data(bio, &temp); std::string ret = std::string(temp, buf_len); BIO_free(bio); return ret; } } else return ""; }
int hr_https_add_vars(struct http_session *hr, struct corerouter_peer *peer, struct uwsgi_buffer *out) { // HTTPS (adapted from nginx) if (hr->session.ugs->mode == UWSGI_HTTP_SSL) { if (uwsgi_buffer_append_keyval(out, "HTTPS", 5, "on", 2)) return -1; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME const char *servername = SSL_get_servername(hr->ssl, TLSEXT_NAMETYPE_host_name); if (servername && strlen(servername) <= 0xff) { peer->key_len = strlen(servername); memcpy(peer->key, servername, peer->key_len) ; } #endif hr->ssl_client_cert = SSL_get_peer_certificate(hr->ssl); if (hr->ssl_client_cert) { X509_NAME *name = X509_get_subject_name(hr->ssl_client_cert); if (name) { hr->ssl_client_dn = X509_NAME_oneline(name, NULL, 0); if (uwsgi_buffer_append_keyval(out, "HTTPS_DN", 8, hr->ssl_client_dn, strlen(hr->ssl_client_dn))) return -1; } if (uhttp.https_export_cert) { hr->ssl_bio = BIO_new(BIO_s_mem()); if (hr->ssl_bio) { if (PEM_write_bio_X509(hr->ssl_bio, hr->ssl_client_cert) > 0) { size_t cc_len = BIO_pending(hr->ssl_bio); hr->ssl_cc = uwsgi_malloc(cc_len); BIO_read(hr->ssl_bio, hr->ssl_cc, cc_len); if (uwsgi_buffer_append_keyval(out, "HTTPS_CC", 8, hr->ssl_cc, cc_len)) return -1; } } } } } else if (hr->session.ugs->mode == UWSGI_HTTP_FORCE_SSL) { hr->force_https = 1; } return 0; }
void print_client_cert(char* path) { X509 *cert =NULL; FILE *fp = NULL; fp = fopen(path,"rb"); cert = PEM_read_X509(fp, NULL, NULL, "900820"); X509_NAME *name=NULL; char buf[8192]={0}; BIO *bio_cert = NULL; name = X509_get_subject_name(cert); X509_NAME_oneline(name,buf,8191); printf("ClientSubjectName:%s\n",buf); memset(buf,0,sizeof(buf)); bio_cert = BIO_new(BIO_s_mem()); PEM_write_bio_X509(bio_cert, cert); BIO_read( bio_cert, buf, 8191); printf("CLIENT CERT:\n%s\n",buf); if(bio_cert)BIO_free(bio_cert); fclose(fp); if(cert) X509_free(cert); }
/* Return a PEM-formatted buffer containing the peer's certificate chain. * * NULL is returned if there is no certificate chain, or if memory allocation fails. */ char *async_ssl__pem_peer_certificate_chain(const SSL *con) { STACK_OF(X509) *cert_stack = NULL; BIO *bio = NULL; char *certs = NULL; int i = 0, pending_bytes = 0; /* [cert_stack] is not to be freed; [SSL_get_peer_cert_chain] simply returns an * internal pointer and no reference count is incremented. */ if ((cert_stack = SSL_get_peer_cert_chain(con)) == NULL) { return NULL; } if ((bio = BIO_new(BIO_s_mem())) == NULL) { return NULL; } for (i = 0; i < sk_X509_num(cert_stack); i++) { if ((PEM_write_bio_X509(bio, sk_X509_value(cert_stack, i))) == 0) { goto cleanup; } } pending_bytes = BIO_ctrl_pending(bio); if ((certs = malloc((pending_bytes + 1) * sizeof(char))) == NULL) { goto cleanup; } if ((BIO_read(bio, certs, pending_bytes)) < pending_bytes) { free(certs); goto cleanup; } certs[pending_bytes] = '\0'; cleanup: BIO_set_close(bio, BIO_CLOSE); BIO_free(bio); return certs; }
extern "C" int ssl_verify_wrapper(int preverify_ok, X509_STORE_CTX *ctx) { unsigned long binding; X509 *cert; SSL *ssl; BUF_MEM *buf; BIO *out; int result; cert = X509_STORE_CTX_get_current_cert(ctx); ssl = (SSL*) X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); binding = (unsigned long) SSL_get_ex_data(ssl, 0); out = BIO_new(BIO_s_mem()); PEM_write_bio_X509(out, cert); BIO_write(out, "\0", 1); BIO_get_mem_ptr(out, &buf); ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject(binding)); result = (cd->VerifySslPeer(buf->data) == true ? 1 : 0); BIO_free(out); return result; }
static void print_stuff(BIO *bio, SSL *s, int full) { X509 *peer=NULL; char *p; static const char *space=" "; char buf[BUFSIZ]; STACK_OF(X509) *sk; STACK_OF(X509_NAME) *sk2; SSL_CIPHER *c; X509_NAME *xn; int j,i; #ifndef OPENSSL_NO_COMP const COMP_METHOD *comp, *expansion; #endif if (full) { int got_a_chain = 0; sk=SSL_get_peer_cert_chain(s); if (sk != NULL) { got_a_chain = 1; /* we don't have it for SSL2 (yet) */ BIO_printf(bio,"---\nCertificate chain\n"); for (i=0; i<sk_X509_num(sk); i++) { X509_NAME_oneline(X509_get_subject_name( sk_X509_value(sk,i)),buf,sizeof buf); BIO_printf(bio,"%2d s:%s\n",i,buf); X509_NAME_oneline(X509_get_issuer_name( sk_X509_value(sk,i)),buf,sizeof buf); BIO_printf(bio," i:%s\n",buf); if (c_showcerts) PEM_write_bio_X509(bio,sk_X509_value(sk,i)); } } BIO_printf(bio,"---\n"); peer=SSL_get_peer_certificate(s); if (peer != NULL) { BIO_printf(bio,"Server certificate\n"); if (!(c_showcerts && got_a_chain)) /* Redundant if we showed the whole chain */ PEM_write_bio_X509(bio,peer); X509_NAME_oneline(X509_get_subject_name(peer), buf,sizeof buf); BIO_printf(bio,"subject=%s\n",buf); X509_NAME_oneline(X509_get_issuer_name(peer), buf,sizeof buf); BIO_printf(bio,"issuer=%s\n",buf); } else BIO_printf(bio,"no peer certificate available\n"); sk2=SSL_get_client_CA_list(s); if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) { BIO_printf(bio,"---\nAcceptable client certificate CA names\n"); for (i=0; i<sk_X509_NAME_num(sk2); i++) { xn=sk_X509_NAME_value(sk2,i); X509_NAME_oneline(xn,buf,sizeof(buf)); BIO_write(bio,buf,strlen(buf)); BIO_write(bio,"\n",1); } } else { BIO_printf(bio,"---\nNo client certificate CA names sent\n"); } p=SSL_get_shared_ciphers(s,buf,sizeof buf); if (p != NULL) { /* This works only for SSL 2. In later protocol * versions, the client does not know what other * ciphers (in addition to the one to be used * in the current connection) the server supports. */ BIO_printf(bio,"---\nCiphers common between both SSL endpoints:\n"); j=i=0; while (*p) { if (*p == ':') { BIO_write(bio,space,15-j%25); i++; j=0; BIO_write(bio,((i%3)?" ":"\n"),1); } else { BIO_write(bio,p,1); j++; } p++; } BIO_write(bio,"\n",1); } BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n", BIO_number_read(SSL_get_rbio(s)), BIO_number_written(SSL_get_wbio(s))); } BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, ")); c=SSL_get_current_cipher(s); BIO_printf(bio,"%s, Cipher is %s\n", SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); if (peer != NULL) { EVP_PKEY *pktmp; pktmp = X509_get_pubkey(peer); BIO_printf(bio,"Server public key is %d bit\n", EVP_PKEY_bits(pktmp)); EVP_PKEY_free(pktmp); } #ifndef OPENSSL_NO_COMP comp=SSL_get_current_compression(s); expansion=SSL_get_current_expansion(s); BIO_printf(bio,"Compression: %s\n", comp ? SSL_COMP_get_name(comp) : "NONE"); BIO_printf(bio,"Expansion: %s\n", expansion ? SSL_COMP_get_name(expansion) : "NONE"); #endif SSL_SESSION_print(bio,SSL_get_session(s)); BIO_printf(bio,"---\n"); if (peer != NULL) X509_free(peer); /* flush, or debugging output gets mixed with http response */ (void)BIO_flush(bio); }
int MAIN(int argc, char **argv) { ENGINE *e = NULL; int ret=1; X509_REQ *req=NULL; X509 *x=NULL,*xca=NULL; ASN1_OBJECT *objtmp; STACK_OF(OPENSSL_STRING) *sigopts = NULL; EVP_PKEY *Upkey=NULL,*CApkey=NULL; ASN1_INTEGER *sno = NULL; int i,num,badops=0; BIO *out=NULL; BIO *STDout=NULL; STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; int informat,outformat,keyformat,CAformat,CAkeyformat; char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL; char *CAkeyfile=NULL,*CAserial=NULL; char *alias=NULL; int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0; int next_serial=0; int subject_hash=0,issuer_hash=0,ocspid=0; #ifndef OPENSSL_NO_MD5 int subject_hash_old=0,issuer_hash_old=0; #endif int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0; int ocsp_uri=0; int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0; int C=0; int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0; int pprint = 0; const char **pp; X509_STORE *ctx=NULL; X509_REQ *rq=NULL; int fingerprint=0; char buf[256]; const EVP_MD *md_alg,*digest=NULL; CONF *extconf = NULL; char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL; int need_rand = 0; int checkend=0,checkoffset=0; unsigned long nmflag = 0, certflag = 0; #ifndef OPENSSL_NO_ENGINE char *engine=NULL; #endif reqfile=0; apps_startup(); if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; STDout=BIO_new_fp(stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); STDout = BIO_push(tmpbio, STDout); } #endif 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; need_rand = 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=atoi(*(++argv)); if (days == 0) { BIO_printf(STDout,"bad number of days\n"); 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; need_rand = 1; } else if (strcmp(*argv,"-CA") == 0) { if (--argc < 1) goto bad; CAfile= *(++argv); CA_flag= ++num; need_rand = 1; } 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; if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv)))) goto bad; } else if (strcmp(*argv,"-addtrust") == 0) { if (--argc < 1) goto bad; if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { BIO_printf(bio_err, "Invalid trust object value %s\n", *argv); goto bad; } if (!trust) trust = sk_ASN1_OBJECT_new_null(); sk_ASN1_OBJECT_push(trust, objtmp); trustout = 1; } else if (strcmp(*argv,"-addreject") == 0) { if (--argc < 1) goto bad; if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { BIO_printf(bio_err, "Invalid reject object value %s\n", *argv); goto bad; } if (!reject) reject = sk_ASN1_OBJECT_new_null(); sk_ASN1_OBJECT_push(reject, objtmp); trustout = 1; } else if (strcmp(*argv,"-setalias") == 0) { if (--argc < 1) goto bad; alias= *(++argv); trustout = 1; } else if (strcmp(*argv,"-certopt") == 0) { if (--argc < 1) goto bad; if (!set_cert_ex(&certflag, *(++argv))) goto bad; } else if (strcmp(*argv,"-nameopt") == 0) { if (--argc < 1) goto bad; if (!set_name_ex(&nmflag, *(++argv))) goto bad; } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } #endif else if (strcmp(*argv,"-C") == 0) C= ++num; else if (strcmp(*argv,"-email") == 0) email= ++num; else if (strcmp(*argv,"-ocsp_uri") == 0) ocsp_uri= ++num; else if (strcmp(*argv,"-serial") == 0) serial= ++num; else if (strcmp(*argv,"-next_serial") == 0) next_serial= ++num; else if (strcmp(*argv,"-modulus") == 0) modulus= ++num; else if (strcmp(*argv,"-pubkey") == 0) pubkey= ++num; else if (strcmp(*argv,"-x509toreq") == 0) x509req= ++num; else if (strcmp(*argv,"-text") == 0) text= ++num; else if (strcmp(*argv,"-hash") == 0 || strcmp(*argv,"-subject_hash") == 0) subject_hash= ++num; #ifndef OPENSSL_NO_MD5 else if (strcmp(*argv,"-subject_hash_old") == 0) subject_hash_old= ++num; #endif else if (strcmp(*argv,"-issuer_hash") == 0) issuer_hash= ++num; #ifndef OPENSSL_NO_MD5 else if (strcmp(*argv,"-issuer_hash_old") == 0) issuer_hash_old= ++num; #endif else if (strcmp(*argv,"-subject") == 0) subject= ++num; else if (strcmp(*argv,"-issuer") == 0) issuer= ++num; else if (strcmp(*argv,"-fingerprint") == 0) fingerprint= ++num; else if (strcmp(*argv,"-dates") == 0) { startdate= ++num; enddate= ++num; } else if (strcmp(*argv,"-purpose") == 0) pprint= ++num; else if (strcmp(*argv,"-startdate") == 0) startdate= ++num; else if (strcmp(*argv,"-enddate") == 0) enddate= ++num; else if (strcmp(*argv,"-checkend") == 0) { if (--argc < 1) goto bad; checkoffset=atoi(*(++argv)); 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; #if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */ else if (strcmp(*argv,"-crlext") == 0) { BIO_printf(bio_err,"use -clrext instead of -crlext\n"); clrext = 1; } #endif else if (strcmp(*argv,"-ocspid") == 0) ocspid= ++num; else if ((md_alg=EVP_get_digestbyname(*argv + 1))) { /* ok */ digest=md_alg; } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badops=1; break; } argc--; argv++; } if (badops) { bad: for (pp=x509_usage; (*pp != NULL); pp++) BIO_printf(bio_err,"%s",*pp); goto end; } #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif if (need_rand) app_RAND_load_file(NULL, bio_err, 0); ERR_load_crypto_strings(); if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (!X509_STORE_set_default_paths(ctx)) { ERR_print_errors(bio_err); goto end; } if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) { CAkeyfile=CAfile; } else if ((CA_flag) && (CAkeyfile == NULL)) { BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n"); goto end; } if (extfile) { long errorline = -1; X509V3_CTX ctx2; extconf = NCONF_new(NULL); if (!NCONF_load(extconf, extfile,&errorline)) { if (errorline <= 0) BIO_printf(bio_err, "error loading the config file '%s'\n", extfile); else BIO_printf(bio_err, "error on line %ld of config file '%s'\n" ,errorline,extfile); goto end; } if (!extsect) { extsect = NCONF_get_string(extconf, "default", "extensions"); if (!extsect) { ERR_clear_error(); extsect = "default"; } } X509V3_set_ctx_test(&ctx2); X509V3_set_nconf(&ctx2, extconf); if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { BIO_printf(bio_err, "Error Loading extension section %s\n", extsect); ERR_print_errors(bio_err); goto end; } } if (reqfile) { EVP_PKEY *pkey; BIO *in; if (!sign_flag && !CA_flag) { BIO_printf(bio_err,"We need a private key to sign with\n"); goto end; } in=BIO_new(BIO_s_file()); if (in == NULL) { ERR_print_errors(bio_err); goto end; } if (infile == NULL) BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT); else { if (BIO_read_filename(in,infile) <= 0) { perror(infile); BIO_free(in); goto end; } } req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL); BIO_free(in); if (req == NULL) { ERR_print_errors(bio_err); goto end; } if ( (req->req_info == NULL) || (req->req_info->pubkey == NULL) || (req->req_info->pubkey->public_key == NULL) || (req->req_info->pubkey->public_key->data == NULL)) { BIO_printf(bio_err,"The certificate request appears to corrupted\n"); BIO_printf(bio_err,"It does not contain a public key\n"); goto end; } if ((pkey=X509_REQ_get_pubkey(req)) == NULL) { BIO_printf(bio_err,"error unpacking public key\n"); goto end; } i=X509_REQ_verify(req,pkey); EVP_PKEY_free(pkey); if (i < 0) { BIO_printf(bio_err,"Signature verification error\n"); ERR_print_errors(bio_err); goto end; } if (i == 0) { BIO_printf(bio_err,"Signature did not match the certificate request\n"); goto end; } else BIO_printf(bio_err,"Signature ok\n"); print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag); if ((x=X509_new()) == NULL) goto end; if (sno == NULL) { sno = ASN1_INTEGER_new(); if (!sno || !rand_serial(NULL, sno)) goto end; if (!X509_set_serialNumber(x, sno)) goto end; ASN1_INTEGER_free(sno); sno = NULL; } else if (!X509_set_serialNumber(x, sno)) goto end; if (!X509_set_issuer_name(x,req->req_info->subject)) goto end; if (!X509_set_subject_name(x,req->req_info->subject)) goto end; X509_gmtime_adj(X509_get_notBefore(x),0); X509_time_adj_ex(X509_get_notAfter(x),days, 0, NULL); pkey = X509_REQ_get_pubkey(req); X509_set_pubkey(x,pkey); EVP_PKEY_free(pkey); } else x=load_cert(bio_err,infile,informat,NULL,e,"Certificate"); if (x == NULL) goto end; if (CA_flag) { xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate"); if (xca == NULL) goto end; } if (!noout || text || next_serial) { OBJ_create("2.99999.3", "SET.ex3","SET x509v3 extension 3"); out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } } if (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="); #ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) BN_print(STDout,pkey->pkey.rsa->n); else #endif #ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) BN_print(STDout,pkey->pkey.dsa->pub_key); else #endif 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=OPENSSL_malloc(z); d=(unsigned char *)m; z=i2d_X509_NAME(X509_get_subject_name(x),&d); BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z); d=(unsigned char *)m; for (y=0; y<z; y++) { BIO_printf(STDout,"0x%02X,",d[y]); if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n"); } if (y%16 != 0) BIO_printf(STDout,"\n"); BIO_printf(STDout,"};\n"); z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d); BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z); d=(unsigned char *)m; for (y=0; y<z; y++) { BIO_printf(STDout,"0x%02X,",d[y]); if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n"); } if (y%16 != 0) BIO_printf(STDout,"\n"); BIO_printf(STDout,"};\n"); z=i2d_X509(x,&d); BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z); d=(unsigned char *)m; for (y=0; y<z; y++) { BIO_printf(STDout,"0x%02X,",d[y]); if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n"); } if (y%16 != 0) BIO_printf(STDout,"\n"); BIO_printf(STDout,"};\n"); OPENSSL_free(m); } else if (text == i) { X509_print_ex(out,x,nmflag, certflag); } else if (startdate == i) { BIO_puts(STDout,"notBefore="); ASN1_TIME_print(STDout,X509_get_notBefore(x)); BIO_puts(STDout,"\n"); } else if (enddate == i) { BIO_puts(STDout,"notAfter="); ASN1_TIME_print(STDout,X509_get_notAfter(x)); BIO_puts(STDout,"\n"); } else if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; const EVP_MD *fdig = digest; if (!fdig) fdig = EVP_sha1(); if (!X509_digest(x,fdig,md,&n)) { BIO_printf(bio_err,"out of memory\n"); goto end; } BIO_printf(STDout,"%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(fdig))); for (j=0; j<(int)n; j++) { BIO_printf(STDout,"%02X%c",md[j], (j+1 == (int)n) ?'\n':':'); } } /* should be in the library */ else if ((sign_flag == i) && (x509req == 0)) { BIO_printf(bio_err,"Getting Private key\n"); if (Upkey == NULL) { Upkey=load_key(bio_err, keyfile, keyformat, 0, passin, e, "Private key"); if (Upkey == NULL) goto end; } 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(bio_err, 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)) goto end; } else if (x509req == i) { EVP_PKEY *pk; BIO_printf(bio_err,"Getting request Private Key\n"); if (keyfile == NULL) { BIO_printf(bio_err,"no request key file specified\n"); goto end; } else { pk=load_key(bio_err, keyfile, keyformat, 0, passin, e, "request key"); if (pk == NULL) goto end; } BIO_printf(bio_err,"Generating certificate request\n"); rq=X509_to_X509_REQ(x,pk,digest); EVP_PKEY_free(pk); if (rq == NULL) { ERR_print_errors(bio_err); goto end; } if (!noout) { X509_REQ_print(out,rq); PEM_write_bio_X509_REQ(out,rq); } noout=1; } else if (ocspid == i) { X509_ocspid_print(out, x); } } } if (checkend) { time_t tcheck=time(NULL) + checkoffset; if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) { BIO_printf(out,"Certificate will expire\n"); ret=1; } else { BIO_printf(out,"Certificate will not expire\n"); ret=0; } goto end; } if (noout) { ret=0; goto end; } if (outformat == FORMAT_ASN1) i=i2d_X509_bio(out,x); else if (outformat == FORMAT_PEM) { if (trustout) i=PEM_write_bio_X509_AUX(out,x); else i=PEM_write_bio_X509(out,x); } else if (outformat == FORMAT_NETSCAPE) { NETSCAPE_X509 nx; ASN1_OCTET_STRING hdr; hdr.data=(unsigned char *)NETSCAPE_CERT_HDR; hdr.length=strlen(NETSCAPE_CERT_HDR); nx.header= &hdr; nx.cert=x; i=ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509),out,&nx); } else { BIO_printf(bio_err,"bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err,"unable to write certificate\n"); ERR_print_errors(bio_err); goto end; } ret=0; end: if (need_rand) app_RAND_write_file(NULL, bio_err); OBJ_cleanup(); NCONF_free(extconf); BIO_free_all(out); BIO_free_all(STDout); X509_STORE_free(ctx); X509_REQ_free(req); X509_free(x); X509_free(xca); EVP_PKEY_free(Upkey); EVP_PKEY_free(CApkey); if (sigopts) sk_OPENSSL_STRING_free(sigopts); X509_REQ_free(rq); ASN1_INTEGER_free(sno); sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); if (passin) OPENSSL_free(passin); apps_shutdown(); OPENSSL_EXIT(ret); }
int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port) { int match; int index; char* common_name = NULL; int common_name_length = 0; char** alt_names = NULL; int alt_names_count = 0; int* alt_names_lengths = NULL; BOOL certificate_status; BOOL hostname_match = FALSE; BOOL verification_status = FALSE; rdpCertificateData* certificate_data; if (tls->settings->ExternalCertificateManagement) { BIO* bio; int status; int length; int offset; BYTE* pemCert; freerdp* instance = (freerdp*) tls->settings->instance; /** * Don't manage certificates internally, leave it up entirely to the external client implementation */ bio = BIO_new(BIO_s_mem()); if (!bio) { WLog_ERR(TAG, "BIO_new() failure"); return -1; } status = PEM_write_bio_X509(bio, cert->px509); if (status < 0) { WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status); return -1; } offset = 0; length = 2048; pemCert = (BYTE*) malloc(length + 1); if (!pemCert) { WLog_ERR(TAG, "error allocating pemCert"); return -1; } status = BIO_read(bio, pemCert, length); if (status < 0) { WLog_ERR(TAG, "failed to read certificate"); return -1; } offset += status; while (offset >= length) { int new_len; BYTE* new_cert; new_len = length * 2; new_cert = (BYTE*) realloc(pemCert, new_len + 1); if (!new_cert) return -1; length = new_len; pemCert = new_cert; status = BIO_read(bio, &pemCert[offset], length); if (status < 0) break; offset += status; } if (status < 0) { WLog_ERR(TAG, "failed to read certificate"); return -1; } length = offset; pemCert[length] = '\0'; status = -1; if (instance->VerifyX509Certificate) status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, tls->isGatewayTransport); else WLog_ERR(TAG, "No VerifyX509Certificate callback registered!"); free(pemCert); BIO_free(bio); if (status < 0) { WLog_ERR(TAG, "VerifyX509Certificate failed: (length = %d) status: [%d] %s", length, status, pemCert); return -1; } return (status == 0) ? 0 : 1; } /* ignore certificate verification if user explicitly required it (discouraged) */ if (tls->settings->IgnoreCertificate) return 1; /* success! */ /* if user explicitly specified a certificate name, use it instead of the hostname */ if (tls->settings->CertificateName) hostname = tls->settings->CertificateName; /* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */ certificate_status = x509_verify_certificate(cert, tls->certificate_store->path); /* verify certificate name match */ certificate_data = crypto_get_certificate_data(cert->px509, hostname, port); /* extra common name and alternative names */ common_name = crypto_cert_subject_common_name(cert->px509, &common_name_length); alt_names = crypto_cert_subject_alt_name(cert->px509, &alt_names_count, &alt_names_lengths); /* compare against common name */ if (common_name) { if (tls_match_hostname(common_name, common_name_length, hostname)) hostname_match = TRUE; } /* compare against alternative names */ if (alt_names) { for (index = 0; index < alt_names_count; index++) { if (tls_match_hostname(alt_names[index], alt_names_lengths[index], hostname)) { hostname_match = TRUE; break; } } } /* if the certificate is valid and the certificate name matches, verification succeeds */ if (certificate_status && hostname_match) verification_status = TRUE; /* success! */ /* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */ if (!certificate_status || !hostname_match) { char* issuer; char* subject; char* fingerprint; freerdp* instance = (freerdp*) tls->settings->instance; DWORD accept_certificate = 0; issuer = crypto_cert_issuer(cert->px509); subject = crypto_cert_subject(cert->px509); fingerprint = crypto_cert_fingerprint(cert->px509); /* search for matching entry in known_hosts file */ match = certificate_data_match(tls->certificate_store, certificate_data); if (match == 1) { /* no entry was found in known_hosts file, prompt user for manual verification */ if (!hostname_match) tls_print_certificate_name_mismatch_error( hostname, port, common_name, alt_names, alt_names_count); /* Automatically accept certificate on first use */ if (tls->settings->AutoAcceptCertificate) { WLog_INFO(TAG, "No certificate stored, automatically accepting."); accept_certificate = 1; } else if (instance->VerifyCertificate) { accept_certificate = instance->VerifyCertificate( instance, common_name, subject, issuer, fingerprint, !hostname_match); } switch (accept_certificate) { case 1: /* user accepted certificate, add entry in known_hosts file */ verification_status = certificate_data_print(tls->certificate_store, certificate_data); break; case 2: /* user did accept temporaty, do not add to known hosts file */ verification_status = TRUE; break; default: /* user did not accept, abort and do not add entry in known_hosts file */ verification_status = FALSE; /* failure! */ break; } } else if (match == -1) { char* old_subject = NULL; char* old_issuer = NULL; char* old_fingerprint = NULL; /* entry was found in known_hosts file, but fingerprint does not match. ask user to use it */ tls_print_certificate_error(hostname, port, fingerprint, tls->certificate_store->file); if (!certificate_get_stored_data(tls->certificate_store, certificate_data, &old_subject, &old_issuer, &old_fingerprint)) WLog_WARN(TAG, "Failed to get certificate entry for %s:%d", hostname, port); if (instance->VerifyChangedCertificate) { accept_certificate = instance->VerifyChangedCertificate( instance, common_name, subject, issuer, fingerprint, old_subject, old_issuer, old_fingerprint); } free(old_subject); free(old_issuer); free(old_fingerprint); switch (accept_certificate) { case 1: /* user accepted certificate, add entry in known_hosts file */ verification_status = certificate_data_replace(tls->certificate_store, certificate_data); break; case 2: /* user did accept temporaty, do not add to known hosts file */ verification_status = TRUE; break; default: /* user did not accept, abort and do not add entry in known_hosts file */ verification_status = FALSE; /* failure! */ break; } } else if (match == 0) verification_status = TRUE; /* success! */ free(issuer); free(subject); free(fingerprint); } certificate_data_free(certificate_data); free(common_name); if (alt_names) crypto_cert_subject_alt_name_free(alt_names_count, alt_names_lengths, alt_names); return (verification_status == 0) ? 0 : 1; }
int MAIN(int argc, char **argv) { SSL_SESSION *x=NULL; int ret=1,i,num,badops=0; BIO *out=NULL; int informat,outformat; char *infile=NULL,*outfile=NULL,*context=NULL; int cert=0,noout=0,text=0; char **pp; apps_startup(); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); informat=FORMAT_PEM; outformat=FORMAT_PEM; 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,"-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,"-text") == 0) text= ++num; else if (strcmp(*argv,"-cert") == 0) cert= ++num; else if (strcmp(*argv,"-noout") == 0) noout= ++num; else if (strcmp(*argv,"-context") == 0) { if(--argc < 1) goto bad; context=*++argv; } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badops=1; break; } argc--; argv++; } if (badops) { bad: for (pp=sess_id_usage; (*pp != NULL); pp++) BIO_printf(bio_err,*pp); goto end; } ERR_load_crypto_strings(); x=load_sess_id(infile,informat); if (x == NULL) { goto end; } if(context) { x->sid_ctx_length=strlen(context); if(x->sid_ctx_length > SSL_MAX_SID_CTX_LENGTH) { BIO_printf(bio_err,"Context too long\n"); goto end; } memcpy(x->sid_ctx,context,x->sid_ctx_length); } #ifdef undef /* just testing for memory leaks :-) */ { SSL_SESSION *s; char buf[1024*10],*p; int i; s=SSL_SESSION_new(); p= &buf; i=i2d_SSL_SESSION(x,&p); p= &buf; d2i_SSL_SESSION(&s,&p,(long)i); p= &buf; d2i_SSL_SESSION(&s,&p,(long)i); p= &buf; d2i_SSL_SESSION(&s,&p,(long)i); SSL_SESSION_free(s); } #endif if (!noout || text) { out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } } if (text) { SSL_SESSION_print(out,x); if (cert) { if (x->peer == NULL) BIO_puts(out,"No certificate present\n"); else X509_print(out,x->peer); } } if (!noout && !cert) { if (outformat == FORMAT_ASN1) i=(int)i2d_SSL_SESSION_bio(out,x); else if (outformat == FORMAT_PEM) i=PEM_write_bio_SSL_SESSION(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 SSL_SESSION\n"); goto end; } } else if (!noout && (x->peer != NULL)) /* just print the certificate */ { if (outformat == FORMAT_ASN1) i=(int)i2d_X509_bio(out,x->peer); else if (outformat == FORMAT_PEM) i=PEM_write_bio_X509(out,x->peer); else { BIO_printf(bio_err,"bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err,"unable to write X509\n"); goto end; } } ret=0; end: if (out != NULL) BIO_free_all(out); if (x != NULL) SSL_SESSION_free(x); EXIT(ret); }
static void https_add_ssl_entries(connection *con) { X509 *xs; X509_NAME *xn; X509_NAME_ENTRY *xe; int i, nentries; if ( SSL_get_verify_result(con->ssl) != X509_V_OK || !(xs = SSL_get_peer_certificate(con->ssl)) ) { return; } xn = X509_get_subject_name(xs); for (i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) { int xobjnid; const char * xobjsn; data_string *envds; if (!(xe = X509_NAME_get_entry(xn, i))) { continue; } xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe)); xobjsn = OBJ_nid2sn(xobjnid); if (!xobjsn) { continue; } if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { envds = data_string_init(); } buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_S_DN_")); buffer_append_string(envds->key, xobjsn); buffer_copy_string_len( envds->value, (const char *)xe->value->data, xe->value->length ); /* pick one of the exported values as "authed user", for example * ssl.verifyclient.username = "******" or "SSL_CLIENT_S_DN_emailAddress" */ if (buffer_is_equal(con->conf.ssl_verifyclient_username, envds->key)) { buffer_copy_string_buffer(con->authed_user, envds->value); } array_insert_unique(con->environment, (data_unset *)envds); } if (con->conf.ssl_verifyclient_export_cert) { BIO *bio; if (NULL != (bio = BIO_new(BIO_s_mem()))) { data_string *envds; int n; PEM_write_bio_X509(bio, xs); n = BIO_pending(bio); if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { envds = data_string_init(); } buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_CERT")); buffer_prepare_copy(envds->value, n+1); BIO_read(bio, envds->value->ptr, n); BIO_free(bio); envds->value->ptr[n] = '\0'; envds->value->used = n+1; array_insert_unique(con->environment, (data_unset *)envds); } } X509_free(xs); }
DDS_ReturnCode_t sp_extract_pem (DDS_Credentials *cred, unsigned char **cert, size_t *cert_len, unsigned char **key, size_t *key_len) { BIO *cert_in, *key_in; int i; FILE *fp; long lSize; if (cred->credentialKind == DDS_ENGINE_BASED) { /* Not implemented */ } else if (cred->credentialKind == DDS_FILE_BASED) { /* Read the certificate pem file */ fp = fopen ( cred->info.filenames.certificate_chain_file , "rb" ); if( !fp ) perror ( cred->info.filenames.certificate_chain_file),exit(1); fseek ( fp , 0L , SEEK_END); lSize = ftell( fp ); rewind ( fp ); *cert = calloc ( 1, lSize+1 ); if( !*cert ) fclose(fp),fputs("memory alloc fails",stderr),exit(1); if( 1!=fread( (void *) *cert , lSize, 1 , fp) ) fclose(fp),free(*cert),fputs("entire read fails",stderr),exit(1); *cert_len = (size_t) lSize; fclose(fp); /* Read private key pem file */ fp = fopen (cred->info.filenames.private_key_file, "rb" ); if (!fp) { perror (cred->info.filenames.private_key_file); exit(1); } fseek ( fp , 0L , SEEK_END); lSize = ftell( fp ); rewind ( fp ); *key = calloc ( 1, lSize+1 ); if( !*key ) fclose(fp),fputs("memory alloc fails",stderr),exit(1); if( 1!=fread( (void *) *key , lSize, 1 , fp) ) fclose(fp),free(*key),fputs("entire read fails",stderr),exit(1); *key_len = (size_t) lSize; fclose(fp); } else if (cred->credentialKind == DDS_SSL_BASED) { cert_in = BIO_new (BIO_s_mem ()); key_in = BIO_new (BIO_s_mem ()); /* Write the X509 to a PEM format in a BIO */ for (i = 0; i < sk_X509_num (cred->info.sslData.certificate_list); i++) PEM_write_bio_X509(cert_in, sk_X509_value (cred->info.sslData.certificate_list, i)); *cert = malloc (sizeof (unsigned char) * cert_in->num_write + 1); /* read from the BIO into a char * */ *cert_len = BIO_read (cert_in, *cert, cert_in->num_write); memset (&(*cert) [(int) *cert_len], '\0', sizeof (char)); /* Write the X509 to a PEM format in a BIO */ PEM_write_bio_PrivateKey(key_in, cred->info.sslData.private_key, NULL, NULL, 0, 0, NULL); *key = malloc (sizeof (unsigned char) * key_in->num_write + 1); /* read from the BIO into a char * */ *key_len = BIO_read (key_in, *key, key_in->num_write); memset (&(*key) [(int) *key_len], '\0', sizeof (char)); BIO_free (cert_in); BIO_free (key_in); } else if (cred->credentialKind == DDS_DATA_BASED) { if (cred->info.data.private_key.format == DDS_FORMAT_PEM) { *key = malloc (sizeof (unsigned char) * cred->info.data.private_key.length + 1); strcpy ((char *) *key, (char *) cred->info.data.private_key.data); *key_len = cred->info.data.private_key.length; } else { /* Not implemented */ } /* This is okay for the current useage, but not for the intended useage */ for (i = 0; i < (int) cred->info.data.num_certificates ; i++) { if (cred->info.data.certificates [i].format == DDS_FORMAT_PEM) { *cert = malloc (sizeof (unsigned char) * cred->info.data.certificates [i].length + 1); strcpy ((char *) *cert, (char *) cred->info.data.certificates [i].data); *cert_len = cred->info.data.certificates [i].length; } } } else { /*TODO: Go get the cert from data*/ } return (DDS_RETCODE_OK); }
DVT_STATUS CERTIFICATE_CLASS::generateFiles(LOG_CLASS* logger_ptr, const char* signerCredentialsFile_ptr, const char* credentialsPassword_ptr, const char* keyPassword_ptr, const char* keyFile_ptr, const char* certificateFile_ptr) // DESCRIPTION : Generate a certificate and key files from this class. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : If signerCredentialsFile_ptr is NULL, a self signed // : certificate will be generated. // : // : Returns: MSG_OK, MSG_LIB_NOT_EXIST, MSG_FILE_NOT_EXIST, // : MSG_ERROR, MSG_INVALID_PASSWORD //<<=========================================================================== { DVT_STATUS ret = MSG_ERROR; unsigned long err; OPENSSL_CLASS* openSsl_ptr; BIO* caBio_ptr = NULL; EVP_PKEY* caPrivateKey_ptr = NULL; X509* caCertificate_ptr = NULL; EVP_PKEY* key_ptr = NULL; X509* cert_ptr = NULL; X509_NAME* name_ptr; time_t effectiveTime; time_t expirationTime; EVP_PKEY* tmpKey_ptr; const EVP_MD *digest_ptr; BIO* pkBio_ptr = NULL; const EVP_CIPHER *cipher_ptr; BIO* certBio_ptr = NULL; // check for the existence of the OpenSSL DLLs openSsl_ptr = OPENSSL_CLASS::getInstance(); if (openSsl_ptr == NULL) { return MSG_LIB_NOT_EXIST; } // clear the error queue ERR_clear_error(); if (signerCredentialsFile_ptr != NULL) { // open the credentials file caBio_ptr = BIO_new(BIO_s_file_internal()); if (caBio_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting up to read CA credentials file"); goto end; } if (BIO_read_filename(caBio_ptr, signerCredentialsFile_ptr) <= 0) { err = ERR_peek_error(); if ((ERR_GET_LIB(err) == ERR_LIB_SYS) && (ERR_GET_REASON(err) == ERROR_FILE_NOT_FOUND)) { // file does not exist ERR_clear_error(); // eat any errors ret = MSG_FILE_NOT_EXIST; } else { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "opening CA credentials file for reading"); } goto end; } // read the certificate authority's private key caPrivateKey_ptr = PEM_read_bio_PrivateKey(caBio_ptr, NULL, NULL, (void*)credentialsPassword_ptr); if (caPrivateKey_ptr == NULL) { err = ERR_peek_error(); if ((ERR_GET_LIB(err) == ERR_LIB_EVP) && (ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT)) { // bad password ERR_clear_error(); // eat any errors ret = MSG_INVALID_PASSWORD; } else { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "reading private key from CA credentials file"); } goto end; } // read the certificate authority's certificate caCertificate_ptr = PEM_read_bio_X509(caBio_ptr, NULL, NULL, (void*)credentialsPassword_ptr); if (caCertificate_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "reading CA certificate from CA credentials file"); goto end; } } // generate the new private/public key pair if (signatureAlgorithmM.compare("RSA") == 0) { // RSA key RSA* rsa_key; rsa_key = RSA_generate_key(signatureKeyLengthM, RSA_3, NULL, 0); if (rsa_key == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "generating RSA key"); goto end; } key_ptr = EVP_PKEY_new(); if (key_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "creating RSA key"); RSA_free(rsa_key); goto end; } EVP_PKEY_assign_RSA(key_ptr, rsa_key); } else { // DSA key DSA* dsa_key; dsa_key = DSA_generate_parameters(signatureKeyLengthM, NULL, 0, NULL, NULL, NULL, 0); if (dsa_key == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "generating DSA parameters"); goto end; } if (DSA_generate_key(dsa_key) == 0) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "generating DSA key"); DSA_free(dsa_key); goto end; } key_ptr = EVP_PKEY_new(); if (key_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "creating DSA key"); DSA_free(dsa_key); goto end; } EVP_PKEY_assign_DSA(key_ptr, dsa_key); } // create the certificate cert_ptr = X509_new(); if (cert_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "creating certificate object"); goto end; } // version if (X509_set_version(cert_ptr, (versionM - 1)) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting certificate version"); goto end; } // subject name_ptr = openSsl_ptr->onelineName2Name(subjectM.c_str()); if (name_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "parsing owner name"); goto end; } if (X509_set_subject_name(cert_ptr, name_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting owner name in certificate"); goto end; } // issuer if (signerCredentialsFile_ptr != NULL) { // CA signed name_ptr = X509_get_subject_name(caCertificate_ptr); if (name_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "getting name from CA certificate"); goto end; } if (X509_set_issuer_name(cert_ptr, name_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting issuer name in certificate"); goto end; } } else { // self signed name_ptr = X509_NAME_dup(name_ptr); // duplicate the name so it can be used again if (name_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "duplicating owner name"); goto end; } if (X509_set_issuer_name(cert_ptr, name_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting issuer name in certificate"); goto end; } } // public key if (X509_set_pubkey(cert_ptr, key_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting public key in certificate"); goto end; } // valid dates effectiveTime = mktime(&effectiveDateM); expirationTime = mktime(&expirationDateM); if ((X509_time_adj(X509_get_notBefore(cert_ptr), 0, &effectiveTime) == NULL) || (X509_time_adj(X509_get_notAfter(cert_ptr), 0, &expirationTime) == NULL)) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting valid dates in certificate"); goto end; } // serial number, use the current time_t ASN1_INTEGER_set(X509_get_serialNumber(cert_ptr), (unsigned)time(NULL)); // sign the certificate if (signerCredentialsFile_ptr != NULL) { // CA signed tmpKey_ptr = caPrivateKey_ptr; } else { // self signed tmpKey_ptr = key_ptr; } if (EVP_PKEY_type(tmpKey_ptr->type) == EVP_PKEY_RSA) { digest_ptr = EVP_sha1(); } else if (EVP_PKEY_type(tmpKey_ptr->type) == EVP_PKEY_DSA) { digest_ptr = EVP_dss1(); } else { if (logger_ptr) { logger_ptr->text(LOG_ERROR, 1, "Unsupported key type in CA private key"); } goto end; } if (!X509_sign(cert_ptr, tmpKey_ptr, digest_ptr)) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "signing certificate"); goto end; } // write out the private key // open the private key file pkBio_ptr = BIO_new(BIO_s_file_internal()); if (pkBio_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting up to write private key file"); goto end; } if (BIO_write_filename(pkBio_ptr, (void *)keyFile_ptr) <= 0) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "opening to write private key file"); goto end; } if ((keyPassword_ptr != NULL) && (strlen(keyPassword_ptr) > 0)) { // we have a password, use 3DES to encrypt the key cipher_ptr = EVP_des_ede3_cbc(); } else { // there is no password, don't encrypt the key cipher_ptr = NULL; } // write out the private key if (PEM_write_bio_PKCS8PrivateKey(pkBio_ptr, key_ptr, cipher_ptr, NULL, 0, NULL, (void *)keyPassword_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing private key"); goto end; } // write the certificate file // open the certificate file certBio_ptr = BIO_new(BIO_s_file_internal()); if (certBio_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting up to write certificate file"); goto end; } if (BIO_write_filename(certBio_ptr, (void *)certificateFile_ptr) <= 0) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "opening to write certificate file"); goto end; } // write the new certificate if (PEM_write_bio_X509(certBio_ptr, cert_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing certificate"); goto end; } // write the new certificate into the credential file if (PEM_write_bio_X509(pkBio_ptr, cert_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing certificate"); goto end; } if (signerCredentialsFile_ptr != NULL) { // write the CA certificate if (PEM_write_bio_X509(certBio_ptr, caCertificate_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing CA certificate"); goto end; } // loop reading certificates from the CA credentials file and writing them to the certificate file X509_free(caCertificate_ptr); while ((caCertificate_ptr = PEM_read_bio_X509(caBio_ptr, NULL, NULL, (void*)credentialsPassword_ptr)) != NULL) { // write the certificate if (PEM_write_bio_X509(certBio_ptr, caCertificate_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing certificate chain"); goto end; } X509_free(caCertificate_ptr); } // check the error err = ERR_peek_error(); if ((ERR_GET_LIB(err) == ERR_LIB_PEM) && (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { // end of data - this is normal ERR_clear_error(); } else { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "reading certificates from CA credentials file"); goto end; } } ret = MSG_OK; end: if (certBio_ptr != NULL) BIO_free(certBio_ptr); if (pkBio_ptr != NULL) BIO_free(pkBio_ptr); if (cert_ptr != NULL) X509_free(cert_ptr); if (key_ptr != NULL) EVP_PKEY_free(key_ptr); if (caCertificate_ptr != NULL) X509_free(caCertificate_ptr); if (caPrivateKey_ptr != NULL) EVP_PKEY_free(caPrivateKey_ptr); if (caBio_ptr != NULL) BIO_free(caBio_ptr); return ret; }
static BOOL tls_extract_pem(CryptoCert cert, BYTE** PublicKey, DWORD* PublicKeyLength) { BIO* bio; int status; size_t offset; int length = 0; BOOL rc = FALSE; BYTE* pemCert = NULL; if (!PublicKey || !PublicKeyLength) return FALSE; *PublicKey = NULL; *PublicKeyLength = 0; /** * Don't manage certificates internally, leave it up entirely to the external client implementation */ bio = BIO_new(BIO_s_mem()); if (!bio) { WLog_ERR(TAG, "BIO_new() failure"); return FALSE; } status = PEM_write_bio_X509(bio, cert->px509); if (status < 0) { WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status); goto fail; } offset = 0; length = 2048; pemCert = (BYTE*) malloc(length + 1); if (!pemCert) { WLog_ERR(TAG, "error allocating pemCert"); goto fail; } status = BIO_read(bio, pemCert, length); if (status < 0) { WLog_ERR(TAG, "failed to read certificate"); goto fail; } offset += status; while (offset >= length) { int new_len; BYTE* new_cert; new_len = length * 2; new_cert = (BYTE*) realloc(pemCert, new_len + 1); if (!new_cert) goto fail; length = new_len; pemCert = new_cert; status = BIO_read(bio, &pemCert[offset], length - offset); if (status < 0) break; offset += status; } if (status < 0) { WLog_ERR(TAG, "failed to read certificate"); goto fail; } length = offset; pemCert[length] = '\0'; *PublicKey = pemCert; *PublicKeyLength = length; rc = TRUE; fail: if (!rc) free(pemCert); BIO_free(bio); return rc; }