Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "filter: exposed functions to Lua to verify digital signature" #77

Merged
merged 1 commit into from
Jun 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 0 additions & 51 deletions docs/root/configuration/http_filters/lua_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -312,57 +312,6 @@ Returns the current request's underlying :repo:`connection <include/envoy/networ

Returns a :ref:`connection object <config_http_filters_lua_connection_wrapper>`.

importPublicKey()
^^^^^^^^^^^^^^^^^

.. code-block:: lua

pkey = handle:importPublicKey(keyder, keyderLenght)

Returns public key which is used by :ref:`verifySignature <verify_signature>` to verify digital signature.

.. attention::

Remember to call :ref:`releasePublicKey <release_public_key>` if *pkey* is not needed to avoid memory leak.

.. _release_public_key:

releasePublicKey()
^^^^^^^^^^^^^^^^^^

.. code-block:: lua

handle:releasePublicKey(pkey)

Free the resource of *pkey*

decodeBase64()
^^^^^^^^^^^^^^

.. code-block:: lua

raw = request_handle:decodeBase64(str)

Decodes base64 encoded string. Returns *nil* if input string is invalid.

.. _verify_signature:

verifySignature()
^^^^^^^^^^^^^^^^^

.. code-block:: lua

ok, error = verifySignature(pkey, hashFunction, signature, signatureLength, data, dataLength)

Verify signature using provided parameters. *pkey* is the public key, *hashFunction* is the variable
for hash function which be used for verifying signature. *MD4*, *MD5*, *SHA1*, *SHA224*, *SHA256*,
*SHA384*, *SHA512* and *MD5_SHA1* are supported. *signature* is the signature to be verified.
*signatureLength* is the length of the signature. *data* is the content which will be hashed.
*dataLength* is the length of data.

The function returns a pair. If the first element is *true*, the second element will be empty
which means signature is verified; otherwise, the second element will store the error message.

.. _config_http_filters_lua_header_wrapper:

Header object API
Expand Down
58 changes: 0 additions & 58 deletions docs/root/intro/version_history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,6 @@ Version history

