Exemple #1
0
/**
 * Init verification of transmitted client certs
 */
static int verify_init(ssl_server_connection *ssl_server) {
  struct stat stat_buf;

  if (!ssl_server->clientpemfile) {
    SSL_CTX_set_verify(ssl_server->ctx, SSL_VERIFY_NONE, NULL);
    return TRUE;
  }

  if (stat(ssl_server->clientpemfile, &stat_buf) == -1) {
    LogError("%s: Cannot stat the SSL pem path '%s' -- %s\n", prog, Run.httpsslclientpem, STRERROR);
    return FALSE;
  }
  
  if (S_ISDIR(stat_buf.st_mode)) {

    if (!SSL_CTX_load_verify_locations(ssl_server->ctx, NULL , ssl_server->clientpemfile)) {
      LogError("%s: Error setting verify directory to %s -- %s\n", prog, Run.httpsslclientpem, SSLERROR);
      return FALSE;
    }

    LogInfo("%s: Loaded SSL client pem directory '%s'\n", prog, ssl_server->clientpemfile);

    /* Monit's server cert for cli support */

    if (!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->pemfile, NULL)) {
      LogError("%s: Error loading verify certificates from %s -- %s\n", prog, ssl_server->pemfile, SSLERROR);
      return FALSE;
    }

    LogInfo("%s: Loaded monit's SSL pem server file '%s'\n", prog, ssl_server->pemfile);

  } else if (S_ISREG(stat_buf.st_mode)) {

    if (!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->clientpemfile, NULL)) {
      LogError("%s: Error loading verify certificates from %s -- %s\n", prog, Run.httpsslclientpem, SSLERROR);
      return FALSE;
    }

    LogInfo("%s: Loaded SSL pem client file '%s'\n", prog, ssl_server->clientpemfile);

    /* Monits server cert for cli support ! */

    if (!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->pemfile, NULL)) {
      LogError("%s: Error loading verify certificates from %s -- %s\n", prog, ssl_server->pemfile, SSLERROR);
      return FALSE;
    }

    LogInfo("%s: Loaded monit's SSL pem server file '%s'\n", prog, ssl_server->pemfile);

    SSL_CTX_set_client_CA_list(ssl_server->ctx, SSL_load_client_CA_file(ssl_server->clientpemfile));

  } else {
    LogError("%s: SSL client pem path is no file or directory %s\n", prog, ssl_server->clientpemfile);
    return FALSE;
  }

  SSL_CTX_set_verify(ssl_server->ctx, SSL_VERIFY_PEER, verify_callback);

  return TRUE;
}
Exemple #2
0
static STACK_OF(X509_NAME) *
tlso_ca_list( char * bundle, char * dir )
{
	STACK_OF(X509_NAME) *ca_list = NULL;

	if ( bundle ) {
		ca_list = SSL_load_client_CA_file( bundle );
	}
#if defined(HAVE_DIRENT_H) || defined(dirent)
	if ( dir ) {
		int freeit = 0;

		if ( !ca_list ) {
			ca_list = sk_X509_NAME_new_null();
			freeit = 1;
		}
		if ( !SSL_add_dir_cert_subjects_to_stack( ca_list, dir ) &&
			freeit ) {
			sk_X509_NAME_free( ca_list );
			ca_list = NULL;
		}
	}
#endif
	return ca_list;
}
Exemple #3
0
/**
 * @brief Load CA list from file
 * @param d domain
 * @return 0 if not configured or on success, -1 on error
 */
static int load_ca_list(tls_domain_t* d)
{
	int i;
	int procs_no;

	if (!d->ca_file.s || !d->ca_file.len) {
		DBG("%s: No CA list configured\n", tls_domain_str(d));
		return 0;
	}
	if (fix_shm_pathname(&d->ca_file) < 0)
		return -1;
	procs_no=get_max_procs();
	for(i = 0; i < procs_no; i++) {
		if (SSL_CTX_load_verify_locations(d->ctx[i], d->ca_file.s, 0) != 1) {
			ERR("%s: Unable to load CA list '%s'\n", tls_domain_str(d),
					d->ca_file.s);
			TLS_ERR("load_ca_list:");
			return -1;
		}
		SSL_CTX_set_client_CA_list(d->ctx[i],
				SSL_load_client_CA_file(d->ca_file.s));
		if (SSL_CTX_get_client_CA_list(d->ctx[i]) == 0) {
			ERR("%s: Error while setting client CA list\n", tls_domain_str(d));
			TLS_ERR("load_ca_list:");
			return -1;
		}
	}
	return 0;
}
Exemple #4
0
int swSSL_set_client_certificate(SSL_CTX *ctx, char *cert_file, int depth)
{
    STACK_OF(X509_NAME) *list;

    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, swSSL_verify_callback);
    SSL_CTX_set_verify_depth(ctx, depth);

    if (SSL_CTX_load_verify_locations(ctx, cert_file, NULL) == 0)
    {
        swWarn("SSL_CTX_load_verify_locations(\"%s\") failed.", cert_file);
        return SW_ERR;
    }

    ERR_clear_error();
    list = SSL_load_client_CA_file(cert_file);
    if (list == NULL)
    {
        swWarn("SSL_load_client_CA_file(\"%s\") failed.", cert_file);
        return SW_ERR;
    }

    ERR_clear_error();
    SSL_CTX_set_client_CA_list(ctx, list);

    return SW_OK;
}
Exemple #5
0
Fichier : ssl.c Projet : N0NB/aprx
int ssl_ca_certificate(struct ssl_t *ssl, const char *cafile, int depth)
{
	STACK_OF(X509_NAME)  *list;
	
	SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ssl_verify_callback);
	SSL_CTX_set_verify_depth(ssl->ctx, depth);
	
	if (SSL_CTX_load_verify_locations(ssl->ctx, cafile, NULL) == 0) {
		hlog(LOG_ERR, "Failed to load trusted CA list from \"%s\"", cafile);
		ssl_error(LOG_ERR, "SSL_CTX_load_verify_locations");
		return -1;
	}
	
	list = SSL_load_client_CA_file(cafile);
	
	if (list == NULL) {
		hlog(LOG_ERR, "Failed to load client CA file from \"%s\"", cafile);
		ssl_error(LOG_ERR, "SSL_load_client_CA_file");
		return -1;
	}
	
	/*
	 * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
	 * always leaved an error in the error queue
	 */
	
	ERR_clear_error();
	
	SSL_CTX_set_client_CA_list(ssl->ctx, list);
	
	ssl->validate = 1;
	
	return 0;
}
Exemple #6
0
static herror_t
_hssl_server_context_init(void)
{
  log_verbose3("enabled=%i, certificate=%p", enabled, certificate);

  if (!enabled || !certificate)
    return H_OK;

  if (!(context = SSL_CTX_new(SSLv23_method())))
  {
    log_error1("Cannot create SSL context");
    return herror_new("_hssl_server_context_init", HSSL_ERROR_CONTEXT,
                      "Unable to create SSL context");
  }

  if (!(SSL_CTX_use_certificate_file(context, certificate, SSL_FILETYPE_PEM)))
  {
    log_error2("Cannot read certificate file: \"%s\"", certificate);
    SSL_CTX_free(context);
    return herror_new("_hssl_server_context_init", HSSL_ERROR_CERTIFICATE,
                      "Unable to use SSL certificate \"%s\"", certificate);
  }

  SSL_CTX_set_default_passwd_cb(context, _hssl_password_callback);

  if (!(SSL_CTX_use_PrivateKey_file(context, certificate, SSL_FILETYPE_PEM)))
  {
    log_error2("Cannot read key file: \"%s\"", certificate);
    SSL_CTX_free(context);
    return herror_new("_hssl_server_context_init", HSSL_ERROR_PEM,
                      "Unable to use private key");
  }

  if (ca_list != NULL && *ca_list != '\0')
  {
    if (!(SSL_CTX_load_verify_locations(context, ca_list, NULL)))
    {
      SSL_CTX_free(context);
      log_error2("Cannot read CA list: \"%s\"", ca_list);
      return herror_new("_hssl_server_context_init", HSSL_ERROR_CA_LIST,
                        "Unable to read certification authorities \"%s\"");
    }

    SSL_CTX_set_client_CA_list(context, SSL_load_client_CA_file(ca_list));
    log_verbose1("Certification authority contacted");
  }

  SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
                     _hssl_cert_verify_callback);
  log_verbose1("Certificate verification callback registered");

  SSL_CTX_set_mode(context, SSL_MODE_AUTO_RETRY);

  SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF);

  _hssl_superseed();

  return H_OK;
}
Exemple #7
0
int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
                                          const pn_ssl_verify_mode_t mode,
                                          const char *trusted_CAs)
{
  if (!domain) return -1;

  switch (mode) {
  case PN_SSL_VERIFY_PEER:
  case PN_SSL_VERIFY_PEER_NAME:

    if (!domain->has_ca_db) {
      pn_transport_logf(NULL, "Error: cannot verify peer without a trusted CA configured.\n"
                 "       Use pn_ssl_domain_set_trusted_ca_db()");
      return -1;
    }

    if (domain->mode == PN_SSL_MODE_SERVER) {
      // openssl requires that server connections supply a list of trusted CAs which is
      // sent to the client
      if (!trusted_CAs) {
        pn_transport_logf(NULL, "Error: a list of trusted CAs must be provided.");
        return -1;
      }
      if (!domain->has_certificate) {
        pn_transport_logf(NULL, "Error: Server cannot verify peer without configuring a certificate.\n"
                   "       Use pn_ssl_domain_set_credentials()");
      }

      if (domain->trusted_CAs) free(domain->trusted_CAs);
      domain->trusted_CAs = pn_strdup( trusted_CAs );
      STACK_OF(X509_NAME) *cert_names;
      cert_names = SSL_load_client_CA_file( domain->trusted_CAs );
      if (cert_names != NULL)
        SSL_CTX_set_client_CA_list(domain->ctx, cert_names);
      else {
        pn_transport_logf(NULL, "Error: Unable to process file of trusted CAs: %s", trusted_CAs);
        return -1;
      }
    }

    SSL_CTX_set_verify( domain->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                        verify_callback);
#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
    SSL_CTX_set_verify_depth(domain->ctx, 1);
#endif
    break;

  case PN_SSL_ANONYMOUS_PEER:   // hippie free love mode... :)
    SSL_CTX_set_verify( domain->ctx, SSL_VERIFY_NONE, NULL );
    break;

  default:
    pn_transport_logf(NULL, "Invalid peer authentication mode given." );
    return -1;
  }

  domain->verify_mode = mode;
  return 0;
}
Exemple #8
0
void SSLContext::loadClientCAList(const char* path) {
  auto clientCAs = SSL_load_client_CA_file(path);
  if (clientCAs == nullptr) {
    LOG(ERROR) << "Unable to load ca file: " << path;
    return;
  }
  SSL_CTX_set_client_CA_list(ctx_, clientCAs);
}
void SecuredServerSession::verifyPeer(const std::string &caFile)
{
    if (!caFile.empty()) {
        auto certs = SSL_load_client_CA_file(caFile.c_str());
        if (!certs)
            throw std::runtime_error(ERR_error_string(ERR_get_error(), nullptr));
        SSL_set_client_CA_list(m_SSL, certs);
    }
    SSL_set_verify(m_SSL, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, &verify_callback);
    SSL_set_verify_depth(m_SSL, 10);
    m_renegotiate = true;
}
Exemple #10
0
void* listen_sslctx_create(char* key, char* pem, char* verifypem)
{
#ifdef HAVE_SSL
	SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
	if(!ctx) {
		log_crypto_err("could not SSL_CTX_new");
		return NULL;
	}
	/* no SSLv2 because has defects */
	if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)){
		log_crypto_err("could not set SSL_OP_NO_SSLv2");
		SSL_CTX_free(ctx);
		return NULL;
	}
	if(!SSL_CTX_use_certificate_file(ctx, pem, SSL_FILETYPE_PEM)) {
		log_err("error for cert file: %s", pem);
		log_crypto_err("error in SSL_CTX use_certificate_file");
		SSL_CTX_free(ctx);
		return NULL;
	}
	if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
		log_err("error for private key file: %s", key);
		log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
		SSL_CTX_free(ctx);
		return NULL;
	}
	if(!SSL_CTX_check_private_key(ctx)) {
		log_err("error for key file: %s", key);
		log_crypto_err("Error in SSL_CTX check_private_key");
		SSL_CTX_free(ctx);
		return NULL;
	}

	if(verifypem && verifypem[0]) {
		if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
			log_crypto_err("Error in SSL_CTX verify locations");
			SSL_CTX_free(ctx);
			return NULL;
		}
		SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(
			verifypem));
		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
	}
	return ctx;
