Browse Source

add support for ro/wo and tests to verify this funcionality..

Also did some line wrapping..
tags/ggatessh-v1.0.0
John-Mark Gurney 4 years ago
parent
commit
349b114752
2 changed files with 238 additions and 63 deletions
  1. +120
    -53
      ggatessh/ggatessh.c
  2. +118
    -10
      tests/ggatessh_test.sh

+ 120
- 53
ggatessh/ggatessh.c View File

@@ -104,8 +104,10 @@ struct ggs_req {
TAILQ_ENTRY(ggs_req) r_next; TAILQ_ENTRY(ggs_req) r_next;
}; };


static TAILQ_HEAD(ggs_reqqueue, ggs_req) procqueue = TAILQ_HEAD_INITIALIZER(procqueue);
static TAILQ_HEAD(ggs_sessqueue, ggs_sess_cache) session_cache = TAILQ_HEAD_INITIALIZER(session_cache);
static TAILQ_HEAD(ggs_reqqueue, ggs_req) procqueue =
TAILQ_HEAD_INITIALIZER(procqueue);
static TAILQ_HEAD(ggs_sessqueue, ggs_sess_cache) session_cache =
TAILQ_HEAD_INITIALIZER(session_cache);
static sem_t nconn_sem; static sem_t nconn_sem;
static pthread_mutex_t procqueue_mtx; static pthread_mutex_t procqueue_mtx;


@@ -196,6 +198,22 @@ tcp_connect(const char *host, const char *service, int af)
return sd; return sd;
} }


static int
get_open_flags()
{

switch (flags) {
case G_GATE_FLAG_READONLY:
return LIBSSH2_FXF_READ;

case G_GATE_FLAG_WRITEONLY:
return LIBSSH2_FXF_WRITE;

default:
return LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE;
}
}

static struct ggs_connection static struct ggs_connection
make_connection(void) make_connection(void)
{ {
@@ -209,7 +227,8 @@ make_connection(void)
sockfd = tcp_connect(hostname, sshport, 0); sockfd = tcp_connect(hostname, sshport, 0);
if (sockfd == -1) { if (sockfd == -1) {
if (errno == ENOENT) if (errno == ENOENT)
g_gate_xlog("tcp_connect: failed to lookup %s", hostname);
g_gate_xlog("tcp_connect: failed to lookup %s",
hostname);
g_gate_xlog("tcp_connect: %s.", strerror(errno)); g_gate_xlog("tcp_connect: %s.", strerror(errno));
} }


@@ -218,11 +237,10 @@ make_connection(void)
if (session == NULL) if (session == NULL)
libssh2_errorx(session, "libssh2_session_init"); libssh2_errorx(session, "libssh2_session_init");


if (g_gate_verbose) {
//libssh2_trace(session, LIBSSH2_TRACE_SOCKET|LIBSSH2_TRACE_TRANS|LIBSSH2_TRACE_KEX|LIBSSH2_TRACE_AUTH|LIBSSH2_TRACE_CONN|LIBSSH2_TRACE_SFTP|LIBSSH2_TRACE_ERROR|LIBSSH2_TRACE_PUBLICKEY);
libssh2_trace(session, LIBSSH2_TRACE_SOCKET|LIBSSH2_TRACE_KEX|LIBSSH2_TRACE_AUTH|LIBSSH2_TRACE_CONN|LIBSSH2_TRACE_SFTP|LIBSSH2_TRACE_ERROR|LIBSSH2_TRACE_PUBLICKEY);
//libssh2_trace(session, LIBSSH2_TRACE_KEX|LIBSSH2_TRACE_AUTH|LIBSSH2_TRACE_CONN|LIBSSH2_TRACE_SFTP|LIBSSH2_TRACE_ERROR|LIBSSH2_TRACE_PUBLICKEY);
}
if (g_gate_verbose)
libssh2_trace(session, LIBSSH2_TRACE_SOCKET|LIBSSH2_TRACE_KEX|
LIBSSH2_TRACE_AUTH|LIBSSH2_TRACE_CONN|LIBSSH2_TRACE_SFTP|
LIBSSH2_TRACE_ERROR|LIBSSH2_TRACE_PUBLICKEY);


/* XXX - libssh2_session_flag to enable compression */ /* XXX - libssh2_session_flag to enable compression */


@@ -247,7 +265,8 @@ make_connection(void)


g_gate_log(LOG_DEBUG, "trying identity file: %s", identityfile); g_gate_log(LOG_DEBUG, "trying identity file: %s", identityfile);


rc = libssh2_userauth_publickey_fromfile(session, username, pubkeyfile, identityfile, NULL);
rc = libssh2_userauth_publickey_fromfile(session, username, pubkeyfile,
identityfile, NULL);
//rc = libssh2_userauth_password(session, "freebsd", "freebsd"); //rc = libssh2_userauth_password(session, "freebsd", "freebsd");
if (rc) { if (rc) {
g_gate_log(LOG_ERR, "identity file: %s", identityfile); g_gate_log(LOG_ERR, "identity file: %s", identityfile);
@@ -260,7 +279,7 @@ make_connection(void)
if (sftp_session == NULL) if (sftp_session == NULL)
g_gate_xlog("libssh2_sftp_init"); g_gate_xlog("libssh2_sftp_init");


handle = libssh2_sftp_open(sftp_session, imgpath, LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE, 0);
handle = libssh2_sftp_open(sftp_session, imgpath, get_open_flags(), 0);
if (handle == NULL) { if (handle == NULL) {
g_gate_log(LOG_ERR, "image file: %s", imgpath); g_gate_log(LOG_ERR, "image file: %s", imgpath);
libssh2_errorx(session, "libssh2_sftp_open"); libssh2_errorx(session, "libssh2_sftp_open");
@@ -291,7 +310,8 @@ mediachg(void *arg __unused)
.gctl_mediasize = mediasize, .gctl_mediasize = mediasize,
}; };
g_gate_ioctl(G_GATE_CMD_MODIFY, &ggiom); g_gate_ioctl(G_GATE_CMD_MODIFY, &ggiom);
g_gate_log(LOG_DEBUG, "updated ggate%d mediasize to %zd", unit, mediasize);
g_gate_log(LOG_DEBUG, "updated ggate%d mediasize to %zd", unit,
mediasize);


return NULL; return NULL;
} }
@@ -407,7 +427,8 @@ req_thread(void *arg __unused)
} }


