|
|
|
@ -95,7 +95,7 @@ static const unsigned char ssb_cap[] = {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void usage() {
|
|
|
|
|
fputs("usage: sbotc [-j] [-a <cap>] [-s <host>] [-p <port>] [-k <key>] [-t <type>] "
|
|
|
|
|
fputs("usage: sbotc [-j] [-T] [-a <cap>] [-s <host>] [-p <port>] [-k <key>] [-t <type>] "
|
|
|
|
|
"<method> [<argument>...]\n", stderr);
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
@ -153,7 +153,7 @@ static int write_all(int fd, const void *buf, size_t count) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void shs_connect(int s, const unsigned char pubkey[32], const unsigned char seckey[64], const unsigned char appkey[32], const unsigned char server_pubkey[32], struct boxs *bs) {
|
|
|
|
|
static void shs_connect(int sfd, int infd, int outfd, const unsigned char pubkey[32], const unsigned char seckey[64], const unsigned char appkey[32], const unsigned char server_pubkey[32], struct boxs *bs) {
|
|
|
|
|
int rc;
|
|
|
|
|
unsigned char local_app_mac[32], remote_app_mac[32];
|
|
|
|
|
|
|
|
|
@ -168,12 +168,12 @@ static void shs_connect(int s, const unsigned char pubkey[32], const unsigned ch
|
|
|
|
|
unsigned char buf[64];
|
|
|
|
|
memcpy(buf, local_app_mac, 32);
|
|
|
|
|
memcpy(buf+32, kx_pk, 32);
|
|
|
|
|
rc = write_all(s, buf, sizeof(buf));
|
|
|
|
|
rc = write_all(outfd, buf, sizeof(buf));
|
|
|
|
|
if (rc < 0) err(1, "failed to send challenge");
|
|
|
|
|
|
|
|
|
|
// recv challenge
|
|
|
|
|
unsigned char remote_kx_pk[32];
|
|
|
|
|
rc = read_all(s, buf, sizeof(buf));
|
|
|
|
|
rc = read_all(infd, buf, sizeof(buf));
|
|
|
|
|
if (rc < 0) err(1, "challenge not accepted");
|
|
|
|
|
memcpy(remote_app_mac, buf, 32);
|
|
|
|
|
memcpy(remote_kx_pk, buf+32, 32);
|
|
|
|
@ -224,13 +224,13 @@ static void shs_connect(int s, const unsigned char pubkey[32], const unsigned ch
|
|
|
|
|
rc = crypto_secretbox_easy(boxed_auth, hello, sizeof(hello), zeros, secret2);
|
|
|
|
|
if (rc < 0) errx(1, "failed to box hello");
|
|
|
|
|
|
|
|
|
|
rc = write_all(s, boxed_auth, sizeof(boxed_auth));
|
|
|
|
|
rc = write_all(outfd, boxed_auth, sizeof(boxed_auth));
|
|
|
|
|
if (rc < 0) errx(1, "failed to send auth");
|
|
|
|
|
|
|
|
|
|
// verify accept
|
|
|
|
|
|
|
|
|
|
unsigned char boxed_okay[80];
|
|
|
|
|
rc = read_all(s, boxed_okay, sizeof(boxed_okay));
|
|
|
|
|
rc = read_all(infd, boxed_okay, sizeof(boxed_okay));
|
|
|
|
|
if (rc < 0) err(1, "hello not accepted");
|
|
|
|
|
|
|
|
|
|
unsigned char local_sk_curve[32];
|
|
|
|
@ -283,7 +283,7 @@ static void shs_connect(int s, const unsigned char pubkey[32], const unsigned ch
|
|
|
|
|
|
|
|
|
|
bs->rx_buf_pos = 0;
|
|
|
|
|
bs->rx_buf_len = 0;
|
|
|
|
|
bs->s = s;
|
|
|
|
|
bs->s = sfd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int pubkey_decode(const char *key_str, unsigned char key[32]) {
|
|
|
|
@ -797,7 +797,7 @@ static int args_to_json(char *out, size_t outlen, unsigned int argc, char *argv[
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
|
int i, s, rc;
|
|
|
|
|
int i, s, infd, outfd, rc;
|
|
|
|
|
const char *key = NULL;
|
|
|
|
|
const char *host = NULL;
|
|
|
|
|
const char *port = "8008";
|
|
|
|
@ -812,7 +812,9 @@ int main(int argc, char *argv[]) {
|
|
|
|
|
enum pkt_type ptype = pkt_type_buffer;
|
|
|
|
|
char method[256];
|
|
|
|
|
char app_dir[_POSIX_PATH_MAX];
|
|
|
|
|
char argument[argument_len];
|
|
|
|
|
ssize_t len;
|
|
|
|
|
bool test = false;
|
|
|
|
|
|
|
|
|
|
get_app_dir(app_dir, sizeof(app_dir));
|
|
|
|
|
|
|
|
|
@ -833,6 +835,7 @@ int main(int argc, char *argv[]) {
|
|
|
|
|
switch (argv[i][1]) {
|
|
|
|
|
case 'c': shs_cap_key_str = argv[++i]; break;
|
|
|
|
|
case 'j': ptype = pkt_type_json; break;
|
|
|
|
|
case 'T': test = true; break;
|
|
|
|
|
case 's': host = argv[++i]; break;
|
|
|
|
|
case 'k': key = argv[++i]; break;
|
|
|
|
|
case 'p': port = argv[++i]; break;
|
|
|
|
@ -840,7 +843,7 @@ int main(int argc, char *argv[]) {
|
|
|
|
|
default: usage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (i < argc) methodstr = argv[i++]; else usage();
|
|
|
|
|
if (i < argc) methodstr = argv[i++]; else if (!test) usage();
|
|
|
|
|
|
|
|
|
|
if (shs_cap_key_str) {
|
|
|
|
|
rc = pubkey_decode(shs_cap_key_str, shs_cap_key);
|
|
|
|
@ -849,33 +852,33 @@ int main(int argc, char *argv[]) {
|
|
|
|
|
memcpy(shs_cap_key, ssb_cap, 32);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!test) {
|
|
|
|
|
argument_len = args_to_json_length(argc-i, argv+i);
|
|
|
|
|
rc = args_to_json(argument, sizeof(argument), argc-i, argv+i);
|
|
|
|
|
if (rc < 0) errx(0, "unable to collect arguments");
|
|
|
|
|
|
|
|
|
|
argument_len = args_to_json_length(argc-i, argv+i);
|
|
|
|
|
char argument[argument_len];
|
|
|
|
|
rc = args_to_json(argument, sizeof(argument), argc-i, argv+i);
|
|
|
|
|
if (rc < 0) errx(0, "unable to collect arguments");
|
|
|
|
|
|
|
|
|
|
char manifest_buf[8192];
|
|
|
|
|
if (!typestr) {
|
|
|
|
|
len = read_file(manifest_buf, sizeof(manifest_buf),
|
|
|
|
|
"%s/manifest.json", app_dir);
|
|
|
|
|
if (len < 0) err(1, "failed to read manifest file");
|
|
|
|
|
|
|
|
|
|
ssize_t type_len = json_get_value(manifest_buf, methodstr, &typestr);
|
|
|
|
|
if (!typestr && errno == ENOMSG) errx(1,
|
|
|
|
|
"unable to find method '%s' in manifest", methodstr);
|
|
|
|
|
if (!typestr) err(1, "unable to read manifest");
|
|
|
|
|
((char *)typestr)[type_len] = '\0';
|
|
|
|
|
}
|
|
|
|
|
if (strcmp(typestr, "sync") == 0) type = muxrpc_type_async;
|
|
|
|
|
else if (strcmp(typestr, "async") == 0) type = muxrpc_type_async;
|
|
|
|
|
else if (strcmp(typestr, "sink") == 0) type = muxrpc_type_sink;
|
|
|
|
|
else if (strcmp(typestr, "source") == 0) type = muxrpc_type_source;
|
|
|
|
|
else if (strcmp(typestr, "duplex") == 0) type = muxrpc_type_duplex;
|
|
|
|
|
else errx(1, "type must be one of <async|sink|source|duplex>");
|
|
|
|
|
|
|
|
|
|
rc = method_to_json(method, sizeof(method), methodstr);
|
|
|
|
|
if (rc < 0) errx(0, "unable to convert method name");
|
|
|
|
|
char manifest_buf[8192];
|
|
|
|
|
if (!typestr) {
|
|
|
|
|
len = read_file(manifest_buf, sizeof(manifest_buf),
|
|
|
|
|
"%s/manifest.json", app_dir);
|
|
|
|
|
if (len < 0) err(1, "failed to read manifest file");
|
|
|
|
|
|
|
|
|
|
ssize_t type_len = json_get_value(manifest_buf, methodstr, &typestr);
|
|
|
|
|
if (!typestr && errno == ENOMSG) errx(1,
|
|
|
|
|
"unable to find method '%s' in manifest", methodstr);
|
|
|
|
|
if (!typestr) err(1, "unable to read manifest");
|
|
|
|
|
((char *)typestr)[type_len] = '\0';
|
|
|
|
|
}
|
|
|
|
|
if (strcmp(typestr, "sync") == 0) type = muxrpc_type_async;
|
|
|
|
|
else if (strcmp(typestr, "async") == 0) type = muxrpc_type_async;
|
|
|
|
|
else if (strcmp(typestr, "sink") == 0) type = muxrpc_type_sink;
|
|
|
|
|
else if (strcmp(typestr, "source") == 0) type = muxrpc_type_source;
|
|
|
|
|
else if (strcmp(typestr, "duplex") == 0) type = muxrpc_type_duplex;
|
|
|
|
|
else errx(1, "type must be one of <async|sink|source|duplex>");
|
|
|
|
|
|
|
|
|
|
rc = method_to_json(method, sizeof(method), methodstr);
|
|
|
|
|
if (rc < 0) errx(0, "unable to convert method name");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
read_private_key(app_dir, private_key);
|
|
|
|
|
|
|
|
|
@ -887,11 +890,27 @@ int main(int argc, char *argv[]) {
|
|
|
|
|
memcpy(remote_key, public_key, 32);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = tcp_connect(host, port);
|
|
|
|
|
if (s < 0) err(1, "tcp_connect");
|
|
|
|
|
if (test) {
|
|
|
|
|
infd = STDIN_FILENO;
|
|
|
|
|
outfd = STDOUT_FILENO;
|
|
|
|
|
s = -1;
|
|
|
|
|
} else {
|
|
|
|
|
s = tcp_connect(host, port);
|
|
|
|
|
if (s < 0) err(1, "tcp_connect");
|
|
|
|
|
infd = outfd = s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct boxs bs;
|
|
|
|
|
shs_connect(s, public_key, private_key, shs_cap_key, remote_key, &bs);
|
|
|
|
|
shs_connect(s, infd, outfd, public_key, private_key, shs_cap_key, remote_key, &bs);
|
|
|
|
|
|
|
|
|
|
if (test) {
|
|
|
|
|
rc = write_all(outfd, bs.encrypt_key, sizeof(bs.encrypt_key));
|
|
|
|
|
rc |= write_all(outfd, bs.nonce1, sizeof(bs.nonce1));
|
|
|
|
|
rc |= write_all(outfd, bs.decrypt_key, sizeof(bs.decrypt_key));
|
|
|
|
|
rc |= write_all(outfd, bs.rx_nonce, sizeof(bs.rx_nonce));
|
|
|
|
|
if (rc < 0) err(1, "failed to write handshake result");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
muxrpc_call(&bs, method, argument, type, typestr, 1);
|
|
|
|
|
|
|
|
|
|