#else
	(void)key; (void)pem; (void)verifypem;
	return NULL;
#endif
}
Exemple #11
0
/**
 * Initializes an SSL context using the specified certificates.
 *
 * @param pubkey The public key.
 * @param privkey The matching private key.
 * @param cakey CA certificate chain file.
 * @returns An SSL context.
 */
shared_ptr<SSL_CTX> MakeSSLContext(const String& pubkey, const String& privkey, const String& cakey)
{
	InitializeOpenSSL();

	shared_ptr<SSL_CTX> sslContext = shared_ptr<SSL_CTX>(SSL_CTX_new(TLSv1_method()), SSL_CTX_free);

	SSL_CTX_set_mode(sslContext.get(), 0);

	if (!SSL_CTX_use_certificate_chain_file(sslContext.get(), pubkey.CStr())) {
		BOOST_THROW_EXCEPTION(openssl_error()
		    << boost::errinfo_api_function("SSL_CTX_use_certificate_chain_file")
		    << errinfo_openssl_error(ERR_get_error())
		    << boost::errinfo_file_name(pubkey));
	}

	if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.CStr(), SSL_FILETYPE_PEM)) {
		BOOST_THROW_EXCEPTION(openssl_error()
		    << boost::errinfo_api_function("SSL_CTX_use_PrivateKey_file")
		    << errinfo_openssl_error(ERR_get_error())
		    << boost::errinfo_file_name(privkey));
	}

	if (!SSL_CTX_check_private_key(sslContext.get())) {
		BOOST_THROW_EXCEPTION(openssl_error()
		    << boost::errinfo_api_function("SSL_CTX_check_private_key")
		    << errinfo_openssl_error(ERR_get_error()));
	}

	if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.CStr(), NULL)) {
		BOOST_THROW_EXCEPTION(openssl_error()
		    << boost::errinfo_api_function("SSL_CTX_load_verify_locations")
		    << errinfo_openssl_error(ERR_get_error())
		    << boost::errinfo_file_name(cakey));
	}

	STACK_OF(X509_NAME) *cert_names;

	cert_names = SSL_load_client_CA_file(cakey.CStr());
	if (cert_names == NULL) {
		BOOST_THROW_EXCEPTION(openssl_error()
		    << boost::errinfo_api_function("SSL_load_client_CA_file")
		    << errinfo_openssl_error(ERR_get_error())
		    << boost::errinfo_file_name(cakey));
	}

	SSL_CTX_set_client_CA_list(sslContext.get(), cert_names);

	return sslContext;
}
Exemple #12
0
int ssl_cca(SSL_CTX *ctx,const char *certfile)
{
  STACK_OF(X509_NAME) *x;

  if (!certfile) return 1;

  x = SSL_load_client_CA_file(certfile);
  if (!x) return 0;

  SSL_CTX_set_client_CA_list(ctx,x);

  SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,0);

  return 1;
}
Exemple #13
0
tls_t *tls_init_master(tls_issues_t *ti)
{
  /* Default id in case RAND fails */
  unsigned char sessionId[32] = "sofia/tls";
  tls_t *tls;

#if HAVE_SIGPIPE
  signal(SIGPIPE, SIG_IGN);  /* Ignore spurios SIGPIPE from OpenSSL */
#endif

  tls_set_default(ti);

  if (!(tls = tls_create(tls_master)))
    return NULL;

  if (tls_init_context(tls, ti) < 0) {
    int err = errno;
    tls_free(tls);
    errno = err;
    return NULL;
  }

  RAND_pseudo_bytes(sessionId, sizeof(sessionId));

  SSL_CTX_set_session_id_context(tls->ctx,
                                 (void*) sessionId,
				 sizeof(sessionId));

  if (ti->CAfile != NULL)
    SSL_CTX_set_client_CA_list(tls->ctx,
                               SSL_load_client_CA_file(ti->CAfile));

#if 0
  if (sock != -1) {
    tls->bio_con = BIO_new_socket(sock, BIO_NOCLOSE);

    if (tls->bio_con == NULL) {
      tls_log_errors(1, "tls_init_master", 0);
      tls_free(tls);
      errno = EIO;
      return NULL;
    }
  }
#endif

  return tls;
}
Exemple #14
0
static int tlsaddcacrl(SSL_CTX *ctx, struct tls *conf) {
    STACK_OF(X509_NAME) *calist;
    X509_STORE *x509_s;
    unsigned long error;

    if (!SSL_CTX_load_verify_locations(ctx, conf->cacertfile, conf->cacertpath)) {
	while ((error = ERR_get_error()))
	    debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
	debug(DBG_ERR, "tlsaddcacrl: Error updating TLS context %s", conf->name);
	return 0;
    }

	calist = conf->cacertfile ? SSL_load_client_CA_file(conf->cacertfile) : NULL;

    if (!conf->cacertfile || calist) {
	if (conf->cacertpath) {
	    if (!calist)
		calist = sk_X509_NAME_new_null();
	    if (!SSL_add_dir_cert_subjects_to_stack(calist, conf->cacertpath)) {
		sk_X509_NAME_free(calist);
		calist = NULL;
	    }
	}
    }
    if (!calist) {
	while ((error = ERR_get_error()))
	    debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
	debug(DBG_ERR, "tlsaddcacrl: Error adding CA subjects in TLS context %s", conf->name);
	return 0;
    }
    ERR_clear_error(); /* add_dir_cert_subj returns errors on success */
    SSL_CTX_set_client_CA_list(ctx, calist);

    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
    SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1);

    if (conf->crlcheck || conf->vpm) {
	x509_s = SSL_CTX_get_cert_store(ctx);
	if (conf->crlcheck)
	    X509_STORE_set_flags(x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
	if (conf->vpm)
	    X509_STORE_set1_param(x509_s, conf->vpm);
    }

    debug(DBG_DBG, "tlsaddcacrl: updated TLS context %s", conf->name);
    return 1;
}
Exemple #15
0
CAMLprim value ocaml_ssl_ctx_set_client_CA_list_from_file(value context, value vfilename)
{
  CAMLparam2(context, vfilename);
  SSL_CTX *ctx = Ctx_val(context);
  char *filename = String_val(vfilename);
  STACK_OF(X509_NAME) *cert_names;

  caml_enter_blocking_section();
  cert_names = SSL_load_client_CA_file(filename);
  if (cert_names != 0)
    SSL_CTX_set_client_CA_list(ctx, cert_names);
  else
  {
    caml_leave_blocking_section();
    caml_raise_constant(*caml_named_value("ssl_exn_certificate_error"));
  }
  caml_leave_blocking_section();

  CAMLreturn(Val_unit);
}
Exemple #16
0
int mailstream_ssl_set_client_certicate(struct mailstream_ssl_context * ssl_context,
    char * filename)
{
#ifdef USE_SSL
#ifdef USE_GNUTLS
  /* not implemented */
  return -1;
#else
  SSL_CTX * ctx = (SSL_CTX *)ssl_context->openssl_ssl_ctx;
  STACK_OF(X509_NAME) *cert_names;
  
  cert_names = SSL_load_client_CA_file(filename);
  if (cert_names != NULL) {
    SSL_CTX_set_client_CA_list(ctx, cert_names);
    return 0;
  }
  else {
    return -1;
  }
#endif /* USE_GNUTLS */
#else
  return -1;
#endif /* USE_SSL */
}
Exemple #17
0
net_socketSSL_t*
net_socketSSL_listen(const char* port, int type,
                     int backlog)
{
	assert(port);
	assert(backlog > 0);

	int socktype;
	if((type >= NET_SOCKETSSL_TCP) &&
	   (type <= NET_SOCKETSSL_TCP_BUFFERED))
	{
		socktype = SOCK_STREAM;
	}
	else
	{
		LOGE("invalid type=%i", type);
		return NULL;
	}

	net_socketSSL_t* self;
	self = (net_socketSSL_t*)
	       malloc(sizeof(net_socketSSL_t));
	if(self == NULL)
	{
		LOGE("malloc failed");
		return NULL;
	}

	// SIGPIPE causes the process to exit for broken streams
	// but we want to receive EPIPE instead
	signal(SIGPIPE, SIG_IGN);

	// init SSL ctx
#if NET_SOCKET_USE_OPENSSL_1_1
	self->ctx = SSL_CTX_new(TLS_server_method());
#else
	// app should call SSL_library_init(); prior to creating any
	// OpenSSL sockets with the old API
	self->ctx = SSL_CTX_new(SSLv23_server_method());
#endif
	if(self->ctx == NULL)
	{
		LOGE("SSL_CTX_new failed");
		goto fail_ctx;
	}
	self->method = NET_SOCKETSSL_METHOD_SERVER;
	self->ssl    = NULL;

	if(SSL_CTX_load_verify_locations(self->ctx,
	                                 "ca_cert.pem", NULL) != 1)
	{
		LOGE("SSL_CTX_load_verify_locations failed");
		goto fail_load_verify;
	}

#if NET_SOCKET_USE_OPENSSL_1_1
	if(SSL_CTX_set_default_verify_file(self->ctx) != 1)
	{
		LOGE("SSL_CTX_set_default_verify_file failed");
		goto fail_set_default_verify_file;
	}
#endif

	STACK_OF(X509_NAME)* cert_names;
	cert_names = SSL_load_client_CA_file("ca_cert.pem");
	if(cert_names == NULL)
	{
		LOGE("SSL_load_client_CA_file failed");
		goto fail_cert_names;
	}
	SSL_CTX_set_client_CA_list(self->ctx, cert_names);

	if(SSL_CTX_use_certificate_file(self->ctx,
	                                "server_cert.pem",
	                                SSL_FILETYPE_PEM) != 1)
	{
		LOGE("SSL_CTX_use_certificate_file failed");
		goto fail_use_cert;
	}

	if(SSL_CTX_use_PrivateKey_file(self->ctx,
	                               "server_key.pem",
	                               SSL_FILETYPE_PEM) != 1)
	{
		LOGE("SSL_CTX_use_PrivateKey_file failed");
		goto fail_use_priv;
	}

	if(SSL_CTX_check_private_key(self->ctx) != 1)
	{
		LOGE("SSL_CTX_check_private_key failed");
		goto fail_check_priv;
	}

	SSL_CTX_set_mode(self->ctx, SSL_MODE_AUTO_RETRY);
	SSL_CTX_set_verify(self->ctx,
	                   SSL_VERIFY_PEER |
	                   SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
	                   NULL);
	SSL_CTX_set_verify_depth(self->ctx, 1);

	// not needed for listening socket
	self->buffer = NULL;
	self->len    = 0;

	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_family   = AF_UNSPEC;
	hints.ai_socktype = socktype;
	hints.ai_flags    = AI_PASSIVE;

	struct addrinfo* info;
	if(getaddrinfo(NULL, port, &hints, &info) != 0)
	{
		LOGD("getaddrinfo failed");
		goto fail_getaddrinfo;
	}

	struct addrinfo* i = info;
	self->sockfd = -1;
	while(i)
	{
		self->sockfd = socket(i->ai_family, i->ai_socktype,
		                      i->ai_protocol);
		if(self->sockfd == -1)
		{
			LOGD("socket failed");
			i = i->ai_next;
			continue;
		}

		int yes = 1;
		if(setsockopt(self->sockfd, SOL_SOCKET,
		              SO_REUSEADDR, &yes,
		              sizeof(int)) == -1)
		{
			LOGD("setsockopt failed");
		}

		// TCP_NODELAY is not needed for server socket

		if(bind(self->sockfd, i->ai_addr,
		        i->ai_addrlen) == -1)
		{
			LOGD("bind failed");
			close(self->sockfd);
			self->sockfd = -1;
			continue;
		}

		break;
	}
	freeaddrinfo(info);

	if(self->sockfd == -1)
	{
		LOGD("socket failed");
		goto fail_socket;
	}

	if(listen(self->sockfd, backlog) == -1)
	{
		LOGD("listen failed");
		goto fail_listen;
	}

	self->error     = 0;
	self->connected = 1;
	self->type      = type;

	// success
	return self;

	// failure
	fail_listen:
		close(self->sockfd);
	fail_socket:
	fail_getaddrinfo:
	fail_check_priv:
	fail_use_priv:
	fail_use_cert:
	fail_cert_names:
#if NET_SOCKET_USE_OPENSSL_1_1
	fail_set_default_verify_file:
#endif
	fail_load_verify:
		SSL_CTX_free(self->ctx);
	fail_ctx:
		free(self);
	return NULL;
}
eventer_ssl_ctx_t *
eventer_ssl_ctx_new(eventer_ssl_orientation_t type,
                    const char *layer,
                    const char *certificate, const char *key,
                    const char *ca, const char *ciphers) {
  char ssl_ctx_key[SSL_CTX_KEYLEN];
  eventer_ssl_ctx_t *ctx;
  const char *layer_str;
  char *ctx_layer, *opts;
  char *opts_fallback = DEFAULT_OPTS_STRING;
  time_t now;
  ctx = calloc(1, sizeof(*ctx));
  if(!ctx) return NULL;

  layer_str = layer ? layer : DEFAULT_LAYER_STRING;
  ctx_layer = alloca(strlen(layer_str)+1);
  memcpy(ctx_layer, layer_str, strlen(layer_str)+1);
  opts = strchr(ctx_layer,':');
  if(opts) *opts++ = '\0';
  else {
    opts = alloca(strlen(opts_fallback)+1);
    memcpy(opts, opts_fallback, strlen(opts_fallback)+1);
  }

  now = time(NULL);
  ssl_ctx_key_write(ssl_ctx_key, sizeof(ssl_ctx_key),
                    type, layer, certificate, key, ca, ciphers);
  ctx->ssl_ctx_cn = ssl_ctx_cache_get(ssl_ctx_key);
  if(ctx->ssl_ctx_cn) {
    if(now - ctx->ssl_ctx_cn->creation_time > ssl_ctx_cache_expiry ||
       (now - ctx->ssl_ctx_cn->last_stat_time > ssl_ctx_cache_finfo_expiry &&
           (validate_finfo(&ctx->ssl_ctx_cn->cert_finfo, certificate) ||
            validate_finfo(&ctx->ssl_ctx_cn->key_finfo, key) ||
            validate_finfo(&ctx->ssl_ctx_cn->ca_finfo, ca) || 
            (ctx->ssl_ctx_cn->last_stat_time = now) == 0))) { /* assignment */
      ssl_ctx_cache_remove(ssl_ctx_key);
      ssl_ctx_cache_node_free(ctx->ssl_ctx_cn);
      ctx->ssl_ctx_cn = NULL;
    }
  }

  if(!ctx->ssl_ctx_cn) {
    char *part = NULL, *brkt = NULL;
    long ctx_options = 0;
    ssl_ctx_cache_node *existing_ctx_cn;
    ctx->ssl_ctx_cn = calloc(1, sizeof(*ctx->ssl_ctx_cn));
    ctx->ssl_ctx_cn->key = strdup(ssl_ctx_key);
    ctx->ssl_ctx_cn->refcnt = 1;
    ctx->ssl_ctx_cn->creation_time = now;
    ctx->ssl_ctx_cn->last_stat_time = now;
    populate_finfo(&ctx->ssl_ctx_cn->cert_finfo, certificate);
    populate_finfo(&ctx->ssl_ctx_cn->key_finfo, key);
    populate_finfo(&ctx->ssl_ctx_cn->ca_finfo, ca);
    ctx->ssl_ctx = NULL;
    if(0)
      ;
#if defined(SSL_TXT_SSLV3) && defined(HAVE_SSLV3_SERVER) && defined(HAVE_SSLV3_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_SSLV3))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 SSLv3_server_method() : SSLv3_client_method());
#endif
#if defined(SSL_TXT_SSLV2) && defined(HAVE_SSLV2_SERVER) && defined(HAVE_SSLV2_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_SSLV2))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 SSLv2_server_method() : SSLv2_client_method());
#endif
#if defined(SSL_TXT_TLSV1) && defined(HAVE_TLSV1_SERVER) && defined(HAVE_TLSV1_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 TLSv1_server_method() : TLSv1_client_method());
#endif
#if defined(SSL_TXT_TLSV1_1) && defined(HAVE_TLSV1_1_SERVER) && defined(HAVE_TLSV1_1_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1_1))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 TLSv1_1_server_method() : TLSv1_1_client_method());
#endif
#if defined(SSL_TXT_TLSV1_2) && defined(HAVE_TLSV1_2_SERVER) && defined(HAVE_TLSV1_2_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1_2))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 TLSv1_2_server_method() : TLSv1_2_client_method());
#endif
    if(ctx->ssl_ctx == NULL)
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 SSLv23_server_method() : SSLv23_client_method());
    if(!ctx->ssl_ctx) goto bail;

    for(part = strtok_r(opts, ",", &brkt);
        part;
        part = strtok_r(NULL, ",", &brkt)) {
      char *optname = part;
      int neg = 0;
      if(*optname == '!') neg = 1, optname++;

#define SETBITOPT(name, neg, opt) \
  if(!strcasecmp(optname, name)) { \
    if(neg) ctx_options &= ~(opt); \
    else    ctx_options |= (opt); \
  }

      SETBITOPT("all", neg, SSL_OP_ALL)
#ifdef SSL_TXT_SSLV2
      else SETBITOPT(SSL_TXT_SSLV2, !neg, SSL_OP_NO_SSLv2)
#endif
#ifdef SSL_TXT_SSLV3
      else SETBITOPT(SSL_TXT_SSLV3, !neg, SSL_OP_NO_SSLv3)
#endif
#ifdef SSL_TXT_TLSV1
      else SETBITOPT(SSL_TXT_TLSV1, !neg, SSL_OP_NO_TLSv1)
#endif
#ifdef SSL_TXT_TLSV1_1
      else SETBITOPT(SSL_TXT_TLSV1_1, !neg, SSL_OP_NO_TLSv1_1)
#endif
#ifdef SSL_TXT_TLSV1_2
      else SETBITOPT(SSL_TXT_TLSV1_2, !neg, SSL_OP_NO_TLSv1_2)
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
      else SETBITOPT("cipher_server_preference", neg, SSL_OP_CIPHER_SERVER_PREFERENCE)
#endif
      else {
        mtevL(mtev_error, "SSL layer part '%s' not understood.\n", optname);
      }
    }

    if (type == SSL_SERVER)
      SSL_CTX_set_session_id_context(ctx->ssl_ctx,
              (unsigned char *)EVENTER_SSL_DATANAME,
              sizeof(EVENTER_SSL_DATANAME)-1);
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
    ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#endif
#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
    ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
#endif
#ifdef SSL_OP_NO_COMPRESSION
    ctx_options |= SSL_OP_NO_COMPRESSION;
#endif
#ifdef SSL_OP_NO_TICKET
    ctx_options |= SSL_OP_NO_TICKET;
#endif
#ifdef SSL_OP_SINGLE_DH_USE
    ctx_options |= SSL_OP_SINGLE_DH_USE;
#endif
#ifdef SSL_OP_SINGLE_ECDH_USE
    ctx_options |= SSL_OP_SINGLE_ECDH_USE;
#endif
    SSL_CTX_set_options(ctx->ssl_ctx, ctx_options);
#ifdef SSL_MODE_RELEASE_BUFFERS
    SSL_CTX_set_mode(ctx->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
    if(certificate &&
       SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, certificate) != 1)
      goto bail;
    if(key &&
       SSL_CTX_use_RSAPrivateKey_file(ctx->ssl_ctx,key,
                                      SSL_FILETYPE_PEM) != 1)
      goto bail;
    if(ca) {
      STACK_OF(X509_NAME) *cert_stack;
      if(!SSL_CTX_load_verify_locations(ctx->ssl_ctx,ca,NULL) ||
         (cert_stack = SSL_load_client_CA_file(ca)) == NULL)
        goto bail;
      SSL_CTX_set_client_CA_list(ctx->ssl_ctx, cert_stack);
    }
    SSL_CTX_set_cipher_list(ctx->ssl_ctx, ciphers ? ciphers : "DEFAULT");
    SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, verify_cb);
