[shrpx] read private key's passwd from a file
This avoids the need to provide the password for your private key interactively. It can be used via --private-key-passwd-file or private-key-passwd-file in the given config file. The first line in the file (without \n) will be treated as the passwd. There isn't any validation and all lines after the first one (if any) are ignored. The security model behind this is a bit simplistic so I am open to better ideas. Basically your password file should be root:root (700) and you *should* drop root and run as an unprivileged user. If the file exists and a line can be read then a callback will be set for the SSL ctxt and it'll feed the passwd when the private key is read (if password is needed). If the file exists with the wrong permisions it'll be logged and ignored.
This commit is contained in:
parent
f97110f092
commit
cbf8ccf7d1
12
src/shrpx.cc
12
src/shrpx.cc
|
@ -312,6 +312,7 @@ void fill_default_config()
|
||||||
set_config_str(&mod_config()->host, "0.0.0.0");
|
set_config_str(&mod_config()->host, "0.0.0.0");
|
||||||
mod_config()->port = 3000;
|
mod_config()->port = 3000;
|
||||||
mod_config()->private_key_file = 0;
|
mod_config()->private_key_file = 0;
|
||||||
|
mod_config()->private_key_passwd = 0;
|
||||||
mod_config()->cert_file = 0;
|
mod_config()->cert_file = 0;
|
||||||
|
|
||||||
// Read timeout for SPDY upstream connection
|
// Read timeout for SPDY upstream connection
|
||||||
|
@ -465,6 +466,11 @@ void print_help(std::ostream& out)
|
||||||
<< " linked OpenSSL is configured to load system\n"
|
<< " linked OpenSSL is configured to load system\n"
|
||||||
<< " wide certificates, they are loaded\n"
|
<< " wide certificates, they are loaded\n"
|
||||||
<< " at startup regardless of this option.\n"
|
<< " at startup regardless of this option.\n"
|
||||||
|
<< " --private-key-passwd-file=<FILEPATH>\n"
|
||||||
|
<< " Path to file that contains password for the\n"
|
||||||
|
<< " server's private key. If none is given and\n"
|
||||||
|
<< " the private key is password protected it'll\n"
|
||||||
|
<< " be requested interactively."
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< " SPDY:\n"
|
<< " SPDY:\n"
|
||||||
<< " -c, --spdy-max-concurrent-streams=<NUM>\n"
|
<< " -c, --spdy-max-concurrent-streams=<NUM>\n"
|
||||||
|
@ -566,6 +572,7 @@ int main(int argc, char **argv)
|
||||||
{"cacert", required_argument, &flag, 19 },
|
{"cacert", required_argument, &flag, 19 },
|
||||||
{"backend-ipv4", no_argument, &flag, 20 },
|
{"backend-ipv4", no_argument, &flag, 20 },
|
||||||
{"backend-ipv6", no_argument, &flag, 21 },
|
{"backend-ipv6", no_argument, &flag, 21 },
|
||||||
|
{"private-key-passwd-file", required_argument, &flag, 22},
|
||||||
{0, 0, 0, 0 }
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
@ -703,6 +710,11 @@ int main(int argc, char **argv)
|
||||||
// --backend-ipv6
|
// --backend-ipv6
|
||||||
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_BACKEND_IPV6, "yes"));
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_BACKEND_IPV6, "yes"));
|
||||||
break;
|
break;
|
||||||
|
case 22:
|
||||||
|
// --private-key-passwd-file
|
||||||
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE,
|
||||||
|
optarg));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
@ -41,6 +44,7 @@ using namespace spdylay;
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
const char SHRPX_OPT_PRIVATE_KEY_FILE[] = "private-key-file";
|
const char SHRPX_OPT_PRIVATE_KEY_FILE[] = "private-key-file";
|
||||||
|
const char SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE[] = "private-key-passwd-file";
|
||||||
const char SHRPX_OPT_CERTIFICATE_FILE[] = "certificate-file";
|
const char SHRPX_OPT_CERTIFICATE_FILE[] = "certificate-file";
|
||||||
|
|
||||||
const char SHRPX_OPT_BACKEND[] = "backend";
|
const char SHRPX_OPT_BACKEND[] = "backend";
|
||||||
|
@ -125,6 +129,41 @@ int split_host_port(char *host, size_t hostlen, uint16_t *port_ptr,
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
bool is_secure(const char *filename)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
int rv = stat(filename, &buf);
|
||||||
|
if (rv == 0) {
|
||||||
|
if ((buf.st_mode & S_IRWXU) &&
|
||||||
|
!(buf.st_mode & S_IRWXG) &&
|
||||||
|
!(buf.st_mode & S_IRWXO)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string read_passwd_from_file(const char *filename)
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
if (!is_secure(filename)) {
|
||||||
|
LOG(ERROR) << "Private key passwd file " << filename
|
||||||
|
<< " has insecure mode.";
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream in(filename, std::ios::binary);
|
||||||
|
if(!in) {
|
||||||
|
LOG(ERROR) << "Could not open key passwd file " << filename;
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::getline(in, line);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
void set_config_str(char **destp, const char *val)
|
void set_config_str(char **destp, const char *val)
|
||||||
{
|
{
|
||||||
if(*destp) {
|
if(*destp) {
|
||||||
|
@ -221,6 +260,13 @@ int parse_config(const char *opt, const char *optarg)
|
||||||
mod_config()->gid = pwd->pw_gid;
|
mod_config()->gid = pwd->pw_gid;
|
||||||
} else if(util::strieq(opt, SHRPX_OPT_PRIVATE_KEY_FILE)) {
|
} else if(util::strieq(opt, SHRPX_OPT_PRIVATE_KEY_FILE)) {
|
||||||
set_config_str(&mod_config()->private_key_file, optarg);
|
set_config_str(&mod_config()->private_key_file, optarg);
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE)) {
|
||||||
|
std::string passwd = read_passwd_from_file(optarg);
|
||||||
|
if (passwd.empty()) {
|
||||||
|
LOG(ERROR) << "Couldn't read key file's passwd from " << optarg;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
set_config_str(&mod_config()->private_key_passwd, passwd.c_str());
|
||||||
} else if(util::strieq(opt, SHRPX_OPT_CERTIFICATE_FILE)) {
|
} else if(util::strieq(opt, SHRPX_OPT_CERTIFICATE_FILE)) {
|
||||||
set_config_str(&mod_config()->cert_file, optarg);
|
set_config_str(&mod_config()->cert_file, optarg);
|
||||||
} else if(util::strieq(opt, SHRPX_OPT_SYSLOG)) {
|
} else if(util::strieq(opt, SHRPX_OPT_SYSLOG)) {
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
extern const char SHRPX_OPT_PRIVATE_KEY_FILE[];
|
extern const char SHRPX_OPT_PRIVATE_KEY_FILE[];
|
||||||
|
extern const char SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE[];
|
||||||
extern const char SHRPX_OPT_CERTIFICATE_FILE[];
|
extern const char SHRPX_OPT_CERTIFICATE_FILE[];
|
||||||
|
|
||||||
extern const char SHRPX_OPT_BACKEND[];
|
extern const char SHRPX_OPT_BACKEND[];
|
||||||
|
@ -81,6 +82,7 @@ struct Config {
|
||||||
char *host;
|
char *host;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
char *private_key_file;
|
char *private_key_file;
|
||||||
|
char *private_key_passwd;
|
||||||
char *cert_file;
|
char *cert_file;
|
||||||
bool verify_client;
|
bool verify_client;
|
||||||
const char *server_name;
|
const char *server_name;
|
||||||
|
@ -136,6 +138,9 @@ int parse_config(const char *opt, const char *optarg);
|
||||||
// -1.
|
// -1.
|
||||||
int load_config(const char *filename);
|
int load_config(const char *filename);
|
||||||
|
|
||||||
|
// Read passwd from |filename|
|
||||||
|
std::string read_passwd_from_file(const char *filename);
|
||||||
|
|
||||||
// Copies NULL-terminated string |val| to |*destp|. If |*destp| is not
|
// Copies NULL-terminated string |val| to |*destp|. If |*destp| is not
|
||||||
// NULL, it is freed before copying.
|
// NULL, it is freed before copying.
|
||||||
void set_config_str(char **destp, const char *val);
|
void set_config_str(char **destp, const char *val);
|
||||||
|
|
|
@ -91,6 +91,22 @@ void set_npn_prefs(unsigned char *out, const char **protos, size_t len)
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
static int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data)
|
||||||
|
{
|
||||||
|
Config *config = (Config *)user_data;
|
||||||
|
int len = (int)strlen(config->private_key_passwd);
|
||||||
|
if (size < len + 1) {
|
||||||
|
LOG(ERROR) << "ssl_pem_passwd_cb: buf is too small " << size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(buf, config->private_key_passwd, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SSL_CTX* create_ssl_context()
|
SSL_CTX* create_ssl_context()
|
||||||
{
|
{
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
|
@ -118,6 +134,10 @@ SSL_CTX* create_ssl_context()
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
|
if (get_config()->private_key_passwd) {
|
||||||
|
SSL_CTX_set_default_passwd_cb(ssl_ctx, ssl_pem_passwd_cb);
|
||||||
|
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)get_config());
|
||||||
|
}
|
||||||
if(SSL_CTX_use_PrivateKey_file(ssl_ctx,
|
if(SSL_CTX_use_PrivateKey_file(ssl_ctx,
|
||||||
get_config()->private_key_file,
|
get_config()->private_key_file,
|
||||||
SSL_FILETYPE_PEM) != 1) {
|
SSL_FILETYPE_PEM) != 1) {
|
||||||
|
|
Loading…
Reference in New Issue