Browse Source

add socket support to ggate{d,c}. This will use a local unix socket

for communication instead of TCP.  This allows you to forward the
connection over ssh in a secure maner.  Though you can forward TCP
sessions over ssh, it doesn't implement authentication, so ANYONE
on the box could end up accessing the disks.  With socks you can use
file system permissions to restrict them.
tags/ggatessh-v1.0.0
John-Mark Gurney 5 years ago
parent
commit
1973d4d2e2
3 changed files with 166 additions and 41 deletions
  1. +53
    -18
      ggatec/ggatec.c
  2. +69
    -23
      ggated/ggated.c
  3. +44
    -0
      tests/ggate_test.sh

+ 53
- 18
ggatec/ggatec.c View File

@@ -49,6 +49,7 @@
#include <sys/syslog.h>
#include <sys/time.h>
#include <sys/bio.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
@@ -56,6 +57,7 @@
#include <geom/gate/g_gate.h>
#include "ggate.h"

static const char *sockprefix = "sock:";

static enum { UNSET, CREATE, DESTROY, LIST, RESCUE } action = UNSET;

@@ -246,37 +248,70 @@ handshake(int dir)
struct g_gate_version ver;
struct g_gate_cinit cinit;
struct g_gate_sinit sinit;
struct sockaddr_in serv;
struct sockaddr *serv;
struct sockaddr_in inaddr;
struct sockaddr_un unixaddr;
socklen_t addrlen;
int sfd;
const char *sockname;

sockname = NULL;

/*
* Do the network stuff.
*/
bzero(&serv, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = g_gate_str2ip(host);
if (serv.sin_addr.s_addr == INADDR_NONE) {
g_gate_log(LOG_DEBUG, "Invalid IP/host name: %s.", host);
return (-1);
}
serv.sin_port = htons(port);
sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd == -1) {
g_gate_log(LOG_DEBUG, "Cannot open socket: %s.",
strerror(errno));
return (-1);
}
if (strncmp(host, sockprefix, strlen(sockprefix)) == 0) {
sockname = host + strlen(sockprefix);
if (strlen(sockname) + 1 > sizeof(unixaddr.sun_path)) {
g_gate_log(LOG_DEBUG, "Socket path is too long.");
return (-1);
}

g_gate_socket_settings(sfd);
unixaddr = (struct sockaddr_un) {
.sun_len = sizeof(unixaddr),
.sun_family = AF_UNIX,
};
strncpy(unixaddr.sun_path, sockname, sizeof(unixaddr.sun_path));
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd == -1) {
g_gate_log(LOG_DEBUG, "Cannot open socket: %s.",
strerror(errno));
return (-1);
}
serv = (struct sockaddr *)&unixaddr;
addrlen = sizeof unixaddr;
} else {
bzero(&inaddr, sizeof(inaddr));
inaddr.sin_family = AF_INET;
inaddr.sin_addr.s_addr = g_gate_str2ip(host);
if (inaddr.sin_addr.s_addr == INADDR_NONE) {
g_gate_log(LOG_DEBUG, "Invalid IP/host name: %s.", host);
return (-1);
}
inaddr.sin_port = htons(port);
sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd == -1) {
g_gate_log(LOG_DEBUG, "Cannot open socket: %s.",
strerror(errno));
return (-1);
}

if (connect(sfd, (struct sockaddr *)&serv, sizeof(serv)) == -1) {
serv = (struct sockaddr *)&inaddr;
addrlen = sizeof inaddr;
g_gate_socket_settings(sfd);
}

if (connect(sfd, serv, addrlen) == -1) {
g_gate_log(LOG_DEBUG, "Cannot connect to server: %s.",
strerror(errno));
close(sfd);
return (-1);
}

g_gate_log(LOG_INFO, "Connected to the server: %s:%d.", host, port);
if (sockname != NULL)
g_gate_log(LOG_INFO, "Connected to socket: %s.", sockname);
else
g_gate_log(LOG_INFO, "Connected to the server: %s:%d.", host, port);