#ifndef OPENSSL_NO_EC
#if defined(SSL_CTX_set_ecdh_auto)
    SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
#elif defined(NID_X9_62_prime256v1)
    EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
    SSL_CTX_set_tmp_ecdh(ctx->ssl_ctx, ec_key);
    EC_KEY_free(ec_key);
#endif
#endif
    existing_ctx_cn = ssl_ctx_cache_set(ctx->ssl_ctx_cn);
    if(existing_ctx_cn != ctx->ssl_ctx_cn) {
      ssl_ctx_cache_node_free(ctx->ssl_ctx_cn);
      ctx->ssl_ctx_cn = existing_ctx_cn;
    }
  }
Exemple #19
0
struct daemon_remote*
daemon_remote_create(struct config_file* cfg)
{
	char* s_cert;
	char* s_key;
	struct daemon_remote* rc = (struct daemon_remote*)calloc(1, 
		sizeof(*rc));
	if(!rc) {
		log_err("out of memory in daemon_remote_create");
		return NULL;
	}
	rc->max_active = 10;

	if(!cfg->remote_control_enable) {
		rc->ctx = NULL;
		return rc;
	}
	rc->ctx = SSL_CTX_new(SSLv23_server_method());
	if(!rc->ctx) {
		log_crypto_err("could not SSL_CTX_new");
		free(rc);
		return NULL;
	}
	/* no SSLv2 because has defects */
	if(!(SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)){
		log_crypto_err("could not set SSL_OP_NO_SSLv2");
		daemon_remote_delete(rc);
		return NULL;
	}
	s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1);
	s_key = fname_after_chroot(cfg->server_key_file, cfg, 1);
	if(!s_cert || !s_key) {
		log_err("out of memory in remote control fname");
		goto setup_error;
	}
	verbose(VERB_ALGO, "setup SSL certificates");
	if (!SSL_CTX_use_certificate_file(rc->ctx,s_cert,SSL_FILETYPE_PEM)) {
		log_err("Error for server-cert-file: %s", s_cert);
		log_crypto_err("Error in SSL_CTX use_certificate_file");
		goto setup_error;
	}
	if(!SSL_CTX_use_PrivateKey_file(rc->ctx,s_key,SSL_FILETYPE_PEM)) {
		log_err("Error for server-key-file: %s", s_key);
		log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
		goto setup_error;
	}
	if(!SSL_CTX_check_private_key(rc->ctx)) {
		log_err("Error for server-key-file: %s", s_key);
		log_crypto_err("Error in SSL_CTX check_private_key");
		goto setup_error;
	}
	if(!SSL_CTX_load_verify_locations(rc->ctx, s_cert, NULL)) {
		log_crypto_err("Error setting up SSL_CTX verify locations");
	setup_error:
		free(s_cert);
		free(s_key);
		daemon_remote_delete(rc);
		return NULL;
	}
	SSL_CTX_set_client_CA_list(rc->ctx, SSL_load_client_CA_file(s_cert));
	SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL);
	free(s_cert);
	free(s_key);

	return rc;
}
Exemple #20
0
void
ssl_init(struct vsf_session* p_sess)
{
  if (!ssl_inited)
  {
    SSL_CTX* p_ctx;
    long options;
    int verify_option = 0;
    SSL_library_init();
    p_ctx = SSL_CTX_new(SSLv23_method());
    if (p_ctx == NULL)
    {
      die("SSL: could not allocate SSL context");
    }
    options = SSL_OP_ALL;
    if (!tunable_sslv2)
    {
      options |= SSL_OP_NO_SSLv2;
    }
    if (!tunable_sslv3)
    {
      options |= SSL_OP_NO_SSLv3;
    }
    if (!tunable_tlsv1)
    {
      options |= SSL_OP_NO_TLSv1;
    }
    SSL_CTX_set_options(p_ctx, options);
    if (tunable_rsa_cert_file)
    {
      const char* p_key = tunable_rsa_private_key_file;
      if (!p_key)
      {
        p_key = tunable_rsa_cert_file;
      }
      if (SSL_CTX_use_certificate_chain_file(p_ctx, tunable_rsa_cert_file) != 1)
      {
        die("SSL: cannot load RSA certificate");
      }
      if (SSL_CTX_use_PrivateKey_file(p_ctx, p_key, X509_FILETYPE_PEM) != 1)
      {
        die("SSL: cannot load RSA private key");
      }
    }
    if (tunable_dsa_cert_file)
    {
      const char* p_key = tunable_dsa_private_key_file;
      if (!p_key)
      {
        p_key = tunable_dsa_cert_file;
      }
      if (SSL_CTX_use_certificate_chain_file(p_ctx, tunable_dsa_cert_file) != 1)
      {
        die("SSL: cannot load DSA certificate");
      }
      if (SSL_CTX_use_PrivateKey_file(p_ctx, p_key, X509_FILETYPE_PEM) != 1)
      {
        die("SSL: cannot load DSA private key");
      }
    }
    if (tunable_ssl_ciphers &&
        SSL_CTX_set_cipher_list(p_ctx, tunable_ssl_ciphers) != 1)
    {
      die("SSL: could not set cipher list");
    }
    if (RAND_status() != 1)
    {
      die("SSL: RNG is not seeded");
    }
    if (tunable_ssl_request_cert)
    {
      verify_option |= SSL_VERIFY_PEER;
    }
    if (tunable_require_cert)
    {
      verify_option |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
    }
    if (verify_option)
    {
      SSL_CTX_set_verify(p_ctx, verify_option, ssl_verify_callback);
      if (tunable_ca_certs_file)
      {
        STACK_OF(X509_NAME)* p_names;
        if (!SSL_CTX_load_verify_locations(p_ctx, tunable_ca_certs_file, NULL))
        {
          die("SSL: could not load verify file");
        }
        p_names = SSL_load_client_CA_file(tunable_ca_certs_file);
        if (!p_names)
        {
          die("SSL: could not load client certs file");
        }
        SSL_CTX_set_client_CA_list(p_ctx, p_names);
      }
    }
    {
      static const char* p_ctx_id = VSF_PROJECT;
      SSL_CTX_set_session_id_context(p_ctx, (void*) p_ctx_id,
                                     vsf_sysutil_strlen(p_ctx_id));
    }
    if (tunable_require_ssl_reuse)
    {
      /* Ensure cached session doesn't expire */
      SSL_CTX_set_timeout(p_ctx, INT_MAX);
    }
    p_sess->p_ssl_ctx = p_ctx;
    ssl_inited = 1;
  }
}
// borrowed from original ngx_event_openssl.c v1.7.1
ngx_int_t
ngx_tcp_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
    ngx_int_t depth, ngx_int_t optional)
{
    STACK_OF(X509_NAME)  *list;

    /* @see https://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
     * When proxying tcp connection, you expect handshake to fail if no 
     * client certificate was send by client and ssl_verify_client=on.
     * But by default nginx allowed connection by any client. 
     */
    int ossl_verify_mode = optional ? SSL_VERIFY_PEER
                            : SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;

    SSL_CTX_set_verify(ssl->ctx, ossl_verify_mode, ngx_tcp_ssl_verify_callback);

    SSL_CTX_set_verify_depth(ssl->ctx, depth);

    if (cert->len == 0) {
        return NGX_OK;
    }

    if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
        return NGX_ERROR;
    }

    if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
        == 0)
    {
        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                      "SSL_CTX_load_verify_locations(\"%s\") failed",
                      cert->data);
        return NGX_ERROR;
    }

    /*
     * SSL_CTX_load_verify_locations() may leave errors in the error queue
     * while returning success
     */

    ERR_clear_error();

    list = SSL_load_client_CA_file((char *) cert->data);

    if (list == NULL) {
        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                      "SSL_load_client_CA_file(\"%s\") failed", cert->data);
        return NGX_ERROR;
    }

    /*
     * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
     * always leaved an error in the error queue
     */

    ERR_clear_error();

    SSL_CTX_set_client_CA_list(ssl->ctx, list);

    return NGX_OK;
}
Exemple #22
0
/*
    Open the SSL module
 */