static int static int
process_pending(struct ggs_reqqueue *req_pending, struct ggs_sessqueue *sessqueue)
process_pending(struct ggs_reqqueue *req_pending,
struct ggs_sessqueue *sessqueue)
{ {
struct ggs_req *greq, *greq2; struct ggs_req *greq, *greq2;
char *errmsg; char *errmsg;
@@ -421,27 +442,40 @@ process_pending(struct ggs_reqqueue *req_pending, struct ggs_sessqueue *sessqueu
again: again:
switch (greq->r_ggio.gctl_cmd) { switch (greq->r_ggio.gctl_cmd) {
case BIO_READ: case BIO_READ:
g_gate_log(LOG_DEBUG, "sftp_read(%p): %d(%d), rem: %d", greq, greq->r_ggio.gctl_offset, greq->r_ggio.gctl_length, greq->r_ggio.gctl_length - greq->r_bufoff);
g_gate_log(LOG_DEBUG, "sftp_read(%p): %d(%d), rem: %d",
greq, greq->r_ggio.gctl_offset,
greq->r_ggio.gctl_length,
greq->r_ggio.gctl_length - greq->r_bufoff);
if (greq->r_didseek == 0) { if (greq->r_didseek == 0) {
libssh2_sftp_seek64(greq->r_handle, greq->r_ggio.gctl_offset);
libssh2_sftp_seek64(greq->r_handle,
greq->r_ggio.gctl_offset);
greq->r_didseek = 1; greq->r_didseek = 1;
} }
rc = libssh2_sftp_read(greq->r_handle, (char *)greq->r_ggio.gctl_data + greq->r_bufoff, greq->r_ggio.gctl_length - greq->r_bufoff);
rc = libssh2_sftp_read(greq->r_handle,
(char *)greq->r_ggio.gctl_data + greq->r_bufoff,
greq->r_ggio.gctl_length - greq->r_bufoff);
g_gate_log(LOG_DEBUG, "sftp_read ret: %d", rc); g_gate_log(LOG_DEBUG, "sftp_read ret: %d", rc);
if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN)
g_gate_log(LOG_ERR, "libssh2_sftp_read"); g_gate_log(LOG_ERR, "libssh2_sftp_read");
break; break;


case BIO_WRITE: case BIO_WRITE:
g_gate_log(LOG_DEBUG, "sftp_write(%p): %d(%d), rem: %d", greq, greq->r_ggio.gctl_offset, greq->r_ggio.gctl_length, greq->r_ggio.gctl_length - greq->r_bufoff);
g_gate_log(LOG_DEBUG, "sftp_write(%p): %d(%d), rem: %d",
greq, greq->r_ggio.gctl_offset,
greq->r_ggio.gctl_length,
greq->r_ggio.gctl_length - greq->r_bufoff);
if (greq->r_didseek == 0) { if (greq->r_didseek == 0) {
libssh2_sftp_seek64(greq->r_handle, greq->r_ggio.gctl_offset);
libssh2_sftp_seek64(greq->r_handle,
greq->r_ggio.gctl_offset);
greq->r_didseek = 1; greq->r_didseek = 1;
} }
rc = libssh2_sftp_write(greq->r_handle, (char *)greq->r_ggio.gctl_data + greq->r_bufoff, greq->r_ggio.gctl_length - greq->r_bufoff);
rc = libssh2_sftp_write(greq->r_handle,
(char *)greq->r_ggio.gctl_data + greq->r_bufoff,
greq->r_ggio.gctl_length - greq->r_bufoff);
g_gate_log(LOG_DEBUG, "sftp_write ret: %d", rc); g_gate_log(LOG_DEBUG, "sftp_write ret: %d", rc);
if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN)
libssh2_errorx(greq->r_ssh_session, "libssh2_sftp_write");
libssh2_errorx(greq->r_ssh_session,
"libssh2_sftp_write");
break; break;


case BIO_FLUSH: case BIO_FLUSH:
@@ -461,8 +495,10 @@ again:
goto completeio; goto completeio;


default: default:
libssh2_session_last_error(greq->r_ssh_session, &errmsg, NULL, 0);
g_gate_log(LOG_ERR, "sftp_flush(%p) ret %d: %s", greq, rc, errmsg);
libssh2_session_last_error(greq->r_ssh_session,
&errmsg, NULL, 0);
g_gate_log(LOG_ERR, "sftp_flush(%p) ret %d: %s",
greq, rc, errmsg);
greq->r_ggio.gctl_error = EIO; greq->r_ggio.gctl_error = EIO;
goto completeio; goto completeio;
} }
@@ -471,7 +507,8 @@ again:


default: default:
rc = 0; rc = 0;
g_gate_log(LOG_ERR, "unhandled op: %d", greq->r_ggio.gctl_cmd);
g_gate_log(LOG_ERR, "unhandled op: %d",
greq->r_ggio.gctl_cmd);
continue; continue;
} }


