From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19123 invoked from network); 20 Jun 2004 16:43:31 -0000 Received: from unknown (HELO lists.gnu.org) (199.232.76.165) by sourceware.org with SMTP; 20 Jun 2004 16:43:31 -0000 Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1Bc5Qz-00058X-Jk for listarch-gnats-devel@sources.redhat.com; Sun, 20 Jun 2004 12:44:45 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.33) id 1Bc5Qt-00057z-VX for help-gnats@gnu.org; Sun, 20 Jun 2004 12:44:40 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.33) id 1Bc5Qs-00057n-TX for help-gnats@gnu.org; Sun, 20 Jun 2004 12:44:39 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1Bc5Qs-00057c-Qd for help-gnats@gnu.org; Sun, 20 Jun 2004 12:44:38 -0400 Received: from [207.217.120.116] (helo=grouse.mail.pas.earthlink.net) by monty-python.gnu.org with esmtp (Exim 4.34) id 1Bc5PZ-0002l8-T5 for help-gnats@gnu.org; Sun, 20 Jun 2004 12:43:18 -0400 Received: from h-68-164-95-117.snvacaid.dynamic.covad.net ([68.164.95.117] helo=earthlink.net) by grouse.mail.pas.earthlink.net with esmtp (Exim 3.33 #1) id 1Bc5PW-0003yW-00 for help-gnats@gnu.org; Sun, 20 Jun 2004 09:43:14 -0700 Message-ID: <40D5BE7A.2080503@earthlink.net> Date: Sun, 20 Jun 2004 17:39:00 -0000 From: Pankaj K Garg Organization: Zee Source User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040113 X-Accept-Language: en-us, en, ja MIME-Version: 1.0 To: help-gnats@gnu.org References: <20040610205814.GA27286@wookimus.net> <40CDCBEA.9050505@earthlink.net> <20040614165706.GG3528@wookimus.net> In-Reply-To: <20040614165706.GG3528@wookimus.net> Content-Type: multipart/mixed; boundary="------------000100030503040501050909" Subject: PAM Authentication Patch X-BeenThere: help-gnats@gnu.org X-Mailman-Version: 2.1.4 Precedence: list Reply-To: gargp@acm.org List-Id: General discussion about GNU GNATS List-Archive: List-Post: List-Help: List-Subscribe: , Sender: help-gnats-bounces+listarch-gnats-devel=sources.redhat.com@gnu.org Errors-To: help-gnats-bounces+listarch-gnats-devel=sources.redhat.com@gnu.org X-SW-Source: 2004-q2/txt/msg00173.txt.bz2 This is a multi-part message in MIME format. --------------000100030503040501050909 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1722 I'm attaching a patch for enabling PAM authentication support. To keep the patch file small, I've not included the diffs to the files 'configure' and 'gnats/configure'. Use autoconf to generate these two files. If you need the generated files, let me know and I'll create another patch. PAM support can now be enabled by using '--enable-pam' switch to configure. With PAM support enabled, you can put an entry in the gantsd.user_access file as: :$p$: and the authentication for the user will be done against the configured PAM modules. The name of the PAM service is taken from the DEFAULT_GANTS_SERVICE define, so by default it should be 'support'. Hence, you can configure PAM by creating the file /etc/pam.d/support on RH Linux. I've tried to make appropriate changes to the documentation. Let me know if any other document requires update. I've done some preliminary testing on my RH 9.0 Linux. Please let me know if there's any problem with it. Pankaj Chad C. Walstrom wrote: > Pankaj K Garg wrote: > >>Is anyone signed up for adding PAM authentication support yet? If not, >>I can sign up for it. > > > No, no one has signed up for this yet. I placed your name in the TODO > list and updated it in CVS. I don't plan on making ChangeLog entries > for these files (.todo and TODO), though I will note the changes made in > the cvs log entry. Welcome aboard! I look forward to getting your > patches! -- Pankaj K Garg garg@zeesource.net 1684 Nightingale Avenue 408-373-4027 Suite 201 408-733-2737(fax) Sunnyvale, CA 94087 http://www.zeesource.net http://home.earthlink.net/~gargp --------------000100030503040501050909 Content-Type: text/plain; name="pam_patch.out" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pam_patch.out" Content-length: 17955 ? autom4te.cache ? pamdiffs.out ? gnats/autom4te.cache ? libiberty/xhost-mkfrag Index: doc/gnats.texi =================================================================== RCS file: /cvsroot/gnats/gnats/doc/gnats.texi,v retrieving revision 1.44 diff -u -p -r1.44 gnats.texi --- doc/gnats.texi 30 Aug 2003 07:55:06 -0000 1.44 +++ doc/gnats.texi 20 Jun 2004 16:34:24 -0000 @@ -1670,8 +1670,9 @@ string @samp{$1$}.@footnote{Some systems methods. In FreeBSD, for instance, a prefix of @samp{$2$} implies Blowfish encoding. @sc{gnats} will happily accept any encryption that the OS supports.} Passwords encrypted by @code{crypt()} should have no -prefix. If no password is given then users can login with an empty -password string. +prefix. If you want to authenticate users with PAM authentication +module, then supply a @samp{$p$} for the password entry. If no +password is given then users can login with an empty password string. A @code{gnats-passwd} tool to manage @file{gnatsd.user_access} files is planned. In the meantime, @code{crypt()} passwords can be generated by Index: gnats/acconfig.h =================================================================== RCS file: /cvsroot/gnats/gnats/gnats/acconfig.h,v retrieving revision 1.3 diff -u -p -r1.3 acconfig.h --- gnats/acconfig.h 26 May 2001 20:42:30 -0000 1.3 +++ gnats/acconfig.h 20 Jun 2004 16:34:24 -0000 @@ -26,3 +26,8 @@ Software Foundation, 59 Temple Place - S /* Define if strftime supports %z. */ #undef HAVE_STRFTIME_WITH_Z + +/* Define to enable system authentication with PAM instead of using the simple + getpwnam interface. This allows authentication (in theory) with any PAM + module, e.g. on systems with shadow passwords or via LDAP */ +#undef HAVE_PAM Index: gnats/autoconf.h.in =================================================================== RCS file: /cvsroot/gnats/gnats/gnats/autoconf.h.in,v retrieving revision 1.11 diff -u -p -r1.11 autoconf.h.in --- gnats/autoconf.h.in 6 Jan 2002 16:16:45 -0000 1.11 +++ gnats/autoconf.h.in 20 Jun 2004 16:34:24 -0000 @@ -1,143 +1,212 @@ -/* autoconf.h.in. Generated automatically from configure.in by autoheader 2.13. */ +/* autoconf.h.in. Generated from configure.in by autoheader. */ +/* GNATS specific autoconf symbols. + Copyright (C) 2001 Milan Zamazal + Copyright (C) 1995, 1996 ??? (FIXME, see ChangeLog.v3) + +This file is part of GNU GNATS. + +GNU GNATS 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. + +GNU GNATS 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 GNU GNATS; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ -/* Define if on AIX 3. - System headers sometimes define this. - We just want to avoid a redefinition error message. */ -#ifndef _ALL_SOURCE -#undef _ALL_SOURCE -#endif +/* Define if you have MIT Kerberos version 4 available. */ +#undef HAVE_KERBEROS -/* Define if using alloca.c. */ -#undef C_ALLOCA +/* Define if your system has socklen_t (glibc?) */ +#undef HAVE_SOCKLEN_T -/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. - This function is required for alloca.c support on those systems. */ +/* Define if strftime supports %z. */ +#undef HAVE_STRFTIME_WITH_Z + +/* Define to enable system authentication with PAM instead of using the simple + getpwnam interface. This allows authentication (in theory) with any PAM + module, e.g. on systems with shadow passwords or via LDAP */ +#undef HAVE_PAM + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ #undef CRAY_STACKSEG_END -/* Define if you have alloca, as a function or macro. */ +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + +/* Define to 1 if you have `alloca', as a function or macro. */ #undef HAVE_ALLOCA -/* Define if you have and it should be used (not on Ultrix). */ +/* Define to 1 if you have and it should be used (not on Ultrix). + */ #undef HAVE_ALLOCA_H -/* Define if on MINIX. */ -#undef _MINIX - -/* Define if the system does not provide POSIX.1 features except - with this defined. */ -#undef _POSIX_1_SOURCE - -/* Define if you need to in order for stat and other things to work. */ -#undef _POSIX_SOURCE - -/* Define to `unsigned' if doesn't define. */ -#undef size_t - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at run-time. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown - */ -#undef STACK_DIRECTION +/* Define to 1 if you have the header file. */ +#undef HAVE_CRYPT_H -/* Define if you have the ANSI C header files. */ -#undef STDC_HEADERS +/* Whether unsetenv is present in headers. */ +#undef HAVE_DECL_UNSETENV -/* Define if you have MIT Kerberos version 4 available. */ -#undef HAVE_KERBEROS +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H -/* Define if your system has socklen_t (glibc?) */ -#undef HAVE_SOCKLEN_T +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H -/* Define if you have the ftime function. */ +/* Define to 1 if you have the `ftime' function. */ #undef HAVE_FTIME -/* Define if you have the krb_get_err_text function. */ +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `krb_get_err_text' function. */ #undef HAVE_KRB_GET_ERR_TEXT -/* Define if you have the mkdir function. */ -#undef HAVE_MKDIR +/* Define to 1 if you have the `crypt' library (-lcrypt). */ +#undef HAVE_LIBCRYPT -/* Define if you have the mkstemp function. */ -#undef HAVE_MKSTEMP +/* Define to 1 if you have the `gen' library (-lgen). */ +#undef HAVE_LIBGEN -/* Define if you have the mktemp function. */ -#undef HAVE_MKTEMP +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBGEN_H -/* Define if you have the unsetenv function. */ -#undef HAVE_UNSETENV +/* Define to 1 if you have the `inet' library (-linet). */ +#undef HAVE_LIBINET -/* Define if you have the header file. */ -#undef HAVE_CRYPT_H +/* Define to 1 if you have the `intl' library (-lintl). */ +#undef HAVE_LIBINTL -/* Define if you have the header file. */ -#undef HAVE_DIRENT_H +/* Define to 1 if you have the `malloc' library (-lmalloc). */ +#undef HAVE_LIBMALLOC -/* Define if you have the header file. */ -#undef HAVE_FCNTL_H +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL -/* Define if you have the header file. */ -#undef HAVE_LIBGEN_H +/* Define to 1 if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_MACHINE_ENDIAN_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H -/* Define if you have the header file. */ +/* Define to 1 if you have the `mkdir' function. */ +#undef HAVE_MKDIR + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the `mktemp' function. */ +#undef HAVE_MKTEMP + +/* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H -/* Define if you have the header file. */ +/* Define to enable system authentication with PAM instead of using the simple + getpwnam interface. This allows authentication (in theory) with any PAM + module, e.g. on systems with shadow passwords or via LDAP */ +#undef HAVE_PAM + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ #undef HAVE_STRING_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ #undef HAVE_SYS_DIR_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file, and it defines `DIR'. + */ #undef HAVE_SYS_NDIR_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H -/* Define if you have the header file. */ -#undef HAVE_SYSLOG_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* Define if you have the crypt library (-lcrypt). */ -#undef HAVE_LIBCRYPT +/* Define to 1 if you have the `unsetenv' function. */ +#undef HAVE_UNSETENV -/* Define if you have the gen library (-lgen). */ -#undef HAVE_LIBGEN +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT -/* Define if you have the inet library (-linet). */ -#undef HAVE_LIBINET +/* Define to the full name of this package. */ +#undef PACKAGE_NAME -/* Define if you have the intl library (-lintl). */ -#undef HAVE_LIBINTL +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING -/* Define if you have the malloc library (-lmalloc). */ -#undef HAVE_LIBMALLOC +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME -/* Define if you have the nsl library (-lnsl). */ -#undef HAVE_LIBNSL +/* Define to the version of this package. */ +#undef PACKAGE_VERSION -/* Define if you have the socket library (-lsocket). */ -#undef HAVE_LIBSOCKET +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION -/* Whether unsetenv is present in headers. */ -#undef HAVE_DECL_UNSETENV +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS -/* Whether unsetenv is present in headers. */ -#undef HAVE_DECL_UNSETENV +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* Define to `unsigned' if does not define. */ +#undef size_t Index: gnats/configure.in =================================================================== RCS file: /cvsroot/gnats/gnats/gnats/configure.in,v retrieving revision 1.31 diff -u -p -r1.31 configure.in --- gnats/configure.in 20 Sep 2003 22:36:43 -0000 1.31 +++ gnats/configure.in 20 Jun 2004 16:34:24 -0000 @@ -291,6 +291,42 @@ if test -z "${GNATS_DEFAULT_DB_DIR}"; th GNATS_DEFAULT_DB_DIR=${sharedstatedir}/gnatsdb fi +dnl +dnl begin --enable-pam +dnl + +dnl +dnl Check if PAM authentication is enabled +dnl +AC_ARG_ENABLE( + [pam], + AC_HELP_STRING( + [--enable-pam], + [Use to enable system authentication with PAM instead of using the + simple file based passwords. This allows authentication (in theory) + with any PAM module, e.g. on systems with shadow passwords or via LDAP]), , + [enable_pam=no] + ) + +if test yes = $enable_pam; then + AC_CHECK_HEADER(security/pam_appl.h, + AC_DEFINE(HAVE_PAM, 1, + [Define to enable system authentication with PAM instead of using the + simple getpwnam interface. This allows authentication (in theory) + with any PAM module, e.g. on systems with shadow passwords or via LDAP]) + AC_CHECK_LIB(pam, pam_start, [LIBS="${LIBS} -lpam"], + AC_MSG_ERROR([Could not find PAM libraries but the headers exist. + Give the --disable-pam option to compile without PAM support (or fix + your broken configuration)]) + ), + AC_MSG_ERROR([Could not find PAM headers]) + ) +fi + +dnl +dnl end --enable-pam +dnl + # Set up default values to be overridden _h=`(hostname || uname -n) 2>/dev/null | sed 1q` Index: gnats/gnatsd.c =================================================================== RCS file: /cvsroot/gnats/gnats/gnats/gnatsd.c,v retrieving revision 1.48 diff -u -p -r1.48 gnatsd.c --- gnats/gnatsd.c 14 Oct 2002 11:42:25 -0000 1.48 +++ gnats/gnatsd.c 20 Jun 2004 16:34:25 -0000 @@ -248,18 +248,133 @@ match (const char *line, const char *pat } } -/* Return true iff `password' matches `hash'. - `hash' is a possibly encrypted password, according to the $?$ convention. */ +#ifdef HAVE_PAM +/** + * + * Support for PAM authentication. Code borrowed from CVS server code + * with similar capability (gargp@acm.org) + * + **/ +#include + +struct gnats_pam_userinfo { + const char *username; + const char *password; +}; + static int -password_match (const char *password, const char *hash) +gnats_pam_conv(int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr ) { - if (strlen(password) && strlen(hash)) + int i; + struct pam_response *response; + struct gnats_pam_userinfo *ui = (struct gnats_pam_userinfo *)appdata_ptr; + + response = xmalloc(num_msg * sizeof(struct pam_response)); + memset(response, 0, num_msg * sizeof(struct pam_response)); + + for (i = 0; i < num_msg; i++) + { + switch(msg[i]->msg_style) + { + /* PAM wants a username */ + case PAM_PROMPT_ECHO_ON: + response[i].resp = xstrdup(ui->username); + break; + /* PAM wants a password */ + case PAM_PROMPT_ECHO_OFF: + response[i].resp = xstrdup(ui->password); + break; + case PAM_ERROR_MSG: + case PAM_TEXT_INFO: + printf("%s\n",msg[i]->msg); + break; + /* PAM wants something we don't understand - bail out */ + default: + goto cleanup; + } + } + + *resp = response; + return PAM_SUCCESS; + + cleanup: + for (i = 0; i < num_msg; i++) + { + if (response[i].resp) + { + free(response[i].resp); + response[i].resp = 0; + } + } + free(response); + return PAM_CONV_ERR; +} + +static bool +pam_password_match( const char *username, const char *password ) +{ + pam_handle_t *pamh = NULL; + int retval, err; + struct gnats_pam_userinfo ui; + struct pam_conv conv; + const char *pam_stage = "start"; + + ui.username = username; + ui.password = password; + + conv.conv = gnats_pam_conv; + conv.appdata_ptr = (void *)&ui; + + retval = pam_start(DEFAULT_GNATS_SERVICE, username, &conv, &pamh); + + if (retval == PAM_SUCCESS) { + pam_stage = "authenticate"; + retval = pam_authenticate(pamh, 0); + } + + if (retval == PAM_SUCCESS) { + pam_stage = "account"; + retval = pam_acct_mgmt(pamh, 0); + } + + if (retval != PAM_SUCCESS) + syslog(LOG_ERR, "PAM %s error: %s\n", pam_stage, pam_strerror(pamh, retval)); + + if ((err = pam_end(pamh, retval)) != PAM_SUCCESS) + { + syslog(LOG_ERR, "PAM error %s\n", pam_strerror(NULL, err)); + exit (EXIT_FAILURE); + } + + return retval == PAM_SUCCESS ? TRUE : FALSE; /* indicate success */ +} +#endif + +/** + * + * Return TRUE iff `password' matches, as specified by `hash'. + * `hash' is a possibly encrypted password, according to the $?$ convention. + * If hash == '$p$', then use the PAM service for authentication. + * + **/ +static int +password_match (const char *user, const char *password, const char *hash) +{ + if (strlen(user) && strlen(password) && strlen(hash)) { if (! strncmp (hash, "$0$", 3)) { /* explicit plain-text password */ return match (password, hash+3, TRUE); } +#ifdef HAVE_PAM + else if (! strncmp (hash, "$p$", 3)) + { + /* check with PAM module */ + return pam_password_match (user, password); + } +#endif else { #ifdef HAVE_LIBCRYPT @@ -461,7 +576,7 @@ findUserAccessLevel (const char *file, c if ((ent->fieldcount == 3 || ent->fieldcount == 4) && match (user, ent->admFields[0], TRUE)) { - if (! password_match (passwd, ent->admFields[1])) + if (! password_match (user, passwd, ent->admFields[1])) { /* Username matched but password didn't. */ if (strlen(ent->admFields[1]) && strlen(passwd)) --------------000100030503040501050909 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 140 _______________________________________________ Help-gnats mailing list Help-gnats@gnu.org http://lists.gnu.org/mailman/listinfo/help-gnats --------------000100030503040501050909--