PUBLIC int sslOpen()
{
    RandBuf     randBuf;
    X509_STORE  *store;
    uchar       resume[16];
    char        *ciphers;

    trace(7, "Initializing SSL");

    randBuf.now = time(0);
    randBuf.pid = getpid();
    RAND_seed((void*) &randBuf, sizeof(randBuf));
#if ME_UNIX_LIKE
    trace(6, "OpenSsl: Before calling RAND_load_file");
    RAND_load_file("/dev/urandom", 256);
    trace(6, "OpenSsl: After calling RAND_load_file");
#endif

    CRYPTO_malloc_init();
#if !ME_WIN_LIKE
    OpenSSL_add_all_algorithms();
#endif
    SSL_library_init();
    SSL_load_error_strings();
    SSLeay_add_ssl_algorithms();

    if ((sslctx = SSL_CTX_new(SSLv23_server_method())) == 0) {
        error("Unable to create SSL context");
        return -1;
    }

    /*
          Set the server certificate and key files
     */
    if (*ME_GOAHEAD_SSL_KEY && sslSetKeyFile(ME_GOAHEAD_SSL_KEY) < 0) {
        sslClose();
        return -1;
    }
    if (*ME_GOAHEAD_SSL_CERTIFICATE && sslSetCertFile(ME_GOAHEAD_SSL_CERTIFICATE) < 0) {
        sslClose();
        return -1;
    }

    if (ME_GOAHEAD_SSL_VERIFY_PEER) {
        SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyClientCertificate);
        SSL_CTX_set_verify_depth(sslctx, VERIFY_DEPTH);
    } else {
        SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyClientCertificate);
    }
    /*
          Set the client certificate verification locations
     */
    if (ME_GOAHEAD_SSL_AUTHORITY && *ME_GOAHEAD_SSL_AUTHORITY) {
        if ((!SSL_CTX_load_verify_locations(sslctx, ME_GOAHEAD_SSL_AUTHORITY, NULL)) ||
                (!SSL_CTX_set_default_verify_paths(sslctx))) {
            error("Unable to read cert verification locations");
            sslClose();
            return -1;
        }
        /*
            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(sslctx, SSL_load_client_CA_file(ME_GOAHEAD_SSL_AUTHORITY));
    }
    if (ME_GOAHEAD_SSL_REVOKE && *ME_GOAHEAD_SSL_REVOKE) {
        store = SSL_CTX_get_cert_store(sslctx);
        if (!X509_STORE_load_locations(store, ME_GOAHEAD_SSL_REVOKE, 0)) {
            error("Cannot load certificate revoke list: %s", ME_GOAHEAD_SSL_REVOKE);
            sslClose();
            return -1;
        }
    }

    /*
        Configure DH parameters
     */
    dhKey = getDhKey();
    SSL_CTX_set_tmp_dh_callback(sslctx, dhcallback);

    /*
        Configure cipher suite
     */
    if (ME_GOAHEAD_SSL_CIPHERS && *ME_GOAHEAD_SSL_CIPHERS) {
        ciphers = ME_GOAHEAD_SSL_CIPHERS;
    } else {
        ciphers = OPENSSL_DEFAULT_CIPHERS;
    }
    ciphers = mapCipherNames(ciphers);
    trace(5, "Using OpenSSL ciphers: %s", ciphers);
    if (SSL_CTX_set_cipher_list(sslctx, ciphers) != 1) {
        error("Unable to set cipher list \"%s\"", ciphers);
        sslClose();
        wfree(ciphers);
        return -1;
    }
    wfree(ciphers);

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

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

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

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

        name = ME_GOAHEAD_SSL_CURVE;
        if ((nid = OBJ_sn2nid(name)) == 0) {
            error("Unknown curve name \"%s\"", name);
            sslClose();
            return -1;
        }
        if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) {
            error("Unable to create curve \"%s\"", name);
            sslClose();
            return -1;
        }
        SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_ECDH_USE);
        SSL_CTX_set_tmp_ecdh(sslctx, ecdh);
        EC_KEY_free(ecdh);
    }
