comparison 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
comparison
equal deleted inserted replaced
287:01755687c565 288:c02c4eb95f95
8 not as server. If noffle runs as server, locking is performed while 8 not as server. If noffle runs as server, locking is performed while
9 executing NNTP commands, but temporarily released if no new command is 9 executing NNTP commands, but temporarily released if no new command is
10 received for some seconds (to allow multiple clients connect at the same 10 received for some seconds (to allow multiple clients connect at the same
11 time). 11 time).
12 12
13 $Id: noffle.c 413 2002-12-27 21:48:25Z bears $ 13 $Id: noffle.c 420 2003-01-10 23:25:45Z bears $
14 */ 14 */
15 15
16 #if HAVE_CONFIG_H 16 #if HAVE_CONFIG_H
17 #include <config.h> 17 #include <config.h>
18 #endif 18 #endif
19 19
20 #include <ctype.h> 20 #include <ctype.h>
21 #include <errno.h> 21 #include <errno.h>
22 #include <signal.h> 22 #include <signal.h>
23 #include <string.h>
23 #include <sys/time.h> 24 #include <sys/time.h>
24 #include <sys/resource.h> 25 #include <sys/resource.h>
25 #include <syslog.h> 26 #include <syslog.h>
26 #include <unistd.h> 27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include "common.h"
31 #include "authenticate.h"
27 #include "client.h" 32 #include "client.h"
28 #include "common.h"
29 #include "content.h" 33 #include "content.h"
30 #include "control.h" 34 #include "control.h"
31 #include "configfile.h" 35 #include "configfile.h"
32 #include "database.h" 36 #include "database.h"
33 #include "expire.h" 37 #include "expire.h"
225 while ( Cfg_nextServ( serv ) ) 229 while ( Cfg_nextServ( serv ) )
226 if ( ! noffle.serverPattern 230 if ( ! noffle.serverPattern
227 || Wld_match( serv, noffle.serverPattern ) ) 231 || Wld_match( serv, noffle.serverPattern ) )
228 if ( Fetch_init( serv ) ) 232 if ( Fetch_init( serv ) )
229 { 233 {
230 int stat = STAT_OK; 234 int status = STAT_OK;
231 235
232 if ( noffle.queryGrps ) 236 if ( noffle.queryGrps )
233 stat = Client_getGrps(); 237 status = Client_getGrps();
234 if ( stat == STAT_OK && noffle.queryDsc ) 238 if ( status == STAT_OK && noffle.queryDsc )
235 Client_getDsc(); 239 Client_getDsc();
236 Fetch_close(); 240 Fetch_close();
237 } 241 }
238 } 242 }
239 243
337 xref = Itl_next( xrefs) ) 341 xref = Itl_next( xrefs) )
338 { 342 {
339 Str xgrp; 343 Str xgrp;
340 int no; 344 int no;
341 345
342 if ( sscanf( xref, "%s:%d", xgrp, &no ) != 2 ) 346 if ( sscanf( xref, MAXCHAR_FMT ":%d", xgrp, &no ) != 2 )
343 { 347 {
344 /* Malformed xref - leave article just in case */ 348 /* Malformed xref - leave article just in case */
345 Log_err( "Malformed Xref: entry in %s: %s", 349 Log_err( "Malformed Xref: entry in %s: %s",
346 msgId, xref); 350 msgId, xref);
347 toDelete = FALSE; 351 toDelete = FALSE;
550 " -u | --unsubscribe <grp> Remove group from fetch list\n" 554 " -u | --unsubscribe <grp> Remove group from fetch list\n"
551 " -v | --version Print version\n"; 555 " -v | --version Print version\n";
552 fprintf( stderr, "%s", msg ); 556 fprintf( stderr, "%s", msg );
553 } 557 }
554 558
559
560 /* Check we are 'root' or the noffle user (usually 'news') */
561 static Bool
562 checkCurrentUser( void )
563 {
564 if ( ! Auth_checkPrivs() )
565 return FALSE;
566
567 /*
568 * If we're noffle.lockAtStartup, we need to drop privs now.
569 * Otherwise we're a server, and privs get dropped after authentication.
570 */
571 if ( noffle.lockAtStartup )
572 if ( ! Auth_dropPrivs() )
573 return FALSE;
574
575 return TRUE;
576 }
577
555 /* 578 /*
556 Check file ownership and permissions. 579 Check file ownership and permissions.
557 This assumes we have cd'd to the spool directory. 580 This assumes we have cd'd to the spool directory.
558 */ 581 */
559 static Bool 582 static Bool
560 checkFileOwnership( void ) 583 checkFileOwnership( void )
561 { 584 {
585 Str confFile;
586 struct stat statBuf;
587
588 Utl_cpyStr( confFile, CONFIGFILE );
589 if ( stat( confFile, &statBuf ) == 0 )
590 {
591 if ( ( statBuf.st_mode & S_IROTH ) != 0 )
592 Log_inf( "Security warning: %s is globally readable." );
593 }
594
562 return TRUE; 595 return TRUE;
563 } 596 }
564 597
565 /* 598 /*
566 Allow core files: Change core limit and change working directory 599 Allow core files: Change core limit and change working directory
587 620
588 static Bool 621 static Bool
589 initNoffle( void ) 622 initNoffle( void )
590 { 623 {
591 Log_init( "noffle", noffle.lockAtStartup, LOG_NEWS ); 624 Log_init( "noffle", noffle.lockAtStartup, LOG_NEWS );
625
592 Cfg_read(); 626 Cfg_read();
593 Log_dbg( LOG_DBG_NOFFLE, "NOFFLE version %s", Cfg_version() ); 627 Log_dbg( LOG_DBG_NOFFLE, "NOFFLE version %s", Cfg_version() );
594 628
629 if ( ! checkCurrentUser() )
630 return FALSE;
631
595 /* cd to the spool directory */ 632 /* cd to the spool directory */
596 if ( chdir( Cfg_spoolDir() ) != 0 ) 633 if ( chdir( Cfg_spoolDir() ) != 0 )
597 { 634 {
598 Log_err( "Cannot change to directory '%s'", Cfg_spoolDir() ); 635 Log_err( "Cannot change to directory '%s'", Cfg_spoolDir() );
599 return FALSE; 636 return FALSE;
796 } 833 }
797 834
798 return res; 835 return res;
799 } 836 }
800 837
838 /* Options available to ordinary users, as opposed to administrators. */
839 static const char* USER_OPTIONS = "adghlpRv";
840
801 int main ( int argc, char **argv ) 841 int main ( int argc, char **argv )
802 { 842 {
803 int c, result; 843 int c, result;
804 const char *cmdname, *p; 844 const char *cmdname, *p;
805 845
812 signal( SIGILL, logSignal ); 852 signal( SIGILL, logSignal );
813 signal( SIGINT, logSignal ); 853 signal( SIGINT, logSignal );
814 signal( SIGTERM, logSignal ); 854 signal( SIGTERM, logSignal );
815 signal( SIGPIPE, logSignal ); 855 signal( SIGPIPE, logSignal );
816 856
857 /* Set umask, just in case. */
858 umask(022);
859
817 /* Find last component of command name. */ 860 /* Find last component of command name. */
818 cmdname = argv[0]; 861 cmdname = argv[0];
819 p = strrchr( cmdname, '/' ); 862 p = strrchr( cmdname, '/' );
820 if ( p != NULL ) 863 if ( p != NULL )
821 cmdname = ++p; 864 cmdname = ++p;
825 868
826 /* Were we invoked as inews? */ 869 /* Were we invoked as inews? */
827 if ( strcmp( cmdname, "inews" ) == 0 ) 870 if ( strcmp( cmdname, "inews" ) == 0 )
828 return doInews( argc, argv ); 871 return doInews( argc, argv );
829 872
830 c = -1; 873 c = 'h';
831 if ( *argv != NULL ) 874 if ( *argv != NULL )
832 { 875 {
833 c = getArgLetter( *argv ); 876 c = getArgLetter( *argv );
834 argv++; 877 argv++;
835 argc--; 878 argc--;
836 } 879 }
837
838 noffle.lockAtStartup = ! ( c == 'r' || c == 'h' );
839 880
840 /* 881 /*
841 If they asked for help, give it before there's a possibility 882 If they asked for help, give it before there's a possibility
842 we could fail on init. 883 we could fail on init.
843 */ 884 */
845 { 886 {
846 printUsage(); 887 printUsage();
847 return EXIT_SUCCESS; 888 return EXIT_SUCCESS;
848 } 889 }
849 890
891 noffle.lockAtStartup = ! ( c == 'r' );
892
850 if ( ! initNoffle() ) 893 if ( ! initNoffle() )
851 return EXIT_FAILURE; 894 return EXIT_FAILURE;
895
896 if ( ! Auth_admin() && strchr( USER_OPTIONS, c ) == NULL )
897 {
898 fprintf( stderr, "You must be a news administrator to do that.\n" );
899 return EXIT_FAILURE;
900 }
901
852 result = EXIT_SUCCESS; 902 result = EXIT_SUCCESS;
853 switch ( c ) 903 switch ( c )
854 { 904 {
855 case 'a': 905 case 'a':
856 if ( *argv == NULL ) 906 if ( *argv == NULL )
901 noffle.serverPattern = *argv; 951 noffle.serverPattern = *argv;
902 doFetch(); 952 doFetch();
903 break; 953 break;
904 case 'g': 954 case 'g':
905 doGrps(); 955 doGrps();
906 break;
907 case -1:
908 case 'h':
909 printUsage();
910 break; 956 break;
911 case 'l': 957 case 'l':
912 doList(); 958 doList();
913 break; 959 break;
914 case 'm': 960 case 'm':