int lws_tls_client_create_vhost_context(struct lws_vhost *vh, const struct lws_context_creation_info *info, const char *cipher_list, const char *ca_filepath, const char *cert_filepath, const char *private_key_filepath) { X509 *d2i_X509(X509 **cert, const unsigned char *buffer, long len); SSL_METHOD *method = (SSL_METHOD *)TLS_client_method(); unsigned long error; lws_filepos_t len; uint8_t *buf; if (!method) { error = ERR_get_error(); lwsl_err("problem creating ssl method %lu: %s\n", error, ERR_error_string(error, (char *)vh->context->pt[0].serv_buf)); return 1; } /* create context */ vh->tls.ssl_client_ctx = SSL_CTX_new(method); if (!vh->tls.ssl_client_ctx) { error = ERR_get_error(); lwsl_err("problem creating ssl context %lu: %s\n", error, ERR_error_string(error, (char *)vh->context->pt[0].serv_buf)); return 1; } if (!ca_filepath) return 0; if (alloc_file(vh->context, ca_filepath, &buf, &len)) { lwsl_err("Load CA cert file %s failed\n", ca_filepath); return 1; } vh->tls.x509_client_CA = d2i_X509(NULL, buf, len); free(buf); if (!vh->tls.x509_client_CA) { lwsl_err("client CA: x509 parse failed\n"); return 1; } if (!vh->tls.ssl_ctx) SSL_CTX_add_client_CA(vh->tls.ssl_client_ctx, vh->tls.x509_client_CA); else SSL_CTX_add_client_CA(vh->tls.ssl_ctx, vh->tls.x509_client_CA); lwsl_notice("client loaded CA for verification %s\n", ca_filepath); return 0; }
int tls_sc_add_ca_cert(lua_State *L) { tls_sc_t *ctx = getSC(L); X509 *x509; int newCAStore = FALSE; if (!ctx->ca_store) { ctx->ca_store = X509_STORE_new(); newCAStore = TRUE; } x509 = _lua_load_x509(L, 2); if (!x509) { lua_pushboolean(L, 0); return 1; } X509_STORE_add_cert(ctx->ca_store, x509); SSL_CTX_add_client_CA(ctx->ctx, x509); X509_free(x509); if (newCAStore) { SSL_CTX_set_cert_store(ctx->ctx, ctx->ca_store); } lua_pushboolean(L, 1); return 1; }
int LWSClient::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { Ref<LWSPeer> peer = static_cast<Ref<LWSPeer> >(_peer); LWSPeer::PeerData *peer_data = (LWSPeer::PeerData *)user; switch (reason) { case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: { PoolByteArray arr = StreamPeerSSL::get_project_cert_array(); if (arr.size() > 0) SSL_CTX_add_client_CA((SSL_CTX *)user, d2i_X509(NULL, &arr.read()[0], arr.size())); else if (verify_ssl) WARN_PRINTS("No CA cert specified in project settings, SSL will not work"); } break; case LWS_CALLBACK_CLIENT_ESTABLISHED: peer->set_wsi(wsi); peer_data->peer_id = 0; peer_data->force_close = false; _on_connect(lws_get_protocol(wsi)->name); break; case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: _on_error(); destroy_context(); return -1; // we should close the connection (would probably happen anyway) case LWS_CALLBACK_CLIENT_CLOSED: peer->close(); destroy_context(); _on_disconnect(); return 0; // we can end here case LWS_CALLBACK_CLIENT_RECEIVE: peer->read_wsi(in, len); if (peer->get_available_packet_count() > 0) _on_peer_packet(); break; case LWS_CALLBACK_CLIENT_WRITEABLE: if (peer_data->force_close) return -1; peer->write_wsi(); break; default: break; } return 0; }
static int openssl_ssl_ctx_add(lua_State*L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); X509* x = CHECK_OBJECT(2, X509, "openssl.x509"); int ret = SSL_CTX_add_client_CA(ctx, x); if (ret == 1 && !lua_isnoneornil(L, 3)) { size_t i; luaL_checktable(L, 3); for (i = 1; ret == 1 && i <= lua_rawlen(L, 3); i++ ) { lua_rawgeti(L, 3, i); x = CHECK_OBJECT(2, X509, "openssl.x509"); lua_pop(L, 1); CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); ret = SSL_CTX_add_extra_chain_cert(ctx, x); } } return openssl_pushresult(L, ret); }
static int do_ca_cert_bootstrap(struct stream *stream) { struct ssl_stream *sslv = ssl_stream_cast(stream); STACK_OF(X509) *chain; X509 *cert; FILE *file; int error; int fd; chain = SSL_get_peer_cert_chain(sslv->ssl); if (!chain || !sk_X509_num(chain)) { VLOG_ERR("could not bootstrap CA cert: no certificate presented by " "peer"); return EPROTO; } cert = sk_X509_value(chain, sk_X509_num(chain) - 1); /* Check that 'cert' is self-signed. Otherwise it is not a CA * certificate and we should not attempt to use it as one. */ error = X509_check_issued(cert, cert); if (error) { VLOG_ERR("could not bootstrap CA cert: obtained certificate is " "not self-signed (%s)", X509_verify_cert_error_string(error)); if (sk_X509_num(chain) < 2) { VLOG_ERR("only one certificate was received, so probably the peer " "is not configured to send its CA certificate"); } return EPROTO; } fd = open(ca_cert.file_name, O_CREAT | O_EXCL | O_WRONLY, 0444); if (fd < 0) { if (errno == EEXIST) { VLOG_INFO_RL(&rl, "reading CA cert %s created by another process", ca_cert.file_name); stream_ssl_set_ca_cert_file__(ca_cert.file_name, true, true); return EPROTO; } else { VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s", ca_cert.file_name, ovs_strerror(errno)); return errno; } } file = fdopen(fd, "w"); if (!file) { error = errno; VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s", ovs_strerror(error)); unlink(ca_cert.file_name); return error; } if (!PEM_write_X509(file, cert)) { VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: " "%s", ca_cert.file_name, ERR_error_string(ERR_get_error(), NULL)); fclose(file); unlink(ca_cert.file_name); return EIO; } if (fclose(file)) { error = errno; VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s", ca_cert.file_name, ovs_strerror(error)); unlink(ca_cert.file_name); return error; } VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert.file_name); log_ca_cert(ca_cert.file_name, cert); bootstrap_ca_cert = false; ca_cert.read = true; /* SSL_CTX_add_client_CA makes a copy of cert's relevant data. */ SSL_CTX_add_client_CA(ctx, cert); SSL_CTX_set_cert_store(ctx, X509_STORE_new()); if (SSL_CTX_load_verify_locations(ctx, ca_cert.file_name, NULL) != 1) { VLOG_ERR("SSL_CTX_load_verify_locations: %s", ERR_error_string(ERR_get_error(), NULL)); return EPROTO; } VLOG_INFO("killing successful connection to retry using CA cert"); return EPROTO; }
int tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, const char *pkcs12_file_inline, bool load_ca_file ) { FILE *fp; EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *ca = NULL; PKCS12 *p12; int i; char password[256]; ASSERT(NULL != ctx); if (!strcmp (pkcs12_file, INLINE_FILE_TAG) && pkcs12_file_inline) { BIO *b64 = BIO_new(BIO_f_base64()); BIO *bio = BIO_new_mem_buf((void *) pkcs12_file_inline, (int) strlen(pkcs12_file_inline)); ASSERT(b64 && bio); BIO_push(b64, bio); p12 = d2i_PKCS12_bio(b64, NULL); if (!p12) msg(M_SSLERR, "Error reading inline PKCS#12 file"); BIO_free(b64); BIO_free(bio); } else { /* Load the PKCS #12 file */ if (!(fp = platform_fopen(pkcs12_file, "rb"))) msg(M_SSLERR, "Error opening file %s", pkcs12_file); p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (!p12) msg(M_SSLERR, "Error reading PKCS#12 file %s", pkcs12_file); } /* Parse the PKCS #12 file */ if (!PKCS12_parse(p12, "", &pkey, &cert, &ca)) { pem_password_callback (password, sizeof(password) - 1, 0, NULL); /* Reparse the PKCS #12 file with password */ ca = NULL; if (!PKCS12_parse(p12, password, &pkey, &cert, &ca)) { #ifdef ENABLE_MANAGEMENT if (management && (ERR_GET_REASON (ERR_peek_error()) == PKCS12_R_MAC_VERIFY_FAILURE)) management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); #endif PKCS12_free(p12); return 1; } } PKCS12_free(p12); /* Load Certificate */ if (!SSL_CTX_use_certificate (ctx->ctx, cert)) msg (M_SSLERR, "Cannot use certificate"); /* Load Private Key */ if (!SSL_CTX_use_PrivateKey (ctx->ctx, pkey)) msg (M_SSLERR, "Cannot use private key"); warn_if_group_others_accessible (pkcs12_file); /* Check Private Key */ if (!SSL_CTX_check_private_key (ctx->ctx)) msg (M_SSLERR, "Private key does not match the certificate"); /* Set Certificate Verification chain */ if (load_ca_file) { if (ca && sk_X509_num(ca)) { for (i = 0; i < sk_X509_num(ca); i++) { if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)"); if (!SSL_CTX_add_client_CA(ctx->ctx, sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)"); } } } return 0; }
/* * call-seq: * ctx.setup => Qtrue # first time * ctx.setup => nil # thereafter * * This method is called automatically when a new SSLSocket is created. * Normally you do not need to call this method (unless you are writing an extension in C). */ static VALUE ossl_sslctx_setup(VALUE self) { SSL_CTX *ctx; X509 *cert = NULL, *client_ca = NULL; X509_STORE *store; EVP_PKEY *key = NULL; char *ca_path = NULL, *ca_file = NULL; int i, verify_mode; VALUE val; if(OBJ_FROZEN(self)) return Qnil; Data_Get_Struct(self, SSL_CTX, ctx); #if !defined(OPENSSL_NO_DH) if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){ SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback); } else{ SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback); } #endif SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self); val = ossl_sslctx_get_cert_store(self); if(!NIL_P(val)){ /* * WORKAROUND: * X509_STORE can count references, but * X509_STORE_free() doesn't care it. * So we won't increment it but mark it by ex_data. */ store = GetX509StorePtr(val); /* NO NEED TO DUP */ SSL_CTX_set_cert_store(ctx, store); SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1); } val = ossl_sslctx_get_extra_cert(self); if(!NIL_P(val)){ rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self); } /* private key may be bundled in certificate file. */ val = ossl_sslctx_get_cert(self); cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */ val = ossl_sslctx_get_key(self); key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */ if (cert && key) { if (!SSL_CTX_use_certificate(ctx, cert)) { /* Adds a ref => Safe to FREE */ ossl_raise(eSSLError, "SSL_CTX_use_certificate:"); } if (!SSL_CTX_use_PrivateKey(ctx, key)) { /* Adds a ref => Safe to FREE */ ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey:"); } if (!SSL_CTX_check_private_key(ctx)) { ossl_raise(eSSLError, "SSL_CTX_check_private_key:"); } } val = ossl_sslctx_get_client_ca(self); if(!NIL_P(val)){ if(TYPE(val) == T_ARRAY){ for(i = 0; i < RARRAY_LEN(val); i++){ client_ca = GetX509CertPtr(RARRAY_PTR(val)[i]); if (!SSL_CTX_add_client_CA(ctx, client_ca)){ /* Copies X509_NAME => FREE it. */ ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); } } } else{ client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */ if (!SSL_CTX_add_client_CA(ctx, client_ca)){ /* Copies X509_NAME => FREE it. */ ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); } } } val = ossl_sslctx_get_ca_file(self); ca_file = NIL_P(val) ? NULL : StringValuePtr(val); val = ossl_sslctx_get_ca_path(self); ca_path = NIL_P(val) ? NULL : StringValuePtr(val); if(ca_file || ca_path){ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) rb_warning("can't set verify locations"); } val = ossl_sslctx_get_verify_mode(self); verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val); SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback); if (RTEST(ossl_sslctx_get_client_cert_cb(self))) SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb); val = ossl_sslctx_get_timeout(self); if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val)); val = ossl_sslctx_get_verify_dep(self); if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2LONG(val)); val = ossl_sslctx_get_options(self); if(!NIL_P(val)) SSL_CTX_set_options(ctx, NUM2LONG(val)); rb_obj_freeze(self); val = ossl_sslctx_get_sess_id_ctx(self); if (!NIL_P(val)){ StringValue(val); if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val), RSTRING_LEN(val))){ ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:"); } } if (RTEST(rb_iv_get(self, "@session_get_cb"))) { SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb); OSSL_Debug("SSL SESSION get callback added"); } if (RTEST(rb_iv_get(self, "@session_new_cb"))) { SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb); OSSL_Debug("SSL SESSION new callback added"); } if (RTEST(rb_iv_get(self, "@session_remove_cb"))) { SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb); OSSL_Debug("SSL SESSION remove callback added"); } #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME val = rb_iv_get(self, "@servername_cb"); if (!NIL_P(val)) { SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); OSSL_Debug("SSL TLSEXT servername callback added"); } #endif return Qtrue; }
static int do_ca_cert_bootstrap(struct vconn *vconn) { struct ssl_vconn *sslv = ssl_vconn_cast(vconn); STACK_OF(X509) *chain; X509 *ca_cert; FILE *file; int error; int fd; chain = SSL_get_peer_cert_chain(sslv->ssl); if (!chain || !sk_X509_num(chain)) { VLOG_ERR("could not bootstrap CA cert: no certificate presented by " "peer"); return EPROTO; } ca_cert = sk_X509_value(chain, sk_X509_num(chain) - 1); /* Check that 'ca_cert' is self-signed. Otherwise it is not a CA * certificate and we should not attempt to use it as one. */ error = X509_check_issued(ca_cert, ca_cert); if (error) { VLOG_ERR("could not bootstrap CA cert: obtained certificate is " "not self-signed (%s)", X509_verify_cert_error_string(error)); if (sk_X509_num(chain) < 2) { VLOG_ERR("only one certificate was received, so probably the peer " "is not configured to send its CA certificate"); } return EPROTO; } fd = open(ca_cert_file, O_CREAT | O_EXCL | O_WRONLY, 0444); if (fd < 0) { VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s", ca_cert_file, strerror(errno)); return errno; } file = fdopen(fd, "w"); if (!file) { int error = errno; VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s", strerror(error)); unlink(ca_cert_file); return error; } if (!PEM_write_X509(file, ca_cert)) { VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: " "%s", ca_cert_file, ERR_error_string(ERR_get_error(), NULL)); fclose(file); unlink(ca_cert_file); return EIO; } if (fclose(file)) { int error = errno; VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s", ca_cert_file, strerror(error)); unlink(ca_cert_file); return error; } VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert_file); log_ca_cert(ca_cert_file, ca_cert); bootstrap_ca_cert = false; has_ca_cert = true; /* SSL_CTX_add_client_CA makes a copy of ca_cert's relevant data. */ SSL_CTX_add_client_CA(ctx, ca_cert); /* SSL_CTX_use_certificate() takes ownership of the certificate passed in. * 'ca_cert' is owned by sslv->ssl, so we need to duplicate it. */ ca_cert = X509_dup(ca_cert); if (!ca_cert) { out_of_memory(); } if (SSL_CTX_load_verify_locations(ctx, ca_cert_file, NULL) != 1) { VLOG_ERR("SSL_CTX_load_verify_locations: %s", ERR_error_string(ERR_get_error(), NULL)); return EPROTO; } VLOG_INFO("killing successful connection to retry using CA cert"); return EPROTO; }
int LLVMFuzzerInitialize(int* argc, char*** argv) { rand_predictable = 1; SSL_library_init(); OpenSSL_add_ssl_algorithms(); ERR_load_crypto_strings(); if (RAND_reset_for_fuzzing) RAND_reset_for_fuzzing(); ctx = SSL_CTX_new(SSLv23_method()); const uint8_t* bufp = kRSAPrivateKeyDER; RSA* privkey = d2i_RSAPrivateKey(NULL, &bufp, sizeof(kRSAPrivateKeyDER)); assert(privkey != NULL); EVP_PKEY* pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, privkey); int ret = SSL_CTX_use_PrivateKey(ctx, pkey); assert(ret == 1); EVP_PKEY_free(pkey); bufp = kCertificateDER; X509* cert = d2i_X509(NULL, &bufp, sizeof(kCertificateDER)); assert(cert != NULL); ret = SSL_CTX_use_certificate(ctx, cert); assert(ret == 1); X509_free(cert); ret = SSL_CTX_set_cipher_list(ctx, "ALL:eNULL:aNULL:DSS"); assert(ret == 1); X509_STORE* store = X509_STORE_new(); assert(store != NULL); bufp = kRSACACertDER; cert = d2i_X509(NULL, &bufp, sizeof(kRSACACertDER)); assert(cert != NULL); ret = SSL_CTX_add_client_CA(ctx, cert); assert(ret == 1); ret = X509_STORE_add_cert(store, cert); assert(ret == 1); X509_free(cert); bufp = kECCACertDER; cert = d2i_X509(NULL, &bufp, sizeof(kECCACertDER)); assert(cert != NULL); ret = SSL_CTX_add_client_CA(ctx, cert); assert(ret == 1); ret = X509_STORE_add_cert(store, cert); assert(ret == 1); X509_free(cert); bufp = kDSACertDER; cert = d2i_X509(NULL, &bufp, sizeof(kDSACertDER)); ret = SSL_CTX_add_client_CA(ctx, cert); assert(ret == 1); ret = X509_STORE_add_cert(store, cert); assert(ret == 1); X509_free(cert); SSL_CTX_set_cert_store(ctx, store); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL); SSL_CTX_set_verify_depth(ctx, 10); #if !defined(LIBRESSL_VERSION_NUMBER) SSL_CTX_set_psk_server_callback(ctx, psk_callback); ret = SSL_CTX_use_psk_identity_hint(ctx, "ABCDEFUZZ"); assert(ret == 1); #endif /* !defined(LIBRESSL_VERSION_NUMBER) */ #if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION) ret = SSL_CTX_set_srp_username_callback(ctx, srp_callback); assert(ret == 1); ret = SSL_CTX_set_srp_cb_arg(ctx, NULL); assert(ret == 1); #endif /* !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION) */ SSL_CTX_set_alpn_select_cb(ctx, alpn_callback, NULL); SSL_CTX_set_next_protos_advertised_cb(ctx, npn_callback, NULL); SSL_CTX_set_ecdh_auto(ctx, 1); return 1; }