#endif
#endif

    SSL_CTX_set_mode(sslctx, 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(sslctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS
    SSL_CTX_set_mode(sslctx, SSL_MODE_RELEASE_BUFFERS);
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
    SSL_CTX_set_mode(sslctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
#endif

    /*
        Select the required protocols
        Disable both SSLv2 and SSLv3 by default - they are insecure
     */
    SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2);
    SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3);

#if defined(SSL_OP_NO_TLSv1) && ME_GOAHEAD_SSL_NO_V1
    SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1);
#endif
#if defined(SSL_OP_NO_TLSv1_1) && ME_GOAHEAD_SSL_NO_V1_1
    SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_1);
#endif
#if defined(SSL_OP_NO_TLSv1_2) && ME_GOAHEAD_SSL_NO_V1_2
    SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2);
#endif


#if defined(SSL_OP_NO_TICKET)
    /*
        Ticket based session reuse is enabled by default
     */
#if defined(ME_GOAHEAD_SSL_TICKET)
    if (ME_GOAHEAD_SSL_TICKET) {
        SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET);
    } else {
        SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET);
    }
#else
    SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET);
#endif
#endif

#if defined(SSL_OP_NO_COMPRESSION)
    /*
        CRIME attack targets compression
     */
    SSL_CTX_clear_options(sslctx, SSL_OP_NO_COMPRESSION);
#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_GOAHEAD_SSL_EMPTY_FRAGMENTS)
    if (ME_GOAHEAD_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(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
    } else {
        SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
    }
#else
    SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
#endif
#endif

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

    return 0;
}
/*
 *	Create Global context SSL and use it in every new session
 *
 *	- Load the trusted CAs
 *	- Load the Private key & the certificate
 *	- Set the Context options & Verify options
 */
static SSL_CTX *init_tls_ctx(EAP_TLS_CONF *conf)
{
	SSL_METHOD *meth;
	SSL_CTX *ctx;
	X509_STORE *certstore;
	int verify_mode = SSL_VERIFY_NONE;
	int ctx_options = 0;
	int type;

	/*
	 *	Add all the default ciphers and message digests
	 *	Create our context.
	 */
	SSL_library_init();
	SSL_load_error_strings();

	/*
	 *	SHA256 is in all versions of OpenSSL, but isn't
	 *	initialized by default.  It's needed for WiMAX
	 *	certificates.
	 */
#ifdef HAVE_OPENSSL_EVP_SHA256
	EVP_add_digest(EVP_sha256());
#endif

	meth = TLSv1_method();
	ctx = SSL_CTX_new(meth);

	/*
	 * Identify the type of certificates that needs to be loaded
	 */
	if (conf->file_type) {
		type = SSL_FILETYPE_PEM;
	} else {
		type = SSL_FILETYPE_ASN1;
	}

	/*
	 * Set the password to load private key
	 */
	if (conf->private_key_password) {
#ifdef __APPLE__
		/*
		 * We don't want to put the private key password in eap.conf, so  check
		 * for our special string which indicates we should get the password
		 * programmatically. 
		 */
		const char* special_string = "Apple:UseCertAdmin";
		if (strncmp(conf->private_key_password,
					special_string,
					strlen(special_string)) == 0)
		{
			char cmd[256];
			const long max_password_len = 128;
			snprintf(cmd, sizeof(cmd) - 1,
					 "/usr/sbin/certadmin --get-private-key-passphrase \"%s\"",
					 conf->private_key_file);

			DEBUG2("rlm_eap: Getting private key passphrase using command \"%s\"", cmd);

			FILE* cmd_pipe = popen(cmd, "r");
			if (!cmd_pipe) {
				radlog(L_ERR, "rlm_eap: %s command failed.	Unable to get private_key_password", cmd);
				radlog(L_ERR, "rlm_eap: Error reading private_key_file %s", conf->private_key_file);
				return NULL;
			}

			free(conf->private_key_password);
			conf->private_key_password = malloc(max_password_len * sizeof(char));
			if (!conf->private_key_password) {
				radlog(L_ERR, "rlm_eap: Can't malloc space for private_key_password");
				radlog(L_ERR, "rlm_eap: Error reading private_key_file %s", conf->private_key_file);
				pclose(cmd_pipe);
				return NULL;
			}

			fgets(conf->private_key_password, max_password_len, cmd_pipe);
			pclose(cmd_pipe);

			/* Get rid of newline at end of password. */
			conf->private_key_password[strlen(conf->private_key_password) - 1] = '\0';
			DEBUG2("rlm_eap:  Password from command = \"%s\"", conf->private_key_password);
		}
#endif
		SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->private_key_password);
		SSL_CTX_set_default_passwd_cb(ctx, cbtls_password);
	}

	/*
	 *	Load our keys and certificates
	 *
	 *	If certificates are of type PEM then we can make use
	 *	of cert chain authentication using openssl api call
	 *	SSL_CTX_use_certificate_chain_file.  Please see how
	 *	the cert chain needs to be given in PEM from
	 *	openSSL.org
	 */
	if (type == SSL_FILETYPE_PEM) {
		if (!(SSL_CTX_use_certificate_chain_file(ctx, conf->certificate_file))) {
			radlog(L_ERR, "rlm_eap: SSL error %s", ERR_error_string(ERR_get_error(), NULL));
			radlog(L_ERR, "rlm_eap_tls: Error reading certificate file %s", conf->certificate_file);
			return NULL;
		}

	} else if (!(SSL_CTX_use_certificate_file(ctx, conf->certificate_file, type))) {
		radlog(L_ERR, "rlm_eap: SSL error %s", ERR_error_string(ERR_get_error(), NULL));
		radlog(L_ERR, "rlm_eap_tls: Error reading certificate file %s", conf->certificate_file);
		return NULL;
	}

	/* Load the CAs we trust */
	if (conf->ca_file || conf->ca_path) {
		if (!SSL_CTX_load_verify_locations(ctx, conf->ca_file, conf->ca_path)) {
			radlog(L_ERR, "rlm_eap: SSL error %s", ERR_error_string(ERR_get_error(), NULL));
			radlog(L_ERR, "rlm_eap_tls: Error reading Trusted root CA list %s",conf->ca_file );
			return NULL;
		}
	}
	if (conf->ca_file && *conf->ca_file) SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(conf->ca_file));
	if (!(SSL_CTX_use_PrivateKey_file(ctx, conf->private_key_file, type))) {
		radlog(L_ERR, "rlm_eap: SSL error %s", ERR_error_string(ERR_get_error(), NULL));
		radlog(L_ERR, "rlm_eap_tls: Error reading private key file %s", conf->private_key_file);
		return NULL;
	}

	/*
	 * Check if the loaded private key is the right one
	 */
	if (!SSL_CTX_check_private_key(ctx)) {
		radlog(L_ERR, "rlm_eap_tls: Private key does not match the certificate public key");
		return NULL;
	}

	/*
	 *	Set ctx_options
	 */
	ctx_options |= SSL_OP_NO_SSLv2;
   	ctx_options |= SSL_OP_NO_SSLv3;
#ifdef SSL_OP_NO_TICKET
	ctx_options |= SSL_OP_NO_TICKET ;
#endif

	/*
	 *	SSL_OP_SINGLE_DH_USE must be used in order to prevent
	 *	small subgroup attacks and forward secrecy. Always
	 *	using
	 *
	 *	SSL_OP_SINGLE_DH_USE has an impact on the computer
	 *	time needed during negotiation, but it is not very
	 *	large.
	 */
   	ctx_options |= SSL_OP_SINGLE_DH_USE;

	/*
	 *	SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS to work around issues
	 *	in Windows Vista client.
	 *	http://www.openssl.org/~bodo/tls-cbc.txt
	 *	http://www.nabble.com/(RADIATOR)-Radiator-Version-3.16-released-t2600070.html
	 */
   	ctx_options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;

	SSL_CTX_set_options(ctx, ctx_options);

	/*
	 *	TODO: Set the RSA & DH
	 *	SSL_CTX_set_tmp_rsa_callback(ctx, cbtls_rsa);
	 *	SSL_CTX_set_tmp_dh_callback(ctx, cbtls_dh);
	 */

	/*
	 *	set the message callback to identify the type of
	 *	message.  For every new session, there can be a
	 *	different callback argument.
	 *
	 *	SSL_CTX_set_msg_callback(ctx, cbtls_msg);
	 */

	/* Set Info callback */
	SSL_CTX_set_info_callback(ctx, cbtls_info);

	/*
	 *	Callbacks, etc. for session resumption.
	 */						      
	if (conf->session_cache_enable) {
		SSL_CTX_sess_set_new_cb(ctx, cbtls_new_session);
		SSL_CTX_sess_set_get_cb(ctx, cbtls_get_session);
		SSL_CTX_sess_set_remove_cb(ctx, cbtls_remove_session);

		SSL_CTX_set_quiet_shutdown(ctx, 1);
	}

	/*
	 *	Check the certificates for revocation.
	 */
#ifdef X509_V_FLAG_CRL_CHECK
	if (conf->check_crl) {
	  certstore = SSL_CTX_get_cert_store(ctx);
	  if (certstore == NULL) {
	    radlog(L_ERR, "rlm_eap: SSL error %s", ERR_error_string(ERR_get_error(), NULL));
	    radlog(L_ERR, "rlm_eap_tls: Error reading Certificate Store");
	    return NULL;
	  }
	  X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK);
	}
