Пример #1
0
/**
 * Create a SSL context.
 */
static int create(lua_State *L)
{
  p_context ctx;
  LSEC_SSL_METHOD *method;

  method = str2method(luaL_checkstring(L, 1));
  if (!method) {
    lua_pushnil(L);
    lua_pushstring(L, "invalid protocol");
    return 2;
  }
  ctx = (p_context) lua_newuserdata(L, sizeof(t_context));
  if (!ctx) {
    lua_pushnil(L);
    lua_pushstring(L, "error creating context");
    return 2;
  }  
  ctx->context = SSL_CTX_new(method);
  if (!ctx->context) {
    lua_pushnil(L);
    lua_pushstring(L, "error creating context");
    return 2;
  }
  ctx->mode = LSEC_MODE_INVALID;
  luaL_getmetatable(L, "SSL:Context");
  lua_setmetatable(L, -2);

  /* No session support */
  SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF);
  /* Link lua_State with the context */
  SSL_CTX_set_app_data(ctx->context, (void*)L);

  return 1;
}
Пример #2
0
static int BSslSetupVerify(SSL_CTX *pSCtx, SslServerBind const *pSSLB)
{
	char const *pszKeyFile = pSSLB->pszKeyFile;

	if (pSSLB->pszCertFile != NULL) {
		if (SSL_CTX_use_certificate_chain_file(pSCtx,
						       pSSLB->pszCertFile) <= 0) {
			ErrSetErrorCode(ERR_SSL_SETCERT, pSSLB->pszCertFile);
			return ERR_SSL_SETCERT;
		}
		if (pszKeyFile == NULL)
			pszKeyFile = pSSLB->pszCertFile;
	}
	if (pszKeyFile != NULL) {
		if (SSL_CTX_use_PrivateKey_file(pSCtx, pszKeyFile,
						SSL_FILETYPE_PEM) <= 0) {
			ErrSetErrorCode(ERR_SSL_SETKEY, pszKeyFile);
			return ERR_SSL_SETKEY;
		}
		if (!SSL_CTX_check_private_key(pSCtx)) {
			ErrSetErrorCode(ERR_SSL_CHECKKEY, pszKeyFile);
			return ERR_SSL_CHECKKEY;
		}
	}
	if (pSSLB->ulFlags & BSSLF_WANT_VERIFY) {
		int iVerMode = SSL_VERIFY_PEER;

		if (pSSLB->ulFlags & BSSLF_WANT_CERT)
			iVerMode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
		SSL_CTX_set_verify(pSCtx, iVerMode, BSslCertVerifyCB);
		if (pSSLB->iMaxDepth > 0)
			SSL_CTX_set_verify_depth(pSCtx, pSSLB->iMaxDepth);
		SSL_CTX_set_app_data(pSCtx, pSSLB);

		if (pSSLB->pszCAFile != NULL || pSSLB->pszCAPath != NULL) {
			if (!SSL_CTX_load_verify_locations(pSCtx, pSSLB->pszCAFile,
							   pSSLB->pszCAPath)) {
				ErrSetErrorCode(ERR_SSL_VERPATHS);
				return ERR_SSL_VERPATHS;
			}
		} else if (!SSL_CTX_set_default_verify_paths(pSCtx)) {
			ErrSetErrorCode(ERR_SSL_VERPATHS);
			return ERR_SSL_VERPATHS;
		}
	}

	return 0;
}
Пример #3
0
int
_openssl_env_init(openssl_env *env, char *engine, int server) {
  /*
   * Create an OpenSSL environment (method and context).
   * If ``server'' is 1, the environment is that of a SSL
   * server.
   */
  const long options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
  env->meth = SSLv23_method();
  env->ctx = SSL_CTX_new(env->meth);
  SSL_CTX_set_options(env->ctx, options);
  if (_options.sslciphers) {
    SSL_CTX_set_cipher_list(env->ctx, _options.sslciphers);
  }
#ifdef HAVE_OPENSSL_ENGINE
  if (engine) {
 retry:
    if ((env->engine = ENGINE_by_id(engine)) == NULL) {
      fprintf(stderr,"invalid engine \"%s\"\n", engine);
      ENGINE_free(env->engine);
      engine = "openssl";
      goto retry;
    }
    if (!ENGINE_set_default(env->engine, ENGINE_METHOD_ALL)) {
      fprintf(stderr,"can't use that engine\n");
      ENGINE_free(env->engine);
      engine = "openssl";
      goto retry;
    }
  }
#endif

#ifdef HAVE_OPENSSL_ENGINE
  SSL_CTX_set_app_data(env->ctx, env);
#endif

  if (server) {
    SSL_CTX_set_options(env->ctx, SSL_OP_SINGLE_DH_USE);
    SSL_CTX_set_session_cache_mode(env->ctx, SSL_SESS_CACHE_OFF);
    SSL_CTX_set_quiet_shutdown(env->ctx, 1);
  }
  return 1;
}
Пример #4
0
static SSL *
open_ssl_connection (rfbClient *client, int sockfd, rfbBool anonTLS)
{
  SSL_CTX *ssl_ctx = NULL;
  SSL *ssl = NULL;
  int n, finished = 0;
  BIO *sbio;

  ssl_ctx = SSL_CTX_new (SSLv23_client_method ());
  SSL_CTX_set_default_verify_paths (ssl_ctx);
  SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, &ssl_verify);
  ssl = SSL_new (ssl_ctx);

  /* TODO: finetune this list, take into account anonTLS bool */
  SSL_set_cipher_list(ssl, "ALL");

  SSL_set_fd (ssl, sockfd);
  SSL_CTX_set_app_data (ssl_ctx, client);

  do
  {
    n = SSL_connect(ssl);
		
    if (n != 1) 
    {
      if (wait_for_data(ssl, n, 1) != 1) 
      {
        finished = 1; 
        if (ssl->ctx)
          SSL_CTX_free (ssl->ctx);
        SSL_free(ssl);
        SSL_shutdown (ssl);

        return NULL;
      }
    }
  } while( n != 1 && finished != 1 );

  return ssl;
}
Пример #5
0
/**
 * Create a SSL context.
 */
