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

Reply via email to