@@ -479,7 +516,10 @@ again:
didwork = 1; didwork = 1;
greq->r_bufoff += rc; greq->r_bufoff += rc;


/* try again on partial read/write, might have more data pending */
/*
* try again on partial read/write,
* might have more data pending
*/
if ((off_t)greq->r_bufoff != greq->r_ggio.gctl_length) if ((off_t)greq->r_bufoff != greq->r_ggio.gctl_length)
goto again; goto again;
} }
@@ -487,10 +527,12 @@ again:
if ((off_t)greq->r_bufoff == greq->r_ggio.gctl_length) { if ((off_t)greq->r_bufoff == greq->r_ggio.gctl_length) {
/* complete */ /* complete */
completeio: completeio:
g_gate_log(LOG_DEBUG, "cmd complete: seq: %d, cmd: %d", greq->r_ggio.gctl_seq, greq->r_ggio.gctl_cmd);
g_gate_log(LOG_DEBUG, "cmd complete: seq: %d, cmd: %d",
greq->r_ggio.gctl_seq, greq->r_ggio.gctl_cmd);
g_gate_ioctl(G_GATE_CMD_DONE, &greq->r_ggio); g_gate_ioctl(G_GATE_CMD_DONE, &greq->r_ggio);
TAILQ_REMOVE(req_pending, greq, r_next); TAILQ_REMOVE(req_pending, greq, r_next);
TAILQ_INSERT_HEAD(sessqueue, greq->r_sesscache, sc_next);
TAILQ_INSERT_HEAD(sessqueue, greq->r_sesscache,
sc_next);
free(greq->r_ggio.gctl_data); free(greq->r_ggio.gctl_data);
free(greq); free(greq);


@@ -562,7 +604,8 @@ proc_thread(void *arg __unused)
FD_ZERO(&fdexcep); FD_ZERO(&fdexcep);


dir = libssh2_session_block_directions(session); dir = libssh2_session_block_directions(session);
if (dir & LIBSSH2_SESSION_BLOCK_INBOUND || gsc_pending != NULL)
if (dir & LIBSSH2_SESSION_BLOCK_INBOUND ||
gsc_pending != NULL)
FD_SET(sockfd, &fdread); FD_SET(sockfd, &fdread);
if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
FD_SET(sockfd, &fdwrite); FD_SET(sockfd, &fdwrite);
@@ -571,24 +614,30 @@ proc_thread(void *arg __unused)
FD_SET(popfd, &fdread); FD_SET(popfd, &fdread);
maxfd = MAX(popfd, sockfd); maxfd = MAX(popfd, sockfd);


#if 0
/* we need to be kj */
if (gsc_pending != NULL)
FD_SET(sockfd, &fdread);
#endif
g_gate_log(LOG_DEBUG, "selecting: %s %s, read: sockfd: %d, popfd: %d, write: sockfd: %d", (dir & LIBSSH2_SESSION_BLOCK_INBOUND) ? "inbound" : "", (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) ? "outbound" : "", FD_ISSET(sockfd, &fdread), FD_ISSET(popfd, &fdread), FD_ISSET(sockfd, &fdwrite));
g_gate_log(LOG_DEBUG, "selecting: %s %s, " \
"read: sockfd: %d, popfd: %d, write: sockfd: %d",
(dir & LIBSSH2_SESSION_BLOCK_INBOUND) ? "inbound" :
"", (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) ?
"outbound" : "", FD_ISSET(sockfd, &fdread),
FD_ISSET(popfd, &fdread),
FD_ISSET(sockfd, &fdwrite));
to = (struct timeval){ .tv_sec = 1, .tv_usec = 1000 }; to = (struct timeval){ .tv_sec = 1, .tv_usec = 1000 };
(void)to; (void)to;
rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, NULL);
rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep,
NULL);
switch (rc) { switch (rc) {
case -1: case -1:
g_gate_log(LOG_ERR, "%s: select failed: %s", __func__,
strerror(errno));
g_gate_log(LOG_ERR, "%s: select failed: %s",
__func__, strerror(errno));
break; break;
case 0: case 0:
default: default:
g_gate_log(LOG_DEBUG, "select: %d, read: sockfd: %d, popfd: %d, write: sockfd: %d", rc, FD_ISSET(sockfd, &fdread), FD_ISSET(popfd, &fdread), FD_ISSET(sockfd, &fdwrite));
g_gate_log(LOG_DEBUG, "select: %d, " \
"read: sockfd: %d, popfd: %d, " \
"write: sockfd: %d", rc,
FD_ISSET(sockfd, &fdread),
FD_ISSET(popfd, &fdread),
FD_ISSET(sockfd, &fdwrite));
break; break;
} }
} }
@@ -623,30 +672,38 @@ procreq:
if (gsc == NULL) { if (gsc == NULL) {
if (gsc_pending == NULL) { if (gsc_pending == NULL) {
/* need new session */ /* need new session */
g_gate_log(LOG_DEBUG, "need new session");
gsc_pending = malloc(sizeof *gsc);
gsc_pending->sc_ssh_session = session;
g_gate_log(LOG_DEBUG,
"need new session");
gsc_pending =
malloc(sizeof *gsc);
gsc_pending->sc_ssh_session =
session;
gsc_pending->sc_session = NULL; gsc_pending->sc_session = NULL;
gsc_pending->sc_handle = NULL; gsc_pending->sc_handle = NULL;
} }


/* put back request */ /* put back request */
error = pthread_mutex_lock(&procqueue_mtx);
error =
pthread_mutex_lock(&procqueue_mtx);
assert(error == 0); assert(error == 0);
TAILQ_INSERT_HEAD(&procqueue, greq, r_next);
error = pthread_mutex_unlock(&procqueue_mtx);
TAILQ_INSERT_HEAD(&procqueue, greq,
r_next);
error = pthread_mutex_unlock(
&procqueue_mtx);
assert(error == 0); assert(error == 0);


break; break;
} else { } else {
/* process request */ /* process request */
TAILQ_REMOVE(&session_cache, gsc, sc_next);
TAILQ_REMOVE(&session_cache, gsc,
sc_next);
greq->r_sesscache = gsc; greq->r_sesscache = gsc;
gsc = NULL; gsc = NULL;


greq->r_bufoff = 0; greq->r_bufoff = 0;


TAILQ_INSERT_TAIL(&req_pending, greq, r_next);
TAILQ_INSERT_TAIL(&req_pending, greq,
r_next);


greq = NULL; greq = NULL;
} }
@@ -657,20 +714,26 @@ procreq:
/* we are creating a new session */ /* we are creating a new session */
if (gsc_pending->sc_session == NULL) { if (gsc_pending->sc_session == NULL) {
didwork = 1; didwork = 1;
gsc_pending->sc_session = libssh2_sftp_init(session);
gsc_pending->sc_session =
libssh2_sftp_init(session);
} }


