pls also consider tls client-certs that oftc and freenode support this way authentication doesn't happen on irc layer any more.
On Wed, Oct 15, 2025 at 5:31 AM noodle via 9fans <[email protected]> wrote: > > i got ircsrv to automatically authenticate via PASS and/or NickServ > through factotum and added a joinlist option. i haven't written much > C in years so comments/criticism welcome :) > > apologies for the sloppy patch + the 60 second sleep (might lower it i > guess). i also should've split it into multiple commits but thought > yall would like to see it. it connects well and i can chat so far. > haven't used it for a while to uncover any hidden bugs > > thank u > > -- > noodle > > --- > diff ef4697c47cda464feb2fb57fcedf9453eb0bfddc > 37e5da47095c2e3d7ab843988decc0c6cd32fc83 > --- a/irc.man > +++ b/irc.man > @@ -4,7 +4,7 @@ > .SH SYNOPSIS > .B ircsrv > [ > -.I -e > +.I -eip > ] > [ > .I -s service > @@ -13,7 +13,7 @@ > .I -f file > ] > [ > -.I -p pass > +.I -j joinlist > ] > .I nickname > .I [net!]irc.server.org[!port] > @@ -79,6 +79,18 @@ > The > .I -e > flag enables SSL, the > +.I -f > +flag sets the pathname of the log file, the > +.I -j > +flag sets a list of channels to join (ex: -j '#aaa,#bbb,#ccc'), the > +.I -s > +flag sets the filename of the service file under /srv, > +.I -i > +flag sends a password to NickServ (from factotum service=ircsrv) after > connecting to server and enables SSL, the > +.I -p > +flag is like the > +.I -i > +flag but sends the password to the server on connection instead (both can be > combined), the > .I -c > flag sets character set conversion using > .IR tcs (1), > --- a/ircsrv.c > +++ b/ircsrv.c > @@ -3,6 +3,8 @@ > #include <auth.h> > #include <libsec.h> > > +enum { ReconDelay = 60 }; /* time in seconds to sleep before > reconnecting to server */ > + > char *post; > char *file; > int ircfd = -1; // the irc server > @@ -10,23 +12,27 @@ > int enctls = 0; // ssl/tls > QLock lck; > > +UserPasswd *pass = nil; > +UserPasswd *nickpass = nil; > +char *chans = nil; > +char *host; > char *server; > -char *passwd; > char *nickname; > -char *realname; > -char *username; > -char *mode = "foo"; > -char *unused = "bar"; > +char *realname = nil; > +char *username = nil; > +char *port = "6667"; > > void ircsrv(void); > void logger(void); > void die(void*, char*); > void reconnect(void); > +void authnick(void); > +void joinchans(void); > > void > usage(void) > { > - fprint(2, "usage: %s [-e] [-s service] [-f file] [-p pass] nickname > [net!]ircserver[!port]\n", argv0); > + fprint(2, "usage: %s [-eip] [-f file] [-j join] [-s service] [ -r > realname ] [ -u username ] nickname [net!]ircserver[!port]\n", argv0); > exits("usage"); > } > > @@ -50,13 +56,17 @@ > void > main(int argc, char *argv[]) > { > - char *tmp; > - int p[2], fd; > + char *netaddr[3]; > + int getpass = 0, getnickpass = 0; > + int nf, p[2], fd; > > ARGBEGIN{ > case 'f': > file = EARGF(usage()); > break; > + case 'j': > + chans = EARGF(usage()); > + break; > case 's': > post = EARGF(usage()); > break; > @@ -63,19 +73,20 @@ > case 'r': > realname = EARGF(usage()); > break; > + case 'u': > + username = EARGF(usage()); > + break; > case 'e': > enctls = 1; > break; > case 'p': > - passwd = EARGF(usage()); > - /* try to obfuscate the password so ps -a won't see it */ > - tmp = passwd; > - passwd = smprint("%s", tmp); > - if(passwd) > - memset(tmp, '\0', strlen(tmp)); > - else > - passwd = tmp; > + getpass = 1; > + enctls = 1; > break; > + case 'i': > + getnickpass = 1; > + enctls = 1; > + break; > default: > usage(); > }ARGEND; > @@ -82,16 +93,34 @@ > > if(argc < 2) > usage(); > + if(enctls) > + port = "6697"; > > - > nickname = argv[0]; > server = argv[1]; > > - username = getuser(); > + nf = getfields(server, netaddr, 3, 0, "!"); > + host = nf == 3 ? netaddr[1] : server; > + if(getpass){ > + pass = auth_getuserpasswd(auth_getkey, > + "proto=pass service=irc server=%q user=%q", host, > nickname); > + if(pass == nil) > + sysfatal("auth_getuserpasswd"); > + } > + if(getnickpass){ > + nickpass = auth_getuserpasswd(auth_getkey, > + "proto=pass service=ircsrv server=%q user=%q", host, > nickname); > + if(nickpass == nil) > + sysfatal("auth_getuserpasswd"); > + } > > + if(!username) > + username = getuser(); > if(strlen(username) > 4) > username[4] = '\0'; > > + if (!realname) > + realname = "<nil>"; > > if(post == nil) > post = smprint("/srv/%sirc", username); > @@ -188,22 +217,51 @@ > TLSconn *conn; > if(ircfd >= 0) > close(ircfd); > - if((ircfd = dial(netmkaddr(server, "tcp", "6667"), nil, nil, nil)) < > 0) > + if((ircfd = dial(netmkaddr(server, "tcp", port), nil, nil, nil)) < 0) > sysfatal("dial %r"); > - if(enctls > 0) { > + if(enctls > 0){ > conn = (TLSconn *)mallocz(sizeof *conn, 1); > - ircfd = tlsClient(ircfd, conn); > + ircfd = tlsClient(ircfd, conn); > if (ircfd < 0) { sysfatal ("tls: %r"); } > } > - if(passwd && strcmp(passwd, "")) > - fprint(ircfd, "PASS %s\r\n", passwd); > - fprint(ircfd, "USER %s %s %s :%s\r\n", > - nickname, mode, unused, realname); > + if(pass && pass->passwd && strcmp(pass->passwd, "")) > + fprint(ircfd, "PASS %s\r\n", pass->passwd); > + fprint(ircfd, "USER %s * * :%s\r\n", username, realname); > fprint(ircfd, "NICK %s\r\n", nickname); > + authnick(); > + joinchans(); > } > > +void > +joinchans(void) > +{ > + char *s, *e; > + if(!chans) > + return; > + for(s = e = chans; *e; e++) > + if (*e == ',' && e - s > 0) { > + fprint(ircfd, "JOIN %.*s\r\n", (int) (e - s), s); > + s = e + 1; > + } > + if(e - s > 0) > + fprint(ircfd, "JOIN %.*s\r\n", (int) (e - s), s); > +} > > void > +authnick(void){ > + char *labels[3]; > + int nf; > + > + if(!nickpass || !nickpass->passwd || !strcmp(nickpass->passwd, "")) > + return; > + nf = getfields(host, labels, 3, 0, "."); > + if(nf == 3 && !strcmp(labels[1], "oftc") && !strcmp(labels[2], "net")) > + fprint(ircfd, "PRIVMSG NickServ :IDENTIFY %s %s\r\n", > nickpass->passwd, nickname); > + else > + fprint(ircfd, "PRIVMSG NickServ :IDENTIFY %s %s\r\n", > nickname, nickpass->passwd); > +} > + > +void > logger(void) > { > char buf[513]; > @@ -211,6 +269,7 @@ > long n; > > for(;;){ > + int doreauth = 0; > while((n = readln(ircfd, buf, sizeof(buf)-1)) > 0){ > fprint(logfd, "%ld ", time(0)); > write(logfd, buf, n); > @@ -221,15 +280,21 @@ > fprint(ircfd, "PONG %s\r\n", f[2]); > fprint(logfd, "%ld PONG %s\r\n", time(0), f[2]); > qunlock(&lck); > - } else if(n == 2 && !cistrcmp(f[0], "PING")){ > + }else if(n == 2 && !cistrcmp(f[0], "PING")){ > qlock(&lck); > fprint(ircfd, "PONG %s\r\n", f[1]); > fprint(logfd, "%ld PONG %s\r\n", time(0), f[1]); > qunlock(&lck); > - } else if(n == 3 && atoi(f[1]) == 433) { > + }else if(n == 3 && (atoi(f[1]) == 433 || atoi(f[1]) > == 437)){ > reregister(); > + doreauth = 1; > + }else if (doreauth && n == 3 && atoi(f[1]) == 001){ > + authnick(); > + fprint(ircfd, "PRIVMSG NickServ :REGAIN > %s\r\n", nickname); > + joinchans(); > } > } > + sleep(ReconDelay * 1000); > reconnect(); > } > } > @@ -251,5 +316,3 @@ > } > killall(); > } > - > - > -- > ⑨ > ------------------------------------------ 9fans: 9fans Permalink: https://9fans.topicbox.com/groups/9fans/Tda2484b041420163-Mb4b0969075a840df49196b2e Delivery options: https://9fans.topicbox.com/groups/9fans/subscription