#endif

	/*
	 *	Set verify modes
	 *	Always verify the peer certificate
	 */
	verify_mode |= SSL_VERIFY_PEER;
	verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
	verify_mode |= SSL_VERIFY_CLIENT_ONCE;
	SSL_CTX_set_verify(ctx, verify_mode, cbtls_verify);

	if (conf->verify_depth) {
		SSL_CTX_set_verify_depth(ctx, conf->verify_depth);
	}

	/* Load randomness */
	if (!(RAND_load_file(conf->random_file, 1024*1024))) {
		radlog(L_ERR, "rlm_eap: SSL error %s", ERR_error_string(ERR_get_error(), NULL));
		radlog(L_ERR, "rlm_eap_tls: Error loading randomness");
		return NULL;
	}

	/*
	 * Set the cipher list if we were told to
	 */
	if (conf->cipher_list) {
		if (!SSL_CTX_set_cipher_list(ctx, conf->cipher_list)) {
			radlog(L_ERR, "rlm_eap_tls: Error setting cipher list");
			return NULL;
		}
	}

	/*
	 *	Setup session caching
	 */
	if (conf->session_cache_enable) {
		/*
		 *	Create a unique context Id per EAP-TLS configuration.
		 */
		if (conf->session_id_name) {
			snprintf(conf->session_context_id,
				 sizeof(conf->session_context_id),
				 "FreeRADIUS EAP-TLS %s",
				 conf->session_id_name);
		} else {
			snprintf(conf->session_context_id,
				 sizeof(conf->session_context_id),
				 "FreeRADIUS EAP-TLS %p", conf);
		}

		/*
		 *	Cache it, and DON'T auto-clear it.
		 */
		SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR);
					       
		SSL_CTX_set_session_id_context(ctx,
					       (unsigned char *) conf->session_context_id,
					       (unsigned int) strlen(conf->session_context_id));

		/*
		 *	Our timeout is in hours, this is in seconds.
		 */
		SSL_CTX_set_timeout(ctx, conf->session_timeout * 3600);
		
		/*
		 *	Set the maximum number of entries in the
		 *	session cache.
		 */
		SSL_CTX_sess_set_cache_size(ctx, conf->session_cache_size);

	} else {
		SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
	}

	/*
	 *	Register the application indices.  We can't use
	 *	hard-coded "0" and "1" as before, because we need to
	 *	set up a "free" handler for the cached session
	 *	information.
	 */
	if (eaptls_handle_idx < 0) {
		eaptls_handle_idx = SSL_get_ex_new_index(0, &eaptls_handle_idx,
							 NULL, NULL, NULL);
	}
	
	if (eaptls_conf_idx < 0) {
		eaptls_conf_idx = SSL_get_ex_new_index(0, &eaptls_conf_idx,
							  NULL, NULL, NULL);
	}

	if (eaptls_store_idx < 0) {
		eaptls_store_idx = SSL_get_ex_new_index(0, "eaptls_store_idx",
							  NULL, NULL, NULL);
	}

	if (eaptls_session_idx < 0) {
		eaptls_session_idx = SSL_get_ex_new_index(0, &eaptls_session_idx,
							  NULL, NULL,
							  eaptls_session_free);
	}

	return ctx;
}
Exemple #24
0
int network_init(server *srv) {
	buffer *b;
	size_t i, j;
	network_backend_t backend;

#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
	EC_KEY *ecdh;
	int nid;
#endif
#endif

#ifdef USE_OPENSSL
# ifndef OPENSSL_NO_DH
	DH *dh;
# endif
	BIO *bio;

       /* 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114)
	* -----BEGIN DH PARAMETERS-----
	* MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y
	* mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4
	* +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV
	* w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0
	* sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR
	* jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA=
	* -----END DH PARAMETERS-----
	*/

	static const unsigned char dh1024_p[]={
		0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E,
		0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6,
		0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86,
		0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0,
		0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C,
		0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70,
		0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA,
		0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0,
		0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF,
		0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08,
		0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71,
	};

	static const unsigned char dh1024_g[]={
		0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42,
		0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F,
		0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E,
		0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13,
		0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F,
		0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1,
		0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08,
		0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A,
		0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59,
		0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24,
		0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5,
	};
#endif

	struct nb_map {
		network_backend_t nb;
		const char *name;
	} network_backends[] = {
		/* lowest id wins */
#if defined USE_SENDFILE
		{ NETWORK_BACKEND_SENDFILE,   "sendfile" },
#endif
#if defined USE_LINUX_SENDFILE
		{ NETWORK_BACKEND_SENDFILE,   "linux-sendfile" },
#endif
#if defined USE_FREEBSD_SENDFILE
		{ NETWORK_BACKEND_SENDFILE,   "freebsd-sendfile" },
#endif
#if defined USE_SOLARIS_SENDFILEV
		{ NETWORK_BACKEND_SENDFILE,   "solaris-sendfilev" },
#endif
#if defined USE_WRITEV
		{ NETWORK_BACKEND_WRITEV,     "writev" },
#endif
		{ NETWORK_BACKEND_WRITE,      "write" },
		{ NETWORK_BACKEND_UNSET,       NULL }
	};

#ifdef USE_OPENSSL
	/* load SSL certificates */
	for (i = 0; i < srv->config_context->used; i++) {
		specific_config *s = srv->config_storage[i];
#ifndef SSL_OP_NO_COMPRESSION
# define SSL_OP_NO_COMPRESSION 0
#endif
		long ssloptions =
			SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION;

		if (buffer_string_is_empty(s->ssl_pemfile) && buffer_string_is_empty(s->ssl_ca_file)) continue;

		if (srv->ssl_is_init == 0) {
			SSL_load_error_strings();
			SSL_library_init();
			OpenSSL_add_all_algorithms();
			srv->ssl_is_init = 1;

			if (0 == RAND_status()) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						"not enough entropy in the pool");
				return -1;
			}
		}

		if (!buffer_string_is_empty(s->ssl_pemfile)) {
#ifdef OPENSSL_NO_TLSEXT
			data_config *dc = (data_config *)srv->config_context->data[i];
			if (COMP_HTTP_HOST == dc->comp) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						"can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
				return -1;
			}
#endif
			if (network_openssl_load_pemfile(srv, i)) return -1;
		}


		if (!buffer_string_is_empty(s->ssl_ca_file)) {
			s->ssl_ca_file_cert_names = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
			if (NULL == s->ssl_ca_file_cert_names) {
				log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
						ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
			}
		}

		if (buffer_string_is_empty(s->ssl_pemfile) || !s->ssl_enabled) continue;

		if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
					ERR_error_string(ERR_get_error(), NULL));
			return -1;
		}

		/* completely useless identifier; required for client cert verification to work with sessions */
		if (0 == SSL_CTX_set_session_id_context(s->ssl_ctx, (const unsigned char*) CONST_STR_LEN("lighttpd"))) {
			log_error_write(srv, __FILE__, __LINE__, "ss:s", "SSL:",
				"failed to set session context",
				ERR_error_string(ERR_get_error(), NULL));
			return -1;
		}

		if (s->ssl_empty_fragments) {
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
			ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#else
			ssloptions &= ~0x00000800L; /* hardcode constant */
			log_error_write(srv, __FILE__, __LINE__, "ss", "WARNING: SSL:",
					"'insert empty fragments' not supported by the openssl version used to compile lighttpd with");
#endif
		}

		SSL_CTX_set_options(s->ssl_ctx, ssloptions);
		SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);

		if (!s->ssl_use_sslv2) {
			/* disable SSLv2 */
			if ((SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) != SSL_OP_NO_SSLv2) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}
		}

		if (!s->ssl_use_sslv3) {
			/* disable SSLv3 */
			if ((SSL_OP_NO_SSLv3 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3)) != SSL_OP_NO_SSLv3) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}
		}

		if (!buffer_string_is_empty(s->ssl_cipher_list)) {
			/* Disable support for low encryption ciphers */
			if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}

			if (s->ssl_honor_cipher_order) {
				SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
			}
		}

#ifndef OPENSSL_NO_DH
		/* Support for Diffie-Hellman key exchange */
		if (!buffer_string_is_empty(s->ssl_dh_file)) {
			/* DH parameters from file */
			bio = BIO_new_file((char *) s->ssl_dh_file->ptr, "r");
			if (bio == NULL) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to open file", s->ssl_dh_file->ptr);
				return -1;
			}
			dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
			BIO_free(bio);
			if (dh == NULL) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: PEM_read_bio_DHparams failed", s->ssl_dh_file->ptr);
				return -1;
			}
		} else {
			BIGNUM *dh_p, *dh_g;
			/* Default DH parameters from RFC5114 */
			dh = DH_new();
			if (dh == NULL) {
				log_error_write(srv, __FILE__, __LINE__, "s", "SSL: DH_new () failed");
				return -1;
			}
			dh_p = BN_bin2bn(dh1024_p,sizeof(dh1024_p), NULL);
			dh_g = BN_bin2bn(dh1024_g,sizeof(dh1024_g), NULL);
			if ((dh_p == NULL) || (dh_g == NULL)) {
				DH_free(dh);
				log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BN_bin2bn () failed");
				return -1;
			}
		      #if OPENSSL_VERSION_NUMBER < 0x10100000L \
			|| defined(LIBRESSL_VERSION_NUMBER)
			dh->p = dh_p;
			dh->g = dh_g;
			dh->length = 160;
		      #else
			DH_set0_pqg(dh, dh_p, NULL, dh_g);
			DH_set_length(dh, 160);
		      #endif
		}
		SSL_CTX_set_tmp_dh(s->ssl_ctx,dh);
		SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE);
		DH_free(dh);
#else
		if (!buffer_string_is_empty(s->ssl_dh_file)) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: openssl compiled without DH support, can't load parameters from", s->ssl_dh_file->ptr);
		}
#endif

#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
		/* Support for Elliptic-Curve Diffie-Hellman key exchange */
		if (!buffer_string_is_empty(s->ssl_ec_curve)) {
			/* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */
			nid = OBJ_sn2nid((char *) s->ssl_ec_curve->ptr);
			if (nid == 0) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unknown curve name", s->ssl_ec_curve->ptr);
				return -1;
			}
		} else {
			/* Default curve */
			nid = OBJ_sn2nid("prime256v1");
		}
		ecdh = EC_KEY_new_by_curve_name(nid);
		if (ecdh == NULL) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to create curve", s->ssl_ec_curve->ptr);
			return -1;
		}
		SSL_CTX_set_tmp_ecdh(s->ssl_ctx,ecdh);
		SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_ECDH_USE);
		EC_KEY_free(ecdh);
#endif
#endif

		/* load all ssl.ca-files specified in the config into each SSL_CTX to be prepared for SNI */
		for (j = 0; j < srv->config_context->used; j++) {
			specific_config *s1 = srv->config_storage[j];

			if (!buffer_string_is_empty(s1->ssl_ca_file)) {
				if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s1->ssl_ca_file->ptr, NULL)) {
					log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
							ERR_error_string(ERR_get_error(), NULL), s1->ssl_ca_file);
					return -1;
				}
			}
		}

		if (s->ssl_verifyclient) {
			if (NULL == s->ssl_ca_file_cert_names) {
				log_error_write(srv, __FILE__, __LINE__, "s",
					"SSL: You specified ssl.verifyclient.activate but no ca_file"
				);
				return -1;
			}
			SSL_CTX_set_client_CA_list(s->ssl_ctx, SSL_dup_CA_list(s->ssl_ca_file_cert_names));
			SSL_CTX_set_verify(
				s->ssl_ctx,
				SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
				NULL
			);
			SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
		}

		if (SSL_CTX_use_certificate(s->ssl_ctx, s->ssl_pemfile_x509) < 0) {
			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
			return -1;
		}

		if (SSL_CTX_use_PrivateKey(s->ssl_ctx, s->ssl_pemfile_pkey) < 0) {
			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
			return -1;
		}

		if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
			log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
					"Private key does not match the certificate public key, reason:",
					ERR_error_string(ERR_get_error(), NULL),
					s->ssl_pemfile);
			return -1;
		}
		SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1);
		SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