static int create(lua_State *L)
{
  p_context ctx;
  const char *str_method;
  LSEC_SSL_METHOD *method;

  str_method = luaL_checkstring(L, 1);
  method = str2method(str_method);
  if (!method) {
    lua_pushnil(L);
    lua_pushfstring(L, "invalid protocol (%s)", str_method);
    return 2;
  }
  ctx = (p_context) lua_newuserdata(L, sizeof(t_context));
  if (!ctx) {
    lua_pushnil(L);
    lua_pushstring(L, "error creating context");
    return 2;
  }
  memset(ctx, 0, sizeof(t_context));
  ctx->context = SSL_CTX_new(method);
  if (!ctx->context) {
    lua_pushnil(L);
    lua_pushfstring(L, "error creating context (%s)",
      ERR_reason_error_string(ERR_get_error()));
    return 2;
  }
  ctx->mode = LSEC_MODE_INVALID;
  ctx->L = L;
  luaL_getmetatable(L, "SSL:Context");
  lua_setmetatable(L, -2);

  /* No session support */
  SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF);
  /* Link LuaSec context with the OpenSSL context */
  SSL_CTX_set_app_data(ctx->context, ctx);

  return 1;
}
Пример #6
0
int MaOpenSslConfig::start()
{
	const SSL_METHOD	*meth;
	char		        *hostName;

	if (keyFile == 0) {
		mprError(MPR_L, MPR_LOG, "OpenSSL: Cant start SSL: missing key file");
		return MPR_ERR_CANT_INITIALIZE;
	}
	if (certFile == 0) {
		mprError(MPR_L, MPR_LOG, "OpenSSL: Cant start SSL: missing certificate file");
		return MPR_ERR_CANT_INITIALIZE;
	}

	//
	//	Depending on the order in the configuration file, we may get called 
	//	by sslModule::start() before OpenSslModule::start has run. So we 
	//	must initialize here.
	//
	openSslModule->start();
	
	hostName = host->getName();
	
	if (protocols == MPR_HTTP_PROTO_SSLV2) {
		meth = SSLv2_server_method();
	} else {
		meth = SSLv23_server_method();
	}
	context = SSL_CTX_new(meth);
	mprAssert(context);
	if (context == 0) {
		mprError(MPR_L, MPR_LOG, "OpenSSL: Unable to create SSL context"); 
		return MPR_ERR_CANT_CREATE;
	}

    SSL_CTX_set_app_data(context, (void*) this);
	SSL_CTX_set_quiet_shutdown(context, 1);
	SSL_CTX_sess_set_cache_size(context, 512);

	//
	//	Configure the certificate for this host
	//
	if (configureCertificates(context, keyFile, certFile) != 0) {
		SSL_CTX_free(context);
		context = 0;
		return MPR_ERR_CANT_INITIALIZE;
	}

	mprLog(4, "SSL: %s: Using ciphers %s\n", hostName, ciphers);
	SSL_CTX_set_cipher_list(context, ciphers);

	//
	//	Configure the client verification certificate locations
	//
	if (verifyClient) {
		if (caFile == 0 && caPath == 0) {
			mprError(MPR_L, MPR_LOG, 
				"OpenSSL: Must define CA certificates if using client verification");
			SSL_CTX_free(context);
			context = 0;
			return MPR_ERR_BAD_STATE;
		}
		if (caFile || caPath) {
			if ((!SSL_CTX_load_verify_locations(context, caFile, caPath)) ||
					(!SSL_CTX_set_default_verify_paths(context))) {
				mprError(MPR_L, MPR_LOG, 
					"OpenSSL: Unable to set certificate locations"); 
				SSL_CTX_free(context);
				context = 0;
				return MPR_ERR_CANT_ACCESS;
			}
			if (caFile) {
				STACK_OF(X509_NAME) *certNames;
				certNames = SSL_load_client_CA_file(caFile);
				if (certNames == 0) {
				} else {
					//
					//	Define the list of CA certificates to send to the client
					//	before they send their client certificate for validation
					//
					SSL_CTX_set_client_CA_list(context, certNames);
				}
			}
		}
		mprLog(4, "SSL: %s: is verifying client connections\n", hostName);
		if (caFile) {
			mprLog(4, "SSL: %s: Using certificates from %s\n", hostName, 
				caFile);
		} else if (caPath) {
			mprLog(4, "SSL: %s: Using certificates from directory %s\n", 
				hostName, caPath);
		}
		SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyX509Certificate);
		SSL_CTX_set_verify_depth(context, verifyDepth);

	} else {
		SSL_CTX_set_verify(context, SSL_VERIFY_NONE, verifyX509Certificate);
	}

	//
	//	Define callbacks
	//
	SSL_CTX_set_tmp_rsa_callback(context, rsaCallback);
	SSL_CTX_set_tmp_dh_callback(context, dhCallback);

	//
	//	Enable all buggy client work-arounds 
	//
	SSL_CTX_set_options(context, SSL_OP_ALL);

#ifdef SSL_OP_NO_TICKET
    SSL_CTX_set_options(context, SSL_OP_NO_TICKET);
#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
    SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
