Add -a passthrough option

main
cel 7 years ago
parent 217595e9b8
commit 25b777fa9d

@ -16,8 +16,10 @@ sudo make install
## Usage
```sh
sbotc [-j] [-T] [-n] [-c <cap>] [-s <host>] [-p <port>] [-u <socket_path>] [-k <key>] [-K <keypair_seed>]
[-t <type>] <method> [<argument>...]
sbotc [-j] [-T]
[ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]
[ [-s <host>] [-p <port>] [ -4 | -6 ] | [-u <socket_path>] ]
[ -a | [-t <type>] <method> [<argument>...] ]
```
Arguments must be explicitly JSON-encoded.

@ -9,6 +9,7 @@
.Nm
.Op Fl j
.Op Fl T
.Op Fl a
.
.Oo
.Fl n
@ -30,9 +31,13 @@
.Op Fl u Ar socket_path
.Oc
.
.Oo
.Fl a
|
.Op Fl t Ar type
.Ar method
.Op Ar argument ...
.Oc
.Sh DESCRIPTION
Connect to a scuttlebot/secret-stack server, and call a method on it, with
standard I/O.
@ -44,6 +49,9 @@ Send stdin data as JSON.
Test using shs1-testsuite protocol. Instead of connecting to a server and running
a command, connect to stdio. On successful handshake, output concatenation of
the encryption key, encryption nonce, decryption key and decryption nonce.
.It Fl a
Passthrough mode. Instead of making a muxrpc call, pass through the box-stream
to stdio.
.It Fl n
Noauth mode. Skip secret-handshake authentication and box-stream encryption.
This option makes the

