diff src/noffle.c @ 288:c02c4eb95f95 noffle

[svn] * src/configfile.h,src/configfile.c,docs/noffle.conf.5: Add noffle-user and noffle-group configs. * src/configfile.c,src/fetch.c,src/fetchlist.c,src/protocol.c, src/server.c: Replace strcpy() with Utl_cpyStr() where appropriate. See Debian bug 168128. * src/control.c,src/configfile.c,src/noffle.c: Replace [s]scanf("%s") with [s]scanf(MAXCHAR_FMT). * src/noffle.c: Log warning if noffle.conf is world readable. * src/noffle.c: Restrict most options to news admins; i.e. those who are root or news on running Noffle. * Makefile.in,acconfig.h,aclocal.m4,config.h.in,configure,configure.in, docs/Makefile.in,docs/noffle.conf.5,packages/Makefile.in, packages/redhat/Makefile.in,src/Makefile.am,src/Makefile.in, src/authenticate.c,src/authenticate.h,src/noffle.c,src/server.c: Add basic authentication using either Noffle-specific user file or authenticating via PAM (service 'noffle'). PAM authentication needs to run as root, so a Noffle server that needs PAM must be started by root. Helpful (?) error messages will be logged if not. Noffle will switch ruid and euid to 'news' (or whatever is configured) ASAP. * src/noffle.c: Add uid checking.
author bears
date Fri, 10 Jan 2003 23:25:45 +0000
parents 5eece4dfd945
children b0e754727abf
line wrap: on
line diff
--- a/src/noffle.c	Fri Jan 10 23:11:43 2003 +0000
+++ b/src/noffle.c	Fri Jan 10 23:25:45 2003 +0000
@@ -10,7 +10,7 @@
   received for some seconds (to allow multiple clients connect at the same
   time).
 
-  $Id: noffle.c 413 2002-12-27 21:48:25Z bears $
+  $Id: noffle.c 420 2003-01-10 23:25:45Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -20,12 +20,16 @@
 #include <ctype.h>
 #include <errno.h>
 #include <signal.h>
+#include <string.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <syslog.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "common.h"
+#include "authenticate.h"
 #include "client.h"
-#include "common.h"
 #include "content.h"
 #include "control.h"
 #include "configfile.h"
@@ -227,11 +231,11 @@
                 || Wld_match( serv, noffle.serverPattern ) )
             if ( Fetch_init( serv ) )
             {
-	        int stat = STAT_OK;
+	        int status = STAT_OK;
 	    
                 if ( noffle.queryGrps )
-                    stat = Client_getGrps();
-                if ( stat == STAT_OK && noffle.queryDsc )
+                    status = Client_getGrps();
+                if ( status == STAT_OK && noffle.queryDsc )
                     Client_getDsc();
                 Fetch_close();
             }
@@ -339,7 +343,7 @@
 		    Str xgrp;
 		    int no;
 
-		    if ( sscanf( xref, "%s:%d", xgrp, &no ) != 2 )
+		    if ( sscanf( xref, MAXCHAR_FMT ":%d", xgrp, &no ) != 2 )
 		    {
 			/* Malformed xref - leave article just in case */
 			Log_err( "Malformed Xref: entry in %s: %s",
@@ -552,6 +556,25 @@
     fprintf( stderr, "%s", msg );
 }
 
+    
+/* Check we are 'root' or the noffle user (usually 'news') */
+static Bool
+checkCurrentUser( void )
+{
+    if ( ! Auth_checkPrivs() )
+	return FALSE;
+    
+    /*
+     * If we're noffle.lockAtStartup, we need to drop privs now.
+     * Otherwise we're a server, and privs get dropped after authentication.
+     */
+    if ( noffle.lockAtStartup )
+	if ( ! Auth_dropPrivs() )
+	    return FALSE;
+    
+    return TRUE;
+}
+
 /*
   Check file ownership and permissions.
   This assumes we have cd'd to the spool directory.
@@ -559,6 +582,16 @@
 static Bool
 checkFileOwnership( void )
 {
+    Str confFile;
+    struct stat statBuf;
+    
+    Utl_cpyStr( confFile, CONFIGFILE );
+    if ( stat( confFile, &statBuf ) == 0 )
+    {
+	if ( ( statBuf.st_mode & S_IROTH ) != 0 )
+	    Log_inf( "Security warning: %s is globally readable." );
+    }
+    
     return TRUE;
 }
 
@@ -589,9 +622,13 @@
 initNoffle( void )
 {
     Log_init( "noffle", noffle.lockAtStartup, LOG_NEWS );
+
     Cfg_read();
     Log_dbg( LOG_DBG_NOFFLE, "NOFFLE version %s", Cfg_version() );
 
+    if ( ! checkCurrentUser() )
+	return FALSE;
+    
     /* cd to the spool directory */
     if ( chdir( Cfg_spoolDir() ) != 0 )
     {
@@ -798,6 +835,9 @@
     return res;
 }
 
+/* Options available to ordinary users, as opposed to administrators. */
+static const char* USER_OPTIONS = "adghlpRv";
+
 int main ( int argc, char **argv )
 {
     int c, result;
@@ -814,6 +854,9 @@
     signal( SIGTERM, logSignal );
     signal( SIGPIPE, logSignal );
 
+    /* Set umask, just in case. */
+    umask(022);
+
     /* Find last component of command name. */
     cmdname = argv[0];
     p = strrchr( cmdname, '/' );
@@ -827,7 +870,7 @@
     if ( strcmp( cmdname, "inews" ) == 0 )
 	return doInews( argc, argv );
 
-    c = -1;
+    c = 'h';
     if ( *argv != NULL )
     {
 	c = getArgLetter( *argv );
@@ -835,8 +878,6 @@
 	argc--;
     }
 
-    noffle.lockAtStartup = ! ( c == 'r' || c == 'h' );
-
     /*
       If they asked for help, give it before there's a possibility
       we could fail on init.
@@ -847,8 +888,17 @@
 	return EXIT_SUCCESS;
     }
 
+    noffle.lockAtStartup = ! ( c == 'r' );
+
     if ( ! initNoffle() )
         return EXIT_FAILURE;
+
+    if ( ! Auth_admin() && strchr( USER_OPTIONS, c ) == NULL )
+    {
+	fprintf( stderr, "You must be a news administrator to do that.\n" );
+	return EXIT_FAILURE;
+    }
+    
     result = EXIT_SUCCESS;
     switch ( c )
     {
@@ -904,10 +954,6 @@
     case 'g':
         doGrps();
         break;
-    case -1:
-    case 'h':
-        printUsage();
-        break;
     case 'l':
         doList();
         break;