Auto-detect local noauth socket

Attempt to connect to local noauth socket, unless TCP or SHS options are specified.
Fall back to TCP+SHS connection, unless noauth option is specified.
main
cel 7 years ago
parent dd8aa406f3
commit 0a1eafebf9

@ -11,7 +11,7 @@
.Op Fl T
.
.Oo
.Op Fl n
.Fl n
|
.Op Fl c Ar cap
.Op Fl k Ar key
@ -104,11 +104,32 @@ secret-handshake protocol.
A map of method names to method types.
.It Pa ~/.ssb/config
JSON file containing key, host, port, and/or SHS cap key to use if the
.Ar -s ,
.Ar -p
.Fl s ,
.Fl p
or
.Ar -c
.Fl c
options are not given, respectively.
.It Pa ~/.ssb/socket
UNIX socket stream file for noauth connections.
If none of the options
.Fl s ,
.Fl p ,
.Fl u ,
.Fl c ,
.Fl k ,
.Fl K ,
.Fl c ,
or
.Fl T
are specified,
.Nm
will attempt to connect in noauth mode to this socket file. If the socket file
is not present or the connection fails,
.Nm
will fall back to connecting with TCP and secret-handshake according to the
config file - unless the
.Fl n
option is specified, in which case the command will fail.
.El
.Pp
The base path

@ -98,7 +98,7 @@ static const unsigned char ssb_cap[] = {
static void usage() {
fputs("usage: sbotc [-j] [-T]\n"
" [ [-n] | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]\n"
" [ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]\n"
" [ [-s <host>] [-p <port>] | [-u <socket_path>] ]\n"
" [-t <type>] <method> [<argument>...]\n", stderr);
exit(EXIT_FAILURE);
@ -132,6 +132,31 @@ static int tcp_connect(const char *host, const char *port) {
return fd;
}
static int unix_connect(const char *path) {
struct sockaddr_un name;
const size_t path_len = strlen(path);
int s, rc;
if (path_len >= sizeof(name.sun_path)-1) errx(1, "socket path too long");
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) return -1;
memset(&name, 0, sizeof(struct sockaddr_un));
name.sun_family = AF_UNIX;
strncpy(name.sun_path, path, sizeof(name.sun_path) - 1);
rc = connect(s, (const struct sockaddr *)&name, sizeof name);
if (rc < 0) return -1;
return s;
}
static int get_socket_path(char *buf, size_t len, const char *app_dir) {
struct stat st;
int sz = snprintf(buf, len-1, "%s/%s", app_dir, "socket");
if (sz < 0 || sz >= (int)len-1) err(1, "failed to get socket path");
int rc = stat(buf, &st);
if (rc < 0) return -1;
if (!(st.st_mode & S_IFSOCK)) { errno = EINVAL; return -1; }
return 0;
}
static int read_all(int fd, void *buf, size_t count) {
ssize_t nbytes;
while (count > 0) {
@ -836,6 +861,7 @@ int main(int argc, char *argv[]) {
bool noauth = false;
bool host_arg = false;
bool port_arg = false;
bool key_arg = false;
bool shs_cap_key_str_arg = false;
get_app_dir(app_dir, sizeof(app_dir));
@ -861,7 +887,7 @@ int main(int argc, char *argv[]) {
case 'j': ptype = pkt_type_json; break;
case 'T': test = true; break;
case 's': host = argv[++i]; host_arg = true; break;
case 'k': key = argv[++i]; break;
case 'k': key = argv[++i]; key_arg = true; break;
case 'K': keypair_seed_str = argv[++i]; break;
case 'p': port = argv[++i]; port_arg = true; break;
case 'u': socket_path = argv[++i]; break;
@ -931,27 +957,33 @@ int main(int argc, char *argv[]) {
memcpy(remote_key, public_key, 32);
}
bool implied_tcp = host_arg || port_arg;
bool implied_auth = key_arg || keypair_seed_str || shs_cap_key_str_arg || test;
if (test) {
infd = STDIN_FILENO;
outfd = STDOUT_FILENO;
s = -1;
} else if (socket_path) {
if (port_arg) errx(1, "-p port conflicts with -u socket_path");
if (host_arg) errx(1, "-s host conflicts with -u socket_path");
struct sockaddr_un name;
size_t path_len = strlen(socket_path);
if (path_len >= sizeof(name.sun_path)-1) errx(1, "socket path too long");
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) err(1, "socket");
memset(&name, 0, sizeof(struct sockaddr_un));
name.sun_family = AF_UNIX;
strncpy(name.sun_path, socket_path, sizeof(name.sun_path) - 1);
rc = connect(s, (const struct sockaddr *)&name, sizeof name);
if (rc < 0) err(1, "connect");
if (implied_tcp) errx(1, "-u option conflicts with -s and -p options");
s = unix_connect(socket_path);
if (s < 0) err(1, "unix_connect");
infd = outfd = s;
} else if (!implied_tcp && !implied_auth) {
char socket_path_buf[_POSIX_PATH_MAX];
rc = get_socket_path(socket_path_buf, sizeof(socket_path_buf), app_dir);
if (rc < 0 && noauth) err(1, "get_socket_path");
if (rc < 0) goto do_tcp_connect;
s = unix_connect(socket_path_buf);
if (s < 0 && noauth) err(1, "unix_connect");
if (s < 0) goto do_tcp_connect;
noauth = true;
infd = outfd = s;
} else {
do_tcp_connect:
s = tcp_connect(host, port);
if (s < 0) err(1, "tcp_connect");
infd = outfd = s;
@ -961,10 +993,7 @@ int main(int argc, char *argv[]) {
if (noauth) {
bs.s = s;
bs.noauth = true;
if (key) errx(1, "-k keypair_seed conflicts with -n (noauth)");
if (keypair_seed_str) errx(1, "-K keypair_seed conflicts with -n (noauth)");
if (shs_cap_key_str_arg) errx(1, "-c cap_key conflicts with -n (noauth)");
if (test) errx(1, "-n (noauth) conflicts with -T (test shs)");
if (implied_auth) errx(1, "-n option conflicts with -k, -K, -c and -T options.");
} else {
shs_connect(s, infd, outfd, public_key, private_key, shs_cap_key, remote_key, &bs);
}

Loading…
Cancel
Save