tls_t *tls_new(xmpp_ctx_t *ctx, xmpp_sock_t sock) { tls_t *tls = xmpp_alloc(ctx, sizeof(*tls)); if (tls) { int ret; memset(tls, 0, sizeof(*tls)); tls->ctx = ctx; tls->sock = sock; tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL); SSL_CTX_set_mode (tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); SSL_CTX_set_verify (tls->ssl_ctx, SSL_VERIFY_NONE, NULL); tls->ssl = SSL_new(tls->ssl_ctx); ret = SSL_set_fd(tls->ssl, sock); if (ret <= 0) { tls->lasterror = SSL_get_error(tls->ssl, ret); tls_error(tls); tls_free(tls); tls = NULL; } } return tls; }
static serf_ssl_context_t *ssl_init_context(void) { serf_ssl_context_t *ssl_ctx; apr_pool_t *pool; serf_bucket_alloc_t *allocator; init_ssl_libraries(); apr_pool_create(&pool, NULL); allocator = serf_bucket_allocator_create(pool, NULL, NULL); ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx)); ssl_ctx->refcount = 0; ssl_ctx->pool = pool; ssl_ctx->allocator = allocator; ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_client_cert_cb(ssl_ctx->ctx, ssl_need_client_cert); ssl_ctx->cached_cert = 0; ssl_ctx->cached_cert_pw = 0; ssl_ctx->pending_err = APR_SUCCESS; SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER, validate_server_certificate); SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_ALL); ssl_ctx->ssl = SSL_new(ssl_ctx->ctx); ssl_ctx->bio = BIO_new(&bio_bucket_method); ssl_ctx->bio->ptr = ssl_ctx; SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio); SSL_set_connect_state(ssl_ctx->ssl); SSL_set_app_data(ssl_ctx->ssl, ssl_ctx); ssl_ctx->encrypt.stream = NULL; ssl_ctx->encrypt.stream_next = NULL; ssl_ctx->encrypt.pending = serf_bucket_aggregate_create(allocator); ssl_ctx->encrypt.status = APR_SUCCESS; serf_databuf_init(&ssl_ctx->encrypt.databuf); ssl_ctx->encrypt.databuf.read = ssl_encrypt; ssl_ctx->encrypt.databuf.read_baton = ssl_ctx; ssl_ctx->decrypt.stream = NULL; ssl_ctx->decrypt.pending = serf_bucket_aggregate_create(allocator); ssl_ctx->decrypt.status = APR_SUCCESS; serf_databuf_init(&ssl_ctx->decrypt.databuf); ssl_ctx->decrypt.databuf.read = ssl_decrypt; ssl_ctx->decrypt.databuf.read_baton = ssl_ctx; return ssl_ctx; }
// nassl.SSL_CTX.new() static PyObject* nassl_SSL_CTX_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { nassl_SSL_CTX_Object *self; int sslVersion; SSL_CTX *sslCtx; self = (nassl_SSL_CTX_Object *)type->tp_alloc(type, 0); if (self == NULL) return NULL; self->sslCtx = NULL; self->pkeyPasswordBuf = NULL; if (!PyArg_ParseTuple(args, "I", &sslVersion)) { Py_DECREF(self); return NULL; } switch (sslVersion) { case sslv23: sslCtx = SSL_CTX_new(SSLv23_method()); break; case sslv2: sslCtx = SSL_CTX_new(SSLv2_method()); break; case sslv3: sslCtx = SSL_CTX_new(SSLv3_method()); break; case tlsv1: sslCtx = SSL_CTX_new(TLSv1_method()); break; case tlsv1_1: sslCtx = SSL_CTX_new(TLSv1_1_method()); break; case tlsv1_2: sslCtx = SSL_CTX_new(TLSv1_2_method()); break; default: PyErr_SetString(PyExc_ValueError, "Invalid value for ssl version"); Py_DECREF(self); return NULL; } if (sslCtx == NULL) { raise_OpenSSL_error(); Py_DECREF(self); return NULL; } // Add the client certificate callback SSL_CTX_set_client_cert_cb(sslCtx, client_cert_cb); self->sslCtx = sslCtx; return (PyObject *)self; }
/* * Initialize global SSL context. */ static int initialize_SSL(PGconn *conn) { struct stat buf; char homedir[MAXPGPATH]; char fnbuf[MAXPGPATH]; if (init_ssl_system(conn)) return -1; /* Set up to verify server cert, if root.crt is present */ if (pqGetHomeDirectory(homedir, sizeof(homedir))) { snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOTCERTFILE); if (stat(fnbuf, &buf) == 0) { if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL)) { char *err = SSLerrmessage(); printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not read root certificate file \"%s\": %s\n"), fnbuf, err); SSLerrfree(err); return -1; } SSL_CTX_set_verify(SSL_context, SSL_VERIFY_PEER, verify_cb); } } /* set up empheral DH keys */ SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb); SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE); /* set up mechanism to provide client certificate, if available */ SSL_CTX_set_client_cert_cb(SSL_context, client_cert_cb); return 0; }
static struct mailstream_ssl_data * ssl_data_new_full(int fd, time_t timeout, SSL_METHOD * method, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) { struct mailstream_ssl_data * ssl_data; SSL * ssl_conn; int r; SSL_CTX * tmp_ctx; struct mailstream_cancel * cancel; struct mailstream_ssl_context * ssl_context = NULL; mailstream_ssl_init(); tmp_ctx = SSL_CTX_new(method); if (tmp_ctx == NULL) goto err; if (callback != NULL) { ssl_context = mailstream_ssl_context_new(tmp_ctx, fd); callback(ssl_context, cb_data); } SSL_CTX_set_app_data(tmp_ctx, ssl_context); SSL_CTX_set_client_cert_cb(tmp_ctx, mailstream_openssl_client_cert_cb); ssl_conn = (SSL *) SSL_new(tmp_ctx); if (ssl_conn == NULL) goto free_ctx; if (SSL_set_fd(ssl_conn, fd) == 0) goto free_ssl_conn; again: r = SSL_connect(ssl_conn); switch(SSL_get_error(ssl_conn, r)) { case SSL_ERROR_WANT_READ: r = wait_SSL_connect(fd, 1, timeout); if (r < 0) goto free_ssl_conn; else goto again; break; case SSL_ERROR_WANT_WRITE: r = wait_SSL_connect(fd, 0, timeout); if (r < 0) goto free_ssl_conn; else goto again; break; } if (r <= 0) goto free_ssl_conn; cancel = mailstream_cancel_new(); if (cancel == NULL) goto free_ssl_conn; r = mailstream_prepare_fd(fd); if (r < 0) goto free_cancel; ssl_data = malloc(sizeof(* ssl_data)); if (ssl_data == NULL) goto free_cancel; ssl_data->fd = fd; ssl_data->ssl_conn = ssl_conn; ssl_data->ssl_ctx = tmp_ctx; ssl_data->cancel = cancel; mailstream_ssl_context_free(ssl_context); return ssl_data; free_cancel: mailstream_cancel_free(cancel); free_ssl_conn: SSL_free(ssl_conn); free_ctx: SSL_CTX_free(tmp_ctx); mailstream_ssl_context_free(ssl_context); err: return NULL; }
static struct mailstream_ssl_data * ssl_data_new_full(int fd, time_t timeout, const SSL_METHOD * method, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) { struct mailstream_ssl_data * ssl_data; SSL * ssl_conn; int r; SSL_CTX * tmp_ctx; struct mailstream_cancel * cancel; struct mailstream_ssl_context * ssl_context = NULL; #if SSL_MODE_RELEASE_BUFFERS long mode = 0; #endif mailstream_ssl_init(); tmp_ctx = SSL_CTX_new(method); if (tmp_ctx == NULL) goto err; if (callback != NULL) { ssl_context = mailstream_ssl_context_new(tmp_ctx, fd); callback(ssl_context, cb_data); } SSL_CTX_set_app_data(tmp_ctx, ssl_context); SSL_CTX_set_client_cert_cb(tmp_ctx, mailstream_openssl_client_cert_cb); ssl_conn = (SSL *) SSL_new(tmp_ctx); #if SSL_MODE_RELEASE_BUFFERS mode = SSL_get_mode(ssl_conn); SSL_set_mode(ssl_conn, mode | SSL_MODE_RELEASE_BUFFERS); #endif if (ssl_conn == NULL) goto free_ctx; #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) if (ssl_context != NULL && ssl_context->server_name != NULL) { SSL_set_tlsext_host_name(ssl_conn, ssl_context->server_name); free(ssl_context->server_name); ssl_context->server_name = NULL; } #endif /* (OPENSSL_VERSION_NUMBER >= 0x10000000L) */ if (SSL_set_fd(ssl_conn, fd) == 0) goto free_ssl_conn; again: r = SSL_connect(ssl_conn); switch(SSL_get_error(ssl_conn, r)) { case SSL_ERROR_WANT_READ: r = wait_SSL_connect(fd, 1, timeout); if (r < 0) goto free_ssl_conn; else goto again; break; case SSL_ERROR_WANT_WRITE: r = wait_SSL_connect(fd, 0, timeout); if (r < 0) goto free_ssl_conn; else goto again; break; } if (r <= 0) goto free_ssl_conn; cancel = mailstream_cancel_new(); if (cancel == NULL) goto free_ssl_conn; r = mailstream_prepare_fd(fd); if (r < 0) goto free_cancel; ssl_data = malloc(sizeof(* ssl_data)); if (ssl_data == NULL) goto free_cancel; ssl_data->fd = fd; ssl_data->ssl_conn = ssl_conn; ssl_data->ssl_ctx = tmp_ctx; ssl_data->cancel = cancel; mailstream_ssl_context_free(ssl_context); return ssl_data; free_cancel: mailstream_cancel_free(cancel); free_ssl_conn: SSL_free(ssl_conn); free_ctx: SSL_CTX_free(tmp_ctx); mailstream_ssl_context_free(ssl_context); err: return NULL; }
extern "C" void CryptoNative_SslCtxSetClientCertCallback(SSL_CTX* ctx, SslClientCertCallback callback) { SSL_CTX_set_client_cert_cb(ctx, callback); }
/* * 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; }
tls_t *tls_new(xmpp_conn_t *conn) { tls_t *tls = xmpp_alloc(conn->ctx, sizeof(*tls)); int mode; if (tls) { int ret; memset(tls, 0, sizeof(*tls)); tls->ctx = conn->ctx; tls->sock = conn->sock; tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if (tls->ssl_ctx == NULL) goto err; /* Enable bug workarounds. */ SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_ALL); /* Disable insecure SSL/TLS versions. */ SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_NO_SSLv2); /* DROWN */ SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_NO_SSLv3); /* POODLE */ SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_NO_TLSv1); /* BEAST */ SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL); SSL_CTX_set_mode(tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); SSL_CTX_set_default_verify_paths(tls->ssl_ctx); tls->ssl = SSL_new(tls->ssl_ctx); if (tls->ssl == NULL) goto err_free_ctx; /* Trust server's certificate when user sets the flag explicitly. */ mode = conn->tls_trust ? SSL_VERIFY_NONE : SSL_VERIFY_PEER; SSL_set_verify(tls->ssl, mode, 0); #if OPENSSL_VERSION_NUMBER >= 0x10002000L /* Hostname verification is supported in OpenSSL 1.0.2 and newer. */ X509_VERIFY_PARAM *param = SSL_get0_param(tls->ssl); /* * Allow only complete wildcards. RFC 6125 discourages wildcard usage * completely, and lists internationalized domain names as a reason * against partial wildcards. * See https://tools.ietf.org/html/rfc6125#section-7.2 for more information. */ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); X509_VERIFY_PARAM_set1_host(param, conn->domain, 0); #endif ret = SSL_set_fd(tls->ssl, conn->sock); if (ret <= 0) goto err_free_ssl; } return tls; err_free_ssl: SSL_free(tls->ssl); err_free_ctx: SSL_CTX_free(tls->ssl_ctx); err: xmpp_free(conn->ctx, tls); _tls_log_error(conn->ctx); return NULL; }