if (gsc_pending->sc_session != NULL) { if (gsc_pending->sc_session != NULL) {
didwork = 1; didwork = 1;
gsc_pending->sc_handle = libssh2_sftp_open(gsc_pending->sc_session, "fstest/data.img", LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE, 0);
gsc_pending->sc_handle = libssh2_sftp_open(
gsc_pending->sc_session, "fstest/data.img",
get_open_flags(), 0);
} }


g_gate_log(LOG_DEBUG, "pending: session: %p, handle: %p", gsc_pending->sc_session, gsc_pending->sc_handle);
g_gate_log(LOG_DEBUG,
"pending: session: %p, handle: %p",
gsc_pending->sc_session, gsc_pending->sc_handle);


/* we have a fully initalized entry, use it */ /* we have a fully initalized entry, use it */
if (gsc_pending->sc_handle != NULL) { if (gsc_pending->sc_handle != NULL) {
g_gate_log(LOG_DEBUG, "new session created"); g_gate_log(LOG_DEBUG, "new session created");
TAILQ_INSERT_HEAD(&session_cache, gsc_pending, sc_next);
TAILQ_INSERT_HEAD(&session_cache, gsc_pending,
sc_next);
gsc_pending = NULL; gsc_pending = NULL;
didwork = 1; didwork = 1;
goto procreq; goto procreq;
@@ -692,13 +755,15 @@ ggatessh_makepidfile(void)


if (!g_gate_verbose) { if (!g_gate_verbose) {
if (ggatessh_pidfile == NULL) { if (ggatessh_pidfile == NULL) {
asprintf(&ggatessh_pidfile, _PATH_VARRUN "/ggatessh.ggate%d.pid", unit);
asprintf(&ggatessh_pidfile,
_PATH_VARRUN "/ggatessh.ggate%d.pid", unit);
err(EXIT_FAILURE, "Cannot allocate memory for pidfile"); err(EXIT_FAILURE, "Cannot allocate memory for pidfile");
} }
pfh = pidfile_open(ggatessh_pidfile, 0600, &otherpid); pfh = pidfile_open(ggatessh_pidfile, 0600, &otherpid);
if (pfh == NULL) { if (pfh == NULL) {
if (errno == EEXIST) { if (errno == EEXIST) {
errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
errx(EXIT_FAILURE,
"Daemon already running, pid: %jd.",
(intmax_t)otherpid); (intmax_t)otherpid);
} }
err(EXIT_FAILURE, "Cannot open/create pidfile"); err(EXIT_FAILURE, "Cannot open/create pidfile");
@@ -824,7 +889,8 @@ g_gatessh_create(void)
ggioc.gctl_maxcount = queue_size; ggioc.gctl_maxcount = queue_size;
ggioc.gctl_timeout = timeout; ggioc.gctl_timeout = timeout;
ggioc.gctl_unit = unit; ggioc.gctl_unit = unit;
snprintf(ggioc.gctl_info, sizeof(ggioc.gctl_info), "%s@%s:%s", username, hostname, imgpath);
snprintf(ggioc.gctl_info, sizeof(ggioc.gctl_info), "%s@%s:%s",
username, hostname, imgpath);
g_gate_ioctl(G_GATE_CMD_CREATE, &ggioc); g_gate_ioctl(G_GATE_CMD_CREATE, &ggioc);
if (unit == -1) { if (unit == -1) {
printf("%s%u\n", G_GATE_PROVIDER_NAME, ggioc.gctl_unit); printf("%s%u\n", G_GATE_PROVIDER_NAME, ggioc.gctl_unit);
@@ -865,7 +931,8 @@ g_gatessh_rescue(void)


error = pthread_create(&mediatd, NULL, mediachg, NULL); error = pthread_create(&mediatd, NULL, mediachg, NULL);
if (error != 0) if (error != 0)
g_gate_xlog("unable to create mediasize change thread", strerror(errno));
g_gate_xlog("unable to create mediasize change thread",
strerror(errno));


g_gatessh_loop(); g_gatessh_loop();
} }


+ 118
- 10
tests/ggatessh_test.sh View File

@@ -12,7 +12,7 @@ ggatessh_head()
atf_set "descr" "ggatessh can proxy to sftp" atf_set "descr" "ggatessh can proxy to sftp"
atf_set "require.progs" "ggatessh" atf_set "require.progs" "ggatessh"
atf_set "require.user" "root" atf_set "require.user" "root"
atf_set "timeout" 20
atf_set "timeout" 10
} }


ggatessh_body() ggatessh_body()
@@ -32,9 +32,12 @@ ggatessh_body()
# sshd authenticates and switches to USER # sshd authenticates and switches to USER
chown "$USER" "$TESTIMG" chown "$USER" "$TESTIMG"


echo 'WARNING: ggatessh error messages goes to syslog (aka /var/log/messages)'
echo 'WARNING: ggatessh error messages goes to syslog' \
'(aka /var/log/messages)'


atf_check ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"
atf_check \
ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
-u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"


ggate_dev=/dev/ggate${us} ggate_dev=/dev/ggate${us}


@@ -50,11 +53,13 @@ EOF


# Test writing # Test writing
atf_check -e ignore -o ignore \ atf_check -e ignore -o ignore \
dd if="$TEMPFILE" of=${ggate_dev} bs=1m count=$n1mchunks conv=notrunc
dd if="$TEMPFILE" of=${ggate_dev} bs=1m count=$n1mchunks \
conv=notrunc


# Test reading # Test reading
atf_check -e ignore -o ignore \ atf_check -e ignore -o ignore \
dd of="$TEMPFILE"2 if=${ggate_dev} bs=1m count=$n1mchunks conv=notrunc
dd of="$TEMPFILE"2 if=${ggate_dev} bs=1m count=$n1mchunks \
conv=notrunc


# Verify that we read what we wrote # Verify that we read what we wrote
atf_check cmp "$TEMPFILE" "$TEMPFILE"2 atf_check cmp "$TEMPFILE" "$TEMPFILE"2
@@ -93,9 +98,12 @@ ggatessh_resize_body()
# sshd authenticates and switches to USER # sshd authenticates and switches to USER
chown "$USER" "$TESTIMG" chown "$USER" "$TESTIMG"


echo 'WARNING: ggatessh error messages goes to syslog (aka /var/log/messages)'
echo 'WARNING: ggatessh error messages goes to syslog' \
'(aka /var/log/messages)'


atf_check ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"
atf_check \
ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
-u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"


ggate_dev=/dev/ggate${us} ggate_dev=/dev/ggate${us}


@@ -122,7 +130,9 @@ EOF
sleep 1 sleep 1


# restart ggate # restart ggate
atf_check ggatessh rescue -v -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG" &
atf_check \
ggatessh rescue -v -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
-u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG" &


sleep 1 sleep 1


@@ -143,10 +153,104 @@ ggatessh_resize_cleanup()
common_cleanup common_cleanup
} }


atf_test_case ggatessh_rowotest cleanup
ggatessh_rowotest_head()
{
atf_set "descr" "ggatessh properly handles the -o flag"
atf_set "require.progs" "ggatessh"
atf_set "require.user" "root"
atf_set "timeout" 10
}

ggatessh_rowotest_body()
{

n1mchunks=4
secsize=4096
us=$(alloc_ggate_dev)

startup_sshd

truncate -s ${n1mchunks}m "$TESTIMG"
# sshd authenticates and switches to USER
chmod 444 "$TESTIMG"

echo 'WARNING: ggatessh error messages goes to syslog' \
'(aka /var/log/messages)'

# make sure it fails in rw mode
atf_check -s not-exit:0 \
ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
-u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"

# open it in read-only mode
atf_check \
ggatessh create -o ro -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
-u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"

ggate_dev=/dev/ggate${us}

wait_for_ggate_device ${ggate_dev}

# make sure it has correct size and sector sizekj
read _dev _secsize _size _nsecs _stripesize _stripeoff <<EOF
$(diskinfo /dev/ggate$us)
EOF
atf_check_equal "$_secsize" $secsize
atf_check_equal "$_size" $(($n1mchunks * 1024 * 1024))
atf_check_equal "$_nsecs" $(($n1mchunks * 1024 * 1024 / $secsize))

# that we can read a read-only ggate device
atf_check -e ignore \
dd if=${ggate_dev} of=/dev/null bs=1m count=$n1mchunks

# that we can not write a read-only ggate device
atf_check -e ignore -s not-exit:0 \
dd of=${ggate_dev} if=/dev/zero bs=1m count=1

# kill off old ggate
pkill -F "$PIDFILE"
ggatessh destroy -f -u $us >/dev/null

# test write-only
chmod 222 "$TESTIMG"

# make sure it fails in rw mode
atf_check -s not-exit:0 \
ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
-u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"

# open it in write-only mode
atf_check \
ggatessh create -o wo -i "$(pwd)/id_rsa" -p "$PORT" \
-F "$PIDFILE" -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"

ggate_dev=/dev/ggate${us}

wait_for_ggate_device ${ggate_dev}

# Note: diskinfo opens w/ read, can't verify device info

# that we can not read a write-only ggate device
atf_check -e ignore -s not-exit:0 \
dd if=${ggate_dev} of=/dev/null bs=1m count=$n1mchunks

# that we can write a write-only ggate device
atf_check -e ignore \
dd of=${ggate_dev} if=/dev/zero bs=1m count=1
}

ggatessh_rowotest_cleanup()
{

common_cleanup
}

atf_init_test_cases() atf_init_test_cases()
{ {
atf_add_test_case ggatessh atf_add_test_case ggatessh
atf_add_test_case ggatessh_resize atf_add_test_case ggatessh_resize
atf_add_test_case ggatessh_rowotest
} }


alloc_ggate_dev() alloc_ggate_dev()
@@ -175,11 +279,15 @@ alloc_md()
# https://serverfault.com/questions/344295/is-it-possible-to-run-sshd-as-a-normal-user # https://serverfault.com/questions/344295/is-it-possible-to-run-sshd-as-a-normal-user
startup_sshd() startup_sshd()
{ {
# ===============================================================
# Note: using shorter keys to speed up tests, these are insecure.
# ===============================================================

# Host keys # Host keys
ssh-keygen -f ssh_host_rsa_key -N '' -t rsa > /dev/null
ssh-keygen -f ssh_host_rsa_key -b 1024 -N '' -t rsa > /dev/null


# user key # user key
ssh-keygen -f id_rsa -N '' -t rsa > /dev/null
ssh-keygen -f id_rsa -b 1024 -N '' -t rsa > /dev/null


(echo -n 'command="/usr/libexec/sftp-server" '; cat id_rsa.pub) > authorized_keys (echo -n 'command="/usr/libexec/sftp-server" '; cat id_rsa.pub) > authorized_keys




Loading…
Cancel
Save