#include #include #include #if 0 /* * Certificate, including private key and certificate chain. */ cert_t * cert_new(void) { cert_t *c; if (!(c = (cert_t *)malloc(sizeof(cert_t)))) return NULL; memset(c, 0, sizeof(cert_t)); if (pthread_mutex_init(&c->mutex, NULL)) { free(c); return NULL; } c->references = 1; return c; } /* * Passed OpenSSL objects are owned by cert_t; refcount will not be * incremented, stack will not be duplicated. */ cert_t * cert_new3(EVP_PKEY *key, X509 *crt, STACK_OF(X509) *chain) { cert_t *c; if (!(c = (cert_t *)malloc(sizeof(cert_t)))) return NULL; if (pthread_mutex_init(&c->mutex, NULL)) { free(c); return NULL; } c->key = key; c->crt = crt; c->chain = chain; c->references = 1; return c; } /* * Passed OpenSSL objects are copied by cert_t; crt/key refcount will be * incremented, stack will be duplicated. */ cert_t * cert_new3_copy(EVP_PKEY *key, X509 *crt, STACK_OF(X509) *chain) { cert_t *c; if (!(c = (cert_t *)malloc(sizeof(cert_t)))) return NULL; if (pthread_mutex_init(&c->mutex, NULL)) { free(c); return NULL; } c->key = key; ssl_key_refcount_inc(c->key); c->crt = crt; ssl_x509_refcount_inc(c->crt); c->chain = sk_X509_dup(chain); for (int i = 0; i < sk_X509_num(c->chain); i++) { ssl_x509_refcount_inc(sk_X509_value(c->chain, i)); } c->references = 1; return c; } /* * Load cert_t from file. */ cert_t * cert_new_load(const char *filename) { cert_t *c; if (!(c = (cert_t *)malloc(sizeof(cert_t)))) return NULL; memset(c, 0, sizeof(cert_t)); if (pthread_mutex_init(&c->mutex, NULL)) { free(c); return NULL; } if (ssl_x509chain_load(&c->crt, &c->chain, filename) == -1) { free(c); return NULL; } c->key = ssl_key_load(filename); if (!c->key) { X509_free(c->crt); if (c->chain) { sk_X509_pop_free(c->chain, X509_free); } free(c); return NULL; } c->references = 1; return c; } /* * Increment reference count. */ void cert_refcount_inc(cert_t *c) { pthread_mutex_lock(&c->mutex); c->references++; pthread_mutex_unlock(&c->mutex); } /* * Thread-safe setter functions; they copy the value (refcounts are inc'd). */ void cert_set_key(cert_t *c, EVP_PKEY *key) { pthread_mutex_lock(&c->mutex); if (c->key) { EVP_PKEY_free(c->key); } c->key = key; if (c->key) { ssl_key_refcount_inc(c->key); } pthread_mutex_unlock(&c->mutex); } void cert_set_crt(cert_t *c, X509 *crt) { pthread_mutex_lock(&c->mutex); if (c->crt) { X509_free(c->crt); } c->crt = crt; if (c->crt) { ssl_x509_refcount_inc(c->crt); } pthread_mutex_unlock(&c->mutex); } void cert_set_chain(cert_t *c, STACK_OF(X509) *chain) { pthread_mutex_lock(&c->mutex); if (c->chain) { sk_X509_pop_free(c->chain, X509_free); } if (chain) { c->chain = sk_X509_dup(chain); for (int i = 0; i < sk_X509_num(c->chain); i++) { ssl_x509_refcount_inc(sk_X509_value(c->chain, i)); } } else { c->chain = NULL; } pthread_mutex_unlock(&c->mutex); } /* * Free cert including internal objects. */ void cert_free(cert_t *c) { pthread_mutex_lock(&c->mutex); c->references--; if (c->references) { pthread_mutex_unlock(&c->mutex); return; } pthread_mutex_unlock(&c->mutex); pthread_mutex_destroy(&c->mutex); if (c->key) { EVP_PKEY_free(c->key); } if (c->crt) { X509_free(c->crt); } if (c->chain) { sk_X509_pop_free(c->chain, X509_free); } free(c); } struct cert_mgr* cert_manager_init(const char* profile) { } void cert_mgr_async_get(struct future* future, struct cert_mgr* mgr, int keyring_id, X509* origin_cert, struct event_base* evbase) { X509* orig_cert=SSL_get_peer_certificate(origssl); //todo: need implement cert_t * cert = NULL; if (opts->tgcrtdir) { if (ctx->sni) { cert = (cert_t *) cachemgr_tgcrt_get(ctx->sni); if (!cert) { char * wildcarded = ssl_wildcardify(ctx->sni); if (!wildcarded) { ctx->enomem = 1; return NULL; } cert = (cert_t *) cachemgr_tgcrt_get(wildcarded); free(wildcarded); } if (cert && OPTS_DEBUG(ctx->opts)) { log_dbg_printf("Target cert by SNI\n"); } } else if (ctx->origcrt) { char ** names = ssl_x509_names(ctx->origcrt); for (char ** p = names; *p; p++) { if (!cert) { cert = (cert_t *) cachemgr_tgcrt_get(*p); } if (!cert) { char * wildcarded = ssl_wildcardify(*p); if (!wildcarded) { ctx->enomem = 1; } else { cert = (cert_t *) (wildcarded); free(wildcarded); } } free(*p); } free(names); if (ctx->enomem) { return NULL; } if (cert && OPTS_DEBUG(ctx->opts)) { log_dbg_printf("Target cert by origcrt\n"); } } if (cert) { ctx->immutable_cert = 1; } } if (!cert && ctx->origcrt && ctx->opts->key) { cert = cert_new(); cert->crt = (X509 *) cachemgr_fkcrt_get(ctx->origcrt); if (cert->crt) { if (OPTS_DEBUG(ctx->opts)) log_dbg_printf("Certificate cache: HIT\n"); } else { if (OPTS_DEBUG(ctx->opts)) log_dbg_printf("Certificate cache: MISS\n"); cert->crt = ssl_x509_forge(ctx->opts->cacrt, ctx->opts->cakey, ctx->origcrt, ctx->opts->key, NULL, ctx->opts->crlurl); cachemgr_fkcrt_set(ctx->origcrt, cert->crt); } cert_set_key(cert, ctx->opts->key); cert_set_chain(cert, ctx->opts->chain); ctx->generated_cert = 1; } if ((WANT_CONNECT_LOG(ctx) || ctx->opts->certgendir) && ctx->origcrt) { ctx->origcrtfpr = ssl_x509_fingerprint(ctx->origcrt, 0); if (!ctx->origcrtfpr) ctx->enomem = 1; } if ((WANT_CONNECT_LOG(ctx) || ctx->opts->certgen_writeall) && cert && cert->crt) { ctx->usedcrtfpr = ssl_x509_fingerprint(cert->crt, 0); if (!ctx->usedcrtfpr) ctx->enomem = 1; } return cert; } void cert_manager_free(cert_t * cert) { cert_free(cert); return; } #endif