Allow SSL certificate and key to be passed in through a file handle.
git-svn-id: https://shellinabox.googlecode.com/svn/trunk@46 0da03de8-d603-11dd-86c2-0f8696b7b6f9
This commit is contained in:
parent
f16b2cb543
commit
e40a555cbf
9 changed files with 214 additions and 8 deletions
|
@ -94,6 +94,7 @@ int serverSupportsSSL();
|
||||||
void serverEnableSSL(Server *server, int flag);
|
void serverEnableSSL(Server *server, int flag);
|
||||||
void serverSetCertificate(Server *server, const char *filename,
|
void serverSetCertificate(Server *server, const char *filename,
|
||||||
int autoGenerateMissing);
|
int autoGenerateMissing);
|
||||||
|
void serverSetCertificateFd(Server *server, int fd);
|
||||||
void serverSetNumericHosts(Server *server, int numericHosts);
|
void serverSetNumericHosts(Server *server, int numericHosts);
|
||||||
|
|
||||||
void httpTransfer(HttpConnection *http, char *msg, int len);
|
void httpTransfer(HttpConnection *http, char *msg, int len);
|
||||||
|
|
|
@ -16,6 +16,7 @@ serverLoop
|
||||||
serverSupportsSSL
|
serverSupportsSSL
|
||||||
serverEnableSSL
|
serverEnableSSL
|
||||||
serverSetCertificate
|
serverSetCertificate
|
||||||
|
serverSetCertificateFd
|
||||||
serverSetNumericHosts
|
serverSetNumericHosts
|
||||||
httpTransfer
|
httpTransfer
|
||||||
httpTransferPartialReply
|
httpTransferPartialReply
|
||||||
|
|
|
@ -537,6 +537,10 @@ void serverSetCertificate(struct Server *server, const char *filename,
|
||||||
sslSetCertificate(&server->ssl, filename, autoGenerateMissing);
|
sslSetCertificate(&server->ssl, filename, autoGenerateMissing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serverSetCertificateFd(struct Server *server, int fd) {
|
||||||
|
sslSetCertificateFd(&server->ssl, fd);
|
||||||
|
}
|
||||||
|
|
||||||
void serverSetNumericHosts(struct Server *server, int numericHosts) {
|
void serverSetNumericHosts(struct Server *server, int numericHosts) {
|
||||||
server->numericHosts = numericHosts;
|
server->numericHosts = numericHosts;
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,7 @@ void serverLoop(struct Server *server);
|
||||||
void serverEnableSSL(struct Server *server, int flag);
|
void serverEnableSSL(struct Server *server, int flag);
|
||||||
void serverSetCertificate(struct Server *server, const char *filename,
|
void serverSetCertificate(struct Server *server, const char *filename,
|
||||||
int autoGenerateMissing);
|
int autoGenerateMissing);
|
||||||
|
void serverSetCertificateFd(struct Server *server, int fd);
|
||||||
void serverSetNumericHosts(struct Server *server, int numericHosts);
|
void serverSetNumericHosts(struct Server *server, int numericHosts);
|
||||||
struct Trie *serverGetHttpHandlers(struct Server *server);
|
struct Trie *serverGetHttpHandlers(struct Server *server);
|
||||||
|
|
||||||
|
|
156
libhttp/ssl.c
156
libhttp/ssl.c
|
@ -90,7 +90,11 @@ long (*SSL_CTX_ctrl)(SSL_CTX *, int, long, void *);
|
||||||
void (*SSL_CTX_free)(SSL_CTX *);
|
void (*SSL_CTX_free)(SSL_CTX *);
|
||||||
SSL_CTX * (*SSL_CTX_new)(SSL_METHOD *);
|
SSL_CTX * (*SSL_CTX_new)(SSL_METHOD *);
|
||||||
int (*SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
|
int (*SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
|
||||||
|
int (*SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *,
|
||||||
|
const unsigned char *, long);
|
||||||
int (*SSL_CTX_use_certificate_file)(SSL_CTX *, const char *, int);
|
int (*SSL_CTX_use_certificate_file)(SSL_CTX *, const char *, int);
|
||||||
|
int (*SSL_CTX_use_certificate_ASN1)(SSL_CTX *, long,
|
||||||
|
const unsigned char *);
|
||||||
long (*SSL_ctrl)(SSL *, int, long, void *);
|
long (*SSL_ctrl)(SSL *, int, long, void *);
|
||||||
void (*SSL_free)(SSL *);
|
void (*SSL_free)(SSL *);
|
||||||
int (*SSL_get_error)(const SSL *, int);
|
int (*SSL_get_error)(const SSL *, int);
|
||||||
|
@ -200,7 +204,9 @@ static void loadSSL(void) {
|
||||||
{ { &SSL_CTX_free }, "SSL_CTX_free" },
|
{ { &SSL_CTX_free }, "SSL_CTX_free" },
|
||||||
{ { &SSL_CTX_new }, "SSL_CTX_new" },
|
{ { &SSL_CTX_new }, "SSL_CTX_new" },
|
||||||
{ { &SSL_CTX_use_PrivateKey_file }, "SSL_CTX_use_PrivateKey_file" },
|
{ { &SSL_CTX_use_PrivateKey_file }, "SSL_CTX_use_PrivateKey_file" },
|
||||||
|
{ { &SSL_CTX_use_PrivateKey_ASN1 }, "SSL_CTX_use_PrivateKey_ASN1" },
|
||||||
{ { &SSL_CTX_use_certificate_file },"SSL_CTX_use_certificate_file"},
|
{ { &SSL_CTX_use_certificate_file },"SSL_CTX_use_certificate_file"},
|
||||||
|
{ { &SSL_CTX_use_certificate_ASN1 },"SSL_CTX_use_certificate_ASN1"},
|
||||||
{ { &SSL_ctrl }, "SSL_ctrl" },
|
{ { &SSL_ctrl }, "SSL_ctrl" },
|
||||||
{ { &SSL_free }, "SSL_free" },
|
{ { &SSL_free }, "SSL_free" },
|
||||||
{ { &SSL_get_error }, "SSL_get_error" },
|
{ { &SSL_get_error }, "SSL_get_error" },
|
||||||
|
@ -419,6 +425,156 @@ void sslSetCertificate(struct SSLSupport *ssl, const char *filename,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
static const unsigned char *sslSecureReadASCIIFileToMem(int fd) {
|
||||||
|
size_t inc = 16384;
|
||||||
|
size_t bufSize = inc;
|
||||||
|
size_t len = 0;
|
||||||
|
unsigned char *buf;
|
||||||
|
check((buf = malloc(bufSize)) != NULL);
|
||||||
|
for (;;) {
|
||||||
|
check(len < bufSize - 1);
|
||||||
|
size_t readLen = bufSize - len - 1;
|
||||||
|
ssize_t bytesRead = NOINTR(read(fd, buf + len, readLen));
|
||||||
|
if (bytesRead > 0) {
|
||||||
|
len += bytesRead;
|
||||||
|
}
|
||||||
|
if (bytesRead != readLen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instead of calling realloc(), allocate a new buffer, copy the data,
|
||||||
|
// and then clear the old buffer. This way, we are not accidentally
|
||||||
|
// leaving key material in memory.
|
||||||
|
unsigned char *newBuf;
|
||||||
|
check((newBuf = malloc(bufSize + inc)) != NULL);
|
||||||
|
memcpy(newBuf, buf, len);
|
||||||
|
memset(buf, 0, bufSize);
|
||||||
|
free(buf);
|
||||||
|
buf = newBuf;
|
||||||
|
bufSize += inc;
|
||||||
|
}
|
||||||
|
check(len < bufSize);
|
||||||
|
buf[len] = '\000';
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned char *sslPEMtoASN1(const unsigned char *pem,
|
||||||
|
const char *record,
|
||||||
|
long *size) {
|
||||||
|
*size = -1;
|
||||||
|
char *marker;
|
||||||
|
check((marker = stringPrintf(NULL, "-----BEGIN %s-----",record))!=NULL);
|
||||||
|
unsigned char *ptr = (unsigned char *)strstr((char *)pem, marker);
|
||||||
|
if (!ptr) {
|
||||||
|
free(marker);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
ptr += strlen(marker);
|
||||||
|
}
|
||||||
|
*marker = '\000';
|
||||||
|
check((marker = stringPrintf(marker, "-----END %s-----",record))!=NULL);
|
||||||
|
unsigned char *end = (unsigned char *)strstr((char *)ptr, marker);
|
||||||
|
free(marker);
|
||||||
|
if (!end) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
unsigned char *ret;
|
||||||
|
size_t maxSize = (((end - ptr)*6)+7)/8;
|
||||||
|
check((ret = malloc(maxSize)) != NULL);
|
||||||
|
unsigned char *out = ret;
|
||||||
|
unsigned bits = 0;
|
||||||
|
int count = 0;
|
||||||
|
while (ptr < end) {
|
||||||
|
unsigned char ch = *ptr++;
|
||||||
|
if (ch >= 'A' && ch <= 'Z') {
|
||||||
|
ch -= 'A';
|
||||||
|
} else if (ch >= 'a' && ch <= 'z') {
|
||||||
|
ch -= 'a' - 26;
|
||||||
|
} else if (ch >= '0' && ch <= '9') {
|
||||||
|
ch += 52 - '0';
|
||||||
|
} else if (ch == '+') {
|
||||||
|
ch += 62 - '+';
|
||||||
|
} else if (ch == '/') {
|
||||||
|
ch += 63 - '/';
|
||||||
|
} else if (ch == '=') {
|
||||||
|
while (ptr < end) {
|
||||||
|
if ((ch = *ptr++) != '=' && ch > ' ') {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (ch <= ' ') {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
err:
|
||||||
|
free(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
check(ch <= 63);
|
||||||
|
check(count >= 0);
|
||||||
|
check(count <= 6);
|
||||||
|
bits = (bits << 6) | ch;
|
||||||
|
count += 6;
|
||||||
|
if (count >= 8) {
|
||||||
|
*out++ = (bits >> (count -= 8)) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check(out - ret <= maxSize);
|
||||||
|
*size = out - ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void sslSetCertificateFd(struct SSLSupport *ssl, int fd) {
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
check(serverSupportsSSL());
|
||||||
|
check(fd >= 0);
|
||||||
|
check(ssl->sslContext = SSL_CTX_new(SSLv23_server_method()));
|
||||||
|
const unsigned char *data = sslSecureReadASCIIFileToMem(fd);
|
||||||
|
check(!NOINTR(close(fd)));
|
||||||
|
long dataSize = (long)strlen((const char *)data);
|
||||||
|
long certSize, rsaSize, dsaSize, ecSize;
|
||||||
|
const unsigned char *cert = sslPEMtoASN1(data, "CERTIFICATE", &certSize);
|
||||||
|
const unsigned char *rsa = sslPEMtoASN1(data, "RSA PRIVATE KEY", &rsaSize);
|
||||||
|
const unsigned char *dsa = sslPEMtoASN1(data, "DSA PRIVATE KEY", &dsaSize);
|
||||||
|
const unsigned char *ec = sslPEMtoASN1(data, "EC PRIVATE KEY", &ecSize);
|
||||||
|
if (!certSize || !(rsaSize > 0 || dsaSize > 0 || ecSize > 0) ||
|
||||||
|
!SSL_CTX_use_certificate_ASN1(ssl->sslContext, certSize, cert) ||
|
||||||
|
(rsaSize > 0 &&
|
||||||
|
!SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, ssl->sslContext, rsa,
|
||||||
|
rsaSize)) ||
|
||||||
|
(dsaSize > 0 &&
|
||||||
|
!SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_DSA, ssl->sslContext, dsa,
|
||||||
|
dsaSize)) ||
|
||||||
|
(ecSize > 0 &&
|
||||||
|
!SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC, ssl->sslContext, ec,
|
||||||
|
ecSize)) ||
|
||||||
|
!SSL_CTX_check_private_key(ssl->sslContext)) {
|
||||||
|
fatal("Cannot read valid certificate from fd %d. Check file format.", fd);
|
||||||
|
}
|
||||||
|
dcheck(!ERR_peek_error());
|
||||||
|
ERR_clear_error();
|
||||||
|
memset((char *)data, 0, dataSize);
|
||||||
|
free((char *)data);
|
||||||
|
memset((char *)cert, 0, certSize);
|
||||||
|
free((char *)cert);
|
||||||
|
if (rsaSize > 0) {
|
||||||
|
memset((char *)rsa, 0, rsaSize);
|
||||||
|
free((char *)rsa);
|
||||||
|
}
|
||||||
|
if (dsaSize > 0) {
|
||||||
|
memset((char *)dsa, 0, dsaSize);
|
||||||
|
free((char *)dsa);
|
||||||
|
}
|
||||||
|
if (ecSize > 0) {
|
||||||
|
memset((char *)ec, 0, ecSize);
|
||||||
|
free((char *)ec);
|
||||||
|
}
|
||||||
|
ssl->generateMissing = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int sslEnable(struct SSLSupport *ssl, int enabled) {
|
int sslEnable(struct SSLSupport *ssl, int enabled) {
|
||||||
int old = ssl->enabled;
|
int old = ssl->enabled;
|
||||||
ssl->enabled = enabled;
|
ssl->enabled = enabled;
|
||||||
|
|
|
@ -83,7 +83,11 @@ extern long (*x_SSL_CTX_ctrl)(SSL_CTX *, int, long, void *);
|
||||||
extern void (*x_SSL_CTX_free)(SSL_CTX *);
|
extern void (*x_SSL_CTX_free)(SSL_CTX *);
|
||||||
extern SSL_CTX*(*x_SSL_CTX_new)(SSL_METHOD *);
|
extern SSL_CTX*(*x_SSL_CTX_new)(SSL_METHOD *);
|
||||||
extern int (*x_SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
|
extern int (*x_SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
|
||||||
|
extern int (*x_SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *,
|
||||||
|
const unsigned char *, long);
|
||||||
extern int (*x_SSL_CTX_use_certificate_file)(SSL_CTX *, const char *, int);
|
extern int (*x_SSL_CTX_use_certificate_file)(SSL_CTX *, const char *, int);
|
||||||
|
extern int (*x_SSL_CTX_use_certificate_ASN1)(SSL_CTX *, long,
|
||||||
|
const unsigned char *);
|
||||||
extern long (*x_SSL_ctrl)(SSL *, int, long, void *);
|
extern long (*x_SSL_ctrl)(SSL *, int, long, void *);
|
||||||
extern void (*x_SSL_free)(SSL *);
|
extern void (*x_SSL_free)(SSL *);
|
||||||
extern int (*x_SSL_get_error)(const SSL *, int);
|
extern int (*x_SSL_get_error)(const SSL *, int);
|
||||||
|
@ -119,7 +123,9 @@ extern SSL_METHOD *(*x_SSLv23_server_method)(void);
|
||||||
#define SSL_CTX_free x_SSL_CTX_free
|
#define SSL_CTX_free x_SSL_CTX_free
|
||||||
#define SSL_CTX_new x_SSL_CTX_new
|
#define SSL_CTX_new x_SSL_CTX_new
|
||||||
#define SSL_CTX_use_PrivateKey_file x_SSL_CTX_use_PrivateKey_file
|
#define SSL_CTX_use_PrivateKey_file x_SSL_CTX_use_PrivateKey_file
|
||||||
|
#define SSL_CTX_use_PrivateKey_ASN1 x_SSL_CTX_use_PrivateKey_ASN1
|
||||||
#define SSL_CTX_use_certificate_file x_SSL_CTX_use_certificate_file
|
#define SSL_CTX_use_certificate_file x_SSL_CTX_use_certificate_file
|
||||||
|
#define SSL_CTX_use_certificate_ASN1 x_SSL_CTX_use_certificate_ASN1
|
||||||
#define SSL_ctrl x_SSL_ctrl
|
#define SSL_ctrl x_SSL_ctrl
|
||||||
#define SSL_free x_SSL_free
|
#define SSL_free x_SSL_free
|
||||||
#define SSL_get_error x_SSL_get_error
|
#define SSL_get_error x_SSL_get_error
|
||||||
|
@ -175,6 +181,7 @@ void deleteSSL(struct SSLSupport *ssl);
|
||||||
void sslGenerateCertificate(const char *certificate, const char *serverName);
|
void sslGenerateCertificate(const char *certificate, const char *serverName);
|
||||||
void sslSetCertificate(struct SSLSupport *ssl, const char *filename,
|
void sslSetCertificate(struct SSLSupport *ssl, const char *filename,
|
||||||
int autoGenerateMissing);
|
int autoGenerateMissing);
|
||||||
|
void sslSetCertificateFd(struct SSLSupport *ssl, int fd);
|
||||||
int sslEnable(struct SSLSupport *ssl, int enabled);
|
int sslEnable(struct SSLSupport *ssl, int enabled);
|
||||||
void sslBlockSigPipe();
|
void sslBlockSigPipe();
|
||||||
int sslUnblockSigPipe();
|
int sslUnblockSigPipe();
|
||||||
|
|
|
@ -1036,7 +1036,6 @@ int forkLauncher(void) {
|
||||||
// Temporarily drop most permissions. We still retain the ability to
|
// Temporarily drop most permissions. We still retain the ability to
|
||||||
// switch back to root, which is necessary for launching "login".
|
// switch back to root, which is necessary for launching "login".
|
||||||
lowerPrivileges();
|
lowerPrivileges();
|
||||||
NOINTR(close(pair[0]));
|
|
||||||
closeAllFds((int []){ pair[1] }, 1);
|
closeAllFds((int []){ pair[1] }, 1);
|
||||||
launcherDaemon(pair[1]);
|
launcherDaemon(pair[1]);
|
||||||
fatal("exit() failed!");
|
fatal("exit() failed!");
|
||||||
|
|
|
@ -78,6 +78,7 @@ static int noBeep = 0;
|
||||||
static int numericHosts = 0;
|
static int numericHosts = 0;
|
||||||
static int enableSSL = 1;
|
static int enableSSL = 1;
|
||||||
static char *certificateDir;
|
static char *certificateDir;
|
||||||
|
static int certificateFd = -1;
|
||||||
static HashMap *externalFiles;
|
static HashMap *externalFiles;
|
||||||
static Server *cgiServer;
|
static Server *cgiServer;
|
||||||
static char *cgiSessionKey;
|
static char *cgiSessionKey;
|
||||||
|
@ -592,7 +593,8 @@ static void usage(void) {
|
||||||
" ${user} - user name",
|
" ${user} - user name",
|
||||||
!serverSupportsSSL() ? "" :
|
!serverSupportsSSL() ? "" :
|
||||||
" -c, --cert=CERTDIR set certificate dir "
|
" -c, --cert=CERTDIR set certificate dir "
|
||||||
"(default: $PWD)\n",
|
"(default: $PWD)\n"
|
||||||
|
" --cert-fd=FD set certificate file from fd",
|
||||||
group, PORTNUM,
|
group, PORTNUM,
|
||||||
!serverSupportsSSL() ? "" :
|
!serverSupportsSSL() ? "" :
|
||||||
" -t, --disable-ssl disable transparent SSL support\n",
|
" -t, --disable-ssl disable transparent SSL support\n",
|
||||||
|
@ -623,6 +625,7 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
{ "help", 0, 0, 'h' },
|
{ "help", 0, 0, 'h' },
|
||||||
{ "background", 2, 0, 'b' },
|
{ "background", 2, 0, 'b' },
|
||||||
{ "cert", 1, 0, 'c' },
|
{ "cert", 1, 0, 'c' },
|
||||||
|
{ "cert-fd", 1, 0, 0 },
|
||||||
{ "cgi", 2, 0, 0 },
|
{ "cgi", 2, 0, 0 },
|
||||||
{ "debug", 0, 0, 'd' },
|
{ "debug", 0, 0, 'd' },
|
||||||
{ "static-file", 1, 0, 'f' },
|
{ "static-file", 1, 0, 'f' },
|
||||||
|
@ -670,10 +673,30 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
if (!hasSSL) {
|
if (!hasSSL) {
|
||||||
warn("Ignoring certificate directory, as SSL support is unavailable");
|
warn("Ignoring certificate directory, as SSL support is unavailable");
|
||||||
}
|
}
|
||||||
|
if (certificateFd) {
|
||||||
|
fatal("Cannot set both a certificate directory and file handle");
|
||||||
|
}
|
||||||
if (certificateDir) {
|
if (certificateDir) {
|
||||||
fatal("Only one certificate directory can be selected");
|
fatal("Only one certificate directory can be selected");
|
||||||
}
|
}
|
||||||
check(certificateDir = strdup(optarg));
|
check(certificateDir = strdup(optarg));
|
||||||
|
} else if (!idx--) {
|
||||||
|
// Certificate file descriptor
|
||||||
|
if (!hasSSL) {
|
||||||
|
warn("Ignoring certificate directory, as SSL support is unavailable");
|
||||||
|
}
|
||||||
|
if (certificateDir) {
|
||||||
|
fatal("Cannot set both a certificate directory and file handle");
|
||||||
|
}
|
||||||
|
if (certificateFd >= 0) {
|
||||||
|
fatal("Only one certificate file handle can be provided");
|
||||||
|
}
|
||||||
|
int tmpFd = strtoint(optarg, 3, INT_MAX);
|
||||||
|
certificateFd = dup(tmpFd);
|
||||||
|
if (certificateFd < 0) {
|
||||||
|
fatal("Invalid certificate file handle");
|
||||||
|
}
|
||||||
|
check(!NOINTR(close(tmpFd)));
|
||||||
} else if (!idx--) {
|
} else if (!idx--) {
|
||||||
// CGI
|
// CGI
|
||||||
if (demonize) {
|
if (demonize) {
|
||||||
|
@ -823,7 +846,7 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
char buf[40];
|
char buf[40];
|
||||||
NOINTR(write(fd, buf, snprintf(buf, 40, "%d", (int)getpid())));
|
NOINTR(write(fd, buf, snprintf(buf, 40, "%d", (int)getpid())));
|
||||||
NOINTR(close(fd));
|
check(!NOINTR(close(fd)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -902,7 +925,8 @@ int main(int argc, char * const argv[]) {
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
free(cgiRoot);
|
free(cgiRoot);
|
||||||
check(!NOINTR(close(fds[1])));
|
check(!NOINTR(close(fds[1])));
|
||||||
closeAllFds((int []){ launcherFd, serverGetFd(server) }, 2);
|
closeAllFds((int []){ launcherFd, serverGetFd(server),
|
||||||
|
certificateFd }, certificateFd >= 0 ? 3 : 2);
|
||||||
logSetLogLevel(MSG_QUIET);
|
logSetLogLevel(MSG_QUIET);
|
||||||
}
|
}
|
||||||
serverEnableSSL(server, enableSSL);
|
serverEnableSSL(server, enableSSL);
|
||||||
|
@ -910,7 +934,9 @@ int main(int argc, char * const argv[]) {
|
||||||
// Enable SSL support (if available)
|
// Enable SSL support (if available)
|
||||||
if (enableSSL) {
|
if (enableSSL) {
|
||||||
check(serverSupportsSSL());
|
check(serverSupportsSSL());
|
||||||
if (certificateDir) {
|
if (certificateFd >= 0) {
|
||||||
|
serverSetCertificateFd(server, certificateFd);
|
||||||
|
} else if (certificateDir) {
|
||||||
char *tmp;
|
char *tmp;
|
||||||
if (strchr(certificateDir, '%')) {
|
if (strchr(certificateDir, '%')) {
|
||||||
fatal("Invalid certificate directory name \"%s\".", certificateDir);
|
fatal("Invalid certificate directory name \"%s\".", certificateDir);
|
||||||
|
|
|
@ -52,6 +52,7 @@ shellinaboxd \- publish command line shell through AJAX interface
|
||||||
.B shellinaboxd
|
.B shellinaboxd
|
||||||
[\ \fB-b\fP\ | \fB--background\fP[\fB=\fP\fIpidfile\fP]\ ]
|
[\ \fB-b\fP\ | \fB--background\fP[\fB=\fP\fIpidfile\fP]\ ]
|
||||||
[\ \fB-c\fP\ | \fB--cert=\fP\fIcertdir\fP\ ]
|
[\ \fB-c\fP\ | \fB--cert=\fP\fIcertdir\fP\ ]
|
||||||
|
[\ \fB-c\fP\ | \fB--cert-fd=\fP\fIfd\fP\ ]
|
||||||
[\ \fB--cgi\fP[\fB=\fP\fIportrange\fP]\ ]
|
[\ \fB--cgi\fP[\fB=\fP\fIportrange\fP]\ ]
|
||||||
[\ \fB-d\fP\ | \fB--debug\fP\ ]
|
[\ \fB-d\fP\ | \fB--debug\fP\ ]
|
||||||
[\ \fB-f\fP\ | \fB--static-file=\fP\fIurl\fP:\fIfile\fP\ ]
|
[\ \fB-f\fP\ | \fB--static-file=\fP\fIurl\fP:\fIfile\fP\ ]
|
||||||
|
@ -138,6 +139,16 @@ certificate. Due to this usability problem, and due to the perceived
|
||||||
security implications, the use of auto-generated self-signed
|
security implications, the use of auto-generated self-signed
|
||||||
certificates is intended for testing or in intranet deployments, only.
|
certificates is intended for testing or in intranet deployments, only.
|
||||||
.TP
|
.TP
|
||||||
|
\fB--cert-fd=\fP\fIfd\fP
|
||||||
|
Instead of providing a
|
||||||
|
.B --cert
|
||||||
|
directory, it is also possible to provide a filedescriptor
|
||||||
|
.I fd
|
||||||
|
where the certificate and key can be retrieved. While this option disables
|
||||||
|
.B SNI
|
||||||
|
support, it does offer an alternative solution for securely providing
|
||||||
|
the private key data to the daemon.
|
||||||
|
.TP
|
||||||
\fB--cgi\fP[\fB=\fP\fIportrange\fP]
|
\fB--cgi\fP[\fB=\fP\fIportrange\fP]
|
||||||
Instead of running
|
Instead of running
|
||||||
.B shellinaboxd
|
.B shellinaboxd
|
||||||
|
|
Loading…
Reference in a new issue