@ -106,7 +106,7 @@ static void usage() {
fputs("usage: sbotc [-j] [-T]\n"
" [ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]\n"
" [ [-s <host>] [-p <port>] [ -4 | -6 ] | [-u <socket_path>] ]\n"
" [-t <type>] <method> [<argument>...]\n", stderr);
" [ -a | [-t <type>] <method> [<argument>...] ]\n", stderr);
exit(EXIT_FAILURE);
}
@ -176,6 +176,16 @@ static int read_all(int fd, void *buf, size_t count) {
return 0;
}
static int read_some(int fd, unsigned char *buf, size_t *lenp) {
ssize_t nbytes;
do nbytes = read(fd, buf, *lenp);
while (nbytes < 0 && errno == EINTR);
if (nbytes == 0) { errno = EPIPE; return -1; }
if (nbytes < 0) return -1;
*lenp = nbytes;
return 0;
}
static int write_all(int fd, const void *buf, size_t count) {
ssize_t nbytes;
while (count > 0) {
@ -485,12 +495,20 @@ static void bs_end(struct boxs *bs) {
if (!bs->noauth) {
bs_write_end_box(bs);
}
shutdown(bs->s, SHUT_WR);
}
static int bs_read_packet(struct boxs *bs, void *buf, size_t *lenp) {
int rc;
if (bs->noauth) {
rc = read_some(bs->s, buf, lenp);
if (rc < 0 && errno == EPIPE) return -1;
if (rc < 0) err(1, "failed to read packet data");
return 0;
}
unsigned char boxed_header[34];
struct boxs_header header;
int rc = read_all(bs->s, boxed_header, 34);
rc = read_all(bs->s, boxed_header, 34);
if (rc < 0 && errno == EPIPE) errx(1, "unexpected end of parent stream");
if (rc < 0) err(1, "failed to read boxed packet header");
rc = crypto_secretbox_open_easy((unsigned char *)&header, boxed_header, 34, bs->rx_nonce, bs->decrypt_key);
@ -531,6 +549,18 @@ static int bs_read(struct boxs *bs, char *buf, size_t len) {
return 0;
}
static enum stream_state bs_read_out_1(struct boxs *bs, int fd) {
size_t buf[4096];
size_t len = sizeof(buf);
int rc;
rc = bs_read_packet(bs, buf, &len);
if (rc < 0 && errno == EPIPE) return stream_state_ended_ok;
if (rc < 0) return stream_state_ended_error;
rc = write_all(fd, buf, len);
if (rc < 0) return stream_state_ended_error;
return stream_state_open;
}
static int bs_read_out(struct boxs *bs, int fd, size_t len) {
size_t chunk;
char buf[4096];
@ -578,6 +608,18 @@ static void bs_write(struct boxs *bs, const unsigned char *buf, size_t len) {
}
}
static enum stream_state bs_write_in_1(struct boxs *bs, int fd) {
unsigned char buf[4096];
ssize_t sz = read(fd, buf, sizeof(buf));
if (sz < 0) err(1, "read");
if (sz == 0) {
bs_end(bs);
return stream_state_ended_ok;
}
bs_write(bs, buf, sz);
return stream_state_open;
}
static void ps_write(struct boxs *bs, const char *data, size_t len, enum pkt_type type, int req_id, bool stream, bool end) {
size_t out_len = 9 + len;
unsigned char out_buf[out_len];
@ -619,6 +661,29 @@ static void muxrpc_call(struct boxs *bs, const char *method, const char *argumen
ps_write(bs, req, reqlen, pkt_type_json, req_id, !is_request, false);
}
static int bs_passthrough(struct boxs *bs, int infd, int outfd) {
int rc;
fd_set rd;
int sfd = bs->s;
int maxfd = infd > sfd ? infd : sfd;
enum stream_state in = stream_state_open;
enum stream_state out = stream_state_open;
while (out == stream_state_open
|| (in == stream_state_open && out != stream_state_ended_error)) {
FD_ZERO(&rd);
if (in == stream_state_open) FD_SET(infd, &rd);
if (out == stream_state_open) FD_SET(sfd, &rd);
rc = select(maxfd + 1, &rd, 0, 0, NULL);
if (rc < 0) err(1, "select");
if (FD_ISSET(infd, &rd)) in = bs_write_in_1(bs, infd);
if (FD_ISSET(sfd, &rd)) out = bs_read_out_1(bs, outfd);
}
return in == stream_state_ended_ok && out == stream_state_ended_ok ? 0 :
in == stream_state_ended_error || out == stream_state_ended_error ? 2 : 1;
}
static void ps_reject(struct boxs *bs, size_t len, int32_t req, enum pkt_flags flags) {
// ignore the packet. if this is a request, the substream on the other end
// will just have to wait until the rpc connection closes.
@ -866,7 +931,7 @@ int main(int argc, char *argv[]) {
const char *keypair_seed_str = NULL;
const char *host = NULL;
const char *port = "8008";
const char *typestr = NULL, *methodstr;
const char *typestr = NULL, *methodstr = NULL;
const char *shs_cap_key_str = NULL;
const char *socket_path = NULL;
size_t argument_len;
@ -887,6 +952,7 @@ int main(int argc, char *argv[]) {
bool shs_cap_key_str_arg = false;
bool ipv4_arg = false;
bool ipv6_arg = false;
bool passthrough = false;
enum ip_family ip_family;
get_app_dir(app_dir, sizeof(app_dir));
@ -920,10 +986,12 @@ int main(int argc, char *argv[]) {
case 'n': noauth = true; break;
case '4': ipv4_arg = true; break;
case '6': ipv6_arg = true; break;
case 'a': passthrough = true; break;
default: usage();
}
}
if (i < argc) methodstr = argv[i++]; else if (!test) usage();
if (i < argc) methodstr = argv[i++];
else if (!test && !passthrough) usage();
if (ipv4_arg && ipv6_arg) errx(1, "options -4 and -6 conflict");
ip_family =
@ -941,9 +1009,15 @@ int main(int argc, char *argv[]) {
argument_len = test ? 0 : args_to_json_length(argc-i, argv+i);
char argument[argument_len];
if (!test) {
if (passthrough) {
if (methodstr) errx(1, "-a option conflicts with method");
if (typestr) errx(1, "-a option conflicts with -t option");
if (argc-i > 0) errx(1, "-a option conflicts with method arguments");
if (test) errx(1, "-a option conflicts with -T test");
} else if (!test) {
rc = args_to_json(argument, sizeof(argument), argc-i, argv+i);
if (rc < 0) errx(0, "unable to collect arguments");
if (rc < 0) errx(1, "unable to collect arguments");
char manifest_buf[8192];
if (!typestr) {
@ -1040,6 +1114,12 @@ do_tcp_connect:
return 0;
}
if (passthrough) {
rc = bs_passthrough(&bs, STDIN_FILENO, STDOUT_FILENO);
close(s);
return rc;
}
muxrpc_call(&bs, method, argument, type, typestr, 1);
switch (type) {

Loading…
Cancel
Save