#endif
    SSL_CTX_set_mode(context, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);

	//
	//	Select the required protocols
	//
    SSL_CTX_set_options(context, SSL_OP_NO_SSLv2);
	if (!(protocols & MPR_HTTP_PROTO_SSLV3)) {
		SSL_CTX_set_options(context, SSL_OP_NO_SSLv3);
		mprLog(4, "SSL: %s: Disabling SSLv3\n", hostName);
	}
	if (!(protocols & MPR_HTTP_PROTO_TLSV1)) {
		SSL_CTX_set_options(context, SSL_OP_NO_TLSv1);
		mprLog(4, "SSL: %s: Disabling TLSv1\n", hostName);
	}

	//
	//	Ensure we generate a new private key for each connection
	//
    SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE);

	//
	//	Pre-generate some keys that are slow to compute
	//
	rsaKey512 = RSA_generate_key(512, RSA_F4, 0, 0);
	rsaKey1024 = RSA_generate_key(1024, RSA_F4, 0, 0);

	dhKey512 = get_dh512();
	dhKey1024 = get_dh1024();

	return 0;
}
Пример #7
0
static void ssl_init_ctx_protocol(server_rec *s,
                                  apr_pool_t *p,
                                  apr_pool_t *ptemp,
                                  modssl_ctx_t *mctx)
{
    SSL_CTX *ctx = NULL;
    MODSSL_SSL_METHOD_CONST SSL_METHOD *method = NULL;
    char *cp;
    int protocol = mctx->protocol;

    /*
     *  Create the new per-server SSL context
     */
    if (protocol == SSL_PROTOCOL_NONE) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                "No SSL protocols available [hint: SSLProtocol]");
        ssl_die();
    }

    cp = apr_pstrcat(p,
                     (protocol & SSL_PROTOCOL_SSLV2 ? "SSLv2, " : ""),
                     (protocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""),
                     (protocol & SSL_PROTOCOL_TLSV1 ? "TLSv1, " : ""),
                     NULL);
    cp[strlen(cp)-2] = NUL;

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "Creating new SSL context (protocols: %s)", cp);

    if (protocol == SSL_PROTOCOL_SSLV2) {
        method = mctx->pkp ?
            SSLv2_client_method() : /* proxy */
            SSLv2_server_method();  /* server */
        ctx = SSL_CTX_new(method);  /* only SSLv2 is left */
    }
    else {
        method = mctx->pkp ?
            SSLv23_client_method() : /* proxy */
            SSLv23_server_method();  /* server */
        ctx = SSL_CTX_new(method); /* be more flexible */
    }

    mctx->ssl_ctx = ctx;

    SSL_CTX_set_options(ctx, SSL_OP_ALL);

    if (!(protocol & SSL_PROTOCOL_SSLV2)) {
        SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
    }

    if (!(protocol & SSL_PROTOCOL_SSLV3)) {
        SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
    }

    if (!(protocol & SSL_PROTOCOL_TLSV1)) {
        SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
    }

#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
    {
        SSLSrvConfigRec *sc = mySrvConfig(s);
        if (sc->cipher_server_pref == TRUE) {
            SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
        }
    }
#endif

    SSL_CTX_set_app_data(ctx, s);

    /*
     * Configure additional context ingredients
     */
    SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);

