Minor fixes for unix domain sockets

* Improved user input checking and error handling for code from #320.
* Added some guards for unlinking socket file in server init and destroy
  functions.
* Added peer name handling for AF_UNIX type connections in HTTP handling
  code.
This commit is contained in:
KLuka 2015-07-06 22:01:40 +02:00
parent c7b41ad4ce
commit c6186530bb
2 changed files with 36 additions and 17 deletions

View file

@ -287,6 +287,14 @@ static char *getPeerName(int fd, int *port, int numericHosts) {
} }
return NULL; return NULL;
} }
char *ret;
if (peerAddr.sa_family == AF_UNIX) {
if (port) {
*port = 0;
}
check(ret = strdup("localhost"));
return ret;
}
char host[256]; char host[256];
if (numericHosts || if (numericHosts ||
getnameinfo(&peerAddr, sockLen, host, sizeof(host), NULL, 0, NI_NOFQDN)){ getnameinfo(&peerAddr, sockLen, host, sizeof(host), NULL, 0, NI_NOFQDN)){
@ -297,7 +305,6 @@ static char *getPeerName(int fd, int *port, int numericHosts) {
if (port) { if (port) {
*port = ntohs(((struct sockaddr_in *)&peerAddr)->sin_port); *port = ntohs(((struct sockaddr_in *)&peerAddr)->sin_port);
} }
char *ret;
check(ret = strdup(host)); check(ret = strdup(host));
return ret; return ret;
} }

View file

@ -140,12 +140,12 @@ 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 unixDomainUser;
int unixDomainGroup; int unixDomainGroup;
int unixDomainChmod; int unixDomainChmod;
char unixDomainSocket[UNIX_PATH_MAX];
struct PayLoad { struct PayLoad {
int (*handler)(struct HttpConnection *, void *, const char *, int); int (*handler)(struct HttpConnection *, void *, const char *, int);
@ -291,27 +291,36 @@ void initServer(struct Server *server, int localhostOnly, int portMin,
int true = 1; int true = 1;
if (unixDomainSocket[0]) { if (*unixDomainSocket) {
server->serverFd = socket(AF_UNIX, SOCK_STREAM, 0);
server->serverFd = socket(AF_UNIX, 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,
&true, sizeof(true))); &true, sizeof(true)));
struct sockaddr_un serverAddr = { 0 };
unlink(unixDomainSocket); struct stat st;
if (!stat(unixDomainSocket, &st) && S_ISSOCK(st.st_mode)) {
serverAddr.sun_family = AF_UNIX; unlink(unixDomainSocket);
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)); struct sockaddr_un serverAddr = { 0 };
check(!chmod(unixDomainSocket, unixDomainChmod)); 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! [%d: %s]", errno, strerror(errno));
}
if (chown(unixDomainSocket, unixDomainUser, unixDomainGroup)) {
fatal("Unable to change ownership on unix socket!");
}
if (chmod(unixDomainSocket, unixDomainChmod)) {
fatal("Unable to change premission on unix socket!");
}
check(!listen(server->serverFd, SOMAXCONN)); check(!listen(server->serverFd, SOMAXCONN));
info("Listening on unix domain socket %s", unixDomainSocket);
check(server->pollFds = malloc(sizeof(struct pollfd))); check(server->pollFds = malloc(sizeof(struct pollfd)));
server->pollFds->fd = server->serverFd; server->pollFds->fd = server->serverFd;
server->pollFds->events = POLLIN; server->pollFds->events = POLLIN;
@ -387,7 +396,10 @@ void destroyServer(struct Server *server) {
destroyTrie(&server->handlers); destroyTrie(&server->handlers);
destroySSL(&server->ssl); destroySSL(&server->ssl);
if (unixDomainSocket[0]) unlink(unixDomainSocket); struct stat st;
if (*unixDomainSocket && !stat(unixDomainSocket, &st) && S_ISSOCK(st.st_mode)) {
unlink(unixDomainSocket);
}
} }
} }