# HG changeset patch # User bears # Date 1042241145 0 # Node ID c02c4eb95f953b54340c11d07d7f3b26db20833c # Parent 01755687c5657498347ff18ad10f11ac68aaedb4 [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. diff -r 01755687c565 -r c02c4eb95f95 ChangeLog --- a/ChangeLog Fri Jan 10 23:11:43 2003 +0000 +++ b/ChangeLog Fri Jan 10 23:25:45 2003 +0000 @@ -1,3 +1,37 @@ +Fri Jan 10 2003 Jim Hague + +* docs/noffle.1: Correct Noffle home page location and add Mirko as author. + Also update Markus's email. Debian bug 173743. +* AUTHORS. Great maintainer I am, can't even credit myself. +* src/fetch.c: Add Reply-To to the front of the list of headers searched + for the article author's email when sending posting SNAFU message. + Debian bug 156952. +* 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/client.c. Replace strcpy() here too. +* src/control.c,src/configfile.c,src/noffle.c: Replace [s]scanf("%s") + with [s]scanf(MAXCHAR_FMT). +* Makefile.am: Install executable owner news.news mode 06755. Install + sample noffle.conf as 0640 news.news. +* 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. +* src/configfile.c: Change snprintf() to Utl_cpyStr(); +* 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. + Mon Jan 6 2003 Jim Hague * src/database.c,src/post.c,src/protocol.h,src/protocol.c: When posting, diff -r 01755687c565 -r c02c4eb95f95 Makefile.in --- a/Makefile.in Fri Jan 10 23:11:43 2003 +0000 +++ b/Makefile.in Fri Jan 10 23:25:45 2003 +0000 @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -62,10 +62,12 @@ CC = @CC@ CONFIGFILE = @CONFIGFILE@ DOCDIR = @DOCDIR@ +LIBPAM = @LIBPAM@ MAKEINFO = @MAKEINFO@ PACKAGE = @PACKAGE@ SENDMAILPROG = @SENDMAILPROG@ SPOOLDIR = @SPOOLDIR@ +USERSFILE = @USERSFILE@ VERSION = @VERSION@ SUBDIRS = src docs packages @@ -96,7 +98,7 @@ $(ACLOCAL_M4): configure.in cd $(srcdir) && $(ACLOCAL) -config.status: $(srcdir)/configure.in $(CONFIG_STATUS_DEPENDENCIES) +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) cd $(srcdir) && $(AUTOCONF) @@ -165,7 +167,7 @@ dot_seen=no; \ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ rev="$$subdir $$rev"; \ - test "$$subdir" = "." && dot_seen=yes; \ + test "$$subdir" != "." || dot_seen=yes; \ done; \ test "$$dot_seen" = "no" && rev=". $$rev"; \ target=`echo $@ | sed s/-recursive//`; \ @@ -207,7 +209,7 @@ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ - || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) + || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP)) mostlyclean-tags: @@ -357,14 +359,14 @@ install-data-local: - $(INSTALL) -m 2755 -o news -g news -d $(DESTDIR)$(SPOOLDIR) + $(INSTALL) -m 06755 -o news -g news -d $(DESTDIR)$(SPOOLDIR) $(INSTALL) -o news -g news -d $(DESTDIR)$(SPOOLDIR)/data $(INSTALL) -o news -g news -d $(DESTDIR)$(SPOOLDIR)/lock $(INSTALL) -o news -g news -d $(DESTDIR)$(SPOOLDIR)/requested $(INSTALL) -o news -g news -d $(DESTDIR)$(SPOOLDIR)/outgoing $(INSTALL) -o news -g news -d $(DESTDIR)$(SPOOLDIR)/overview chown -R news.news $(DESTDIR)$(SPOOLDIR) - $(INSTALL) -m 755 -o 0 -g 0 -d $(DESTDIR)$(DOCDIR) + $(INSTALL) -m 0755 -o 0 -g 0 -d $(DESTDIR)$(DOCDIR) $(INSTALL_DATA) -o 0 -g 0 $(srcdir)/AUTHORS $(DESTDIR)$(DOCDIR) $(INSTALL_DATA) -o 0 -g 0 $(srcdir)/COPYING $(DESTDIR)$(DOCDIR) $(INSTALL_DATA) -o 0 -g 0 $(srcdir)/ChangeLog $(DESTDIR)$(DOCDIR) @@ -375,7 +377,7 @@ $(INSTALL_DATA) -D -o 0 -g 0 $(srcdir)/noffle.conf.example \ $(DESTDIR)$(CONFIGFILE).example chown news.news $(DESTDIR)$(CONFIGFILE).example - chmod 600 $(DESTDIR)$(CONFIGFILE).example + chmod 0640 $(DESTDIR)$(CONFIGFILE).example @echo @echo "****************************************************************" @echo "You should now copy $(DESTDIR)$(CONFIGFILE).example to $(CONFIGFILE)" @@ -385,7 +387,7 @@ install-exec-local: chown news.news $(DESTDIR)$(bindir)/`echo $(PACKAGE)|sed '$(transform)'` - chmod 4755 $(DESTDIR)$(bindir)/`echo $(PACKAGE)|sed '$(transform)'` + chmod 06755 $(DESTDIR)$(bindir)/`echo $(PACKAGE)|sed '$(transform)'` uninstall-local: rm -f $(DESTDIR)$(DOCDIR)/AUTHORS diff -r 01755687c565 -r c02c4eb95f95 acconfig.h --- a/acconfig.h Fri Jan 10 23:11:43 2003 +0000 +++ b/acconfig.h Fri Jan 10 23:25:45 2003 +0000 @@ -6,6 +6,9 @@ /* The NOFFLE config-file */ #undef CONFIGFILE +/* The NOFFLE users-file */ +#undef USERSFILE + /* The default NOFFLE spool-directory */ #undef SPOOLDIR @@ -18,6 +21,12 @@ /* path to sendmail binary */ #undef SENDMAILPROG +/* Is authentication enabled? */ +#undef USE_AUTH + +/* Are we using PAM for authentication? */ +#undef USE_PAM + @TOP@ /* autoheader generated things inserted here. */ @BOTTOM@ diff -r 01755687c565 -r c02c4eb95f95 aclocal.m4 --- a/aclocal.m4 Fri Jan 10 23:11:43 2003 +0000 +++ b/aclocal.m4 Fri Jan 10 23:25:45 2003 +0000 @@ -1,6 +1,6 @@ -dnl aclocal.m4 generated automatically by aclocal 1.4-p4 +dnl aclocal.m4 generated automatically by aclocal 1.4-p6 -dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -12,7 +12,7 @@ # Like AC_CONFIG_HEADER, but automatically create stamp file. -AC_DEFUN(AM_CONFIG_HEADER, +AC_DEFUN([AM_CONFIG_HEADER], [AC_PREREQ([2.12]) AC_CONFIG_HEADER([$1]) dnl When config.status generates a header, we must update the stamp-h file. @@ -42,8 +42,9 @@ dnl Usage: dnl AM_INIT_AUTOMAKE(package,version, [no-define]) -AC_DEFUN(AM_INIT_AUTOMAKE, -[AC_REQUIRE([AC_PROG_INSTALL]) +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL]) PACKAGE=[$1] AC_SUBST(PACKAGE) VERSION=[$2] @@ -59,18 +60,47 @@ AC_REQUIRE([AC_ARG_PROGRAM]) dnl FIXME This is truly gross. missing_dir=`cd $ac_aux_dir && pwd` -AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}, $missing_dir) AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) -AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}, $missing_dir) AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) AC_REQUIRE([AC_PROG_MAKE_SET])]) +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.4"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.4-p6])]) + # # Check to make sure that the build environment is sane. # -AC_DEFUN(AM_SANITY_CHECK, +AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 @@ -111,7 +141,7 @@ dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) dnl The program must properly implement --version. -AC_DEFUN(AM_MISSING_PROG, +AC_DEFUN([AM_MISSING_PROG], [AC_MSG_CHECKING(for working $2) # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. @@ -125,3 +155,30 @@ fi AC_SUBST($1)]) +# isc-posix.m4 serial 2 (gettext-0.11.2) +dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +# This file is not needed with autoconf-2.53 and newer. Remove it in 2005. + +# This test replaces the one in autoconf. +# Currently this macro should have the same name as the autoconf macro +# because gettext's gettext.m4 (distributed in the automake package) +# still uses it. Otherwise, the use in gettext.m4 makes autoheader +# give these diagnostics: +# configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX +# configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX + +undefine([AC_ISC_POSIX]) + +AC_DEFUN([AC_ISC_POSIX], + [ + dnl This test replaces the obsolescent AC_ISC_POSIX kludge. + AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"]) + ] +) + diff -r 01755687c565 -r c02c4eb95f95 config.h.in --- a/config.h.in Fri Jan 10 23:11:43 2003 +0000 +++ b/config.h.in Fri Jan 10 23:25:45 2003 +0000 @@ -7,6 +7,9 @@ /* The NOFFLE config-file */ #undef CONFIGFILE +/* The NOFFLE users-file */ +#undef USERSFILE + /* The default NOFFLE spool-directory */ #undef SPOOLDIR @@ -19,6 +22,12 @@ /* path to sendmail binary */ #undef SENDMAILPROG +/* Is authentication enabled? */ +#undef USE_AUTH + +/* Are we using PAM for authentication? */ +#undef USE_PAM + /* Define if on AIX 3. System headers sometimes define this. @@ -127,6 +136,9 @@ /* Define if you have the header file. */ #undef HAVE_NETDB_H +/* Define if you have the header file. */ +#undef HAVE_PWD_H + /* Define if you have the header file. */ #undef HAVE_REGEX_H diff -r 01755687c565 -r c02c4eb95f95 configure --- a/configure Fri Jan 10 23:11:43 2003 +0000 +++ b/configure Fri Jan 10 23:25:45 2003 +0000 @@ -16,6 +16,10 @@ ac_help="$ac_help --with-gdbm-libdir=DIR GDBM library files are in DIR" ac_help="$ac_help + --enable-auth=[no/file/pam] enable authentication [default=no]" +ac_help="$ac_help + --with-usersfile=FILE users file [/etc/noffle.users]" +ac_help="$ac_help --enable-debug=[no/yes] build with debugging [default=no]" ac_help="$ac_help --with-docdir=DIR other documentation [PREFIX/share/doc/noffle]" @@ -560,6 +564,7 @@ ac_config_sub=$ac_aux_dir/config.sub ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. +am__api_version="1.4" # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: @@ -572,7 +577,7 @@ # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:576: checking for a BSD compatible install" >&5 +echo "configure:581: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -625,7 +630,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 -echo "configure:629: checking whether build environment is sane" >&5 +echo "configure:634: checking whether build environment is sane" >&5 # Just in case sleep 1 echo timestamp > conftestfile @@ -682,7 +687,7 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x," echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:686: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:691: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -727,21 +732,21 @@ missing_dir=`cd $ac_aux_dir && pwd` -echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 -echo "configure:732: checking for working aclocal" >&5 +echo $ac_n "checking for working aclocal-${am__api_version}""... $ac_c" 1>&6 +echo "configure:737: checking for working aclocal-${am__api_version}" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. -if (aclocal --version) < /dev/null > /dev/null 2>&1; then - ACLOCAL=aclocal +if (aclocal-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal-${am__api_version} echo "$ac_t""found" 1>&6 else - ACLOCAL="$missing_dir/missing aclocal" + ACLOCAL="$missing_dir/missing aclocal-${am__api_version}" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 -echo "configure:745: checking for working autoconf" >&5 +echo "configure:750: checking for working autoconf" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. @@ -753,21 +758,21 @@ echo "$ac_t""missing" 1>&6 fi -echo $ac_n "checking for working automake""... $ac_c" 1>&6 -echo "configure:758: checking for working automake" >&5 +echo $ac_n "checking for working automake-${am__api_version}""... $ac_c" 1>&6 +echo "configure:763: checking for working automake-${am__api_version}" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. -if (automake --version) < /dev/null > /dev/null 2>&1; then - AUTOMAKE=automake +if (automake-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake-${am__api_version} echo "$ac_t""found" 1>&6 else - AUTOMAKE="$missing_dir/missing automake" + AUTOMAKE="$missing_dir/missing automake-${am__api_version}" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 -echo "configure:771: checking for working autoheader" >&5 +echo "configure:776: checking for working autoheader" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. @@ -780,7 +785,7 @@ fi echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 -echo "configure:784: checking for working makeinfo" >&5 +echo "configure:789: checking for working makeinfo" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. @@ -813,7 +818,7 @@ # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:817: checking for $ac_word" >&5 +echo "configure:822: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -843,7 +848,7 @@ # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:847: checking for $ac_word" >&5 +echo "configure:852: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -894,7 +899,7 @@ # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:898: checking for $ac_word" >&5 +echo "configure:903: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -926,7 +931,7 @@ fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:930: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:935: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -937,12 +942,12 @@ cat > conftest.$ac_ext << EOF -#line 941 "configure" +#line 946 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:951: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -968,12 +973,12 @@ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:972: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:977: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:977: checking whether we are using GNU C" >&5 +echo "configure:982: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -982,7 +987,7 @@ yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:986: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:991: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1001,7 +1006,7 @@ ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1005: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1010: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1033,7 +1038,7 @@ fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1037: checking how to run the C preprocessor" >&5 +echo "configure:1042: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1048,13 +1053,13 @@ # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1058: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1063: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1065,13 +1070,13 @@ rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1075: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1080: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1082,13 +1087,13 @@ rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1092: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1097: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1114,13 +1119,13 @@ if test $ac_cv_prog_gcc = yes; then echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 -echo "configure:1118: checking whether ${CC-cc} needs -traditional" >&5 +echo "configure:1123: checking whether ${CC-cc} needs -traditional" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_pattern="Autoconf.*'x'" cat > conftest.$ac_ext < Autoconf TIOCGETP @@ -1138,7 +1143,7 @@ if test $ac_cv_prog_gcc_traditional = no; then cat > conftest.$ac_ext < Autoconf TCGETA @@ -1171,7 +1176,7 @@ # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:1175: checking for a BSD compatible install" >&5 +echo "configure:1180: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1224,7 +1229,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:1228: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:1233: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1254,7 +1259,7 @@ # Extract the first word of "sendmail", so it can be a program name with args. set dummy sendmail; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1258: checking for $ac_word" >&5 +echo "configure:1263: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_SENDMAILPROG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1293,9 +1298,9 @@ echo $ac_n "checking for AIX""... $ac_c" 1>&6 -echo "configure:1297: checking for AIX" >&5 +echo "configure:1302: checking for AIX" >&5 cat > conftest.$ac_ext <&6 -echo "configure:1321: checking for POSIXized ISC" >&5 -if test -d /etc/conf/kconfig.d && - grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 -then + + echo $ac_n "checking for strerror in -lcposix""... $ac_c" 1>&6 +echo "configure:1327: checking for strerror in -lcposix" >&5 +ac_lib_var=`echo cposix'_'strerror | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lcposix $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - ISC=yes # If later tests want to check for ISC. - cat >> confdefs.h <<\EOF -#define _POSIX_SOURCE 1 -EOF - - if test "$GCC" = yes; then - CC="$CC -posix" - else - CC="$CC -Xp" - fi + LIBS="$LIBS -lcposix" else echo "$ac_t""no" 1>&6 - ISC= fi + + ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6 -echo "configure:1343: checking for minix/config.h" >&5 +echo "configure:1370: checking for minix/config.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1353: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1380: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1398,12 +1425,12 @@ # [ This is ripped from GNU tar. ] echo $ac_n "checking for gethostent""... $ac_c" 1>&6 -echo "configure:1402: checking for gethostent" >&5 +echo "configure:1429: checking for gethostent" >&5 if eval "test \"`echo '$''{'ac_cv_func_gethostent'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostent=yes" else @@ -1447,7 +1474,7 @@ if test $ac_cv_func_gethostent = no; then echo $ac_n "checking for gethostent in -lnsl""... $ac_c" 1>&6 -echo "configure:1451: checking for gethostent in -lnsl" >&5 +echo "configure:1478: checking for gethostent in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1455,7 +1482,7 @@ ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1495,12 +1522,12 @@ fi echo $ac_n "checking for setsockopt""... $ac_c" 1>&6 -echo "configure:1499: checking for setsockopt" >&5 +echo "configure:1526: checking for setsockopt" >&5 if eval "test \"`echo '$''{'ac_cv_func_setsockopt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1554: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_setsockopt=yes" else @@ -1544,7 +1571,7 @@ if test $ac_cv_func_setsockopt = no; then echo $ac_n "checking for setsockopt in -lsocket""... $ac_c" 1>&6 -echo "configure:1548: checking for setsockopt in -lsocket" >&5 +echo "configure:1575: checking for setsockopt in -lsocket" >&5 ac_lib_var=`echo socket'_'setsockopt | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1552,7 +1579,7 @@ ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1594: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1607,7 +1634,7 @@ fi echo $ac_n "checking for gdbm_open in -lgdbm""... $ac_c" 1>&6 -echo "configure:1611: checking for gdbm_open in -lgdbm" >&5 +echo "configure:1638: checking for gdbm_open in -lgdbm" >&5 ac_lib_var=`echo gdbm'_'gdbm_open | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1615,7 +1642,7 @@ ac_save_LIBS="$LIBS" LIBS="-lgdbm $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1657: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1643,17 +1670,17 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "gdbm.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for gdbm.h""... $ac_c" 1>&6 -echo "configure:1647: checking for gdbm.h" >&5 +echo "configure:1674: checking for gdbm.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1657: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1684: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1683,12 +1710,12 @@ echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:1687: checking for ANSI C header files" >&5 +echo "configure:1714: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1696,7 +1723,7 @@ #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1700: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1727: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1713,7 +1740,7 @@ if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1731,7 +1758,7 @@ if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1752,7 +1779,7 @@ : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -1763,7 +1790,7 @@ exit (0); } EOF -if { (eval echo configure:1767: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -1791,12 +1818,12 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 -echo "configure:1795: checking for $ac_hdr that defines DIR" >&5 +echo "configure:1822: checking for $ac_hdr that defines DIR" >&5 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_hdr> @@ -1804,7 +1831,7 @@ DIR *dirp = 0; ; return 0; } EOF -if { (eval echo configure:1808: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1835: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" else @@ -1829,7 +1856,7 @@ # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 -echo "configure:1833: checking for opendir in -ldir" >&5 +echo "configure:1860: checking for opendir in -ldir" >&5 ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1837,7 +1864,7 @@ ac_save_LIBS="$LIBS" LIBS="-ldir $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1879: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1870,7 +1897,7 @@ else echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 -echo "configure:1874: checking for opendir in -lx" >&5 +echo "configure:1901: checking for opendir in -lx" >&5 ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1878,7 +1905,7 @@ ac_save_LIBS="$LIBS" LIBS="-lx $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1920: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1915,17 +1942,17 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1919: checking for $ac_hdr" >&5 +echo "configure:1946: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1929: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1956: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1955,17 +1982,17 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1959: checking for $ac_hdr" >&5 +echo "configure:1986: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1969: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1996: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1995,17 +2022,17 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1999: checking for $ac_hdr" >&5 +echo "configure:2026: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2009: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2036: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2031,21 +2058,21 @@ fi done -for ac_hdr in sys/types.h regex.h +for ac_hdr in sys/types.h regex.h pwd.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2039: checking for $ac_hdr" >&5 +echo "configure:2066: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2049: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2076: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2075,12 +2102,12 @@ echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:2079: checking for working const" >&5 +echo "configure:2106: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2160: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -2150,12 +2177,12 @@ fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:2154: checking for size_t" >&5 +echo "configure:2181: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2183,12 +2210,12 @@ fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 -echo "configure:2187: checking whether time.h and sys/time.h may both be included" >&5 +echo "configure:2214: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2197,7 +2224,7 @@ struct tm *tp; ; return 0; } EOF -if { (eval echo configure:2201: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2228: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else @@ -2218,12 +2245,12 @@ fi echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 -echo "configure:2222: checking whether struct tm is in sys/time.h or time.h" >&5 +echo "configure:2249: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2231,7 +2258,7 @@ struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:2235: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2262: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else @@ -2253,12 +2280,12 @@ echo $ac_n "checking socklen_t""... $ac_c" 1>&6 -echo "configure:2257: checking socklen_t" >&5 +echo "configure:2284: checking socklen_t" >&5 if eval "test \"`echo '$''{'noffle_cv_type_socklen_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -2268,7 +2295,7 @@ socklen_t s; ; return 0; } EOF -if { (eval echo configure:2272: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2299: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* noffle_cv_type_socklen_t=yes else @@ -2294,12 +2321,12 @@ echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:2298: checking return type of signal handlers" >&5 +echo "configure:2325: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2316,7 +2343,7 @@ int i; ; return 0; } EOF -if { (eval echo configure:2320: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2347: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else @@ -2335,12 +2362,12 @@ echo $ac_n "checking for strftime""... $ac_c" 1>&6 -echo "configure:2339: checking for strftime" >&5 +echo "configure:2366: checking for strftime" >&5 if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2394: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strftime=yes" else @@ -2385,7 +2412,7 @@ echo "$ac_t""no" 1>&6 # strftime is in -lintl on SCO UNIX. echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6 -echo "configure:2389: checking for strftime in -lintl" >&5 +echo "configure:2416: checking for strftime in -lintl" >&5 ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2393,7 +2420,7 @@ ac_save_LIBS="$LIBS" LIBS="-lintl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2435: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2431,7 +2458,7 @@ fi echo $ac_n "checking for working fnmatch""... $ac_c" 1>&6 -echo "configure:2435: checking for working fnmatch" >&5 +echo "configure:2462: checking for working fnmatch" >&5 if eval "test \"`echo '$''{'ac_cv_func_fnmatch_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2442,11 +2469,11 @@ ac_cv_func_fnmatch_works=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2477: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_fnmatch_works=yes else @@ -2471,12 +2498,12 @@ for ac_func in fdopen mkdir select socket do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2475: checking for $ac_func" >&5 +echo "configure:2502: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2530: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2526,12 +2553,12 @@ for ac_func in gethostname uname do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2530: checking for $ac_func" >&5 +echo "configure:2557: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2585: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2581,12 +2608,12 @@ for ac_func in snprintf vsnprintf __vsnprintf __snprintf do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2585: checking for $ac_func" >&5 +echo "configure:2612: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2640: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2636,12 +2663,12 @@ for ac_func in strerror strstr do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2640: checking for $ac_func" >&5 +echo "configure:2667: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2695: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2691,12 +2718,12 @@ for ac_func in mktime timegm do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2695: checking for $ac_func" >&5 +echo "configure:2722: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2750: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2748,6 +2775,131 @@ +# Check whether --enable-auth or --disable-auth was given. +if test "${enable_auth+set}" = set; then + enableval="$enable_auth" + : +else + enable_auth=no +fi + + +if test "x$enable_auth" = "xfile"; then + cat >> confdefs.h <<\EOF +#define USE_AUTH 1 +EOF + +fi +if test "x$enable_auth" = "xpam"; then + + echo $ac_n "checking for pam_start in -lpam""... $ac_c" 1>&6 +echo "configure:2797: checking for pam_start in -lpam" >&5 +ac_lib_var=`echo pam'_'pam_start | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lpam $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_safe=`echo "security/pam_appl.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for security/pam_appl.h""... $ac_c" 1>&6 +echo "configure:2833: checking for security/pam_appl.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2843: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +{ echo "configure: error: cannot find security/pam_appl.h" 1>&2; exit 1; } +fi + +else + echo "$ac_t""no" 1>&6 +{ echo "configure: error: cannot find libpam" 1>&2; exit 1; } +fi + + LIBPAM="-lpam" + cat >> confdefs.h <<\EOF +#define USE_PAM 1 +EOF + + cat >> confdefs.h <<\EOF +#define USE_AUTH 1 +EOF + +fi + +echo $ac_n "checking usersfile""... $ac_c" 1>&6 +echo "configure:2882: checking usersfile" >&5 +# Check whether --with-usersfile or --without-usersfile was given. +if test "${with_usersfile+set}" = set; then + withval="$with_usersfile" + if echo "$withval" | egrep >/dev/null -v '^/' ; then + { echo "configure: error: you must give an absolute path" 1>&2; exit 1; } + fi + withval=`echo "$withval" | sed 'sx/*$xx;'` +else + withval="/etc/$PACKAGE.users" + +fi + +USERSFILE=$withval +echo "$ac_t""$USERSFILE" 1>&6 +cat >> confdefs.h <&6 -echo "configure:2783: checking other documentation diretcory" >&5 + echo $ac_n "checking other documentation directory""... $ac_c" 1>&6 +echo "configure:2935: checking other documentation directory" >&5 if eval "test \"`echo '$''{'noffle_cv_docdir'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2798,7 +2950,7 @@ echo $ac_n "checking spooldir""... $ac_c" 1>&6 -echo "configure:2802: checking spooldir" >&5 +echo "configure:2954: checking spooldir" >&5 # Check whether --with-spooldir or --without-spooldir was given. if test "${with_spooldir+set}" = set; then withval="$with_spooldir" @@ -2821,7 +2973,7 @@ echo $ac_n "checking configfile""... $ac_c" 1>&6 -echo "configure:2825: checking configfile" >&5 +echo "configure:2977: checking configfile" >&5 # Check whether --with-configfile or --without-configfile was given. if test "${with_configfile+set}" = set; then withval="$with_configfile" @@ -3002,6 +3154,8 @@ s%@CC@%$CC%g s%@CPP@%$CPP%g s%@SENDMAILPROG@%$SENDMAILPROG%g +s%@LIBPAM@%$LIBPAM%g +s%@USERSFILE@%$USERSFILE%g s%@SPOOLDIR@%$SPOOLDIR%g s%@CONFIGFILE@%$CONFIGFILE%g s%@DOCDIR@%$DOCDIR%g diff -r 01755687c565 -r c02c4eb95f95 configure.in --- a/configure.in Fri Jan 10 23:11:43 2003 +0000 +++ b/configure.in Fri Jan 10 23:25:45 2003 +0000 @@ -84,7 +84,7 @@ AC_CHECK_HEADERS(syslog.h sys/resource.h sys/utsname.h) AC_CHECK_HEADERS(fnmatch.h errno.h getopt.h time.h sys/time.h signal.h) AC_CHECK_HEADERS(netdb.h sys/socket.h fcntl.h limits.h unistd.h) -AC_CHECK_HEADERS(sys/types.h regex.h) +AC_CHECK_HEADERS(sys/types.h regex.h pwd.h) dnl --------------------------------------------------------------------------- @@ -130,6 +130,43 @@ dnl --------------------------------------------------------------------------- +dnl Authentication options +dnl --------------------------------------------------------------------------- + +AC_ARG_ENABLE(auth, +[ --enable-auth=[no/file/pam] enable authentication [default=no]], , +enable_auth=no) + +if test "x$enable_auth" = "xfile"; then + AC_DEFINE(USE_AUTH) +fi +if test "x$enable_auth" = "xpam"; then + AC_SUBST(LIBPAM) + AC_CHECK_LIB(pam, pam_start, + AC_CHECK_HEADER(security/pam_appl.h,, + AC_MSG_ERROR([cannot find security/pam_appl.h])), + AC_MSG_ERROR([cannot find libpam])) + LIBPAM="-lpam" + AC_DEFINE(USE_PAM) + AC_DEFINE(USE_AUTH) +fi + +dnl check where to put the users file +AC_MSG_CHECKING(usersfile) +AC_ARG_WITH(usersfile, + [ --with-usersfile=FILE users file [/etc/noffle.users]], + if echo "$withval" | egrep >/dev/null -v '^/' ; then + AC_MSG_ERROR(you must give an absolute path) + fi + withval=`echo "$withval" | sed 'sx/*$xx;'`, + withval="/etc/$PACKAGE.users" +) +USERSFILE=$withval +AC_MSG_RESULT($USERSFILE) +AC_DEFINE_UNQUOTED(USERSFILE,"$USERSFILE") +AC_SUBST(USERSFILE) + +dnl --------------------------------------------------------------------------- dnl Handle user-specified configure options dnl --------------------------------------------------------------------------- @@ -156,7 +193,7 @@ AC_ARG_WITH(docdir, [ --with-docdir=DIR other documentation [PREFIX/share/doc/noffle]], [noffle_cv_docdir=$withval], -[ AC_CACHE_CHECK(other documentation diretcory, noffle_cv_docdir, +[ AC_CACHE_CHECK(other documentation directory, noffle_cv_docdir, [if test x$prefix = xNONE; then noffle_cv_prefix=$ac_default_prefix else diff -r 01755687c565 -r c02c4eb95f95 docs/Makefile.in --- a/docs/Makefile.in Fri Jan 10 23:11:43 2003 +0000 +++ b/docs/Makefile.in Fri Jan 10 23:25:45 2003 +0000 @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -62,10 +62,12 @@ CC = @CC@ CONFIGFILE = @CONFIGFILE@ DOCDIR = @DOCDIR@ +LIBPAM = @LIBPAM@ MAKEINFO = @MAKEINFO@ PACKAGE = @PACKAGE@ SENDMAILPROG = @SENDMAILPROG@ SPOOLDIR = @SPOOLDIR@ +USERSFILE = @USERSFILE@ VERSION = @VERSION@ man_MANS = $(PACKAGE).1 $(PACKAGE).conf.5 diff -r 01755687c565 -r c02c4eb95f95 docs/noffle.conf.5 --- a/docs/noffle.conf.5 Fri Jan 10 23:11:43 2003 +0000 +++ b/docs/noffle.conf.5 Fri Jan 10 23:25:45 2003 +0000 @@ -1,5 +1,5 @@ .TH noffle.conf 5 -.\" $Id: noffle.conf.5 381 2002-05-14 14:25:45Z mirkol $ +.\" $Id: noffle.conf.5 420 2003-01-10 23:25:45Z bears $ .SH NAME noffle.conf \- Configuration file for NOFFLE news server @@ -98,6 +98,7 @@ .BR all , .BR none , .BR config , +.BR auth , .BR control , .BR expire , .BR fetch , @@ -204,6 +205,22 @@ Default: yes .TP +.B authenticate-client yes|no +Insist that clients authenticate themselves using the NNTP +AUTHINFO USER/AUTHINFO PASS transaction before any news is served. +The form of the authentication is determined at compile time; either +PAM is used (with a service name "noffle"), or the userlist +file is scanned. This file, by default \fI/etc/noffle.users\fP, +is a text file. Spaces, comments starting with '#' and blank lines are +ignored. Other lines must contain space-separated 'username password' +pairs. For security reasons the userlist file must be a regular file, +not a link, and must be owner readable only. Finally, note that the +NNTP AUTHINFO USER/AUTHINFO PASS transaction is not encrypted in any +way, and so must itself be considered insecure. +.br +Default: no + +.TP .B post-locally yes|no Place articles posted to external servers in the local aticle database immediately. Some servers may rewrite Message-IDs, which will cause @@ -257,6 +274,21 @@ Default: 14 .TP +.B noffle-user +The username under which NOFFLE normally runs. If NOFFLE is invoked by +root, it will drop its real and effective UID to this user as soon as +possible. +.br +Default: news + +.TP +.B noffle-group +The group under which NOFFLE normally runs. NOFFLE will change to this +real and effective GID as soon as possible. +.br +Default: news + +.TP .B expire The expiry period for a newsgroup or set of newsgroups, in days. The expiry pattern can contain \fIwildcards\fP, and there can be multiple @@ -287,7 +319,7 @@ uses a wildcard format that closely matches filename-style wildcards. \fIalt.binaries.*\fP, for example, matches all newsgroups under the .I alt.binaries -hierarchy. A full description of the fomat (known as +hierarchy. A full description of the format (known as .B wildmat patterns) is as follows. diff -r 01755687c565 -r c02c4eb95f95 packages/Makefile.in --- a/packages/Makefile.in Fri Jan 10 23:11:43 2003 +0000 +++ b/packages/Makefile.in Fri Jan 10 23:25:45 2003 +0000 @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -62,10 +62,12 @@ CC = @CC@ CONFIGFILE = @CONFIGFILE@ DOCDIR = @DOCDIR@ +LIBPAM = @LIBPAM@ MAKEINFO = @MAKEINFO@ PACKAGE = @PACKAGE@ SENDMAILPROG = @SENDMAILPROG@ SPOOLDIR = @SPOOLDIR@ +USERSFILE = @USERSFILE@ VERSION = @VERSION@ SUBDIRS = redhat @@ -125,7 +127,7 @@ dot_seen=no; \ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ rev="$$subdir $$rev"; \ - test "$$subdir" = "." && dot_seen=yes; \ + test "$$subdir" != "." || dot_seen=yes; \ done; \ test "$$dot_seen" = "no" && rev=". $$rev"; \ target=`echo $@ | sed s/-recursive//`; \ @@ -167,7 +169,7 @@ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ - || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP)) mostlyclean-tags: diff -r 01755687c565 -r c02c4eb95f95 packages/redhat/Makefile.in --- a/packages/redhat/Makefile.in Fri Jan 10 23:11:43 2003 +0000 +++ b/packages/redhat/Makefile.in Fri Jan 10 23:25:45 2003 +0000 @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -62,10 +62,12 @@ CC = @CC@ CONFIGFILE = @CONFIGFILE@ DOCDIR = @DOCDIR@ +LIBPAM = @LIBPAM@ MAKEINFO = @MAKEINFO@ PACKAGE = @PACKAGE@ SENDMAILPROG = @SENDMAILPROG@ SPOOLDIR = @SPOOLDIR@ +USERSFILE = @USERSFILE@ VERSION = @VERSION@ EXTRA_DIST = noffle-expire noffle.spec diff -r 01755687c565 -r c02c4eb95f95 src/Makefile.am --- a/src/Makefile.am Fri Jan 10 23:11:43 2003 +0000 +++ b/src/Makefile.am Fri Jan 10 23:25:45 2003 +0000 @@ -4,6 +4,7 @@ bin_PROGRAMS = noffle noffle_SOURCES = \ +authenticate.c authenticate.h \ client.c client.h \ common.h \ configfile.c configfile.h \ @@ -32,7 +33,7 @@ util.c util.h \ wildmat.c wildmat.h -noffle_LDADD = -lgdbm +noffle_LDADD = -lgdbm $(LIBPAM) tags: etags $(noffle_SOURCES) diff -r 01755687c565 -r c02c4eb95f95 src/Makefile.in --- a/src/Makefile.in Fri Jan 10 23:11:43 2003 +0000 +++ b/src/Makefile.in Fri Jan 10 23:25:45 2003 +0000 @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -63,18 +63,20 @@ CC = @CC@ CONFIGFILE = @CONFIGFILE@ DOCDIR = @DOCDIR@ +LIBPAM = @LIBPAM@ MAKEINFO = @MAKEINFO@ PACKAGE = @PACKAGE@ SENDMAILPROG = @SENDMAILPROG@ SPOOLDIR = @SPOOLDIR@ +USERSFILE = @USERSFILE@ VERSION = @VERSION@ bin_PROGRAMS = noffle -noffle_SOURCES = client.c client.h common.h configfile.c configfile.h content.c content.h control.c control.h database.c database.h dynamicstring.c dynamicstring.h expire.c expire.h fetch.c fetch.h fetchlist.c fetchlist.h filter.c filter.h group.c group.h itemlist.c itemlist.h lock.c lock.h log.c log.h noffle.c online.c online.h outgoing.c outgoing.h over.c over.h portable.h post.c post.h protocol.c protocol.h pseudo.c pseudo.h request.c request.h server.c server.h util.c util.h wildmat.c wildmat.h +noffle_SOURCES = authenticate.c authenticate.h client.c client.h common.h configfile.c configfile.h content.c content.h control.c control.h database.c database.h dynamicstring.c dynamicstring.h expire.c expire.h fetch.c fetch.h fetchlist.c fetchlist.h filter.c filter.h group.c group.h itemlist.c itemlist.h lock.c lock.h log.c log.h noffle.c online.c online.h outgoing.c outgoing.h over.c over.h portable.h post.c post.h protocol.c protocol.h pseudo.c pseudo.h request.c request.h server.c server.h util.c util.h wildmat.c wildmat.h -noffle_LDADD = -lgdbm +noffle_LDADD = -lgdbm $(LIBPAM) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../config.h CONFIG_CLEAN_FILES = @@ -85,10 +87,10 @@ CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ -noffle_OBJECTS = client.o configfile.o content.o control.o database.o \ -dynamicstring.o expire.o fetch.o fetchlist.o filter.o group.o \ -itemlist.o lock.o log.o noffle.o online.o outgoing.o over.o post.o \ -protocol.o pseudo.o request.o server.o util.o wildmat.o +noffle_OBJECTS = authenticate.o client.o configfile.o content.o \ +control.o database.o dynamicstring.o expire.o fetch.o fetchlist.o \ +filter.o group.o itemlist.o lock.o log.o noffle.o online.o outgoing.o \ +over.o post.o protocol.o pseudo.o request.o server.o util.o wildmat.o noffle_DEPENDENCIES = noffle_LDFLAGS = CFLAGS = @CFLAGS@ @@ -102,13 +104,13 @@ TAR = tar GZIP_ENV = --best -DEP_FILES = .deps/client.P .deps/configfile.P .deps/content.P \ -.deps/control.P .deps/database.P .deps/dynamicstring.P .deps/expire.P \ -.deps/fetch.P .deps/fetchlist.P .deps/filter.P .deps/group.P \ -.deps/itemlist.P .deps/lock.P .deps/log.P .deps/noffle.P .deps/online.P \ -.deps/outgoing.P .deps/over.P .deps/post.P .deps/protocol.P \ -.deps/pseudo.P .deps/request.P .deps/server.P .deps/util.P \ -.deps/wildmat.P +DEP_FILES = .deps/authenticate.P .deps/client.P .deps/configfile.P \ +.deps/content.P .deps/control.P .deps/database.P .deps/dynamicstring.P \ +.deps/expire.P .deps/fetch.P .deps/fetchlist.P .deps/filter.P \ +.deps/group.P .deps/itemlist.P .deps/lock.P .deps/log.P .deps/noffle.P \ +.deps/online.P .deps/outgoing.P .deps/over.P .deps/post.P \ +.deps/protocol.P .deps/pseudo.P .deps/request.P .deps/server.P \ +.deps/util.P .deps/wildmat.P SOURCES = $(noffle_SOURCES) OBJECTS = $(noffle_OBJECTS) @@ -184,7 +186,7 @@ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ - || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP)) mostlyclean-tags: diff -r 01755687c565 -r c02c4eb95f95 src/authenticate.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/authenticate.c Fri Jan 10 23:25:45 2003 +0000 @@ -0,0 +1,445 @@ +/* + authenticate.c + + Do client authentication + + $Id: authenticate.c 420 2003-01-10 23:25:45Z bears $ +*/ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "authenticate.h" +#include "configfile.h" +#include "log.h" +#include "portable.h" +#include "util.h" + +#if USE_AUTH + +#if USE_PAM +#include + +static const char *password; + +/* + * It's a bit tricky to go around asking PAM questions at this stage, + * as well as not fitting NNTP, so just repond to all PAM questions + * with the password and hope that works. + */ +static int noffle_conv( int num_msg, + const struct pam_message **msgm, + struct pam_response **response, + void *appdata_ptr ) +{ + struct pam_response *reply; + + UNUSED(appdata_ptr); + UNUSED(msgm); + + reply = calloc( num_msg, sizeof (struct pam_response) ); + reply->resp = strdup( password ); + reply->resp_retcode = 0; + *response = reply; + return PAM_SUCCESS; +} + +static struct pam_conv conv = { + noffle_conv, + NULL +}; + +static pam_handle_t *pamh = NULL; +static Bool pam_session_opened = FALSE; +static Bool pam_set_cred = FALSE; +static uid_t oldEuid; + +static Bool +PAM_open( void ) +{ + int retval; + + /* To use PAM successfully we need to be root. */ + ASSERT ( getuid() == 0 ); + + ASSERT( pamh == NULL ); + + /* + * Preserve old eUid to be restored when PAM closes and set + * current euid to root for PAMs benefit. + */ + oldEuid = geteuid(); + if ( seteuid( 0 ) < 0 ) + { + Log_err( "Cannot set euid to root: %s", strerror( errno ) ); + return FALSE; + } + + retval = pam_start( "noffle", NULL, &conv, &pamh ); + if ( retval != PAM_SUCCESS ) + { + Log_err( "Cannot starting authentication: %s", + pam_strerror( pamh, retval ) ); + return FALSE; + } + + return TRUE; +} + +static enum AuthResult +PAM_authenticate( const char *user, const char *pass ) +{ + int retval; + + ASSERT( pamh != NULL ); + + password = pass; + + retval = pam_set_item( pamh, PAM_USER, user ); + if ( retval != PAM_SUCCESS ) + Log_dbg( LOG_DBG_AUTH, "pam_set_item failed: %s", + pam_strerror( pamh, retval ) ); + + if ( retval == PAM_SUCCESS ) + { + retval = pam_authenticate( pamh, PAM_SILENT ); + if ( retval != PAM_SUCCESS ) + Log_dbg( LOG_DBG_AUTH, "pam_authenticate failed: %s", + pam_strerror( pamh, retval ) ); + } + + if ( retval == PAM_SUCCESS ) + { + retval = pam_setcred( pamh, PAM_ESTABLISH_CRED ); + if ( retval != PAM_SUCCESS ) + Log_dbg( LOG_DBG_AUTH, "pam_setcred failed: %s", + pam_strerror( pamh, retval ) ); + else + pam_set_cred = TRUE; + } + + if ( retval == PAM_SUCCESS ) + { + retval = pam_open_session( pamh, 0 ); + if ( retval != PAM_SUCCESS ) + Log_dbg( LOG_DBG_AUTH, "pam_open_session failed: %s", + pam_strerror( pamh, retval ) ); + else + pam_session_opened = TRUE; + } + + switch ( retval ) + { + case PAM_SUCCESS: + return AUTH_OK; + + case PAM_MAXTRIES: + return AUTH_DISCONNECT; + + case PAM_ABORT: + return AUTH_ERROR; + } + + return AUTH_FAILED; +} + +static void +PAM_close( void ) +{ + int retval = 0; + + ASSERT ( pamh != NULL ); + + if ( pam_session_opened ) + { + pam_session_opened = FALSE; + retval = pam_close_session( pamh, 0 ); + if ( retval != PAM_SUCCESS ) + Log_dbg( LOG_DBG_AUTH, "pam_close_session failed: %s", + pam_strerror( pamh, retval ) ); + } + + if ( pam_set_cred ) + { + pam_set_cred = FALSE; + retval = pam_setcred( pamh, PAM_DELETE_CRED ); + if ( retval != PAM_SUCCESS ) + Log_dbg( LOG_DBG_AUTH, "pam_set_cred failed: %s", + pam_strerror( pamh, retval ) ); + } + + retval = pam_end( pamh, retval ); + if ( retval != PAM_SUCCESS ) + Log_dbg( LOG_DBG_AUTH, "pam_end failed: %s", + pam_strerror( pamh, retval ) ); + pamh = NULL; + + /* + * For completeness set euid back to original value, though it'll + * probably be set again by Auth_dropPrivs. + */ + if ( seteuid( oldEuid ) < 0 ) + Log_err( "Cannot set euid back to %d: %s", + oldEuid, strerror( errno ) ); +} + +#else + +/* + * No PAM, so provide a simple alternative. + * + * USERSFILE is a simple plain-text file consisting of username password + * pairs, one pair per line. Comments are prefixed by '#'. Blank lines + * are ignored. + * + * By way of a simple security check, the users file MUST be only + * readable and writable by the owner. + */ + +#define AUTH_MAX_TRIES 3 + +static int authTries = 0; + +static enum AuthResult +file_authenticate( const char *user, const char *pass ) +{ + Str file, line; + FILE *f; + struct stat statBuf; + enum AuthResult res = AUTH_FAILED; + + Utl_cpyStr( file, USERSFILE ); + if ( stat( file, &statBuf ) < 0 ) + { + Log_err( "Cannot read %s (%s)", file, strerror( errno ) ); + return AUTH_ERROR; + } + if ( !S_ISREG( statBuf.st_mode ) ) + { + Log_err( "%s must be a regular file, not a link", file ); + return AUTH_ERROR; + } + if ( ( statBuf.st_mode & ( S_IRWXG | S_IRWXO ) ) != 0 ) + { + Log_err( "%s must be readable only by its owner", file ); + return AUTH_ERROR; + } + + if ( ! ( f = fopen( file, "r" ) ) ) + { + Log_err( "Cannot read %s (%s)", file, strerror( errno ) ); + return AUTH_ERROR; + } + while ( res == AUTH_FAILED && fgets( line, MAXCHAR, f ) ) + { + Str theUser, thePass; + char *p; + + p = Utl_stripWhiteSpace( line ); + Utl_stripComment( p ); + + if ( *p == '\0' ) + continue; + + if ( sscanf( p, MAXCHAR_FMT " " MAXCHAR_FMT, theUser, thePass ) != 2 ) + { + res = AUTH_ERROR; + Log_err( "Badly formatted line %s in %s", p, file ); + break; + } + + if ( strcmp( user, theUser ) == 0 ) + { + if ( strcmp( pass, thePass ) == 0 ) + res = AUTH_OK; + break; + } + } + + fclose( f ); + + if ( res == AUTH_FAILED ) + { + authTries++; + sleep( authTries * authTries ); + if ( authTries >= AUTH_MAX_TRIES ) + res = AUTH_DISCONNECT; + } + + return res; +} + +#endif /* USE_PAM */ +#endif /* USE_AUTH */ + +/* Open authentication session. */ +Bool +Auth_open( void ) +{ +#if USE_AUTH +#if USE_PAM + return PAM_open(); +#else + return TRUE; +#endif +#else + return TRUE; +#endif +} + +/* Authenticate a user and password. */ +enum AuthResult +Auth_authenticate( const char *user, const char *pass ) +{ +#if USE_AUTH +#if USE_PAM + return PAM_authenticate( user, pass ); +#else + return file_authenticate( user, pass ); +#endif +#else + UNUSED(user); + UNUSED(pass); + + return TRUE; +#endif +} + +/* Authentication session now closed. */ +void +Auth_close( void ) +{ +#if USE_AUTH && USE_PAM + PAM_close(); +#endif +} + +static uid_t noffleUid = (uid_t) -1; +static gid_t noffleGid= (gid_t) -1; +static Bool adminUser = FALSE; + +/* Check we have appropriate privs for authentication. */ +Bool +Auth_checkPrivs( void ) +{ + uid_t euid; + gid_t egid; + uid_t ruid; + struct passwd* pwnam; + struct group* grnam; + + euid = geteuid(); + egid = getegid(); + + pwnam = getpwnam( Cfg_noffleUser() ); + if ( pwnam == NULL ) + { + Log_err( "Noffle user %s is not a known user", Cfg_noffleUser() ); + return FALSE; + } + noffleUid = pwnam->pw_uid; + + grnam = getgrnam( Cfg_noffleGroup() ); + if ( grnam == NULL ) + { + Log_err( "Noffle group %s is not a known group", Cfg_noffleGroup() ); + return FALSE; + } + noffleGid = grnam->gr_gid; + + ruid = getuid(); + adminUser = ( ruid == 0 || ruid == noffleUid ); + + /* + * If we're really root, we will set the privs we require later. Otherwise + * we need to check that everything is as it should be. + */ + if ( ruid != 0 ) + { +#if USE_AUTH && USE_PAM + if( Cfg_needClientAuth() ) + { + Log_err( "Noffle must run as root to use PAM authentication" ); + return FALSE; + } +#endif + + if ( noffleUid != euid ) + { + Log_err( "Noffle needs to run as root or user %s", Cfg_noffleUser() ); + return FALSE; + } + + if ( noffleGid != egid ) + { + Log_err( "Noffle needs to run as root or as group %s", + Cfg_noffleGroup() ); + return FALSE; + } + } + + return TRUE; +} + +/* + * See if we should be permitted admin access. Admins can do anything, + * non-admins can only read articles, list groups and post. + * + * This must be called after Auth_checkPrivs. + */ +Bool +Auth_admin( void ) +{ + ASSERT( noffleUid != (uid_t) -1 && noffleGid != (gid_t) -1 ); + + return adminUser; +} + + +/* + * Drop any privs required for authentication. + * + * Must be called AFTER Auth_checkPrivs. + */ +Bool +Auth_dropPrivs( void ) +{ + uid_t euid; + + ASSERT( noffleUid != (uid_t) -1 && noffleGid != (gid_t) -1 ); + + /* + * We only need to drop privs if we're currently root. We + * should have already checked we're the news user on startup. + */ + euid = geteuid(); + if ( euid != 0 ) + return TRUE; + + if ( setgid( noffleGid ) != 0 ) + { + Log_err( "Can't set group %s: %s", + Cfg_noffleGroup(), strerror( errno ) ); + return FALSE; + } + + if ( setuid( noffleUid ) != 0 ) + { + Log_err( "Can't set user to %s: %s", + Cfg_noffleUser(), strerror( errno ) ); + return FALSE; + } + + return TRUE; +} + diff -r 01755687c565 -r c02c4eb95f95 src/authenticate.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/authenticate.h Fri Jan 10 23:25:45 2003 +0000 @@ -0,0 +1,40 @@ +/* + authenticate.h + + Do client authentication + + $Id: authenticate.h 420 2003-01-10 23:25:45Z bears $ +*/ + +#ifndef AUTHENTICATE_H +#define AUTHENTICATE_H + +#include "common.h" + +enum AuthResult { AUTH_ERROR, AUTH_DISCONNECT, AUTH_FAILED, AUTH_OK }; + +/* Authenticate a user and password. */ +enum AuthResult +Auth_authenticate( const char *user, const char *pass ); + +/* Open authentication session. */ +Bool +Auth_open( void ); + +/* Authentication session now closed. */ +void +Auth_close( void ); + +/* Check we have appropriate privs for authentication. */ +Bool +Auth_checkPrivs( void ); + +/* Are are privs sufficient only for admin access? */ +Bool +Auth_admin( void ); + +/* Drop any privs required for authentication. */ +Bool +Auth_dropPrivs( void ); + +#endif diff -r 01755687c565 -r c02c4eb95f95 src/noffle.c --- 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 #include #include +#include #include #include #include #include +#include +#include +#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; diff -r 01755687c565 -r c02c4eb95f95 src/server.c --- a/src/server.c Fri Jan 10 23:11:43 2003 +0000 +++ b/src/server.c Fri Jan 10 23:25:45 2003 +0000 @@ -1,7 +1,7 @@ /* server.c - $Id: server.c 403 2002-11-10 11:32:17Z bears $ + $Id: server.c 420 2003-01-10 23:25:45Z bears $ */ #if HAVE_CONFIG_H @@ -26,6 +26,7 @@ #include #include #include +#include "authenticate.h" #include "client.h" #include "common.h" #include "configfile.h" @@ -49,6 +50,12 @@ #include "wildmat.h" #include "portable.h" +enum AuthState { + NEED_USER, + NEED_PASS, + AUTH_DONE +}; + struct { Bool running; @@ -58,18 +65,32 @@ DynStr *reply; Bool eotAfterReply; Bool groupReady; -} server = { FALSE, 0L, 0, "", NULL, FALSE, FALSE }; + enum AuthState auth; + char *user; +} server = { + FALSE, /* running */ + 0L, /* lastServerOpen */ + 0, /* artPtr */ + "", /* grp */ + NULL, /* reply */ + FALSE, /* eotAfterReply */ + FALSE, /* groupReady */ + NEED_USER, /* auth */ + NULL /* user */ +}; typedef struct Cmd { const char *name; const char *syntax; + Bool needAuth; /* Returns false, if quit cmd */ Bool (*cmdProc)( char *arg, const struct Cmd *cmd ); } Cmd; static Bool doArt( char *arg, const Cmd *cmd ); +static Bool doAuthinfo( char *arg, const Cmd *cmd ); static Bool doBody( char *arg, const Cmd *cmd ); static Bool doGrp( char *arg, const Cmd *cmd ); static Bool doHead( char *arg, const Cmd *cmd ); @@ -96,27 +117,28 @@ Cmd commands[] = { - { "article", "ARTICLE [msg-id|n]", &doArt }, - { "body", "BODY [msg-id|n]", &doBody }, - { "head", "HEAD [msg-id|n]", &doHead }, - { "group", "GROUP grp", &doGrp }, - { "help", "HELP", &doHelp }, - { "ihave", "IHAVE (ignored)", &doIhave }, - { "last", "LAST", &doLast }, + { "article", "ARTICLE [msg-id|n]", TRUE, &doArt }, + { "authinfo", "AUTHINFO USER username|PASS password", FALSE, &doAuthinfo }, + { "body", "BODY [msg-id|n]", TRUE, &doBody }, + { "head", "HEAD [msg-id|n]", TRUE, &doHead }, + { "group", "GROUP grp", TRUE, &doGrp }, + { "help", "HELP", FALSE, &doHelp }, + { "ihave", "IHAVE (ignored)", TRUE, &doIhave }, + { "last", "LAST", TRUE, &doLast }, { "list", "LIST [ACTIVE [pat]]|ACTIVE.TIMES [pat]|" - "EXTENSIONS|NEWSGROUPS [pat]|OVERVIEW.FMT", &doList }, - { "listgroup", "LISTGROUP grp", &doListgrp }, - { "mode", "MODE (ignored)", &doMode }, - { "newgroups", "NEWGROUPS [xx]yymmdd hhmmss [GMT]", &doNewgrps }, - { "newnews", "NEWNEWS (not implemented)", ¬Implemented }, - { "next", "NEXT", &doNext }, - { "post", "POST", &doPost }, - { "quit", "QUIT", &doQuit }, - { "slave", "SLAVE (ignored)", &doSlave }, - { "stat", "STAT [msg-id|n]", &doStat }, - { "xhdr", "XHDR over-field [msg-id|m[-[n]]]", &doXhdr }, - { "xpat", "XPAT over-field msg-id|m[-[n]] pat", &doXpat }, - { "xover", "XOVER [m[-[n]]]", &doXOver } + "EXTENSIONS|NEWSGROUPS [pat]|OVERVIEW.FMT", TRUE, &doList }, + { "listgroup", "LISTGROUP grp", TRUE, &doListgrp }, + { "mode", "MODE (ignored)", FALSE, &doMode }, + { "newgroups", "NEWGROUPS [xx]yymmdd hhmmss [GMT]", TRUE, &doNewgrps }, + { "newnews", "NEWNEWS (not implemented)", TRUE, ¬Implemented }, + { "next", "NEXT", TRUE, &doNext }, + { "post", "POST", TRUE, &doPost }, + { "quit", "QUIT", FALSE, &doQuit }, + { "slave", "SLAVE (ignored)", TRUE, &doSlave }, + { "stat", "STAT [msg-id|n]", TRUE, &doStat }, + { "xhdr", "XHDR over-field [msg-id|m[-[n]]]", TRUE, &doXhdr }, + { "xpat", "XPAT over-field msg-id|m[-[n]] pat", TRUE, &doXpat }, + { "xover", "XOVER [m[-[n]]]", TRUE, &doXOver } }; /* @@ -664,6 +686,102 @@ } static Bool +doAuthinfo( char *line, const Cmd *cmd ) +{ +#if USE_AUTH + Str s, arg; + const char *data; + + if ( ! Cfg_needClientAuth() ) + { + putStat( STAT_AUTH_REJECTED, "Authentication not required" ); + return TRUE; + } + + if ( sscanf( line, MAXCHAR_FMT, s ) != 1 ) + { + badsyntax: + if ( server.auth != AUTH_DONE ) + server.auth = NEED_USER; + putSyntax( cmd ); + } + else + { + Utl_toLower( s ); + Utl_cpyStr( arg, Utl_restOfLn( line, 1 ) ); + data = Utl_stripWhiteSpace( arg ); + + if ( strcmp( "user", s ) != 0 && strcmp( "pass", s ) != 0 ) + goto badsyntax; + + if ( strcmp( "user", s ) == 0 && server.auth == NEED_USER ) + { + if ( server.user != NULL ) + free( server.user ); + Utl_allocAndCpy( &server.user, data ); + server.auth = NEED_PASS; + putStat( STAT_MORE_AUTH_REQUIRED, "More authentication required" ); + } + else if ( strcmp( "pass", s ) == 0 && server.auth == NEED_PASS ) + { + enum AuthResult authRes = Auth_authenticate( server.user, data ); + char *p; + + /* Zap the password */ + for ( p = line; *p != '\0'; p++ ) + *p = 'X'; + + switch ( authRes ) + { + case AUTH_OK: + server.auth = AUTH_DONE; + putStat( STAT_AUTH_ACCEPTED, "Authentication accepted" ); + Log_inf( "User %s authenticated", server.user ); + break; + + case AUTH_FAILED: + server.auth = NEED_USER; + putStat( STAT_NO_PERMISSION, "No permission"); + Log_dbg( LOG_DBG_AUTH, "User %s password %s rejected", + server.user, data ); + break; + + case AUTH_DISCONNECT: + putStat( STAT_NO_PERMISSION, "No permission - disconnecting" ); + Log_dbg( LOG_DBG_AUTH, + "User %s password %s rejected - disconnecting", + server.user, data ); + return FALSE; + + default: /* AUTH_ERROR */ + putStat( STAT_PROGRAM_FAULT, "Authentication program error" ); + Log_dbg( LOG_DBG_AUTH, + "Error authenticating User %s password %s", + server.user, data ); + return FALSE; + } + } + else + { + if ( server.auth == AUTH_DONE ) + putStat( STAT_AUTH_REJECTED, "Reauthentication not possible" ); + else + { + putStat( STAT_AUTH_REJECTED, "Authentication rejected" ); + server.auth = NEED_USER; + } + } + } +#else + UNUSED( line ); + UNUSED( cmd ); + + putStat( STAT_AUTH_REJECTED, "Authentication not possible" ); +#endif + return TRUE; +} + +static Bool doHelp( char *arg, const Cmd *cmd ) { unsigned int i; @@ -839,7 +957,7 @@ else { Utl_toLower( s ); - strcpy( arg, Utl_restOfLn( line, 1 ) ); + Utl_cpyStr( arg, Utl_restOfLn( line, 1 ) ); pat = Utl_stripWhiteSpace( arg ); if ( pat[ 0 ] == '\0' ) pat = "*"; @@ -1437,7 +1555,7 @@ /* Parse line, execute command and return FALSE, if it was the quit command. */ static Bool -parseAndExecute( Str line ) +parseAndExecute( Str line, Bool authDone ) { unsigned int i, n; Cmd *c; @@ -1447,11 +1565,20 @@ if ( sscanf( line, MAXCHAR_FMT, s ) == 1 ) { Utl_toLower( s ); - strcpy( arg, Utl_restOfLn( line, 1 ) ); + Utl_cpyStr( arg, Utl_restOfLn( line, 1 ) ); n = sizeof( commands ) / sizeof( commands[ 0 ] ); for ( i = 0, c = commands; i < n; ++i, ++c ) if ( strcmp( c->name, s ) == 0 ) { +#if USE_AUTH + if ( c->needAuth && ! authDone ) + { + putStat( STAT_AUTH_REQUIRED, "Authentication required" ); + return TRUE; + } +#else + UNUSED( authDone ); +#endif ret = c->cmdProc( Utl_stripWhiteSpace( arg ), c ); return ret; } @@ -1501,6 +1628,63 @@ Str line; putWelcome(); + +#if USE_AUTH + /* + * If authentication is required, we issue the welcome message and + * go into a command loop that doesn't open the databases and just + * accepts authentication commands. Once successfully authenticated, + * we drop root privs (if we have them - they are needed for PAM + * authentication to work) and proceed to the normal loop. + */ + if ( Cfg_needClientAuth() ) + { + if ( ! Auth_open() ) + { + initOutput(); + putFatal( "Cannot open authorisation" ); + sendOutput(); + return; + } + + done = FALSE; + while ( ! done ) + { + if ( Prt_getLn( line, stdin, -1 ) ) + { + initOutput(); + + if ( ! parseAndExecute( line, FALSE ) ) + done = TRUE; + + if ( server.auth == AUTH_DONE ) + done = TRUE; + + sendOutput(); + } + else + { + Log_inf( "Client disconnected. Terminating." ); + done = TRUE; + } + } + + Auth_close(); + + /* Did we finish because we successfully authenticated? */ + if ( server.auth != AUTH_DONE ) + return; + } +#endif + + if ( ! Auth_dropPrivs() ) + { + initOutput(); + putFatal( "Cannot set user privs" ); + sendOutput(); + return; + } + done = FALSE; while ( ! done ) { @@ -1515,7 +1699,7 @@ } else { - if ( ! parseAndExecute( line ) ) + if ( ! parseAndExecute( line, TRUE ) ) done = TRUE; }