I am having a application in. c that uses openssl for TLS v1.2 implemention.
The application shall open multiple remote connections to remote server running with the same version of TLS. I have a single set of key, certificate and CA_certificate to be used for all connections.
I need to maintain the SSL_CTX object for each client separately. But, I wish to create a single global SSL_CTX context object and configure it once for the following:
SSL_CTX_set_ecdh_auto()
SSL_CTX_use_certificate_file()
SL_CTX_use_PrivateKey_file()
SSL_CTX_set_verify()
SSL_CTX_set_options()
SSL_CTX_load_verify_locations
SSL_CTX_set_verify_depth()
And then, for each connections initiated by the application, I can duplicate (make a copy) of the above configured context ctx and call SSL_new() directly, without going through the listed steps over and over for each client.
Does Openssl provide any function to duplicate the SSL_CTX object?
If not is there any other safe way to do so? like memcpy() etc.
SSL_CTX has a counting reference. It means it will be freed when its reference counts reaches zero.
So rather than copying SSL_CTX, just increase its reference by SSL_CTX_up_ref() and use same object. As a result, your code will be something like this:
SSL_CTX *g_ssl_ctx = nullptr;
//...
//init g_ssl_ctx
//...
SSL_CTX *get_client_ctx() {
SSL_CTX_up_ref(g_ssl_ctx);
return g_ssl_ctx;
}
Related
I have a X509_STORE* pointer, my goal is to get its associated X509_STORE_CTX* pointer. May I know how to do this? I cannot get access to where initialize the X509_STORE_CTX*.
probably this is a simple question, but I check the OpenSSL manual API and its related header file again and again, not find any API could do this. Thanks.
A single X509_STORE can be used/shared by an unlimited number of X509_STORE_CTX, but most of the time isn't used/referenced by any, so an API to get "its ... pointer" makes no sense and does not exist.
This (not at all coincidentally) reflects a similar, but inversely named, difference at the SSL module (libssl) level. An SSL_CTX object defines security parameters that can be used by any number of connections each implemented as an SSL object. In the original design, the SSL_CTX owns an X509_STORE representing the truststore -- the set of roots (or other anchors if PARTIAL_CHAIN is used) used to validate peer certs and potentially to build out 'own' chains -- which you can modify using the CTX APIs like SSL_CTX_load_verify_locations or you can get the (automatically created) store with SSL_CTX_get_cert_store and modify it or create your own and install it with SSL_CTX_set_cert_store. OTOH each SSL dynamically creates its own X509_STORE_CTX while validating or sending a cert; no X509_STORE_CTX exists at other times. In 1.0.2 up an SSL by default uses the SSL_CTX store but you can override with SSL_set[01]_{verify,chain}_cert_store.
When you create an X509_STORE_CTX you identify the X509_STORE to use with X509_STORE_CTX_init. When you _free it this use/reference is terminated.
I am developing shared library and subagent for net-snmp. I need to send v3 traps for specific hardware events. I would like to know what value need to be filled in the context value of send_v3trap API.
void send_v3trap(netsnmp_variable_list * vars,const char * context )
Is this context value, same as user defined engine id ? i.e., the one which needs to be configured in snmptrapd.conf as below ?
createUser -e ENGINEID myuser SHA "my authentication pass" AES "my encryption pass"
More on configuring in this link
There is an example source code available for sending
v2traps
By looking at the net-snmp source code, send_v3trap calls internally send_v2trap and eventually,
/* A context name was provided, so copy it and its length to the v2 pdu
* template. */
if (context != NULL)
{
template_v2pdu->contextName = strdup(context);
template_v2pdu->contextNameLen = strlen(context);
}
Answering my own question.
"context" value can be filled with
value returned by "snmpv3_get_engineID"
NULL
As long as, configurations are proper in terms of v3 i.e., trapsess -v3 specified in the host and on the target, engineid of net-snmp is specified, then everything works fine.
Only unclear part still is, if someone is able to send v3 traps without specifying "context", in which scenario would it be useful really !
In the context of an Apache2 module written in C, how can I determine if a request (request_rec *r) is encrypted? I've seen code that seems to do that, but I either haven't been able to figure out how to implement it or it always return 'true', even on unencrypted connections.
In PHP, $_SERVER['HTTPS'] gets set to 'on' if HTTPS is used.
In your own module, define
#include <mod_ssl.h>
static int is_https(conn_rec *c)
{
int (*is_https_conn)(conn_rec *c);
is_https_conn = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
if (is_https_conn)
return is_https_conn(c);
return 0;
}
so you can test if request request_rec *r uses an SSL/TLS connection, using
if (is_https(r->connection)) {
/* Yes, request is via an SSL/TLS-encrypted connection */
} else {
/* No, the request is not via an encrypted connection */
}
The logic is based on the fact that the SSL/TLS module uses APR_REGISTER_OPTIONAL_FN(ssl_is_https) to register the function ssl_is_https() in modules/ssl/ssl_engine_vars.c:ssl_var_register(). This function takes a connection (conn_rec *), and returns nonzero if the connection uses SSL/TLS encryption (HTTPS).
We use APR_RETRIEVE_OPTIONAL_FN(ssl_is_https) to retrieve the pointer to said function. If it is not registered, this returns NULL (and obviously no connection can then be encrypted). If it returns a non-NULL pointer, we call the function. It will return nonzero if the connection is HTTPS.
I want to get multiple connections with OpenSSL.
Should I create new SSL_CTX context for every new connection or accept all connections with one context?
Should I do additional actions with memory or something with start/stop connection, except
close(_socket); //socket which accept the connection
SSL_shutdown(_ssl); //_ssl — SSL connection
SSL_free (_ssl);
Should I create new SSL_CTX context for every new connection or accept all connections with one context?
It depends on the number of server names and distinct certificates.
If you have one server name and one certificate, then use one default context.
If you have multiple server names and one certificate, then use one default context.
If you have multiple server names and multiple certificate, then see below on the SNI or servername callback and swapping in a context.
If your server listens for foo.com and bar.com with distinct certifcates, then you will need three contexts. One default context is for non-SNI clients, one context is for foo.com, and one context is for bar.com.
Effectively, the only thing that will likely change between the two sites is the certificate that's served. So you listen with the default context. If the client provided a servername via SNI, then you swap-in one of the other two contexts in the servername callback and SSL_set_SSL_CTX. Here's how it would look:
static int ServerNameCallback(SSL *ssl, int *ad, void *arg)
{
UNUSED(ad);
UNUSED(arg);
ASSERT(ssl);
if (ssl == NULL)
return SSL_TLSEXT_ERR_NOACK;
const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
ASSERT(servername && servername[0]);
if (!servername || servername[0] == '\0')
return SSL_TLSEXT_ERR_NOACK;
/* Need a certificate and context for this domain */
SSL_CTX* ctx = GetServerContext(servername);
ASSERT(ctx != NULL);
if (ctx == NULL)
return SSL_TLSEXT_ERR_NOACK;
/* We should not be peeking into the object like this... */
ASSERT(ctx != ssl->ctx);
/* Useless return value */
SSL_CTX* v = SSL_set_SSL_CTX(ssl, ctx);
return SSL_TLSEXT_ERR_OK;
}
GetServerContext just provides the context for foo.com or bar.com. It creates them once, and then reuses the same ones.
For the default context, you set the servername callback with SSL_CTX_set_tlsext_servername_callback. There's no need to set it for non-default contexts.
SSL_CTX_set_tlsext_servername_callback(ctx, ServerNameCallback);
Contexts are referenced counted, so you can reuse them.
Should I do additional actions with memory or something with
start/stop connection, except
close(_socket); //socket which accept the connection
SSL_shutdown(_ssl); //_ssl — SSL connection
SSL_free (_ssl);
Here, you should seek a treatment of the subject. For example, you should not call close before SSL_shutdown. And the first call to SSL_shutdown may fail, so you need to know what to do next.
For a treatment of the subject, see Eric Rescorla's tutorials: An Introduction to OpenSSL Programming, Part I of II and An Introduction to OpenSSL Programming, Part II of II. Or get the book: Network Security with OpenSSL.
I am trying to use OpenSSL in my application, and achieve a secure connection.
At first I tried:
create ssl struct
create socketbio for the tcp socket
create a sslbio
set socketbio to SSL strcut
SSL_accept(ssl)
BIO_push(ssl, socketbio)
This cause handshake to happen successfully, but application data wasn't properly decrypted.
Then I tweaked a little, and relaced 6 with
(new) BIO_ctrl(sslbio, SET_SSL, ssl)
and things worked fine.
I Wanted to know, what's wrong with previous approach, and what's causing the new apprach work?
It's hard to answer the question without knowing why you think BIO_push is all you need to do. At any rate, you shouldn't call BIO_ctrl directly. You should use the high-level wrapper BIO_set_ssl defined in bio.h:
#define BIO_set_ssl(b,ssl,c) BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)ssl)
This macro sets the ssl member of the BIO object as you can see in bio_ssl.c:
case BIO_C_SET_SSL:
if (ssl != NULL)
ssl_free(b);
b->shutdown=(int)num;
ssl=(SSL *)ptr;
((BIO_SSL *)b->ptr)->ssl=ssl;
bio=SSL_get_rbio(ssl);
if (bio != NULL)
{
if (b->next_bio != NULL)
BIO_push(bio,b->next_bio);
b->next_bio=bio;
CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO);
}
b->init=1;
break;
The important step in this function is not the BIO_push, but rather is where it sets the ssl pointer in the BIO_SSL object to your active SSL context, i.e., ((BIO_SSL *)b->ptr)->ssl=ssl;.