#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
    /*
     * Disallow a session from being resumed during a renegotiation,
     * so that an acceptable cipher suite can be negotiated.
     */
    SSL_CTX_set_options(ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
#endif
}
Пример #8
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;
}
Пример #9
0
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;
}
Пример #10
0
static int openssl_ssl_ctx_new(lua_State*L)
{
  const char* meth = luaL_optstring(L, 1, "TLSv1");
#if OPENSSL_VERSION_NUMBER >= 0x01000000L
  const
#endif
  SSL_METHOD* method = NULL;
  const char* ciphers;
  SSL_CTX* ctx;
  if (strcmp(meth, "SSLv3") == 0)
    method = SSLv3_method();    /* SSLv3 */
  else if (strcmp(meth, "SSLv3_server") == 0)
    method = SSLv3_server_method(); /* SSLv3 */
  else if (strcmp(meth, "SSLv3_client") == 0)
    method = SSLv3_client_method(); /* SSLv3 */
  else if (strcmp(meth, "SSLv23") == 0)
    method = SSLv23_method();   /* SSLv3 but can rollback to v2 */
  else if (strcmp(meth, "SSLv23_server") == 0)
    method = SSLv23_server_method();  /* SSLv3 but can rollback to v2 */
  else if (strcmp(meth, "SSLv23_client") == 0)
    method = SSLv23_client_method();  /* SSLv3 but can rollback to v2 */

  else if (strcmp(meth, "TLSv1_1") == 0)
    method = TLSv1_1_method();    /* TLSv1.0 */
  else if (strcmp(meth, "TLSv1_1_server") == 0)
    method = TLSv1_1_server_method(); /* TLSv1.0 */
  else if (strcmp(meth, "TLSv1_1_client") == 0)
    method = TLSv1_1_client_method(); /* TLSv1.0 */

  else if (strcmp(meth, "TLSv1_2") == 0)
    method = TLSv1_2_method();    /* TLSv1.0 */
  else if (strcmp(meth, "TLSv1_2_server") == 0)
    method = TLSv1_2_server_method(); /* TLSv1.0 */
  else if (strcmp(meth, "TLSv1_2_client") == 0)
    method = TLSv1_2_client_method(); /* TLSv1.0 */

  else if (strcmp(meth, "TLSv1") == 0)
    method = TLSv1_method();    /* TLSv1.0 */
  else if (strcmp(meth, "TLSv1_server") == 0)
    method = TLSv1_server_method(); /* TLSv1.0 */
  else if (strcmp(meth, "TLSv1_client") == 0)
    method = TLSv1_client_method(); /* TLSv1.0 */

  else if (strcmp(meth, "DTLSv1") == 0)
    method = DTLSv1_method();   /* DTLSv1.0 */
  else if (strcmp(meth, "DTLSv1_server") == 0)
    method = DTLSv1_server_method();  /* DTLSv1.0 */
  else if (strcmp(meth, "DTLSv1_client") == 0)
    method = DTLSv1_client_method();  /* DTLSv1.0 */
#ifndef OPENSSL_NO_SSL2
#if OPENSSL_VERSION_NUMBER < 0x10100000L
  else if (strcmp(meth, "SSLv2") == 0)
    method = SSLv2_method();    /* SSLv2 */
  else if (strcmp(meth, "SSLv2_server") == 0)
    method = SSLv2_server_method(); /* SSLv2 */
  else if (strcmp(meth, "SSLv2_client") == 0)
    method = SSLv2_client_method();
#endif
#ifdef LOAD_SSL_CUSTOM
  LOAD_SSL_CUSTOM
#endif

#endif
  else
    luaL_error(L, "#1:%s not supported\n"
               "Maybe SSLv3 SSLv23 TLSv1 TLSv1_1 TLSv1_2 DTLSv1 [SSLv2], option followed by _client or _server\n",
               "default is SSLv3",
               meth);
  ciphers = luaL_optstring(L, 2, SSL_DEFAULT_CIPHER_LIST);
  ctx = SSL_CTX_new(method);
  if (!ctx)
    luaL_error(L, "#1:%s not supported\n"
               "Maybe SSLv3 SSLv23 TLSv1 TLSv1_1 TLSv1_2 DTLSv1 [SSLv2], option followed by _client or _server\n",
               "default is SSLv3",
               meth);
  openssl_newvalue(L, ctx);
  SSL_CTX_set_cipher_list(ctx, ciphers);
  PUSH_OBJECT(ctx, "openssl.ssl_ctx");
  SSL_CTX_set_app_data(ctx, L);

  return 1;
}
Пример #11
0
static CURLcode sslctxfun(CURL* curl, void* sslctx, void* parm)
{
    SSL_CTX_set_app_data(reinterpret_cast<SSL_CTX*>(sslctx), parm);
    SSL_CTX_set_verify(reinterpret_cast<SSL_CTX*>(sslctx), SSL_VERIFY_PEER, certVerifyCallback);
    return CURLE_OK;
}
Пример #12
0
/*
    Create and initialize an SSL configuration for a route. This configuration is used by all requests for
    a given route. An application can have different SSL configurations for different routes. There is also
    a default SSL configuration that is used when a route does not define a configuration and one for clients.
 */