/*
* Create and send version packet.


+ 69
- 23
ggated/ggated.c View File

@@ -37,6 +37,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -96,7 +97,6 @@ struct ggd_export {

static const char *exports_file = GGATED_EXPORT_FILE;
static int got_sighup = 0;
static in_addr_t bindaddr;

static TAILQ_HEAD(, ggd_request) inqueue = TAILQ_HEAD_INITIALIZER(inqueue);
static TAILQ_HEAD(, ggd_request) outqueue = TAILQ_HEAD_INITIALIZER(outqueue);
@@ -115,7 +115,7 @@ usage(void)
{

fprintf(stderr, "usage: %s [-nv] [-a address] [-F pidfile] [-p port] "
"[-R rcvbuf] [-S sndbuf] [exports file]\n", getprogname());
"[-R rcvbuf] [-S sndbuf] [-s socket] [exports file]\n", getprogname());
exit(EXIT_FAILURE);
}

@@ -948,21 +948,76 @@ huphandler(int sig __unused)
got_sighup = 1;
}

/*
* If sockaddr is not NULL, bind to the Unix domain socket at sockname,
* otherwise bind to the INET addr:port
*/
static int
bindsocket(in_addr_t bindaddr, int port, char *sockname)
{
struct sockaddr_un unixaddr;
struct sockaddr_in serv;
int sfd;

g_gate_log(LOG_INFO, "binding socket");

if (sockname != NULL) {
if (strlen(sockname) + 1 > sizeof(unixaddr.sun_path))
g_gate_xlog("Socket path is too long.");

sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd == -1)
g_gate_xlog("Cannot open stream socket: %s.", strerror(errno));
unixaddr = (struct sockaddr_un) {
.sun_len = sizeof(unixaddr),
.sun_family = AF_UNIX,
};
strncpy(unixaddr.sun_path, sockname, sizeof(unixaddr.sun_path));

if (bind(sfd, (struct sockaddr *)&unixaddr, sizeof(unixaddr)) == -1)
g_gate_xlog("bind(): %s.", strerror(errno));
if (listen(sfd, 5) == -1)
g_gate_xlog("listen(): %s.", strerror(errno));

g_gate_log(LOG_INFO, "Listen on path: %s.", sockname);
} else {
sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd == -1)
g_gate_xlog("Cannot open stream socket: %s.", strerror(errno));
bzero(&serv, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = bindaddr;
serv.sin_port = htons(port);

g_gate_socket_settings(sfd);

if (bind(sfd, (struct sockaddr *)&serv, sizeof(serv)) == -1)
g_gate_xlog("bind(): %s.", strerror(errno));
if (listen(sfd, 5) == -1)
g_gate_xlog("listen(): %s.", strerror(errno));

g_gate_log(LOG_INFO, "Listen on port: %d.", port);
}

return sfd;
}

int
main(int argc, char *argv[])
{
const char *ggated_pidfile = _PATH_VARRUN "/ggated.pid";
char *sockname = NULL;
struct pidfh *pfh;
struct sockaddr_in serv;
struct sockaddr from;
socklen_t fromlen;
in_addr_t bindaddr;
pid_t otherpid;
int ch, sfd, tmpsfd;
unsigned port;

bindaddr = htonl(INADDR_ANY);
port = G_GATE_PORT;
while ((ch = getopt(argc, argv, "a:hnp:F:R:S:v")) != -1) {
while ((ch = getopt(argc, argv, "a:hnp:F:R:S:s:v")) != -1) {
switch (ch) {
case 'a':
bindaddr = g_gate_str2ip(optarg);
@@ -995,6 +1050,9 @@ main(int argc, char *argv[])
if (sndbuf == 0 && errno != 0)
errx(EXIT_FAILURE, "Invalid sndbuf.");
break;
case 's':
sockname = strdup(optarg);
break;
case 'v':
g_gate_verbose++;
break;
@@ -1019,33 +1077,21 @@ main(int argc, char *argv[])
err(EXIT_FAILURE, "Cannot open/create pidfile");
}

signal(SIGCHLD, SIG_IGN);

sfd = bindsocket(bindaddr, port, sockname);

if (!g_gate_verbose) {
FILE *t = fopen("local.log", "w");
/* Run in daemon mode. */
if (daemon(0, 0) == -1)
g_gate_xlog("Cannot daemonize: %s", strerror(errno));

stderr = t;
}

pidfile_write(pfh);

signal(SIGCHLD, SIG_IGN);

sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd == -1)
g_gate_xlog("Cannot open stream socket: %s.", strerror(errno));
bzero(&serv, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = bindaddr;
serv.sin_port = htons(port);

g_gate_socket_settings(sfd);

if (bind(sfd, (struct sockaddr *)&serv, sizeof(serv)) == -1)
g_gate_xlog("bind(): %s.", strerror(errno));
if (listen(sfd, 5) == -1)
g_gate_xlog("listen(): %s.", strerror(errno));

g_gate_log(LOG_INFO, "Listen on port: %d.", port);

signal(SIGHUP, huphandler);

for (;;) {


+ 44
- 0
tests/ggate_test.sh View File

@@ -123,11 +123,55 @@ ggatel_md_cleanup()
common_cleanup
}

atf_test_case ggate_sock cleanup
ggate_sock_head()
{
atf_set "descr" "ggatec can connect to ggated over unix domain socket"
atf_set "require.progs" "ggatec ggated"
atf_set "require.user" "root"
atf_set "timeout" 5
}

ggate_sock_body()
{
load_ggate

us=$(alloc_ggate_dev)
work=$(alloc_md)
src=$(alloc_md)

atf_check -e ignore -o ignore \
dd if=/dev/random of=/dev/$work bs=1m count=1 conv=notrunc
atf_check -e ignore -o ignore \
dd if=/dev/random of=/dev/$src bs=1m count=1 conv=notrunc

echo $CONF >> $PLAINFILES
echo "0.0.0.0 RW /dev/$work" > $CONF

atf_check ggated -s local.sock -F $PIDFILE $CONF
atf_check ggatec create -u $us sock:"$(pwd)/local.sock" /dev/$work

ggate_dev=/dev/ggate${us}

wait_for_ggate_device ${ggate_dev}

atf_check -e ignore -o ignore \
dd if=/dev/${src} of=${ggate_dev} bs=1m count=1 conv=notrunc

checksum /dev/$src /dev/$work
}

ggate_sock_cleanup()
{
common_cleanup
}

atf_init_test_cases()
{
atf_add_test_case ggated
atf_add_test_case ggatel_file
atf_add_test_case ggatel_md
atf_add_test_case ggate_sock
}

alloc_ggate_dev()


Loading…
Cancel
Save