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 <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -138,8 +140,13 @@ int x_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
|
||||||
#define poll x_poll
|
#define poll x_poll
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char unixDomainSocket[UNIX_PATH_MAX];
|
||||||
time_t currentTime;
|
time_t currentTime;
|
||||||
|
|
||||||
|
int unixDomainUser;
|
||||||
|
int unixDomainGroup;
|
||||||
|
int unixDomainChmod;
|
||||||
|
|
||||||
struct PayLoad {
|
struct PayLoad {
|
||||||
int (*handler)(struct HttpConnection *, void *, const char *, int);
|
int (*handler)(struct HttpConnection *, void *, const char *, int);
|
||||||
void *arg;
|
void *arg;
|
||||||
|
@ -283,6 +290,38 @@ void initServer(struct Server *server, int localhostOnly, int portMin,
|
||||||
server->numConnections = 0;
|
server->numConnections = 0;
|
||||||
|
|
||||||
int true = 1;
|
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);
|
server->serverFd = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
check(server->serverFd >= 0);
|
check(server->serverFd >= 0);
|
||||||
check(!setsockopt(server->serverFd, SOL_SOCKET, SO_REUSEADDR,
|
check(!setsockopt(server->serverFd, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
@ -347,6 +386,8 @@ void destroyServer(struct Server *server) {
|
||||||
free(server->pollFds);
|
free(server->pollFds);
|
||||||
destroyTrie(&server->handlers);
|
destroyTrie(&server->handlers);
|
||||||
destroySSL(&server->ssl);
|
destroySSL(&server->ssl);
|
||||||
|
|
||||||
|
if (unixDomainSocket[0]) unlink(unixDomainSocket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,15 @@
|
||||||
#include "libhttp/http.h"
|
#include "libhttp/http.h"
|
||||||
#include "libhttp/ssl.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 Server;
|
||||||
|
|
||||||
struct ServerConnection {
|
struct ServerConnection {
|
||||||
|
|
|
@ -61,6 +61,9 @@
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifdef HAVE_SYS_PRCTL_H
|
#ifdef HAVE_SYS_PRCTL_H
|
||||||
|
@ -68,6 +71,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "libhttp/http.h"
|
#include "libhttp/http.h"
|
||||||
|
#include "libhttp/server.h"
|
||||||
#include "logging/logging.h"
|
#include "logging/logging.h"
|
||||||
#include "shellinabox/externalfile.h"
|
#include "shellinabox/externalfile.h"
|
||||||
#include "shellinabox/launcher.h"
|
#include "shellinabox/launcher.h"
|
||||||
|
@ -785,6 +789,7 @@ static void usage(void) {
|
||||||
" -s, --service=SERVICE define one or more services\n"
|
" -s, --service=SERVICE define one or more services\n"
|
||||||
"%s"
|
"%s"
|
||||||
" -q, --quiet turn off all messages\n"
|
" -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"
|
" -u, --user=UID switch to this user (default: %s)\n"
|
||||||
" --user-css=STYLES defines user-selectable CSS options\n"
|
" --user-css=STYLES defines user-selectable CSS options\n"
|
||||||
" -v, --verbose enable logging messages\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", 0, 0, 't' },
|
||||||
{ "disable-ssl-menu", 0, 0, 0 },
|
{ "disable-ssl-menu", 0, 0, 0 },
|
||||||
{ "quiet", 0, 0, 'q' },
|
{ "quiet", 0, 0, 'q' },
|
||||||
|
{ "unixdomain-only", 1, 0, 0, },
|
||||||
{ "user", 1, 0, 'u' },
|
{ "user", 1, 0, 'u' },
|
||||||
{ "user-css", 1, 0, 0 },
|
{ "user-css", 1, 0, 0 },
|
||||||
{ "verbose", 0, 0, 'v' },
|
{ "verbose", 0, 0, 'v' },
|
||||||
|
@ -1126,6 +1132,43 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
}
|
}
|
||||||
verbosity = MSG_QUIET;
|
verbosity = MSG_QUIET;
|
||||||
logSetLogLevel(verbosity);
|
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--) {
|
} else if (!idx--) {
|
||||||
// User
|
// User
|
||||||
if (runAsUser >= 0) {
|
if (runAsUser >= 0) {
|
||||||
|
|
Loading…
Reference in a new issue