static int configOss(MprSsl *ssl, int flags, char **errorMsg)
{
    OpenConfig      *cfg;
    X509_STORE      *store;
    SSL_CTX         *ctx;
    cchar           *key;
    uchar           resume[16];
    int             verifyMode;

    assert(ssl);
    if (ssl->config && !ssl->changed) {
        return 0;
    }
    if ((ssl->config = mprAllocObj(OpenConfig, manageOpenConfig)) == 0) {
        return MPR_ERR_MEMORY;
    }
    cfg = ssl->config;

    if ((ctx = SSL_CTX_new(SSLv23_method())) == 0) {
        mprLog("error openssl", 0, "Unable to create SSL context");
        return MPR_ERR_CANT_INITIALIZE;
    }
    SSL_CTX_set_app_data(ctx, (void*) ssl);

    if (ssl->verifyPeer && !(ssl->caFile || ssl->caPath)) {
        *errorMsg = sfmt("Cannot verify peer due to undefined CA certificates");
        SSL_CTX_free(ctx);
        return MPR_ERR_CANT_INITIALIZE;
    }

    /*
        Configure the certificates
     */
    if (ssl->certFile) {
        if (setCertFile(ctx, ssl->certFile) < 0) {
            SSL_CTX_free(ctx);
            return MPR_ERR_CANT_INITIALIZE;
        }
        key = (ssl->keyFile == 0) ? ssl->certFile : ssl->keyFile;
        if (key) {
            if (setKeyFile(ctx, key) < 0) {
                SSL_CTX_free(ctx);
                return MPR_ERR_CANT_INITIALIZE;
            }
            if (!SSL_CTX_check_private_key(ctx)) {
                mprLog("error openssl", 0, "Check of private key file failed: %s", key);
                SSL_CTX_free(ctx);
                return MPR_ERR_CANT_INITIALIZE;
            }
        }
    }
    if (ssl->ciphers) {
        ssl->ciphers = mapCipherNames(ssl->ciphers);
    }
    if (!ssl->ciphers && (flags & MPR_SOCKET_SERVER)) {
        ssl->ciphers = sclone(OPENSSL_DEFAULT_CIPHERS);
    }
    if (ssl->ciphers) {
        mprLog("info openssl", 5, "Using SSL ciphers: %s", ssl->ciphers);
        if (SSL_CTX_set_cipher_list(ctx, ssl->ciphers) != 1) {
            *errorMsg = sfmt("Unable to set cipher list \"%s\"", ssl->ciphers);
            SSL_CTX_free(ctx);
            return MPR_ERR_CANT_INITIALIZE;
        }
    }
    verifyMode = ssl->verifyPeer ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE;
    if (verifyMode != SSL_VERIFY_NONE) {
        if (!(ssl->caFile || ssl->caPath)) {
            *errorMsg = sclone("No defined certificate authority file");
            SSL_CTX_free(ctx);
            return MPR_ERR_CANT_INITIALIZE;
        }
        if ((!SSL_CTX_load_verify_locations(ctx, (char*) ssl->caFile, (char*) ssl->caPath)) ||
                (!SSL_CTX_set_default_verify_paths(ctx))) {
            *errorMsg = sfmt("Unable to set certificate locations: %s: %s", ssl->caFile, ssl->caPath);
            SSL_CTX_free(ctx);
            return MPR_ERR_CANT_INITIALIZE;
        }
        if (ssl->caFile) {
            STACK_OF(X509_NAME) *certNames;
            certNames = SSL_load_client_CA_file(ssl->caFile);
            if (certNames) {
                /*
                    Define the list of CA certificates to send to the client
                    before they send their client certificate for validation
                 */
                SSL_CTX_set_client_CA_list(ctx, certNames);
            }
        }
        store = SSL_CTX_get_cert_store(ctx);
        if (ssl->revoke && !X509_STORE_load_locations(store, ssl->revoke, 0)) {
            mprLog("error openssl", 0, "Cannot load certificate revoke list: %s", ssl->revoke);
            SSL_CTX_free(ctx);
            return MPR_ERR_CANT_INITIALIZE;
        }
        if (flags & MPR_SOCKET_SERVER) {
            SSL_CTX_set_verify_depth(ctx, ssl->verifyDepth);
        }
    }

    /*
        Define callbacks
     */
    SSL_CTX_set_verify(ctx, verifyMode, verifyPeerCertificate);
    if (flags & MPR_SOCKET_SERVER) {
        SSL_CTX_set_tlsext_servername_callback(ctx, sniHostname);
    }

    /*
        Configure DH parameters
     */
    SSL_CTX_set_tmp_dh_callback(ctx, dhcallback);
    cfg->dhKey = getDhKey();

    /*
        Define default OpenSSL options
        Ensure we generate a new private key for each connection
        Disable SSLv2 and SSLv3 by default -- they are insecure.
     */
    cfg->setFlags = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
#ifdef SSL_OP_NO_TLSv1
    if (!(ssl->protocols & MPR_PROTO_TLSV1)) {
        cfg->setFlags |= SSL_OP_NO_TLSv1;
    }
#endif
#ifdef SSL_OP_NO_TLSv1_1
    if (!(ssl->protocols & MPR_PROTO_TLSV1_1)) {
        cfg->setFlags |= SSL_OP_NO_TLSv1_1;
    }
#endif
#ifdef SSL_OP_NO_TLSv1_2
    if (!(ssl->protocols & MPR_PROTO_TLSV1_2)) {
        cfg->setFlags |= SSL_OP_NO_TLSv1_2;
    }
#endif
#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
    cfg->setFlags |= SSL_OP_MSIE_SSLV2_RSA_PADDING;
#endif
#if defined(SSL_OP_NO_TICKET)
    /*
        Ticket based session reuse is enabled by default
     */
    #if defined(ME_MPR_SSL_TICKET)
        if (ME_MPR_SSL_TICKET) {
            cfg->clearFlags |= SSL_OP_NO_TICKET;
        } else {
            cfg->setFlags |= SSL_OP_NO_TICKET;
        }
    #else
        cfg->clearFlags |= SSL_OP_NO_TICKET;
    #endif
#endif

#if defined(SSL_OP_NO_COMPRESSION)
    /*
        CRIME attack targets compression
     */
    cfg->clearFlags |= SSL_OP_NO_COMPRESSION;
#endif

#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
    /*
        Force a new session on renegotiation. Default to true.
        This is required when using SNI and changing context during the SSL hello
     */
    #if defined(ME_MPR_SSL_RENEGOTIATE)
        if (ME_MPR_SSL_RENEGOTIATE) {
            cfg->clearFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
        } else {
            cfg->setFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
        }
    #else
        cfg->setFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
    #endif
#endif

#if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
    /*
        Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers.
        Defaults to true.
     */
    #if defined(ME_MPR_SSL_EMPTY_FRAGMENTS)
        if (ME_MPR_SSL_EMPTY_FRAGMENTS) {
            /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */
            cfg->clearFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
        } else {
            cfg->setFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
        }
    #else
        cfg->setFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
    #endif
#endif

    /*
        Define a session reuse context
     */
    RAND_bytes(resume, sizeof(resume));
    SSL_CTX_set_session_id_context(ctx, resume, sizeof(resume));

    /*
        Elliptic Curve initialization
     */
#if SSL_OP_SINGLE_ECDH_USE
    #ifdef SSL_CTX_set_ecdh_auto
        /* This is supported in OpenSSL 1.0.2 */
        SSL_CTX_set_ecdh_auto(ctx, 1);
    #else
        {
            EC_KEY  *ecdh;
            cchar   *name;
            int      nid;

            name = ME_MPR_SSL_CURVE;
            if ((nid = OBJ_sn2nid(name)) == 0) {
                *errorMsg = sfmt("Unknown curve name \"%s\"", name);
                SSL_CTX_free(ctx);
                return MPR_ERR_CANT_INITIALIZE;
            }
            if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) {
                *errorMsg = sfmt("Unable to create curve \"%s\"", name);
                SSL_CTX_free(ctx);
                return MPR_ERR_CANT_INITIALIZE;
            }
            SSL_CTX_set_tmp_ecdh(ctx, ecdh);
            EC_KEY_free(ecdh);
        }
    #endif
