fix sasl authenticate again

This commit is contained in:
2026-04-07 08:08:37 +08:00
parent f52d54ccc7
commit 5a43139f75
+37 -18
View File
@@ -196,6 +196,7 @@ typedef struct {
int reconnect_pending; int reconnect_pending;
pthread_t reconnect_tid; pthread_t reconnect_tid;
int sasl_auth_sent; /* guard: only send AUTHENTICATE once per session */
/* per-server event pipe */ /* per-server event pipe */
int evpipe[2]; int evpipe[2];
@@ -579,17 +580,18 @@ static const char b64tab[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static void base64_encode(const unsigned char *in, int inlen, char *out) { static void base64_encode(const unsigned char *in, int inlen, char *out) {
int i=0, j=0; int j = 0;
while (i < inlen) { for (int i = 0; i < inlen; i += 3) {
unsigned int a=i<inlen?(unsigned char)in[i++]:0; unsigned int a = (unsigned char)in[i];
unsigned int b=i<inlen?(unsigned char)in[i++]:0; unsigned int b = (i+1 < inlen) ? (unsigned char)in[i+1] : 0;
unsigned int c=i<inlen?(unsigned char)in[i++]:0; unsigned int c = (i+2 < inlen) ? (unsigned char)in[i+2] : 0;
unsigned int n=(a<<16)|(b<<8)|c; unsigned int n = (a << 16) | (b << 8) | c;
out[j++]=b64tab[(n>>18)&63]; out[j++]=b64tab[(n>>12)&63]; out[j++] = b64tab[(n >> 18) & 63];
out[j++]=(i-2<=inlen)?b64tab[(n>>6)&63]:'='; out[j++] = b64tab[(n >> 12) & 63];
out[j++]=(i-1<=inlen)?b64tab[n&63]:'='; out[j++] = (i+1 < inlen) ? b64tab[(n >> 6) & 63] : '=';
out[j++] = (i+2 < inlen) ? b64tab[n & 63] : '=';
} }
out[j]='\0'; out[j] = '\0';
} }
/* ── IRC line handler (net thread — uses si to tag every event) ────────────── */ /* ── IRC line handler (net thread — uses si to tag every event) ────────────── */
@@ -604,18 +606,33 @@ static void handle_irc_line(int si, const char *raw) {
return; return;
} }
/* SASL */ /* SASL / CAP negotiation */
if (strcmp(m.cmd,"CAP")==0) { if (strcmp(m.cmd,"CAP")==0) {
char sub[16]=""; char sub[16]="";
if (m.nparams>=2) str_upper(sub, m.params[1], sizeof(sub)); if (m.nparams>=2) str_upper(sub, m.params[1], sizeof(sub));
if (strcmp(sub,"ACK")==0) { else if (m.nparams>=1) str_upper(sub, m.params[0], sizeof(sub));
/* trail or last param may contain "sasl" */
const char *caps = m.trail[0] ? m.trail : m.params[m.nparams-1]; /* log all CAP lines to status for visibility */
char capdbg[MAX_LINE];
snprintf(capdbg,sizeof(capdbg),"[CAP] %s",raw);
ev_simple(EV_STATUS, si, NULL, NULL, capdbg);
if (strcmp(sub,"LS")==0) {
/* server advertising capabilities -- request sasl */
srv_send_raw(si, "CAP REQ :sasl");
} else if (strcmp(sub,"ACK")==0) {
const char *caps = m.trail[0] ? m.trail : (m.nparams>0?m.params[m.nparams-1]:"");
if (strstr(caps,"sasl")) { if (strstr(caps,"sasl")) {
if (!s->sasl_auth_sent) {
s->sasl_auth_sent = 1;
srv_send_raw(si, "AUTHENTICATE PLAIN"); srv_send_raw(si, "AUTHENTICATE PLAIN");
} }
} else {
srv_send_raw(si, "CAP END");
}
} else if (strcmp(sub,"NAK")==0) { } else if (strcmp(sub,"NAK")==0) {
ev_simple(EV_ERROR, si, NULL, NULL, "Server rejected SASL CAP."); ev_simple(EV_ERROR, si, NULL, NULL, "Server rejected SASL CAP -- connecting without SASL.");
srv_send_raw(si, "CAP END");
srv_sendf(si, "NICK %s", s->nick); srv_sendf(si, "NICK %s", s->nick);
srv_sendf(si, "USER %s 0 * :sirc", s->nick); srv_sendf(si, "USER %s 0 * :sirc", s->nick);
} }
@@ -991,9 +1008,11 @@ static void *net_thread(void *arg) {
} }
int sasl_pending=(s->sasl_user[0]&&s->sasl_pass[0])?1:0; int sasl_pending=(s->sasl_user[0]&&s->sasl_pass[0])?1:0;
if (sasl_pending) s->sasl_auth_sent = 0;
srv_send_raw(si,"CAP REQ :sasl"); if (sasl_pending) {
else { /* CAP LS 302: proper negotiation, handler sends CAP REQ :sasl on LS reply */
srv_send_raw(si,"CAP LS 302");
} else {
srv_sendf(si,"NICK %s",s->nick); srv_sendf(si,"NICK %s",s->nick);
srv_sendf(si,"USER %s 0 * :sirc",s->nick); srv_sendf(si,"USER %s 0 * :sirc",s->nick);
} }