1.11.0 (Pending)
================
* access log: added a new field for downstream TLS session ID to file and gRPC access logger.
* access log: added a new field for route name to file and gRPC access logger.
* access log: added a new field for response code details in :ref:`file access logger<config_access_log_format_response_code_details>` and :ref:`gRPC access logger<envoy_api_field_data.accesslog.v2.HTTPResponseProperties.response_code_details>`.
* admin: the administration interface now includes a :ref:`/ready endpoint <operations_admin_interface>` for easier readiness checks.
* admin: extend :ref:`/runtime_modify endpoint <operations_admin_interface_runtime_modify>` to support parameters within the request body.
* api: track and report requests issued since last load report.
* build: releases are built with Clang and linked with LLD.
* dubbo_proxy: support the :ref:`Dubbo proxy filter <config_network_filters_dubbo_proxy>`.
* eds: added support to specify max time for which endpoints can be used :ref:`gRPC filter <envoy_api_msg_ClusterLoadAssignment.Policy>`.
* event: added :ref:`loop duration and poll delay statistics <operations_performance>`.
* ext_authz: added a `x-envoy-auth-partial-body` metadata header set to `false|true` indicating if there is a partial body sent in the authorization request message.
* ext_authz: added configurable status code that allows customizing HTTP responses on filter check status errors.
* ext_authz: added option to `ext_authz` that allows the filter clearing route cache.
* filter: exposed functions to Lua to verify digital signature.
* grpc-json: added support for :ref:`auto mapping
<envoy_api_field_config.filter.http.transcoder.v2.GrpcJsonTranscoder.auto_mapping>`.
* health check: added :ref:`initial jitter <envoy_api_field_core.HealthCheck.initial_jitter>` to add jitter to the first health check in order to prevent thundering herd on Envoy startup.
* hot restart: stats are no longer shared between hot restart parent/child via shared memory, but rather by RPC. Hot restart version incremented to 11.
* http: fixed a bug where large unbufferable responses were not tracked in stats and logs correctly.
* http: fixed a crashing bug where gRPC local replies would cause segfaults when upstream access logging was on.
* http: mitigated a race condition with the :ref:`delayed_close_timeout<envoy_api_field_config.filter.network.http_connection_manager.v2.HttpConnectionManager.delayed_close_timeout>` where it could trigger while actively flushing a pending write buffer for a downstream connection.
* http: changed `sendLocalReply` to send percent-encoded `GrpcMessage`.
* jwt_authn: make filter's parsing of JWT more flexible, allowing syntax like ``jwt=eyJhbGciOiJS...ZFnFIw,extra=7,realm=123``
* original_src filter: added the :ref:`filter<config_http_filters_original_src>`.
* rbac: migrated from v2alpha to v2.
* redis: add support for Redis cluster custom cluster type.
* redis: added :ref:`prefix routing <envoy_api_field_config.filter.network.redis_proxy.v2.RedisProxy.prefix_routes>` to enable routing commands based on their key's prefix to different upstream.
* redis: add support for zpopmax and zpopmin commands.
* redis: added
:ref:`max_buffer_size_before_flush <envoy_api_field_config.filter.network.redis_proxy.v2.RedisProxy.ConnPoolSettings.max_buffer_size_before_flush>` to batch commands together until the encoder buffer hits a certain size, and
:ref:`buffer_flush_timeout <envoy_api_field_config.filter.network.redis_proxy.v2.RedisProxy.ConnPoolSettings.buffer_flush_timeout>` to control how quickly the buffer is flushed if it is not full.
* redis: added auth support :ref:`downstream_auth_password <envoy_api_field_config.filter.network.redis_proxy.v2.RedisProxy.downstream_auth_password>` for downstream client authentication, and :ref:`auth_password <envoy_api_field_config.filter.network.redis_proxy.v2.RedisProtocolOptions.auth_password>` to configure authentication passwords for upstream server clusters.
* router: add support for configuring a :ref:`grpc timeout offset <envoy_api_field_route.RouteAction.grpc_timeout_offset>` on incoming requests.
* router: added ability to control retry back-off intervals via :ref:`retry policy <envoy_api_msg_route.RetryPolicy.RetryBackOff>`.
* router: added ability to issue a hedged retry in response to a per try timeout via a :ref:`hedge policy <envoy_api_msg_route.HedgePolicy>`.
* router: added a route name field to each http route in route.Route list
* router: per try timeouts will no longer start before the downstream request has been received
in full by the router. This ensures that the per try timeout does not account for slow
downstreams and that will not start before the global timeout.
* runtime: added support for :ref:`flexible layering configuration
<envoy_api_field_config.bootstrap.v2.Bootstrap.layered_runtime>`.
* runtime: added support for statically :ref:`specifying the runtime in the bootstrap configuration
<envoy_api_field_config.bootstrap.v2.Runtime.base>`.
* sandbox: added :ref:`CSRF sandbox <install_sandboxes_csrf>`.
* server: ``--define manual_stamp=manual_stamp`` was added to allow server stamping outside of binary rules.
more info in the `bazel docs <https://github.com/envoyproxy/envoy/blob/master/bazel/README.md#enabling-optional-features>`_.
* tool: added :repo:`proto <test/tools/router_check/validation.proto>` support for :ref:`router check tool <install_tools_route_table_check_tool>` tests.
* tracing: add trace sampling configuration to the route, to override the route level.
* upstream: added :ref:`upstream_cx_pool_overflow <config_cluster_manager_cluster_stats>` for the connection pool circuit breaker.
* upstream: an EDS management server can now force removal of a host that is still passing active
health checking by first marking the host as failed via EDS health check and subsequently removing
it in a future update. This is a mechanism to work around a race condition in which an EDS
implementation may remove a host before it has stopped passing active HC, thus causing the host
to become stranded until a future update.
* upstream: added :ref:`an option <envoy_api_field_Cluster.CommonLbConfig.ignore_new_hosts_until_first_hc>`
that allows ignoring new hosts for the purpose of load balancing calculations until they have
been health checked for the first time.
* upstream: added runtime error checking to prevent setting dns type to STRICT_DNS or LOGICAL_DNS when custom resolver name is specified.