#endif

    SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#ifdef SSL_MODE_RELEASE_BUFFERS
    SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
    SSL_CTX_set_mode(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
#endif

#if defined(ME_MPR_SSL_CACHE)
    /*
        Set the number of sessions supported. Default in OpenSSL is 20K.
     */
    SSL_CTX_sess_set_cache_size(ctx, ME_MPR_SSL_CACHE);
#else
    SSL_CTX_sess_set_cache_size(ctx, 1024);
#endif

    SSL_CTX_set_options(ctx, cfg->setFlags);
    SSL_CTX_clear_options(ctx, cfg->clearFlags);

    cfg->ctx = ctx;
    ssl->changed = 0;
    ssl->config = cfg;
    return 0;
}
Пример #13
0
int
evhtp_ssl_init(evhtp * htp, evhtp_ssl_cfg * cfg) {
    long                  cache_mode;
    evhtp_ssl_scache_init init_cb = NULL;
    evhtp_ssl_scache_add  add_cb  = NULL;
    evhtp_ssl_scache_get  get_cb  = NULL;
    evhtp_ssl_scache_del  del_cb  = NULL;

    if (cfg == NULL || htp == NULL || cfg->pemfile == NULL) {
        return -1;
    }

    SSL_library_init();
    SSL_load_error_strings();
    RAND_poll();

    STACK_OF(SSL_COMP) * comp_methods = SSL_COMP_get_compression_methods();
    sk_SSL_COMP_zero(comp_methods);

    htp->ssl_cfg = cfg;
    htp->ssl_ctx = SSL_CTX_new(SSLv23_server_method());

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
    SSL_CTX_set_options(htp->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
    SSL_CTX_set_timeout(htp->ssl_ctx, 60 * 60 * 48);
#endif

    SSL_CTX_set_options(htp->ssl_ctx, cfg->ssl_opts);

    if (cfg->ciphers != NULL) {
        SSL_CTX_set_cipher_list(htp->ssl_ctx, cfg->ciphers);
    }

    SSL_CTX_load_verify_locations(htp->ssl_ctx, cfg->cafile, cfg->capath);
    X509_STORE_set_flags(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->store_flags);
    SSL_CTX_set_verify(htp->ssl_ctx, cfg->verify_peer, cfg->x509_verify_cb);

    if (cfg->x509_chk_issued_cb != NULL) {
        htp->ssl_ctx->cert_store->check_issued = cfg->x509_chk_issued_cb;
    }

    if (cfg->verify_depth) {
        SSL_CTX_set_verify_depth(htp->ssl_ctx, cfg->verify_depth);
    }

    switch (cfg->scache_type) {
        case evhtp_ssl_scache_type_disabled:
            cache_mode = SSL_SESS_CACHE_OFF;
            break;
        case evhtp_ssl_scache_type_user:
            cache_mode = SSL_SESS_CACHE_SERVER |
                         SSL_SESS_CACHE_NO_INTERNAL |
                         SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;

            init_cb    = cfg->scache_init;
            add_cb     = cfg->scache_add;
            get_cb     = cfg->scache_get;
            del_cb     = cfg->scache_del;
            break;
        case evhtp_ssl_scache_type_builtin:
            cache_mode = SSL_SESS_CACHE_SERVER |
                         SSL_SESS_CACHE_NO_INTERNAL |
                         SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;

#if 0
            init_cb    = _evhtp_ssl_builtin_init;
            add_cb     = _evhtp_ssl_builtin_add;
            get_cb     = _evhtp_ssl_builtin_get;
            del_cb     = _evhtp_ssl_builtin_del;
#endif
            break;
        case evhtp_ssl_scache_type_internal:
        default:
            cache_mode = SSL_SESS_CACHE_SERVER;
            break;
    }     /* switch */

    SSL_CTX_use_certificate_file(htp->ssl_ctx, cfg->pemfile, SSL_FILETYPE_PEM);
    SSL_CTX_use_PrivateKey_file(htp->ssl_ctx, cfg->privfile ? cfg->privfile: cfg->pemfile, SSL_FILETYPE_PEM);

    SSL_CTX_set_session_id_context(htp->ssl_ctx,
                                   (const unsigned char*)&session_id_context,
                                   sizeof(session_id_context));

    SSL_CTX_set_app_data(htp->ssl_ctx, htp);
    SSL_CTX_set_session_cache_mode(htp->ssl_ctx, cache_mode);

    if (cache_mode != SSL_SESS_CACHE_OFF) {
        SSL_CTX_sess_set_cache_size(htp->ssl_ctx,
                                    cfg->scache_size ? cfg->scache_size : 1024);

        if (cfg->scache_type == evhtp_ssl_scache_type_builtin ||
            cfg->scache_type == evhtp_ssl_scache_type_user) {
            SSL_CTX_sess_set_new_cb(htp->ssl_ctx, _evhtp_ssl_add_scache_ent);
            SSL_CTX_sess_set_get_cb(htp->ssl_ctx, _evhtp_ssl_get_scache_ent);
            SSL_CTX_sess_set_remove_cb(htp->ssl_ctx, _evhtp_ssl_delete_scache_ent);

            if (cfg->scache_init) {
                cfg->args = (cfg->scache_init)(htp);
            }
        }
    }

    return 0;
}     /* evhtp_use_ssl */
Пример #14
0
int BSslBindServer(BSOCK_HANDLE hBSock, SslServerBind const *pSSLB,
		   int (*pfEnvCB)(void *, int, void const *), void *pPrivate)
{
	int iError;
	SYS_SOCKET SockFD;
	SSL_METHOD const *pMethod;
	SSL_CTX *pSCtx;
	SSL *pSSL;
	X509 *pCert;
	SslBindCtx *pCtx;

	pMethod = SSLv23_server_method();
	if ((pSCtx = SSL_CTX_new((SSL_METHOD *) pMethod)) == NULL) {
		ErrSetErrorCode(ERR_SSLCTX_CREATE);
		return ERR_SSLCTX_CREATE;
	}
	SSL_CTX_set_session_cache_mode(pSCtx, SSL_SESS_CACHE_OFF);
	if (BSslSetupVerify(pSCtx, pSSLB) < 0) {
		SSL_CTX_free(pSCtx);
		return ErrGetErrorCode();
	}
	if ((pSSL = SSL_new(pSCtx)) == NULL) {
		SSL_CTX_free(pSCtx);
		ErrSetErrorCode(ERR_SSL_CREATE);
		return ERR_SSL_CREATE;
	}
	SockFD = BSckGetAttachedSocket(hBSock);
	/*
	 * We want blocking sockets during the initial SSL negotiation.
	 */
	SysBlockSocket(SockFD, 1);
	SSL_set_fd(pSSL, SockFD);
	if (SSL_accept(pSSL) == -1) {
		SysBlockSocket(SockFD, -1);
		SSL_free(pSSL);
		SSL_CTX_free(pSCtx);
		ErrSetErrorCode(ERR_SSL_ACCEPT);
		return ERR_SSL_ACCEPT;
	}
	SSL_CTX_set_app_data(pSCtx, NULL);
	/*
	 * Client may not supply a certificate.
	 */
	iError = 0;
	if (pfEnvCB != NULL &&
	    (pCert = SSL_get_peer_certificate(pSSL)) != NULL) {
		iError = BSslEnvExport(pSCtx, pSSL, pCert, pfEnvCB, pPrivate);
		X509_free(pCert);
	}
	if (iError < 0 ||
	    BSslAllocCtx(&pCtx, SockFD, pSCtx, pSSL) < 0) {
		ErrorPush();
		SysBlockSocket(SockFD, -1);
		SSL_free(pSSL);
		SSL_CTX_free(pSCtx);
		return ErrorPop();
	}
	/*
	 * Need to use non-blocking socket to implement read/write timeouts.
	 */
	SysBlockSocket(SockFD, 0);
	BSckSetIOops(hBSock, &pCtx->IOOps);

	return 0;
}
Пример #15
0
/*
    Create and initialize an SSL configuration for a route. This configuration is used by all requests for
    a given route. An application can have different SSL configurations for different routes. There is also 
    a default SSL configuration that is used when a route does not define a configuration and one for clients.
 */
static OpenConfig *createOpenSslConfig(MprSocket *sp)
{
    MprSsl          *ssl;
    OpenConfig      *cfg;
    X509_STORE      *store;
    SSL_CTX         *context;
    cchar           *key;
    uchar           resume[16];
    int             verifyMode;

    ssl = sp->ssl;
    assert(ssl);

    if ((ssl->config = mprAllocObj(OpenConfig, manageOpenConfig)) == 0) {
        return 0;
    }
    cfg = ssl->config;

    if ((context = SSL_CTX_new(SSLv23_method())) == 0) {
        mprLog("error openssl", 0, "Unable to create SSL context"); 
        return 0;
    }
    SSL_CTX_set_app_data(context, (void*) ssl);

    if (ssl->verifyPeer && !(ssl->caFile || ssl->caPath)) {
        sp->errorMsg = sfmt("Cannot verify peer due to undefined CA certificates");
        SSL_CTX_free(context);
        return 0;
    }

    /*
        Configure the certificates
     */
    if (ssl->certFile) {
        if (SSL_CTX_use_certificate_chain_file(context, ssl->certFile) <= 0) {
            if (SSL_CTX_use_certificate_file(context, ssl->certFile, SSL_FILETYPE_ASN1) <= 0) {
                mprLog("error openssl", 0, "Cannot open certificate file: %s", ssl->certFile);
                SSL_CTX_free(context);
                return 0;
            }
        }
        key = (ssl->keyFile == 0) ? ssl->certFile : ssl->keyFile;
        if (key) {
            if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_PEM) <= 0) {
                /* attempt ASN1 for self-signed format */
                if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_ASN1) <= 0) {
                    mprLog("error openssl", 0, "Cannot open private key file: %s", key);
                    SSL_CTX_free(context);
                    return 0;
                }
            }
            if (!SSL_CTX_check_private_key(context)) {
                mprLog("error openssl", 0, "Check of private key file failed: %s", key);
                SSL_CTX_free(context);
                return 0;
            }
        }
    }
    if (ssl->ciphers) {
        ssl->ciphers = mapCipherNames(ssl->ciphers);
    }
    if (!ssl->ciphers && (sp->flags & MPR_SOCKET_SERVER)) {
        ssl->ciphers = sclone(OPENSSL_DEFAULT_CIPHERS);
    }
    if (ssl->ciphers) {
        mprLog("info openssl", 5, "Using SSL ciphers: %s", ssl->ciphers);
        if (SSL_CTX_set_cipher_list(context, ssl->ciphers) != 1) {
            sp->errorMsg = sfmt("Unable to set cipher list \"%s\". %s", ssl->ciphers, getOssError(sp)); 
            SSL_CTX_free(context);
            return 0;
        }
    }
    verifyMode = ssl->verifyPeer ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE;
    if (verifyMode != SSL_VERIFY_NONE) {
        if (!(ssl->caFile || ssl->caPath)) {
            sp->errorMsg = sclone("No defined certificate authority file");
            SSL_CTX_free(context);
            return 0;
        }
        if ((!SSL_CTX_load_verify_locations(context, (char*) ssl->caFile, (char*) ssl->caPath)) ||
                (!SSL_CTX_set_default_verify_paths(context))) {
            sp->errorMsg = sfmt("Unable to set certificate locations: %s: %s", ssl->caFile, ssl->caPath); 
            SSL_CTX_free(context);
            return 0;
        }
        if (ssl->caFile) {
            STACK_OF(X509_NAME) *certNames;
            certNames = SSL_load_client_CA_file(ssl->caFile);
            if (certNames) {
                /*
                    Define the list of CA certificates to send to the client
                    before they send their client certificate for validation
                 */
                SSL_CTX_set_client_CA_list(context, certNames);
            }
        }
        store = SSL_CTX_get_cert_store(context);
        if (ssl->revokeList && !X509_STORE_load_locations(store, ssl->revokeList, 0)) {
            mprLog("error openssl", 0, "Cannot load certificate revoke list: %s", ssl->revokeList);
            SSL_CTX_free(context);
            return 0;
        }
        if (sp->flags & MPR_SOCKET_SERVER) {
            SSL_CTX_set_verify_depth(context, ssl->verifyDepth);
        }
    }

    /*
        Define callbacks
     */
    SSL_CTX_set_verify(context, verifyMode, verifyPeerCertificate);

    /*
        Configure DH parameters
     */
    SSL_CTX_set_tmp_dh_callback(context, dhcallback);
    cfg->dhKey = getDhKey();

    /*
        Define default OpenSSL options
     */
    SSL_CTX_set_options(context, SSL_OP_ALL);

    /*
        Ensure we generate a new private key for each connection
     */
    SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE);

    /*
        Define a session reuse context
     */
    RAND_bytes(resume, sizeof(resume));
    SSL_CTX_set_session_id_context(context, resume, sizeof(resume));

    /*
        Elliptic Curve initialization
     */
