nghttpx: Add --verify-client option
This option requires client certificate and successful verification. Use --cacert option to add CA certificates as necessary.
This commit is contained in:
parent
1835bda02e
commit
02acfd7d70
21
src/shrpx.cc
21
src/shrpx.cc
|
@ -417,6 +417,7 @@ void fill_default_config()
|
||||||
mod_config()->write_rate = 0;
|
mod_config()->write_rate = 0;
|
||||||
mod_config()->write_burst = 0;
|
mod_config()->write_burst = 0;
|
||||||
mod_config()->npn_list = nullptr;
|
mod_config()->npn_list = nullptr;
|
||||||
|
mod_config()->verify_client = false;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -593,6 +594,7 @@ void print_help(std::ostream& out)
|
||||||
<< " comma only and any white spaces are treated\n"
|
<< " comma only and any white spaces are treated\n"
|
||||||
<< " as a part of protocol string.\n"
|
<< " as a part of protocol string.\n"
|
||||||
<< " Default: " << DEFAULT_NPN_LIST << "\n"
|
<< " Default: " << DEFAULT_NPN_LIST << "\n"
|
||||||
|
<< " --verify-client Require and verify client certificate.\n"
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< " HTTP/2.0 and SPDY:\n"
|
<< " HTTP/2.0 and SPDY:\n"
|
||||||
<< " -c, --spdy-max-concurrent-streams=<NUM>\n"
|
<< " -c, --spdy-max-concurrent-streams=<NUM>\n"
|
||||||
|
@ -730,6 +732,7 @@ int main(int argc, char **argv)
|
||||||
{"write-rate", required_argument, &flag, 36},
|
{"write-rate", required_argument, &flag, 36},
|
||||||
{"write-burst", required_argument, &flag, 37},
|
{"write-burst", required_argument, &flag, 37},
|
||||||
{"npn-list", required_argument, &flag, 38},
|
{"npn-list", required_argument, &flag, 38},
|
||||||
|
{"verify-client", no_argument, &flag, 39},
|
||||||
{nullptr, 0, nullptr, 0 }
|
{nullptr, 0, nullptr, 0 }
|
||||||
};
|
};
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
@ -933,6 +936,10 @@ int main(int argc, char **argv)
|
||||||
// --npn-list
|
// --npn-list
|
||||||
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_NPN_LIST, optarg));
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_NPN_LIST, optarg));
|
||||||
break;
|
break;
|
||||||
|
case 39:
|
||||||
|
// --verify-client
|
||||||
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_VERIFY_CLIENT, "yes"));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -975,6 +982,20 @@ int main(int argc, char **argv)
|
||||||
parse_config_npn_list(DEFAULT_NPN_LIST);
|
parse_config_npn_list(DEFAULT_NPN_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!get_config()->subcerts.empty()) {
|
||||||
|
mod_config()->cert_tree = ssl::cert_lookup_tree_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& keycert : get_config()->subcerts) {
|
||||||
|
auto ssl_ctx = ssl::create_ssl_context(keycert.first.c_str(),
|
||||||
|
keycert.second.c_str());
|
||||||
|
if(ssl::cert_lookup_tree_add_cert_from_file
|
||||||
|
(get_config()->cert_tree, ssl_ctx, keycert.second.c_str()) == -1) {
|
||||||
|
LOG(FATAL) << "Failed to add sub certificate.";
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(get_config()->cert_file && get_config()->private_key_file) {
|
if(get_config()->cert_file && get_config()->private_key_file) {
|
||||||
mod_config()->default_ssl_ctx =
|
mod_config()->default_ssl_ctx =
|
||||||
ssl::create_ssl_context(get_config()->private_key_file,
|
ssl::create_ssl_context(get_config()->private_key_file,
|
||||||
|
|
|
@ -100,6 +100,7 @@ const char SHRPX_OPT_READ_BURST[] = "read-burst";
|
||||||
const char SHRPX_OPT_WRITE_RATE[] = "write-rate";
|
const char SHRPX_OPT_WRITE_RATE[] = "write-rate";
|
||||||
const char SHRPX_OPT_WRITE_BURST[] = "write-burst";
|
const char SHRPX_OPT_WRITE_BURST[] = "write-burst";
|
||||||
const char SHRPX_OPT_NPN_LIST[] = "npn-list";
|
const char SHRPX_OPT_NPN_LIST[] = "npn-list";
|
||||||
|
const char SHRPX_OPT_VERIFY_CLIENT[] = "verify-client";
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
Config *config = nullptr;
|
Config *config = nullptr;
|
||||||
|
@ -335,14 +336,7 @@ int parse_config(const char *opt, const char *optarg)
|
||||||
if(sp) {
|
if(sp) {
|
||||||
std::string keyfile(optarg, sp);
|
std::string keyfile(optarg, sp);
|
||||||
// TODO Do we need private key for subcert?
|
// TODO Do we need private key for subcert?
|
||||||
auto ssl_ctx = ssl::create_ssl_context(keyfile.c_str(), sp+1);
|
mod_config()->subcerts.emplace_back(keyfile, sp+1);
|
||||||
if(!get_config()->cert_tree) {
|
|
||||||
mod_config()->cert_tree = ssl::cert_lookup_tree_new();
|
|
||||||
}
|
|
||||||
if(ssl::cert_lookup_tree_add_cert_from_file(get_config()->cert_tree,
|
|
||||||
ssl_ctx, sp+1) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if(util::strieq(opt, SHRPX_OPT_SYSLOG)) {
|
} else if(util::strieq(opt, SHRPX_OPT_SYSLOG)) {
|
||||||
mod_config()->syslog = util::strieq(optarg, "yes");
|
mod_config()->syslog = util::strieq(optarg, "yes");
|
||||||
|
@ -413,6 +407,8 @@ int parse_config(const char *opt, const char *optarg)
|
||||||
mod_config()->write_burst = strtoul(optarg, nullptr, 10);
|
mod_config()->write_burst = strtoul(optarg, nullptr, 10);
|
||||||
} else if(util::strieq(opt, SHRPX_OPT_NPN_LIST)) {
|
} else if(util::strieq(opt, SHRPX_OPT_NPN_LIST)) {
|
||||||
parse_config_npn_list(optarg);
|
parse_config_npn_list(optarg);
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_VERIFY_CLIENT)) {
|
||||||
|
mod_config()->verify_client = util::strieq(optarg, "yes");
|
||||||
} else if(util::strieq(opt, "conf")) {
|
} else if(util::strieq(opt, "conf")) {
|
||||||
LOG(WARNING) << "conf is ignored";
|
LOG(WARNING) << "conf is ignored";
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -91,6 +91,7 @@ extern const char SHRPX_OPT_READ_BURST[];
|
||||||
extern const char SHRPX_OPT_WRITE_RATE[];
|
extern const char SHRPX_OPT_WRITE_RATE[];
|
||||||
extern const char SHRPX_OPT_WRITE_BURST[];
|
extern const char SHRPX_OPT_WRITE_BURST[];
|
||||||
extern const char SHRPX_OPT_NPN_LIST[];
|
extern const char SHRPX_OPT_NPN_LIST[];
|
||||||
|
extern const char SHRPX_OPT_VERIFY_CLIENT[];
|
||||||
|
|
||||||
union sockaddr_union {
|
union sockaddr_union {
|
||||||
sockaddr sa;
|
sockaddr sa;
|
||||||
|
@ -184,6 +185,8 @@ struct Config {
|
||||||
char **npn_list;
|
char **npn_list;
|
||||||
// The number of elements in npn_list
|
// The number of elements in npn_list
|
||||||
size_t npn_list_len;
|
size_t npn_list_len;
|
||||||
|
// The list of (private key file, certificate file) pair
|
||||||
|
std::vector<std::pair<std::string, std::string>> subcerts;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Config* get_config();
|
const Config* get_config();
|
||||||
|
|
|
@ -73,9 +73,14 @@ int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
||||||
namespace {
|
namespace {
|
||||||
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
||||||
{
|
{
|
||||||
// We don't verify the client certificate. Just request it for the
|
if(!preverify_ok) {
|
||||||
// testing purpose.
|
int err = X509_STORE_CTX_get_error(ctx);
|
||||||
return 1;
|
int depth = X509_STORE_CTX_get_error_depth(ctx);
|
||||||
|
LOG(ERROR) << "client certificate verify error:num=" << err << ":"
|
||||||
|
<< X509_verify_cert_error_string(err)
|
||||||
|
<< ":depth=" << depth;
|
||||||
|
}
|
||||||
|
return preverify_ok;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -213,6 +218,19 @@ SSL_CTX* create_ssl_context(const char *private_key_file,
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
if(get_config()->verify_client) {
|
if(get_config()->verify_client) {
|
||||||
|
if(SSL_CTX_set_default_verify_paths(ssl_ctx) != 1) {
|
||||||
|
LOG(WARNING) << "Could not load system trusted ca certificates: "
|
||||||
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
|
}
|
||||||
|
if(get_config()->cacert) {
|
||||||
|
if(SSL_CTX_load_verify_locations(ssl_ctx, get_config()->cacert, nullptr)
|
||||||
|
!= 1) {
|
||||||
|
LOG(FATAL) << "Could not load trusted ca certificates from "
|
||||||
|
<< get_config()->cacert << ": "
|
||||||
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
|
DIE();
|
||||||
|
}
|
||||||
|
}
|
||||||
SSL_CTX_set_verify(ssl_ctx,
|
SSL_CTX_set_verify(ssl_ctx,
|
||||||
SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE |
|
SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE |
|
||||||
SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
|
||||||
|
|
Loading…
Reference in New Issue