# ifndef OPENSSL_NO_TLSEXT
		if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) ||
		    !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
					"failed to initialize TLS servername callback, openssl library does not support TLS servername extension");
			return -1;
		}
# endif
	}
#endif

	b = buffer_init();

	buffer_copy_buffer(b, srv->srvconf.bindhost);
	buffer_append_string_len(b, CONST_STR_LEN(":"));
	buffer_append_int(b, srv->srvconf.port);

	if (0 != network_server_init(srv, b, srv->config_storage[0])) {
		buffer_free(b);
		return -1;
	}
	buffer_free(b);

#ifdef USE_OPENSSL
	srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
#endif

	/* get a usefull default */
	backend = network_backends[0].nb;

	/* match name against known types */
	if (!buffer_string_is_empty(srv->srvconf.network_backend)) {
		for (i = 0; network_backends[i].name; i++) {
			/**/
			if (buffer_is_equal_string(srv->srvconf.network_backend, network_backends[i].name, strlen(network_backends[i].name))) {
				backend = network_backends[i].nb;
				break;
			}
		}
		if (NULL == network_backends[i].name) {
			/* we don't know it */

			log_error_write(srv, __FILE__, __LINE__, "sb",
					"server.network-backend has a unknown value:",
					srv->srvconf.network_backend);

			return -1;
		}
	}

	switch(backend) {
	case NETWORK_BACKEND_WRITE:
		srv->network_backend_write = network_write_chunkqueue_write;
		break;
#if defined(USE_WRITEV)
	case NETWORK_BACKEND_WRITEV:
		srv->network_backend_write = network_write_chunkqueue_writev;
		break;
#endif
#if defined(USE_SENDFILE)
	case NETWORK_BACKEND_SENDFILE:
		srv->network_backend_write = network_write_chunkqueue_sendfile;
		break;
#endif
	default:
		return -1;
	}

	/* check for $SERVER["socket"] */
	for (i = 1; i < srv->config_context->used; i++) {
		data_config *dc = (data_config *)srv->config_context->data[i];
		specific_config *s = srv->config_storage[i];

		/* not our stage */
		if (COMP_SERVER_SOCKET != dc->comp) continue;

		if (dc->cond != CONFIG_COND_EQ) continue;

		/* check if we already know this socket,
		 * if yes, don't init it */
		for (j = 0; j < srv->srv_sockets.used; j++) {
			if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) {
				break;
			}
		}

		if (j == srv->srv_sockets.used) {
			if (0 != network_server_init(srv, dc->string, s)) return -1;
		}
	}

	return 0;
}
Exemple #25
0
/**
 * Init verification of transmitted client certs
 */
static int verify_init(ssl_server_connection *ssl_server) {

    struct stat stat_buf;

    if (ssl_server->clientpemfile==NULL) {

        allow_any_purpose= TRUE;
        SSL_CTX_set_verify(ssl_server->ctx, SSL_VERIFY_PEER ,
                           verify_callback_noclientcert);
        goto end_success; /* No verification, but we have to call the callback! */

    }

    if ( -1 == stat(ssl_server->clientpemfile, &stat_buf )) {

        log("%s: verify_init(): Cannot stat the SSL pem path '%s' -- %s\n",
            prog, Run.httpsslclientpem, STRERROR);

        goto end_error;

    }

    if (S_ISDIR(stat_buf.st_mode)) {

        if (!SSL_CTX_load_verify_locations(ssl_server->ctx, NULL ,
                                           ssl_server->clientpemfile)) {

            handle_ssl_error("verify_init()");
            log("%s: verify_init(): Error setting verify directory to %s\n",
                Run.httpsslclientpem);

            goto end_error;

        }

        log("%s: verify_init(): Loaded SSL client pem directory '%s'\n",
            prog, ssl_server->clientpemfile);

        /* Monits server cert for cli support ! */

        if(!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->pemfile,
                                          NULL)) {

            handle_ssl_error("verify_init()");
            log("%s: verify_init(): Error loading verify certificates from %s\n",
                prog, ssl_server->pemfile);

            goto end_error;

        }

        log("%s: verify_init(): Loaded monit's SSL pem server file '%s'\n",
            prog, ssl_server->pemfile);

    } else if (S_ISREG(stat_buf.st_mode)) {

        if(!SSL_CTX_load_verify_locations(ssl_server->ctx,
                                          ssl_server->clientpemfile,
                                          NULL)) {

            handle_ssl_error("verify_init()");
            log("%s: verify_init(): Error loading verify certificates from %s\n",
                prog, Run.httpsslclientpem);

            goto end_error;

        }

        log("%s: verify_init(): Loaded SSL pem client file '%s'\n",
            prog, ssl_server->clientpemfile);

        /* Monits server cert for cli support ! */

        if(!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->pemfile,
                                          NULL)) {

            handle_ssl_error("verify_init()");
            log("%s: verify_init(): Error loading verify certificates from %s\n",
                prog, ssl_server->pemfile);

            goto end_error;

        }

        log("%s: verify_init(): Loaded monit's SSL pem server file '%s'\n",
            prog, ssl_server->pemfile);

        SSL_CTX_set_client_CA_list(ssl_server->ctx,
                                   SSL_load_client_CA_file(ssl_server->clientpemfile));

    } else {

        log("%s: verify_init(): SSL client pem path is no file or directory %s\n",
            prog, ssl_server->clientpemfile);

        goto end_error;

    }

    allow_any_purpose= FALSE;
    SSL_CTX_set_verify(ssl_server->ctx, SSL_VERIFY_PEER , verify_callback);

end_success:

    return TRUE;

end_error:

    return FALSE;
}
Exemple #26
0
PUBLIC int sslOpen()
{
    RandBuf     randBuf;

    trace(7, "Initializing SSL"); 

    randBuf.now = time(0);
    randBuf.pid = getpid();
    RAND_seed((void*) &randBuf, sizeof(randBuf));
#if BIT_UNIX_LIKE
    trace(6, "OpenSsl: Before calling RAND_load_file");
    RAND_load_file("/dev/urandom", 256);
    trace(6, "OpenSsl: After calling RAND_load_file");
#endif

    CRYPTO_malloc_init(); 
#if !BIT_WIN_LIKE
    OpenSSL_add_all_algorithms();
#endif
    SSL_library_init();
    SSL_load_error_strings();
    SSLeay_add_ssl_algorithms();

    if ((sslctx = SSL_CTX_new(SSLv23_server_method())) == 0) {
        error("Unable to create SSL context"); 
        return -1;
    }

    /*
          Set the client certificate verification locations
     */
    if (*BIT_GOAHEAD_CA) {
        if ((!SSL_CTX_load_verify_locations(sslctx, BIT_GOAHEAD_CA, NULL)) || (!SSL_CTX_set_default_verify_paths(sslctx))) {
            error("Unable to read cert verification locations");
            sslClose();
            return -1;
        }
    }
    /*
          Set the server certificate and key files
     */
    if (*BIT_GOAHEAD_KEY && sslSetKeyFile(BIT_GOAHEAD_KEY) < 0) {
        sslClose();
        return -1;
    }
    if (*BIT_GOAHEAD_CERTIFICATE && sslSetCertFile(BIT_GOAHEAD_CERTIFICATE) < 0) {
        sslClose();
        return -1;
    }
    SSL_CTX_set_tmp_rsa_callback(sslctx, rsaCallback);

#if VERIFY_CLIENT
    if (verifyPeer) {
        SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyX509Certificate);
#if FUTURE && KEEP
        SSL_CTX_set_verify_depth(context, VERIFY_DEPTH);
#endif
    } else {
        SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyX509Certificate);
    }
#else
    SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyX509Certificate);
#endif
    /*
          Set the certificate authority list for the client
     */
    if (BIT_GOAHEAD_CA && *BIT_GOAHEAD_CA) {
        SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(BIT_GOAHEAD_CA));
    }
    SSL_CTX_set_cipher_list(sslctx, BIT_GOAHEAD_CIPHERS);
    SSL_CTX_set_options(sslctx, SSL_OP_ALL);
    SSL_CTX_sess_set_cache_size(sslctx, 128);
#ifdef SSL_OP_NO_TICKET
    SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET);
#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION                                                       
    SSL_CTX_set_options(sslctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
#endif                                                                                                     
    SSL_CTX_set_mode(sslctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
    SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2);

    /* 
        Ensure we generate a new private key for each connection
     */
    SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE);
    return 0;
}
Exemple #27
0
int main ()
{
    int err;

    int i;

    int s, AcceptSocket;


#ifdef _WIN32
    WORD wVersionRequested;

    WSADATA wsaData;

#endif                            /*  */
    struct sockaddr_in service;

    pthread_t pid;

    size_t client_len;

    SSL_CTX *ctx;

    SSL *ssl;

    X509 *client_cert;

    char *str;

    char buf[1024];

    SSL_METHOD *meth;

    //加载EVP cipher/digest算法
    SSLeay_add_ssl_algorithms ();

    //加载crypto/ssl错误提示
    SSL_load_error_strings ();

    //为服务器构造TLSv1 SSL_METHOD结构
    meth = SSLv3_server_method ();

    //建立新的SSL上下文
    ctx = SSL_CTX_new (meth);
    if (!ctx)

    {
        ERR_print_errors_fp (stderr);
        exit (2);
    }

    //加载可信任证书库: 为SSL_CTX对象提供一个默认的信任证书
    if ((!SSL_CTX_load_verify_locations (ctx, CAFILE, NULL)) || (!SSL_CTX_set_default_verify_paths (ctx)))

    {
        printf ("error load verify locations.\n");
        exit (1);
    }

    //加载服务器端证书
    if (SSL_CTX_use_certificate_file (ctx, CERTF, SSL_FILETYPE_PEM) <= 0)

    {
        ERR_print_errors_fp (stderr);
        exit (3);
    }

    //加载服务器私钥文件
    if (SSL_CTX_use_PrivateKey_file_pass (ctx, KEYF, "123456") <= 0)

    {
        ERR_print_errors_fp (stderr);
        exit (4);
    }

    //验证私钥与证书是否一致
    if (!SSL_CTX_check_private_key (ctx))

    {
        fprintf (stderr, "Private key does not match the certificate public key\n");
        exit (5);
    }
    s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE;
    SSL_CTX_set_verify (ctx, s_server_verify, verify_callback_server);

    //当需要客户端验证的时候,服务器把CAfile里面的可信任CA证书发往客户端。
    SSL_CTX_set_client_CA_list (ctx, SSL_load_client_CA_file (CAFILE));

#ifdef _WIN32
    wVersionRequested = MAKEWORD (2, 2);
    err = WSAStartup (wVersionRequested, &wsaData);
    if (err != 0)

    {
        printf ("err\n");
        return -1;
    }

#endif                            /*  */

    //首先建立连接
    s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s < 0)
        return -1;
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = INADDR_ANY;    //inet_addr("127.0.0.1");
    service.sin_port = htons (8888);
    if (bind (s, (struct sockaddr *) &service, sizeof (service)) < 0)

    {
        printf ("bind() failed.\n");
        close (s);
        return -1;
    }
    if (listen (s, 1) < 0)
        printf ("Error listening on socket.\n");
    printf ("recv .....\n");

    //openssl是不支持多线程的,需要自己做加锁处理
    //参见:http://blog.csdn.net/jaylong35/article/details/6988690
    lock_cs = OPENSSL_malloc (CRYPTO_num_locks () * sizeof (pthread_mutex_t));
    lock_count = OPENSSL_malloc (CRYPTO_num_locks () * sizeof (long));
    for (i = 0; i < CRYPTO_num_locks (); i++)

    {
        lock_count[i] = 0;
        pthread_mutex_init (&(lock_cs[i]), NULL);
    }

    //通过这两个设置就可以解决HTTPS多线程请求出现crash的问题
    CRYPTO_set_id_callback ((unsigned long (*)()) pthreads_thread_id);
    CRYPTO_set_locking_callback ((void (*)()) pthreads_locking_callback);
    while (1)

    {
        struct timeval tv;

        fd_set fdset;

        char *str = "JDDH-JDECC3-JDCIPH-JDMD";

        tv.tv_sec = 1;
        tv.tv_usec = 0;
        FD_ZERO (&fdset);
        FD_SET (s, &fdset);
        select (s + 1, &fdset, NULL, NULL, (struct timeval *) &tv);
        if (FD_ISSET (s, &fdset))

        {
            AcceptSocket = accept (s, NULL, NULL);
            ssl = SSL_new (ctx);

            //提交一份自己能够支持的加密方法的列表
            //SSL_set_cipher_list(ssl,"ECDH-RSA-AES256-SHA");
            SSL_set_cipher_list (ssl, "RC4-MD5");
            CHK_NULL (ssl);

            //将SSL与socket进行关联
            err = SSL_set_fd (ssl, AcceptSocket);
            if (err > 0)

            {
                err = pthread_create (&pid, NULL, &thread_main, (void *) ssl);
                pthread_detach (pid);
            }

            else
                continue;
        }
    }
    SSL_CTX_free (ctx);
    return 0;
}
Exemple #28
0
/*
 *	Initialize global SSL context.
 */
