Add a fuzzer for ssl server side

pull/8642/head
yang-g 8 years ago
parent 3b476d4d3e
commit 31e2128571
  1. 70
      Makefile
  2. 13
      build.yaml
  3. 154
      test/core/security/ssl_server_fuzzer.c
  4. 44
      tools/fuzzer/runners/ssl_server_fuzzer.sh
  5. 35
      tools/run_tests/sources_and_headers.json

@ -1019,6 +1019,7 @@ set_initial_connect_string_test: $(BINDIR)/$(CONFIG)/set_initial_connect_string_
sockaddr_resolver_test: $(BINDIR)/$(CONFIG)/sockaddr_resolver_test
sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test
socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test
ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer
tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test
tcp_posix_test: $(BINDIR)/$(CONFIG)/tcp_posix_test
tcp_server_posix_test: $(BINDIR)/$(CONFIG)/tcp_server_posix_test
@ -1183,6 +1184,7 @@ nanopb_fuzzer_serverlist_test_one_entry: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serve
percent_decode_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer_one_entry
percent_encode_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer_one_entry
server_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/server_fuzzer_one_entry
ssl_server_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer_one_entry
uri_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry
run_dep_checks:
@ -1411,6 +1413,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/percent_decode_fuzzer_one_entry \
$(BINDIR)/$(CONFIG)/percent_encode_fuzzer_one_entry \
$(BINDIR)/$(CONFIG)/server_fuzzer_one_entry \
$(BINDIR)/$(CONFIG)/ssl_server_fuzzer_one_entry \
$(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry \
@ -10779,6 +10782,38 @@ endif
endif
SSL_SERVER_FUZZER_SRC = \
test/core/security/ssl_server_fuzzer.c \
SSL_SERVER_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SSL_SERVER_FUZZER_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/ssl_server_fuzzer: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/ssl_server_fuzzer: $(SSL_SERVER_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(SSL_SERVER_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/ssl_server_fuzzer
endif
$(OBJDIR)/$(CONFIG)/test/core/security/ssl_server_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_ssl_server_fuzzer: $(SSL_SERVER_FUZZER_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(SSL_SERVER_FUZZER_OBJS:.o=.dep)
endif
endif
TCP_CLIENT_POSIX_TEST_SRC = \
test/core/iomgr/tcp_client_posix_test.c \
@ -16225,6 +16260,41 @@ endif
endif
SSL_SERVER_FUZZER_ONE_ENTRY_SRC = \
test/core/security/ssl_server_fuzzer.c \
test/core/util/one_corpus_entry_fuzzer.c \
SSL_SERVER_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SSL_SERVER_FUZZER_ONE_ENTRY_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/ssl_server_fuzzer_one_entry: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/ssl_server_fuzzer_one_entry: $(SSL_SERVER_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(SSL_SERVER_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/ssl_server_fuzzer_one_entry
endif
$(OBJDIR)/$(CONFIG)/test/core/security/ssl_server_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_ssl_server_fuzzer_one_entry: $(SSL_SERVER_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(SSL_SERVER_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
endif
endif
URI_FUZZER_TEST_ONE_ENTRY_SRC = \
test/core/client_channel/uri_fuzzer_test.c \
test/core/util/one_corpus_entry_fuzzer.c \

@ -2554,6 +2554,19 @@ targets:
- mac
- linux
- posix
- name: ssl_server_fuzzer
build: fuzzer
language: c
src:
- test/core/security/ssl_server_fuzzer.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
corpus_dirs:
- test/core/security/corpus/ssl_server_corpus
maxlen: 2048
- name: tcp_client_posix_test
cpu_cost: 0.5
build: test

@ -0,0 +1,154 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/transport/security_connector.h"
#include "test/core/util/memory_counters.h"
#include "test/core/util/mock_endpoint.h"
bool squelch = true;
// ssl has an array of global gpr_mu's that are never released.
// Turning this on will fail the leak check.
bool leak_check = false;
#define SSL_CERT_PATH "src/core/lib/tsi/test_creds/server1.pem"
#define SSL_KEY_PATH "src/core/lib/tsi/test_creds/server1.key"
#define SSL_CA_PATH "src/core/lib/tsi/test_creds/ca.pem"
static void discard_write(gpr_slice slice) {}
static void dont_log(gpr_log_func_args *args) {}
struct handshake_state {
bool done_callback_called;
};
static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
grpc_security_status status,
grpc_endpoint *secure_endpoint,
grpc_auth_context *auth_context) {
struct handshake_state *state = (struct handshake_state *)statep;
GPR_ASSERT(state->done_callback_called == false);
state->done_callback_called = true;
// The fuzzer should not pass the handshake.
GPR_ASSERT(status != GRPC_SECURITY_OK);
GPR_ASSERT(secure_endpoint == NULL);
GPR_ASSERT(auth_context == NULL);
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
struct grpc_memory_counters counters;
if (squelch) gpr_set_log_function(dont_log);
if (leak_check) grpc_memory_counters_init();
grpc_init();
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_resource_quota *resource_quota =
grpc_resource_quota_create("ssl_server_fuzzer");
grpc_endpoint *mock_endpoint =
grpc_mock_endpoint_create(discard_write, resource_quota);
grpc_resource_quota_internal_unref(&exec_ctx, resource_quota);
grpc_mock_endpoint_put_read(
&exec_ctx, mock_endpoint,
gpr_slice_from_copied_buffer((const char *)data, size));
// Load key pair and establish server SSL credentials.
grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
gpr_slice ca_slice, cert_slice, key_slice;
GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
const char *ca_cert = (const char *)GPR_SLICE_START_PTR(ca_slice);
pem_key_cert_pair.private_key = (const char *)GPR_SLICE_START_PTR(key_slice);
pem_key_cert_pair.cert_chain = (const char *)GPR_SLICE_START_PTR(cert_slice);
grpc_server_credentials *creds = grpc_ssl_server_credentials_create(
ca_cert, &pem_key_cert_pair, 1, 0, NULL);
// Create security connector
grpc_server_security_connector *sc = NULL;
grpc_security_status status =
grpc_server_credentials_create_security_connector(creds, &sc);
GPR_ASSERT(status == GRPC_SECURITY_OK);
sc->channel_args = NULL;
gpr_timespec deadline = gpr_time_add(
gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_seconds(1, GPR_TIMESPAN));
struct handshake_state state;
state.done_callback_called = false;
grpc_server_security_connector_do_handshake(
&exec_ctx, sc, NULL, mock_endpoint, NULL, deadline,
on_secure_handshake_done, &state);
grpc_exec_ctx_flush(&exec_ctx);
bool mock_endpoint_shutdown = false;
// If the given string happens to be part of the correct client hello, the
// server will wait for more data. Explicitly fail the server by shutting down
// the endpoint.
if (!state.done_callback_called) {
mock_endpoint_shutdown = true;
grpc_endpoint_shutdown(&exec_ctx, mock_endpoint);
grpc_exec_ctx_flush(&exec_ctx);
}
GPR_ASSERT(state.done_callback_called);
GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "test");
grpc_server_credentials_release(creds);
gpr_slice_unref(cert_slice);
gpr_slice_unref(key_slice);
gpr_slice_unref(ca_slice);
// grpc_endpoint_destroy has been called in handshake failure handling code.
if (!mock_endpoint_shutdown) {
grpc_endpoint_shutdown(&exec_ctx, mock_endpoint);
grpc_exec_ctx_flush(&exec_ctx);
}
grpc_exec_ctx_flush(&exec_ctx);
grpc_shutdown();
if (leak_check) {
counters = grpc_memory_counters_snapshot();
grpc_memory_counters_destroy();
GPR_ASSERT(counters.total_size_relative == 0);
}
return 0;
}

@ -0,0 +1,44 @@
#!/bin/bash
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
if [ "$jobs" != "1" ]
then
flags="-jobs=$jobs -workers=$jobs $flags"
fi
if [ "$config" == "asan-trace-cmp" ]
then
flags="-use_traces=1 $flags"
fi
bins/$config/ssl_server_fuzzer $flags fuzzer_output test/core/security/corpus/ssl_server_corpus

@ -1909,6 +1909,23 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "ssl_server_fuzzer",
"src": [
"test/core/security/ssl_server_fuzzer.c"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -4782,6 +4799,24 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "ssl_server_fuzzer_one_entry",
"src": [
"test/core/security/ssl_server_fuzzer.c",
"test/core/util/one_corpus_entry_fuzzer.c"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",

Loading…
Cancel
Save