git ssb

8+

cel / sbotc



Commit 25b777fa9d60463685a4dbba6fd2e0413b846caf

Add -a passthrough option

cel committed on 12/2/2018, 3:20:32 AM
Parent: 217595e9b848c0df705f2e2430b8edd651aeb0f8

Files changed

README.mdchanged
sbotc.1changed
sbotc.cchanged
README.mdView
@@ -15,10 +15,12 @@
1515
1616 ## Usage
1717
1818 ```sh
19-sbotc [-j] [-T] [-n] [-c <cap>] [-s <host>] [-p <port>] [-u <socket_path>] [-k <key>] [-K <keypair_seed>]
20- [-t <type>] <method> [<argument>...]
19 +sbotc [-j] [-T]
20 + [ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]
21 + [ [-s <host>] [-p <port>] [ -4 | -6 ] | [-u <socket_path>] ]
22 + [ -a | [-t <type>] <method> [<argument>...] ]
2123 ```
2224
2325 Arguments must be explicitly JSON-encoded.
2426
sbotc.1View
@@ -8,8 +8,9 @@
88 .Sh SYNOPSIS
99 .Nm
1010 .Op Fl j
1111 .Op Fl T
12 +.Op Fl a
1213 .
1314 .Oo
1415 .Fl n
1516 |
@@ -29,11 +30,15 @@
2930 |
3031 .Op Fl u Ar socket_path
3132 .Oc
3233 .
34 +.Oo
35 +.Fl a
36 +|
3337 .Op Fl t Ar type
3438 .Ar method
3539 .Op Ar argument ...
40 +.Oc
3641 .Sh DESCRIPTION
3742 Connect to a scuttlebot/secret-stack server, and call a method on it, with
3843 standard I/O.
3944 .Sh OPTIONS
@@ -43,8 +48,11 @@
4348 .It Fl T
4449 Test using shs1-testsuite protocol. Instead of connecting to a server and running
4550 a command, connect to stdio. On successful handshake, output concatenation of
4651 the encryption key, encryption nonce, decryption key and decryption nonce.
52 +.It Fl a
53 +Passthrough mode. Instead of making a muxrpc call, pass through the box-stream
54 +to stdio.
4755 .It Fl n
4856 Noauth mode. Skip secret-handshake authentication and box-stream encryption.
4957 This option makes the
5058 .Fl k ,
sbotc.cView
@@ -105,9 +105,9 @@
105105 static void usage() {
106106 fputs("usage: sbotc [-j] [-T]\n"
107107 " [ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]\n"
108108 " [ [-s <host>] [-p <port>] [ -4 | -6 ] | [-u <socket_path>] ]\n"
109- " [-t <type>] <method> [<argument>...]\n", stderr);
109 + " [ -a | [-t <type>] <method> [<argument>...] ]\n", stderr);
110110 exit(EXIT_FAILURE);
111111 }
112112
113113 static int tcp_connect(const char *host, const char *port, enum ip_family ip_family) {
@@ -175,8 +175,18 @@
175175 }
176176 return 0;
177177 }
178178
179 +static int read_some(int fd, unsigned char *buf, size_t *lenp) {
180 + ssize_t nbytes;
181 + do nbytes = read(fd, buf, *lenp);
182 + while (nbytes < 0 && errno == EINTR);
183 + if (nbytes == 0) { errno = EPIPE; return -1; }
184 + if (nbytes < 0) return -1;
185 + *lenp = nbytes;
186 + return 0;
187 +}
188 +
179189 static int write_all(int fd, const void *buf, size_t count) {
180190 ssize_t nbytes;
181191 while (count > 0) {
182192 nbytes = write(fd, buf, count);
@@ -484,14 +494,22 @@
484494 static void bs_end(struct boxs *bs) {
485495 if (!bs->noauth) {
486496 bs_write_end_box(bs);
487497 }
498 + shutdown(bs->s, SHUT_WR);
488499 }
489500
490501 static int bs_read_packet(struct boxs *bs, void *buf, size_t *lenp) {
502 + int rc;
503 + if (bs->noauth) {
504 + rc = read_some(bs->s, buf, lenp);
505 + if (rc < 0 && errno == EPIPE) return -1;
506 + if (rc < 0) err(1, "failed to read packet data");
507 + return 0;
508 + }
491509 unsigned char boxed_header[34];
492510 struct boxs_header header;
493- int rc = read_all(bs->s, boxed_header, 34);
511 + rc = read_all(bs->s, boxed_header, 34);
494512 if (rc < 0 && errno == EPIPE) errx(1, "unexpected end of parent stream");
495513 if (rc < 0) err(1, "failed to read boxed packet header");
496514 rc = crypto_secretbox_open_easy((unsigned char *)&header, boxed_header, 34, bs->rx_nonce, bs->decrypt_key);
497515 if (rc < 0) errx(1, "failed to unbox packet header");
@@ -530,8 +548,20 @@
530548 }
531549 return 0;
532550 }
533551
552 +static enum stream_state bs_read_out_1(struct boxs *bs, int fd) {
553 + size_t buf[4096];
554 + size_t len = sizeof(buf);
555 + int rc;
556 + rc = bs_read_packet(bs, buf, &len);
557 + if (rc < 0 && errno == EPIPE) return stream_state_ended_ok;
558 + if (rc < 0) return stream_state_ended_error;
559 + rc = write_all(fd, buf, len);
560 + if (rc < 0) return stream_state_ended_error;
561 + return stream_state_open;
562 +}
563 +
534564 static int bs_read_out(struct boxs *bs, int fd, size_t len) {
535565 size_t chunk;
536566 char buf[4096];
537567 int rc;
@@ -577,8 +607,20 @@
577607 buf += l;
578608 }
579609 }
580610
611 +static enum stream_state bs_write_in_1(struct boxs *bs, int fd) {
612 + unsigned char buf[4096];
613 + ssize_t sz = read(fd, buf, sizeof(buf));
614 + if (sz < 0) err(1, "read");
615 + if (sz == 0) {
616 + bs_end(bs);
617 + return stream_state_ended_ok;
618 + }
619 + bs_write(bs, buf, sz);
620 + return stream_state_open;
621 +}
622 +
581623 static void ps_write(struct boxs *bs, const char *data, size_t len, enum pkt_type type, int req_id, bool stream, bool end) {
582624 size_t out_len = 9 + len;
583625 unsigned char out_buf[out_len];
584626 struct pkt_header header = {htonl(len), htonl(req_id)};
@@ -618,8 +660,31 @@
618660
619661 ps_write(bs, req, reqlen, pkt_type_json, req_id, !is_request, false);
620662 }
621663
664 +static int bs_passthrough(struct boxs *bs, int infd, int outfd) {
665 + int rc;
666 + fd_set rd;
667 + int sfd = bs->s;
668 + int maxfd = infd > sfd ? infd : sfd;
669 + enum stream_state in = stream_state_open;
670 + enum stream_state out = stream_state_open;
671 +
672 + while (out == stream_state_open
673 + || (in == stream_state_open && out != stream_state_ended_error)) {
674 + FD_ZERO(&rd);
675 + if (in == stream_state_open) FD_SET(infd, &rd);
676 + if (out == stream_state_open) FD_SET(sfd, &rd);
677 + rc = select(maxfd + 1, &rd, 0, 0, NULL);
678 + if (rc < 0) err(1, "select");
679 + if (FD_ISSET(infd, &rd)) in = bs_write_in_1(bs, infd);
680 + if (FD_ISSET(sfd, &rd)) out = bs_read_out_1(bs, outfd);
681 + }
682 +
683 + return in == stream_state_ended_ok && out == stream_state_ended_ok ? 0 :
684 + in == stream_state_ended_error || out == stream_state_ended_error ? 2 : 1;
685 +}
686 +
622687 static void ps_reject(struct boxs *bs, size_t len, int32_t req, enum pkt_flags flags) {
623688 // ignore the packet. if this is a request, the substream on the other end
624689 // will just have to wait until the rpc connection closes.
625690 (void)req;
@@ -865,9 +930,9 @@
865930 const char *key = NULL;
866931 const char *keypair_seed_str = NULL;
867932 const char *host = NULL;
868933 const char *port = "8008";
869- const char *typestr = NULL, *methodstr;
934 + const char *typestr = NULL, *methodstr = NULL;
870935 const char *shs_cap_key_str = NULL;
871936 const char *socket_path = NULL;
872937 size_t argument_len;
873938 unsigned char private_key[64];
@@ -886,8 +951,9 @@
886951 bool key_arg = false;
887952 bool shs_cap_key_str_arg = false;
888953 bool ipv4_arg = false;
889954 bool ipv6_arg = false;
955 + bool passthrough = false;
890956 enum ip_family ip_family;
891957
892958 get_app_dir(app_dir, sizeof(app_dir));
893959
@@ -919,12 +985,14 @@
919985 case 't': typestr = argv[++i]; break;
920986 case 'n': noauth = true; break;
921987 case '4': ipv4_arg = true; break;
922988 case '6': ipv6_arg = true; break;
989 + case 'a': passthrough = true; break;
923990 default: usage();
924991 }
925992 }
926- if (i < argc) methodstr = argv[i++]; else if (!test) usage();
993 + if (i < argc) methodstr = argv[i++];
994 + else if (!test && !passthrough) usage();
927995
928996 if (ipv4_arg && ipv6_arg) errx(1, "options -4 and -6 conflict");
929997 ip_family =
930998 ipv4_arg ? ip_family_ipv4 :
@@ -940,11 +1008,17 @@
9401008
9411009 argument_len = test ? 0 : args_to_json_length(argc-i, argv+i);
9421010 char argument[argument_len];
9431011
944- if (!test) {
1012 + if (passthrough) {
1013 + if (methodstr) errx(1, "-a option conflicts with method");
1014 + if (typestr) errx(1, "-a option conflicts with -t option");
1015 + if (argc-i > 0) errx(1, "-a option conflicts with method arguments");
1016 + if (test) errx(1, "-a option conflicts with -T test");
1017 +
1018 + } else if (!test) {
9451019 rc = args_to_json(argument, sizeof(argument), argc-i, argv+i);
946- if (rc < 0) errx(0, "unable to collect arguments");
1020 + if (rc < 0) errx(1, "unable to collect arguments");
9471021
9481022 char manifest_buf[8192];
9491023 if (!typestr) {
9501024 len = read_file(manifest_buf, sizeof(manifest_buf),
@@ -1039,8 +1113,14 @@
10391113 if (rc < 0) err(1, "failed to write handshake result");
10401114 return 0;
10411115 }
10421116
1117 + if (passthrough) {
1118 + rc = bs_passthrough(&bs, STDIN_FILENO, STDOUT_FILENO);
1119 + close(s);
1120 + return rc;
1121 + }
1122 +
10431123 muxrpc_call(&bs, method, argument, type, typestr, 1);
10441124
10451125 switch (type) {
10461126 case muxrpc_type_async:

Built with git-ssb-web