diff options
-rw-r--r-- | bounce.c | 11 | ||||
-rw-r--r-- | bounce.h | 2 | ||||
-rw-r--r-- | pounce.1 | 11 | ||||
-rw-r--r-- | state.c | 28 |
4 files changed, 31 insertions, 21 deletions
diff --git a/bounce.c b/bounce.c index 1dd9138..8ed4234 100644 --- a/bounce.c +++ b/bounce.c @@ -285,8 +285,8 @@ int main(int argc, char *argv[]) { const char *host = NULL; const char *port = "6697"; char *pass = NULL; - bool sasl = false; char *plain = NULL; + enum Cap blindReq = 0; const char *nick = NULL; const char *user = NULL; const char *real = NULL; @@ -303,6 +303,7 @@ int main(int argc, char *argv[]) { { .val = 'N', .name = "no-names", no_argument }, { .val = 'P', .name = "local-port", required_argument }, { .val = 'Q', .name = "queue-interval", required_argument }, + { .val = 'R', .name = "blind-req", required_argument }, { .val = 'S', .name = "bind", required_argument }, { .val = 'T', .name = "no-sts", no_argument }, { .val = 'U', .name = "local-path", required_argument }, @@ -353,13 +354,14 @@ int main(int argc, char *argv[]) { break; case 'N': stateNoNames = true; break; case 'P': bindPort = optarg; break; case 'Q': serverQueueInterval = parseInterval(optarg); + break; case 'R': blindReq |= capParse(optarg, NULL); break; case 'S': serverBindHost = optarg; break; case 'T': clientSTS = false; break; case 'U': strlcpy(bindPath, optarg, sizeof(bindPath)); break; case 'W': clientPass = optarg; - break; case 'a': sasl = true; plain = optarg; + break; case 'a': blindReq |= CapSASL; plain = optarg; break; case 'c': clientCert = optarg; - break; case 'e': sasl = true; + break; case 'e': blindReq |= CapSASL; break; case 'f': savePath = optarg; break; case 'g': genPath = optarg; break; case 'h': host = optarg; @@ -378,6 +380,7 @@ int main(int argc, char *argv[]) { break; default: return EX_USAGE; } } + if (blindReq & CapUnsupported) errx(EX_CONFIG, "unsupported capability"); if (genPath) genCert(genPath, caPath); if (bindPath[0]) { @@ -460,7 +463,7 @@ int main(int argc, char *argv[]) { capLimit(server, &sockRights); #endif - stateLogin(pass, sasl, plain, nick, user, real); + stateLogin(pass, blindReq, plain, nick, user, real); if (pass) explicit_bzero(pass, strlen(pass)); if (plain) explicit_bzero(plain, strlen(plain)); diff --git a/bounce.h b/bounce.h index 39d1e1f..a58eca1 100644 --- a/bounce.h +++ b/bounce.h @@ -198,7 +198,7 @@ void clientConsume(struct Client *client); extern bool stateNoNames; extern enum Cap stateCaps; void stateLogin( - const char *pass, bool sasl, const char *plain, + const char *pass, enum Cap blind, const char *plain, const char *nick, const char *user, const char *real ); bool stateReady(void); diff --git a/pounce.1 b/pounce.1 index cf0e10b..6190d6d 100644 --- a/pounce.1 +++ b/pounce.1 @@ -1,4 +1,4 @@ -.Dd May 19, 2020 +.Dd July 6, 2020 .Dt POUNCE 1 .Os . @@ -15,6 +15,7 @@ .Op Fl K Ar priv .Op Fl P Ar port .Op Fl Q Ar time +.Op Fl R Ar caps .Op Fl S Ar bind .Op Fl U Ar unix .Op Fl W Ar pass @@ -160,6 +161,14 @@ Messages from clients are sent to the server immediately. The default interval is 200 milliseconds. . +.It Fl R Ar caps , Cm blind-req = Ar caps +Blindly request the IRCv3 capabilities +.Ar caps . +This can be used to enable hidden capabilities, +such as +.Sy userhost-in-names +on freenode. +. .It Fl S Ar host , Cm bind = Ar host Bind to source address .Ar host diff --git a/state.c b/state.c index ff05638..f35f29f 100644 --- a/state.c +++ b/state.c @@ -56,26 +56,24 @@ enum { AuthLen = 299 }; static char plainBase64[BASE64_SIZE(AuthLen)]; void stateLogin( - const char *pass, bool sasl, const char *plain, + const char *pass, enum Cap blind, const char *plain, const char *nick, const char *user, const char *real ) { serverFormat("CAP LS 302\r\n"); if (pass) serverFormat("PASS :%s\r\n", pass); - if (sasl) { - serverFormat("CAP REQ :%s\r\n", capList(CapSASL, NULL)); - if (plain) { - byte buf[AuthLen]; - size_t len = 1 + strlen(plain); - if (sizeof(buf) < len) { - errx(EX_SOFTWARE, "SASL PLAIN is too long"); - } - buf[0] = 0; - for (size_t i = 0; plain[i]; ++i) { - buf[1 + i] = (plain[i] == ':' ? 0 : plain[i]); - } - base64(plainBase64, buf, len); - explicit_bzero(buf, sizeof(buf)); + if (blind) serverFormat("CAP REQ :%s\r\n", capList(blind, NULL)); + if (plain) { + byte buf[AuthLen]; + size_t len = 1 + strlen(plain); + if (sizeof(buf) < len) { + errx(EX_SOFTWARE, "SASL PLAIN is too long"); } + buf[0] = 0; + for (size_t i = 0; plain[i]; ++i) { + buf[1 + i] = (plain[i] == ':' ? 0 : plain[i]); + } + base64(plainBase64, buf, len); + explicit_bzero(buf, sizeof(buf)); } serverFormat("NICK %s\r\n", nick); serverFormat("USER %s 0 * :%s\r\n", user, real); |