#if SSL_OP_SINGLE_ECDH_USE
    #ifdef SSL_CTX_set_ecdh_auto
        SSL_CTX_set_ecdh_auto(context, 1);
    #else
        {
            EC_KEY  *ecdh;
            cchar   *name;
            int      nid;

            name = ME_MPR_SSL_CURVE;
            if ((nid = OBJ_sn2nid(name)) == 0) {
                sp->errorMsg = sfmt("Unknown curve name \"%s\"", name);
                SSL_CTX_free(context);
                return 0;
            }
            if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) {
                sp->errorMsg = sfmt("Unable to create curve \"%s\"", name);
                SSL_CTX_free(context);
                return 0;
            }
            SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
            SSL_CTX_set_tmp_ecdh(context, ecdh);
            EC_KEY_free(ecdh);
        }
    #endif
#endif

    SSL_CTX_set_mode(context, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
    SSL_CTX_set_options(context, SSL_OP_MSIE_SSLV2_RSA_PADDING);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS
    SSL_CTX_set_mode(context, SSL_MODE_RELEASE_BUFFERS);
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
    SSL_CTX_set_mode(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
#endif
    /*
        Select the required protocols
        Disable SSLv2 and SSLv3 by default -- they are insecure.
     */
    SSL_CTX_set_options(context, SSL_OP_NO_SSLv2);
    SSL_CTX_set_options(context, SSL_OP_NO_SSLv3);
#ifdef SSL_OP_NO_TLSv1
    if (!(ssl->protocols & MPR_PROTO_TLSV1)) {
        SSL_CTX_set_options(context, SSL_OP_NO_TLSv1);
    }
#endif
#ifdef SSL_OP_NO_TLSv1_1
    if (!(ssl->protocols & MPR_PROTO_TLSV1_1)) {
        SSL_CTX_set_options(context, SSL_OP_NO_TLSv1_1);
    }
#endif
#ifdef SSL_OP_NO_TLSv1_2
    if (!(ssl->protocols & MPR_PROTO_TLSV1_2)) {
        SSL_CTX_set_options(context, SSL_OP_NO_TLSv1_2);
    }
#endif

    /*
        Options set via main.me mpr.ssl.*
     */
#if defined(SSL_OP_NO_TICKET)
    /*
        Ticket based session reuse is enabled by default
     */
    #if defined(ME_MPR_SSL_TICKET)
        if (ME_MPR_SSL_TICKET) {
            SSL_CTX_clear_options(context, SSL_OP_NO_TICKET);
        } else {
            SSL_CTX_set_options(context, SSL_OP_NO_TICKET);
        }
    #else
        SSL_CTX_clear_options(context, SSL_OP_NO_TICKET);
    #endif
#endif

#if defined(SSL_OP_NO_COMPRESSION)
    /* 
        Use of compression is not secure. Disabled by default.
     */
    #if defined(ME_MPR_SSL_COMPRESSION)
        if (ME_MPR_SSL_COMPRESSION) {
            SSL_CTX_clear_options(context, SSL_OP_NO_COMPRESSION);
        } else {
            SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
        }
    #else
        /*
            CRIME attack targets compression
         */
        SSL_CTX_clear_options(context, SSL_OP_NO_COMPRESSION);
    #endif
#endif

#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
    /*
        Force a new session on renegotiation. Default to true.
     */
    #if defined(ME_MPR_SSL_RENEGOTIATE)
        if (ME_MPR_SSL_RENEGOTIATE) {
            SSL_CTX_clear_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
        } else {
            SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
        }
    #else
        SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
    #endif
#endif

#if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
    /*
        Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers.
        Defaults to true.
     */
    #if defined(ME_MPR_SSL_EMPTY_FRAGMENTS)
        if (ME_MPR_SSL_EMPTY_FRAGMENTS) {
            /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */
            SSL_CTX_clear_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
        } else {
            SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
        }
    #else
        SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
    #endif
#endif

#if defined(ME_MPR_SSL_CACHE)
    /*
        Set the number of sessions supported. Default in OpenSSL is 20K.
     */
    SSL_CTX_sess_set_cache_size(context, ME_MPR_SSL_CACHE);
#else
    SSL_CTX_sess_set_cache_size(context, 1024);
#endif

    cfg->context = context;
    return cfg;
}