[ Debian BTS CC:ed - I sent the patch there too ]
On Fri, Oct 19, 2001 at 05:37:39PM -0400, [EMAIL PROTECTED] wrote:
>
>Steve McIntyre wrote:
>
>> The patch here adds PAM support to CVS, so it now works for us in an
>> all-PAM (LDAP) environment:
>
>Did I miss something? It appears you've added some includes and two new
>functions, but no calls to these functions.
Oops. Sorry - I clearly cut the patch short somehow. I've attached the
full patch below.
>Also, though we can probably dispense with the test cases, the
>HAVE_PAM should be tied into the configure script and this deserves
>comments in the news file.
Obviously, yes. I've never played with autoconf and friends, so I
thought it best left alone.
--
Steve McIntyre, Allstor Software [EMAIL PROTECTED]
Support the Campaign for Audiovisual Free Expression: http://www.eff.org/cafe/
--- cvs-1.11.1p1.orig/src/Makefile.in
+++ cvs-1.11.1p1/src/Makefile.in
@@ -180,7 +180,7 @@
cvs_LDADD = \
../diff/libdiff.a \
../lib/libcvs.a \
- ../zlib/libz.a \
+ -lz -ldl -lpam \
version.o
cvs_EXTRA_DIST = version.c
--- cvs-1.11.1p1.orig/src/server.c
+++ cvs-1.11.1p1/src/server.c
@@ -16,6 +16,13 @@
#include "getline.h"
#include "buffer.h"
+#define HAVE_PAM
+
+#ifdef HAVE_PAM
+#include <security/pam_misc.h>
+#include <security/pam_appl.h>
+#endif
+
#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
# ifdef HAVE_GSSAPI
/* This stuff isn't included solely with SERVER_SUPPORT since some of these
@@ -5526,6 +5536,106 @@
return retval;
}
+#ifdef HAVE_PAM
+/* The callback function that the pam modules will use to talk to
+ us. Modelled closely on the misc_conv module of Linux-PAM. This
+ blatantly subverts one of the principles of PAM - PAM is meant to
+ handle all the password work. Bu this does the job and means I can
+ transition to LDAP right now. */
+int cvs_conv(int num_msg, const struct pam_message **msgm,
+ struct pam_response **response, void *appdata_ptr)
+{
+ int count=0;
+ struct pam_response *reply;
+
+ if (num_msg <= 0)
+ return PAM_CONV_ERR;
+
+ reply = (struct pam_response *) calloc(num_msg,
+ sizeof(struct pam_response));
+ if (reply == NULL)
+ return PAM_CONV_ERR;
+
+ for (count=0; count < num_msg; ++count)
+ {
+ char *string=NULL;
+
+ switch (msgm[count]->msg_style)
+ {
+ case PAM_PROMPT_ECHO_OFF:
+ case PAM_PROMPT_ECHO_ON:
+ string = (char *)appdata_ptr;
+ break;
+ default:
+ break;
+ }
+
+ if (string) /* must add to reply array */
+ {
+ /* add string to list of responses */
+ reply[count].resp_retcode = 0;
+ reply[count].resp = string;
+ string = NULL;
+ }
+ }
+
+ *response = reply;
+ reply = NULL;
+
+ return PAM_SUCCESS;
+}
+
+static struct pam_conv conv = {
+ cvs_conv,
+ NULL
+};
+
+/* Modelled very closely on the example code in "The Linux-PAM
+ Application Developers' Guide" by Andrew G. Morgan. */
+static int
+check_pam_password (username, password, repository, host_user_ptr)
+ char *username, *password, *repository, **host_user_ptr;
+{
+ pam_handle_t *pamh=NULL;
+ int retval;
+ int rc = 0;
+
+ conv.appdata_ptr = password;
+
+ retval = pam_start("cvs", username, &conv, &pamh);
+
+ if (retval == PAM_SUCCESS)
+ retval = pam_authenticate(pamh, 0); /* is user really user? */
+
+ if (retval == PAM_SUCCESS)
+ retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
+
+ /* This is where we have been authorized or not. */
+
+ switch(retval)
+ {
+ case PAM_SUCCESS:
+ *host_user_ptr = xstrdup(username);
+ rc = 1;
+ break;
+ case PAM_AUTH_ERR:
+ *host_user_ptr = NULL;
+ rc = 2;
+ break;
+ default:
+ *host_user_ptr = NULL;
+ rc = 0;
+ break;
+ }
+
+ if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close PAM */
+ pamh = NULL;
+ fprintf(stderr, "failed to release authenticator\n");
+ }
+
+ return rc; /* indicate success */
+}
+#endif /* HAVE_PAM */
/* Return a hosting username if password matches, else NULL. */
static char *
@@ -5552,6 +5662,24 @@
/* host_user already set by reference, so just return. */
goto handle_return;
}
+
+#ifdef HAVE_PAM
+ else if(rc == 0 && system_auth)
+ {
+ rc = check_pam_password (username, password, repository,
+ &host_user);
+ if (rc == 2)
+ return NULL;
+
+ /* else */
+
+ if (rc == 1)
+ {
+ /* host_user already set by reference, so just return. */
+ goto handle_return;
+ }
+ }
+#else /* HAVE_PAM */
else if (rc == 0 && system_auth)
{
/* No cvs password found, so try /etc/passwd. */
@@ -5613,6 +5741,7 @@
goto handle_return;
}
}
+#endif /* HAVE_PAM */
else if (rc == 0)
{
/* Note that the message _does_ distinguish between the case in