Unix domain sockets support.
The socket is not removed on shutdown, but the rest seems to work.
This commit is contained in:
parent
8f38e7873b
commit
4d8ec30100
3 changed files with 93 additions and 0 deletions
|
@ -52,7 +52,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
@ -138,8 +140,13 @@ int x_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
|
|||
#define poll x_poll
|
||||
#endif
|
||||
|
||||
char unixDomainSocket[UNIX_PATH_MAX];
|
||||
time_t currentTime;
|
||||
|
||||
int unixDomainUser;
|
||||
int unixDomainGroup;
|
||||
int unixDomainChmod;
|
||||
|
||||
struct PayLoad {
|
||||
int (*handler)(struct HttpConnection *, void *, const char *, int);
|
||||
void *arg;
|
||||
|
@ -283,6 +290,38 @@ void initServer(struct Server *server, int localhostOnly, int portMin,
|
|||
server->numConnections = 0;
|
||||
|
||||
int true = 1;
|
||||
|
||||
if (unixDomainSocket[0]) {
|
||||
server->serverFd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
check(server->serverFd >= 0);
|
||||
check(!setsockopt(server->serverFd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&true, sizeof(true)));
|
||||
struct sockaddr_un serverAddr = { 0 };
|
||||
|
||||
unlink(unixDomainSocket);
|
||||
|
||||
serverAddr.sun_family = AF_UNIX;
|
||||
strcpy(serverAddr.sun_path, unixDomainSocket);
|
||||
int servlen = sizeof(serverAddr.sun_family) + strlen(unixDomainSocket);
|
||||
|
||||
if (bind(server->serverFd, (struct sockaddr *)&serverAddr, servlen)) {
|
||||
fatal("Failed to bind to unix socket");
|
||||
}
|
||||
|
||||
check(!chown(unixDomainSocket, unixDomainUser, unixDomainGroup));
|
||||
check(!chmod(unixDomainSocket, unixDomainChmod));
|
||||
|
||||
check(!listen(server->serverFd, SOMAXCONN));
|
||||
check(server->pollFds = malloc(sizeof(struct pollfd)));
|
||||
server->pollFds->fd = server->serverFd;
|
||||
server->pollFds->events = POLLIN;
|
||||
|
||||
initTrie(&server->handlers, serverDestroyHandlers, NULL);
|
||||
serverRegisterStreamingHttpHandler(server, "/quit", serverQuitHandler, NULL);
|
||||
initSSL(&server->ssl);
|
||||
return;
|
||||
}
|
||||
|
||||
server->serverFd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
check(server->serverFd >= 0);
|
||||
check(!setsockopt(server->serverFd, SOL_SOCKET, SO_REUSEADDR,
|
||||
|
@ -347,6 +386,8 @@ void destroyServer(struct Server *server) {
|
|||
free(server->pollFds);
|
||||
destroyTrie(&server->handlers);
|
||||
destroySSL(&server->ssl);
|
||||
|
||||
if (unixDomainSocket[0]) unlink(unixDomainSocket);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,15 @@
|
|||
#include "libhttp/http.h"
|
||||
#include "libhttp/ssl.h"
|
||||
|
||||
#ifndef UNIX_PATH_MAX
|
||||
#define UNIX_PATH_MAX 108
|
||||
#endif
|
||||
|
||||
extern int unixDomainUser;
|
||||
extern int unixDomainGroup;
|
||||
extern int unixDomainChmod;
|
||||
extern char unixDomainSocket[UNIX_PATH_MAX];
|
||||
|
||||
struct Server;
|
||||
|
||||
struct ServerConnection {
|
||||
|
|
|
@ -61,6 +61,9 @@
|
|||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_SYS_PRCTL_H
|
||||
|
@ -68,6 +71,7 @@
|
|||
#endif
|
||||
|
||||
#include "libhttp/http.h"
|
||||
#include "libhttp/server.h"
|
||||
#include "logging/logging.h"
|
||||
#include "shellinabox/externalfile.h"
|
||||
#include "shellinabox/launcher.h"
|
||||
|
@ -785,6 +789,7 @@ static void usage(void) {
|
|||
" -s, --service=SERVICE define one or more services\n"
|
||||
"%s"
|
||||
" -q, --quiet turn off all messages\n"
|
||||
" --unixdomain-only=PATH:USER:GROUP:CHMOD listen on unix socket\n"
|
||||
" -u, --user=UID switch to this user (default: %s)\n"
|
||||
" --user-css=STYLES defines user-selectable CSS options\n"
|
||||
" -v, --verbose enable logging messages\n"
|
||||
|
@ -891,6 +896,7 @@ static void parseArgs(int argc, char * const argv[]) {
|
|||
{ "disable-ssl", 0, 0, 't' },
|
||||
{ "disable-ssl-menu", 0, 0, 0 },
|
||||
{ "quiet", 0, 0, 'q' },
|
||||
{ "unixdomain-only", 1, 0, 0, },
|
||||
{ "user", 1, 0, 'u' },
|
||||
{ "user-css", 1, 0, 0 },
|
||||
{ "verbose", 0, 0, 'v' },
|
||||
|
@ -1126,6 +1132,43 @@ static void parseArgs(int argc, char * const argv[]) {
|
|||
}
|
||||
verbosity = MSG_QUIET;
|
||||
logSetLogLevel(verbosity);
|
||||
} else if (!idx--) {
|
||||
// Unix domain only
|
||||
if (!optarg || !*optarg) {
|
||||
fatal("Option \"--unixdomain-only\" expects an argument.");
|
||||
}
|
||||
char *ptr, *s, *tmp;
|
||||
|
||||
s = optarg;
|
||||
ptr = strchr(s, ':');
|
||||
if (ptr == NULL) {
|
||||
fatal("Syntax error in unixdomain-only definition \"%s\".", optarg);
|
||||
}
|
||||
check(ptr - s < UNIX_PATH_MAX);
|
||||
memcpy(unixDomainSocket, s, ptr - s);
|
||||
unixDomainSocket[ptr - s] = '\000';
|
||||
|
||||
s = ptr + 1;
|
||||
ptr = strchr(s, ':');
|
||||
if (ptr == NULL) {
|
||||
fatal("Syntax error in unixdomain-only definition \"%s\".", optarg);
|
||||
}
|
||||
check(tmp = strndup(s, ptr - s));
|
||||
unixDomainUser = parseUserArg(tmp, NULL);
|
||||
free(tmp);
|
||||
|
||||
s = ptr + 1;
|
||||
ptr = strchr(s, ':');
|
||||
if (ptr == NULL) {
|
||||
fatal("Syntax error in unixdomain-only definition \"%s\".", optarg);
|
||||
}
|
||||
check(tmp = strndup(s, ptr - s));
|
||||
unixDomainGroup = parseGroupArg(tmp, NULL);
|
||||
free(tmp);
|
||||
|
||||
s = ptr + 1;
|
||||
unixDomainChmod = strtol(s, NULL, 0);
|
||||
|
||||
} else if (!idx--) {
|
||||
// User
|
||||
if (runAsUser >= 0) {
|
||||
|
|
Loading…
Reference in a new issue