static void
initialize_SSL(void)
{
	struct stat buf;

	STACK_OF(X509_NAME) *root_cert_list = NULL;

	if (!SSL_context)
	{
#if SSLEAY_VERSION_NUMBER >= 0x0907000L
		OPENSSL_config(NULL);
#endif
		SSL_library_init();
		SSL_load_error_strings();
		SSL_context = SSL_CTX_new(SSLv23_method());
		if (!SSL_context)
			ereport(FATAL,
					(errmsg("could not create SSL context: %s",
							SSLerrmessage())));

		/*
		 * Disable OpenSSL's moving-write-buffer sanity check, because it
		 * causes unnecessary failures in nonblocking send cases.
		 */
		SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

		/*
		 * Load and verify server's certificate and private key
		 */
		if (SSL_CTX_use_certificate_chain_file(SSL_context,
											   SERVER_CERT_FILE) != 1)
			ereport(FATAL,
					(errcode(ERRCODE_CONFIG_FILE_ERROR),
				  errmsg("could not load server certificate file \"%s\": %s",
						 SERVER_CERT_FILE, SSLerrmessage())));

		if (stat(SERVER_PRIVATE_KEY_FILE, &buf) != 0)
			ereport(FATAL,
					(errcode_for_file_access(),
					 errmsg("could not access private key file \"%s\": %m",
							SERVER_PRIVATE_KEY_FILE)));

		/*
		 * Require no public access to key file.
		 *
		 * XXX temporarily suppress check when on Windows, because there may
		 * not be proper support for Unix-y file permissions.  Need to think
		 * of a reasonable check to apply on Windows.  (See also the data
		 * directory permission check in postmaster.c)
		 */
#if !defined(WIN32) && !defined(__CYGWIN__)
		if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
			ereport(FATAL,
					(errcode(ERRCODE_CONFIG_FILE_ERROR),
				  errmsg("private key file \"%s\" has group or world access",
						 SERVER_PRIVATE_KEY_FILE),
				   errdetail("Permissions should be u=rw (0600) or less.")));
#endif

		if (SSL_CTX_use_PrivateKey_file(SSL_context,
										SERVER_PRIVATE_KEY_FILE,
										SSL_FILETYPE_PEM) != 1)
			ereport(FATAL,
					(errmsg("could not load private key file \"%s\": %s",
							SERVER_PRIVATE_KEY_FILE, SSLerrmessage())));

		if (SSL_CTX_check_private_key(SSL_context) != 1)
			ereport(FATAL,
					(errmsg("check of private key failed: %s",
							SSLerrmessage())));
	}

	/* set up ephemeral DH keys, and disallow SSL v2 while at it */
	SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb);
	SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2);

	/* set up the allowed cipher list */
	if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1)
		elog(FATAL, "could not set the cipher list (no valid ciphers available)");

	/*
	 * Attempt to load CA store, so we can verify client certificates if
	 * needed.
	 */
	ssl_loaded_verify_locations = false;

	if (access(ROOT_CERT_FILE, R_OK) != 0)
	{
		/*
		 * If root certificate file simply not found, don't log an error here,
		 * because it's quite likely the user isn't planning on using client
		 * certificates. If we can't access it for other reasons, it is an
		 * error.
		 */
		if (errno != ENOENT)
			ereport(FATAL,
				 (errmsg("could not access root certificate file \"%s\": %m",
						 ROOT_CERT_FILE)));
	}
	else if (SSL_CTX_load_verify_locations(SSL_context, ROOT_CERT_FILE, NULL) != 1 ||
		  (root_cert_list = SSL_load_client_CA_file(ROOT_CERT_FILE)) == NULL)
	{
		/*
		 * File was there, but we could not load it. This means the file is
		 * somehow broken, and we cannot do verification at all - so fail.
		 */
		ereport(FATAL,
				(errmsg("could not load root certificate file \"%s\": %s",
						ROOT_CERT_FILE, SSLerrmessage())));
	}
	else
	{
		/*----------
		 * Load the Certificate Revocation List (CRL) if file exists.
		 * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html
		 *----------
		 */
		X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context);

		if (cvstore)
		{
			/* Set the flags to check against the complete CRL chain */
			if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) == 1)
			{
				/* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
#ifdef X509_V_FLAG_CRL_CHECK
				X509_STORE_set_flags(cvstore,
						  X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
#else
				ereport(LOG,
				(errmsg("SSL certificate revocation list file \"%s\" ignored",
						ROOT_CRL_FILE),
				 errdetail("SSL library does not support certificate revocation lists.")));
#endif
			}
			else
			{
				/* Not fatal - we do not require CRL */
				ereport(LOG,
						(errmsg("SSL certificate revocation list file \"%s\" not found, skipping: %s",
								ROOT_CRL_FILE, SSLerrmessage()),
						 errdetail("Certificates will not be checked against revocation list.")));
			}

			/*
			 * Always ask for SSL client cert, but don't fail if it's not
			 * presented.  We might fail such connections later, depending on
			 * what we find in pg_hba.conf.
			 */
			SSL_CTX_set_verify(SSL_context,
							   (SSL_VERIFY_PEER |
								SSL_VERIFY_CLIENT_ONCE),
							   verify_cb);

			/* Set flag to remember CA store is successfully loaded */
			ssl_loaded_verify_locations = true;
		}

		/*
		 * Tell OpenSSL to send the list of root certs we trust to clients in
		 * CertificateRequests.  This lets a client with a keystore select the
		 * appropriate client certificate to send to us.
		 */
		SSL_CTX_set_client_CA_list(SSL_context, root_cert_list);
	}
}
Exemple #29
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;
}
Exemple #30
0
BOOL CSSLContext::LoadCertAndKey(SSL_CTX* sslCtx, int iVerifyMode, LPCTSTR lpszPemCertFile, LPCTSTR lpszPemKeyFile, LPCTSTR lpszKeyPasswod, LPCTSTR lpszCAPemCertFileOrPath)
{
	USES_CONVERSION;

	if(lpszCAPemCertFileOrPath != nullptr)
	{
		LPCTSTR lpszCAPemCertFile = nullptr;
		LPCTSTR lpszCAPemCertPath = nullptr;

		if(!ATLPath::FileExists(lpszCAPemCertFileOrPath))
		{
			::SetLastError(ERROR_FILE_NOT_FOUND);
			return FALSE;
		}

		if(!ATLPath::IsDirectory(lpszCAPemCertFileOrPath))
			lpszCAPemCertFile = lpszCAPemCertFileOrPath;
		else
			lpszCAPemCertPath = lpszCAPemCertFileOrPath;

		if(!SSL_CTX_load_verify_locations(sslCtx, T2CA(lpszCAPemCertFile), T2CA(lpszCAPemCertPath)))
		{
			::SetLastError(ERROR_INVALID_DATA);
			return FALSE;
		}

		if(!SSL_CTX_set_default_verify_paths(sslCtx))
		{
			::SetLastError(ERROR_FUNCTION_FAILED);
			return FALSE;
		}

		if(m_enSessionMode == SSL_SM_SERVER && iVerifyMode & SSL_VM_PEER)
		{
			STACK_OF(X509_NAME)* caCertNames = SSL_load_client_CA_file(T2CA(lpszCAPemCertFileOrPath));

			if(caCertNames == nullptr)
			{
				::SetLastError(ERROR_EMPTY);
				return FALSE;
			}

			SSL_CTX_set_client_CA_list(sslCtx, caCertNames);
		}
	}

	if(lpszPemCertFile != nullptr)
	{
		if(	!ATLPath::FileExists(lpszPemCertFile)	||
			ATLPath::IsDirectory(lpszPemCertFile)	)
		{
			::SetLastError(ERROR_FILE_NOT_FOUND);
			return FALSE;
		}

		if(	lpszPemKeyFile == nullptr				||
			!ATLPath::FileExists(lpszPemKeyFile)	||
			ATLPath::IsDirectory(lpszPemKeyFile)	)
		{
			::SetLastError(ERROR_FILE_NOT_FOUND);
			return FALSE;
		}
		
		if(lpszKeyPasswod != nullptr)
			SSL_CTX_set_default_passwd_cb_userdata(sslCtx, (void*)T2CA(lpszKeyPasswod));

		if(!SSL_CTX_use_PrivateKey_file(sslCtx, T2CA(lpszPemKeyFile), SSL_FILETYPE_PEM))
		{
			::SetLastError(ERROR_INVALID_PASSWORD);
			return FALSE;
		}

		if(!SSL_CTX_use_certificate_chain_file(sslCtx, T2CA(lpszPemCertFile)))
		{
			::SetLastError(ERROR_INVALID_DATA);
			return FALSE;
		}

		if(!SSL_CTX_check_private_key(sslCtx))
		{
			::SetLastError(ERROR_INVALID_ACCESS);
			return FALSE;
		}
	}

	return TRUE;
}