Mercurial > noffle
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': |