1.10.0 (Apr 5, 2019)
====================
Expand Down
1 change: 0 additions & 1 deletion source/extensions/filters/common/lua/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ envoy_cc_library(
hdrs = ["lua.h"],
external_deps = [
"luajit",
"ssl",
],
deps = [
"//include/envoy/thread_local:thread_local_interface",
Expand Down
130 changes: 0 additions & 130 deletions source/extensions/filters/http/lua/lua_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,6 @@
#include "common/common/enum_to_int.h"
#include "common/http/message_impl.h"

#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "openssl/base64.h"
#include "openssl/bytestring.h"
#include "openssl/evp.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
Expand Down Expand Up @@ -433,129 +426,6 @@ int StreamHandleWrapper::luaLogCritical(lua_State* state) {
return 0;
}

const EVP_MD* StreamHandleWrapper::getDigest(const absl::string_view& name) {
std::string hash = absl::AsciiStrToLower(name);

// Hash Hash algorithms set refers
// https://github.com/google/boringssl/blob/ff62b38b4b5a0e7926034b5f93d0c276e55b571d/include/openssl/digest.h
if (hash == "md4") {
return EVP_md4();
} else if (hash == "md5") {
return EVP_md5();
} else if (hash == "sha1") {
return EVP_sha1();
} else if (hash == "sha224") {
return EVP_sha224();
} else if (hash == "sha256") {
return EVP_sha256();
} else if (hash == "sha384") {
return EVP_sha384();
} else if (hash == "sha512") {
return EVP_sha512();
} else if (hash == "md5_sha1") {
return EVP_md5_sha1();
} else {
return nullptr;
}
}

int StreamHandleWrapper::luaVerifySignature(lua_State* state) {
// Step 1: get public key
auto ptr = lua_touserdata(state, 2);
auto key = reinterpret_cast<EVP_PKEY*>(ptr);

// Step 2: initialize EVP_MD_CTX
EVP_MD_CTX* ctx = EVP_MD_CTX_new();

// Step 3: initialize EVP_MD
absl::string_view hash_func = luaL_checkstring(state, 3);
const EVP_MD* md = getDigest(hash_func);

if (md == nullptr) {
lua_pushboolean(state, false);
std::string err_msg = absl::StrCat(hash_func, " is not supported.");
lua_pushlstring(state, err_msg.data(), err_msg.length());
EVP_MD_CTX_free(ctx);
return 2;
}

// Step 4: initialize EVP_DigestVerify
int ok = EVP_DigestVerifyInit(ctx, nullptr, md, nullptr, key);
if (!ok) {
lua_pushboolean(state, false);
absl::string_view err_msg = "Failed to initialize digest verify.";
lua_pushlstring(state, err_msg.data(), err_msg.length());
EVP_MD_CTX_free(ctx);
return 2;
}

// Step 5: verify signature
const char* signature = luaL_checkstring(state, 4);
int sigLen = luaL_checknumber(state, 5);
absl::string_view sig(signature, sigLen);

const char* clearText = luaL_checkstring(state, 6);
int textLen = luaL_checknumber(state, 7);
absl::string_view text(clearText, textLen);

ok = EVP_DigestVerify(ctx, reinterpret_cast<const uint8_t*>(sig.data()), sig.length(),
reinterpret_cast<const uint8_t*>(text.data()), text.length());

// Step 6: check result
if (ok == 1) {
lua_pushboolean(state, true);
lua_pushnil(state);
EVP_MD_CTX_free(ctx);
return 2;
}

lua_pushboolean(state, false);
std::string err_msg = absl::StrCat("Failed to verify digest. Error code: ", ok);
lua_pushlstring(state, err_msg.data(), err_msg.length());
EVP_MD_CTX_free(ctx);
return 2;
}

int StreamHandleWrapper::luaDecodeBase64(lua_State* state) {
// Get input string
absl::string_view str = luaL_checkstring(state, 2);
std::string output;

bool ok = absl::Base64Unescape(str, &output);

if (ok) {
lua_pushlstring(state, output.data(), output.length());
} else {
// If decode failed, push a nil into stack.
lua_pushnil(state);
}

return 1;
}

int StreamHandleWrapper::luaImportPublicKey(lua_State* state) {
// Get byte array and the length.
const char* str = luaL_checkstring(state, 2);
int n = luaL_checknumber(state, 3);

absl::string_view keyder(str, n);
CBS cbs({reinterpret_cast<const uint8_t*>(keyder.data()), keyder.length()});
EVP_PKEY* key = EVP_parse_public_key(&cbs);
if (key == nullptr) {
lua_pushnil(state);
} else {
lua_pushlightuserdata(state, key);
}
return 1;
}

int StreamHandleWrapper::luaReleasePublicKey(lua_State* state) {
auto ptr = lua_touserdata(state, 2);
auto key = reinterpret_cast<EVP_PKEY*>(ptr);
EVP_PKEY_free(key);
return 0;
}

FilterConfig::FilterConfig(const std::string& lua_code, ThreadLocal::SlotAllocator& tls,
Upstream::ClusterManager& cluster_manager)
: cluster_manager_(cluster_manager), lua_state_(lua_code, tls) {
Expand Down
66 changes: 8 additions & 58 deletions source/extensions/filters/http/lua/lua_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
#include "extensions/filters/http/lua/wrappers.h"
#include "extensions/filters/http/well_known_names.h"

#include "openssl/evp.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
Expand Down Expand Up @@ -129,25 +127,14 @@ class StreamHandleWrapper : public Filters::Common::Lua::BaseLuaObject<StreamHan
}

static ExportedFunctions exportedFunctions() {
return {{"headers", static_luaHeaders},
{"body", static_luaBody},
{"bodyChunks", static_luaBodyChunks},
{"trailers", static_luaTrailers},
{"metadata", static_luaMetadata},
{"logTrace", static_luaLogTrace},
{"logDebug", static_luaLogDebug},
{"logInfo", static_luaLogInfo},
{"logWarn", static_luaLogWarn},
{"logErr", static_luaLogErr},
{"logCritical", static_luaLogCritical},
{"httpCall", static_luaHttpCall},
{"respond", static_luaRespond},
{"streamInfo", static_luaStreamInfo},
{"connection", static_luaConnection},
{"decodeBase64", static_luaDecodeBase64},
{"importPublicKey", static_luaImportPublicKey},
{"releasePublicKey", static_luaReleasePublicKey},
{"verifySignature", static_luaVerifySignature}};
return {{"headers", static_luaHeaders}, {"body", static_luaBody},
{"bodyChunks", static_luaBodyChunks}, {"trailers", static_luaTrailers},
{"metadata", static_luaMetadata}, {"logTrace", static_luaLogTrace},
{"logDebug", static_luaLogDebug}, {"logInfo", static_luaLogInfo},
{"logWarn", static_luaLogWarn}, {"logErr", static_luaLogErr},
{"logCritical", static_luaLogCritical}, {"httpCall", static_luaHttpCall},
{"respond", static_luaRespond}, {"streamInfo", static_luaStreamInfo},
{"connection", static_luaConnection}};
}

private:
Expand Down Expand Up @@ -222,50 +209,13 @@ class StreamHandleWrapper : public Filters::Common::Lua::BaseLuaObject<StreamHan
DECLARE_LUA_FUNCTION(StreamHandleWrapper, luaLogErr);
DECLARE_LUA_FUNCTION(StreamHandleWrapper, luaLogCritical);

/**
* Verify cryptographic signatures.
* @param 1 (void*) pointer to public key
* @param 2 (string) hash function(including MD4, MD5, SHA1, SHA224, SHA256, SHA384, SHA512,
* MD5_SHA1)
* @param 3 (string) signature
* @param 4 (int) length of signature
* @param 5 (string) clear text
* @param 6 (int) length of clear text
* @return (bool, string) If the first element is true, the second element is empty; otherwise,
* the second element stores the error message
*/
DECLARE_LUA_FUNCTION(StreamHandleWrapper, luaVerifySignature);

/**
* Decode string encoded in base64.
* @param 1 (string) string encoded in base64
* @return nil or raw string
*/
DECLARE_LUA_FUNCTION(StreamHandleWrapper, luaDecodeBase64);

/**
* Import public key.
* @param 1 (string) keyder string
* @param 2 (int) length of keyder string
* @return pointer to public key
*/
DECLARE_LUA_FUNCTION(StreamHandleWrapper, luaImportPublicKey);

/**
* Release public key.
* @param 1 (void*) pointer to public key
*/
DECLARE_LUA_FUNCTION(StreamHandleWrapper, luaReleasePublicKey);

/**
* This is the closure/iterator returned by luaBodyChunks() above.
*/
DECLARE_LUA_CLOSURE(StreamHandleWrapper, luaBodyIterator);

static Http::HeaderMapPtr buildHeadersFromTable(lua_State* state, int table_index);

static const EVP_MD* getDigest(const absl::string_view& hash_name);

// Filters::Common::Lua::BaseLuaObject
void onMarkDead() override {
// Headers/body/trailers wrappers do not survive any yields. The user can request them
Expand Down
Loading