Adding Authinfo Support

Starling <[email protected]>
Newsgroups gmane.network.sn
Message-ID <[email protected]>
Say um... shouldn't sn do some form of authinfo?  I mean, a local news
server would be perfect for a message board if it had authinfo (and
perhaps stunnel but that's another story...).  Is anyone working on
this?  Eh, well regardless I added authinfo for write-access support
to my copy of sn yesterday.  Might as well attach the diff.  Sorry for
stepping on anyone's toes. I think it's pretty much bug free.

I've never done a diff before.  Is this the right numbering scheme,
diff format, et. al?

Starling
Who's going to do some homework now.
sn.diff (text/x-patch, 11.5 KB)
diff -U 3 --new-file sn-0.3.5/CHANGES sn-0.3.6/CHANGES
--- sn-0.3.5/CHANGES	Sat Jul  6 08:38:51 2002
+++ sn-0.3.6/CHANGES	Mon Dec  9 20:51:37 2002
@@ -1,5 +1,26 @@
 --
-0.3.5 Sat Jul  6 18:37:50 EEST 2002
+0.3.6 Sun Dec 8 21:17:30 PDT 2002
+Added AUTHINFO functionality.  I mean, jeez...
+New configuration files:
+SNROOT/user.allow
+	file with "user:password" pairs, one per line
+	Note, the "user:password" line has a MAX of 200 characters,
+		'cause I'm too lazy to use dynamic memory.  Administrators
+		beware.
+	Note, this file has to be chown news.news and chmod o-rw or snntpd 
+		will not use it and post a warning log.
+
+SNROOT/.auth
+	presence activates authentication
+
+The RFC didn't say to drop the connection on failed authentication,
+but my emacs gnus seems to depend on that and I noticed another news
+server doing it so...
+
+entry by Starling ([email protected])
+
+--
+0.3.5 Sat Jul 6 18:37:50 EEST 2002
 Added an FAQ, containg the solution to the infamous POST problem.
 NEWGROUPS and NEWNEWS now works properly during DST. (Was offset one hour.)
 Made "sncat -i foo" work for users with read-only access to the spool.
@@ -34,7 +55,7 @@
 snexpire bug related to =junk.
 writefifo has been failing for a few revs now!  Fixed.
 --
-0.3.2 Fri Mar  3 22:33:02 SGT 2000
+0.3.2 Fri Mar 3 22:33:02 SGT 2000
 Changed ctime to mtime, when checking .created.
 Date conversion error, e.g. for NEWGROUPS and NEWNEWS.
 Doc error, command line example using tcpserver.
@@ -99,14 +120,14 @@
 snget (and others) takes -P, passes to snfetch.
 0-length article bodies now legal in snntpd and snscan.
 --
-0.2.3 Mon Dec  7 12:44:03 SGT 1998
+0.2.3 Mon Dec 7 12:44:03 SGT 1998
 Option -m for snget to limit initial articles.
 snpost locking now performed.
 snmail EOL conversion error; rewrite.
 snntpd LIST command output format error.
 snfetch rnews format error.
 --
-0.2.2 Thu Oct  8 11:02:54 SGT 1998
+0.2.2 Thu Oct 8 11:02:54 SGT 1998
 -r option in snstore, snfetch, sncat.
 Rewrote snget as binary instead of script.
 Merged dh_dump() into sndumpdb.c, it didn't belong in dhash.c.
@@ -125,7 +146,7 @@
 Better snpost reporting.
 Off-by-one in art.c, resulting in random crashes.
 --
-0.2.1 Wed Aug  5 18:29:37 SGT 1998
+0.2.1 Wed Aug 5 18:29:37 SGT 1998
 Missing realloc in subscribed.c, reorg in newsgroup.c.
 --
 0.2.0 Sat Jul 11 13:34:03 SGT 1998
diff -U 3 --new-file sn-0.3.5/Makefile sn-0.3.6/Makefile
--- sn-0.3.5/Makefile	Wed Jun 12 03:16:33 2002
+++ sn-0.3.6/Makefile	Sun Dec  8 23:14:06 2002
@@ -10,14 +10,14 @@
 ## No: Leave ZLIB undefined.
 #ZLIB =
 ## Where the news spool will be, e.g.: SNROOT=/var/spool/news
-SNROOT =/home/patrik/spool/news
+SNROOT =/var/spool/news
 ## Where to install the executables, e.g.: BINDIR=/usr/local/sbin
-BINDIR =/home/patrik/sn/bin
+BINDIR =/usr/local/news/bin
 ## Where to install the man pages, e.g.: MANDIR=/usr/local/man
-MANDIR =/home/patrik/sn/man
+MANDIR =/usr/local/news/man
 ## Where to send mail for the admin if neither the NEWSMASTER nor
 ## the LOGNAME environment variable is set
-DEFAULT_ADMIN_EMAIL =newsmaster
+DEFAULT_ADMIN_EMAIL =news
 
 #
 # OS-specific settings. Uncomment only one section below.
@@ -47,7 +47,7 @@
 #
 
 VERSION =0.3.5
-AOBJS =art.o cache.o group.o times.o dh_find.o dhash.o \
+AOBJS =art.o auth.o cache.o group.o times.o dh_find.o dhash.o \
  allocate.o newsgroup.o hostname.o \
  store.o parameters.o args.o body.o unfold.o path.o \
  addr.o valid.o key.o field.o
@@ -166,6 +166,7 @@
 ## DO NOT REMOVE ##
 
 art.o: art.c config.h art.h artfile.h cache.h
+auth.o: auth.c auth.h
 cache.o: cache.c cache.h
 group.o: group.c config.h cache.h group.h artfile.h
 times.o: times.c config.h times.h cache.h
diff -U 3 --new-file sn-0.3.5/auth.c sn-0.3.6/auth.c
--- sn-0.3.5/auth.c	Wed Dec 31 16:00:00 1969
+++ sn-0.3.6/auth.c	Mon Dec  9 20:43:48 2002
@@ -0,0 +1,111 @@
+#include "auth.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+extern void log (char *fmt, ...);
+
+struct authinfo auth;
+int auth_required = 0;
+
+#define BUFSIZE 200
+
+static char complete[BUFSIZE];
+static char buffer[BUFSIZE];
+
+int checkperms(int fd)
+{
+	struct stat statbuf;
+
+	if(fstat(fd, &statbuf))
+	{
+		log("Stat error! %s\n", strerror(errno));
+		return 0;
+	}
+
+	if(statbuf.st_mode & ( S_IWOTH | S_IROTH | S_IXOTH) ||
+	   statbuf.st_uid != getuid() ||
+	   statbuf.st_gid != getgid())
+	{
+		log("user.allow needs to be chown news.news or chmod 660.");
+		return 0;
+	}
+
+	return 1;
+}	
+
+int find_user(char* data)
+{
+	FILE* db = fopen("user.allow", "r");
+	int len = 0;
+
+	if(!db) goto FAIL;
+
+	if(!checkperms(fileno(db))) goto FAIL;
+
+	while(fgets(buffer, BUFSIZE, db))
+	{
+		if((len = (int) (strchr(buffer, ':') - buffer)))
+		{
+			strncpy(complete, buffer, len);
+			if(!strncmp(complete, data, strlen(data)))
+			{
+				fclose(db);
+				return 1;
+			}
+		}
+	}
+
+  FAIL:
+
+	bzero(complete, BUFSIZE);
+
+	fclose(db);
+	return 0;
+}
+
+int find_pass(char* data)
+{
+	FILE* db = fopen("user.allow", "r");
+
+	if(!db) goto FAIL;
+	if(!checkperms(fileno(db))) goto FAIL;
+
+	strcat(complete, ":");
+	
+	if(strlen(data) + strlen(complete) > BUFSIZE) goto FAIL;
+	
+	strcat(complete, data);
+
+	while(fgets(buffer, BUFSIZE, db))
+	{
+		char* p = strchr(buffer, '\n');
+		if(p) *p = '\0';
+		
+		if(!strcmp(buffer, complete))
+		{
+			fclose(db);
+			return 1;
+		}
+	}
+
+  FAIL:
+
+	bzero(complete, BUFSIZE);
+
+	fclose(db);
+	return 0;
+}
+
+void check_user(char* data)
+{
+	auth.user = find_user(data);
+}
+
+void check_pass(char* data)
+{
+	auth.pass = auth.user = find_pass(data);
+}
diff -U 3 --new-file sn-0.3.5/auth.h sn-0.3.6/auth.h
--- sn-0.3.5/auth.h	Wed Dec 31 16:00:00 1969
+++ sn-0.3.6/auth.h	Sun Dec  8 23:14:06 2002
@@ -0,0 +1,12 @@
+/* Interface for authorization. */
+
+struct authinfo {
+	int user;
+	int pass;
+};
+
+extern struct authinfo auth;
+extern int auth_required;
+
+void check_user(char* data);
+void check_pass(char* data);
diff -U 3 --new-file sn-0.3.5/commands.c sn-0.3.6/commands.c
--- sn-0.3.5/commands.c	Tue May 28 14:31:44 2002
+++ sn-0.3.6/commands.c	Sun Dec  8 23:26:35 2002
@@ -27,6 +27,7 @@
 #include "body.h"
 #include "snntpd.h"
 #include "key.h"
+#include "auth.h"
 #include <b.h>
 #include <tokensep.h>
 #include <wildmat.h>
@@ -37,18 +38,76 @@
 
 #define putdot() args_write(1, ".\r\n")
 
-void do_ihave (void) { args_write(1, "435 I'm happy for you\r\n"); }
+void do_ihave (void) { args_write(1, "435 I'm happy for you.  Try post.\r\n"); }
 void do_sendme (void) { args_write(1, "500 No thanks\r\n"); }
-void do_slave (void) { args_write(1, "202 Whatever\r\n"); }
+void do_slave (void) { args_write(1, "202 Not since the civil war, yank.\r\n"); }
 void do_help (void) { args_write(1, "100 Help yourself\r\n.\r\n"); }
 
 void do_mode (void)
 {
-   if (posting_ok)
-      args_write(1, "200 Hi, you can post (sn version " VERSION ")\r\n");
-   else
-      args_write(1, "201 Hi, you can't post (sn version " VERSION ")\r\n");
+	if (posting_ok)
+		args_write(1, "200 Hi, you can post (sn version " VERSION ")\r\n");
+	else
+		args_write(1, "201 Hi, you can't post (sn version " VERSION ")\r\n");
 }
+
+/* Authorization mode.  */
+
+extern void do_quit(void);
+
+void do_authinfo(void)
+{
+	char flag;
+	char* data;
+
+	if(!auth_required)
+	{
+		args_write(1, "102 No authorization required.\r\n");
+		return;
+	}
+
+	if(strcasecmp(args[1],"user") && strcasecmp(args[1], "pass")) {
+		args_write(1, "501 Usage authinfo user <user> then authinfo pass <pass>\r\n");
+		return;
+	}
+
+	flag = args[1][0];
+	data = args[2];
+
+	switch(flag)
+	{
+		case 'u':
+		case 'U':
+			check_user(data);
+			args_write(1, "381 PASS required for %s\r\n", data);
+			break;
+		case 'p':
+		case 'P':
+			if(!auth.user)
+			{
+				args_write(1, "482 USER required\r\n");
+				break;
+			} else {
+				check_pass(data);
+				if(!auth.pass)
+				{
+					args_write(1, "502 Authentication failed\r\n");
+					do_quit();
+				}
+			}
+			break;
+		default:
+			args_write(1, "502 %s doesn't start with '%c'?\r\n", args[1], flag);
+			break;
+	};
+
+	if(auth.user && auth.pass)
+	{
+		posting_ok = 1;
+		args_write(1, "281 I know you!  You can post\r\n");
+	}
+}
+	
 
 /* Several ways to specify an article.  The group may be the current
    one, or it may be a different one */
Common subdirectories: sn-0.3.5/lib and sn-0.3.6/lib
diff -U 3 --new-file sn-0.3.5/parameters.c sn-0.3.6/parameters.c
--- sn-0.3.5/parameters.c	Thu May 23 17:37:11 2002
+++ sn-0.3.6/parameters.c	Sun Dec  8 23:14:06 2002
@@ -27,7 +27,7 @@
       snroot = SNROOT;
 
    if (-1 == stat(snroot, &st))
-      fail(2, "Can't find \"%s\":%m");
+      fail(2, "Can't find \"%s\":%m", snroot);
    if (!S_ISDIR(st.st_mode))
       fail(2, "%s is not a directory");
    snuid = st.st_uid;
diff -U 3 --new-file sn-0.3.5/post.c sn-0.3.6/post.c
--- sn-0.3.5/post.c	Sat Oct  6 09:39:48 2001
+++ sn-0.3.6/post.c	Sun Dec  8 23:14:06 2002
@@ -98,7 +98,10 @@
 
    if (!posting_ok)
    {
-      args_write(1, "440 Posting not allowed\r\n");
+      if(!auth_required)
+		  args_write(1, "440 Posting not allowed\r\n");
+	  else
+		  args_write(1, "480 Authorization required\r\n");
       return;
    }
 
diff -U 3 --new-file sn-0.3.5/snntpd.8.in sn-0.3.6/snntpd.8.in
--- sn-0.3.5/snntpd.8.in	Mon Jul 26 02:55:49 1999
+++ sn-0.3.6/snntpd.8.in	Mon Dec  9 20:45:40 2002
@@ -48,7 +48,7 @@
 .SH POSTING AND POSTING PERMISSIONS
 Posts are usually handled externally by the
 .RB !!BINDIR!!/ POST
-script, 
+script,
 which is responsible for fine-grain posting control; handling of
 control messages; and the ultimate distribution of the posted
 article.
@@ -73,6 +73,19 @@
 .RB $ POSTING_OK
 is not currently used, but is reserved.
 
+
+.TP
+.B AUTHINFO
+If
+.RB !!SNROOT!!/ .auth
+exists, authinfo support is enabled.
+
+.RB !!SNROOT!!/ user.access
+should have a list of newline delineated user:pass pairs for
+which user is authorized by which password.  These do not
+correspond to login users.  user.access must be owned by
+news.news and not world read or writeable.
+
 .SH FILES
 .TP
 .RB !!SNROOT!!/ .fifo
@@ -94,6 +107,12 @@
 
 .TP
 .RB !!SNROOT!!/ .nopost
+See
+.B POSTING PERMISSIONS
+above.
+
+.TP
+.RB !!SNROOT!!/ .auth
 See
 .B POSTING PERMISSIONS
 above.
diff -U 3 --new-file sn-0.3.5/snntpd.c sn-0.3.6/snntpd.c
--- sn-0.3.5/snntpd.c	Mon May 27 13:17:35 2002
+++ sn-0.3.6/snntpd.c	Sun Dec  8 23:14:06 2002
@@ -55,6 +55,7 @@
 extern int currentserial;
 
 extern void do_article (void);
+extern void do_authinfo(void);
 extern void do_body (void);
 extern void do_group (void);
 extern void do_head (void);
@@ -91,6 +92,7 @@
 
 static struct cmd cmds[] = {
    DEF(article, 1, 0, 0, 0)
+   DEF(authinfo, 3, 0, 0, 0)
    DEF(body, 1, 0, 0, 0)
    DEF(group, 2, 0, 0, 1)
    DEF(head, 1, 0, 0, 0)
@@ -199,6 +201,15 @@
       posting_ok = 1;
    else
       posting_ok = 0;
+
+   if (0 == stat(".auth", &st))
+   {
+	   auth_required = 1;
+	   posting_ok = 0;
+   }
+   else
+	   auth_required = 0;
+   
    openfifo();
    checkservice = 0;
 }
diff -U 3 --new-file sn-0.3.5/snntpd.h sn-0.3.6/snntpd.h
--- sn-0.3.5/snntpd.h	Sat Oct  6 10:27:33 2001
+++ sn-0.3.6/snntpd.h	Sun Dec  8 23:14:06 2002
@@ -9,6 +9,7 @@
 #define SNNTPD_H
 
 extern int posting_ok;
+extern int auth_required;
 extern char *client_ip;
 extern char *me;
 extern struct readln input;
diff -U 3 --new-file sn-0.3.5/user.allow.EXAMPLE sn-0.3.6/user.allow.EXAMPLE
--- sn-0.3.5/user.allow.EXAMPLE	Wed Dec 31 16:00:00 1969
+++ sn-0.3.6/user.allow.EXAMPLE	Sun Dec  8 23:45:52 2002
@@ -0,0 +1,6 @@
+ima_user:mypassword
+Foobar:eatshorts
+Hmm:dmm
+Dorothy:toto
+legolas:gandalf
+ozy:millie
\ No newline at end of file
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.