[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
patch for pam authentication in cvs
From: |
Brian Murphy |
Subject: |
patch for pam authentication in cvs |
Date: |
Fri, 11 Apr 2003 14:58:42 +0200 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020623 Debian/1.0.0-0.woody.1 |
Here is a patch to allow cvs to authenticate via pam.
You need a configuration file like this (for linux)
in /etc/pam.d/cvs:
auth sufficient pam_ldap.so
account sufficient pam_ldap.so
auth required pam_unix.so
account required pam_unix.so
to authenticate via ldap first and then to try via
the standard unix shadow/passwd method.
I have not tested this but it should also work on
any system supporting PAM (sun, hp, freebsd).
I hope this comes into the standard distribution. If not
I know there are others with the same needs as me who
can use this.
If there are any problems just contact me and I'll be
glad to fix them.
/Brian
Index: config.h.in
===================================================================
RCS file: /cvs/ccvs/config.h.in,v
retrieving revision 1.74
diff -u -r1.74 config.h.in
--- config.h.in 19 Mar 2003 21:13:29 -0000 1.74
+++ config.h.in 11 Apr 2003 13:47:00 -0000
@@ -205,6 +205,9 @@
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
+
+/* Defined if you have pam */
+#undef HAVE_PAM
/* Define to 1 if you have the `putenv' function. */
#undef HAVE_PUTENV
Index: configure.in
===================================================================
RCS file: /cvs/ccvs/configure.in,v
retrieving revision 1.187
diff -u -r1.187 configure.in
--- configure.in 1 Apr 2003 22:49:26 -0000 1.187
+++ configure.in 11 Apr 2003 13:47:07 -0000
@@ -315,6 +315,11 @@
dnl begin --with-*
dnl
+AC_CHECK_HEADER(security/pam_appl.h,
+ AC_DEFINE(HAVE_PAM, 1, [Defined if you have pam])
+)
+AC_CHECK_LIB(pam, pam_start, [LIBS="${LIBS} -lpam"])
+
dnl
dnl set $(KRB4) from --with-krb4=value -- WITH_KRB4
dnl
Index: src/server.c
===================================================================
RCS file: /cvs/ccvs/src/server.c,v
retrieving revision 1.290
diff -u -r1.290 server.c
--- src/server.c 17 Mar 2003 06:32:11 -0000 1.290
+++ src/server.c 11 Apr 2003 13:47:12 -0000
@@ -5548,50 +5548,99 @@
return retval;
}
+#ifdef HAVE_PAM
-/* Return a hosting username if password matches, else NULL. */
-static char *
-check_password (username, password, repository)
- char *username, *password, *repository;
-{
- int rc;
- char *host_user = NULL;
- char *found_passwd = NULL;
- struct passwd *pw;
+#include <security/pam_appl.h>
- /* First we see if this user has a password in the CVS-specific
- password file. If so, that's enough to authenticate with. If
- not, we'll check /etc/passwd. */
+#define PAM_SERVICENAME "cvs"
- rc = check_repository_password (username, password, repository,
- &host_user);
+struct cvs_pam_userinfo {
+ char *username;
+ char *password;
+};
- if (rc == 2)
- return NULL;
+#if SOLARIS2 == 260
+struct cvs_pam_userinfo *global_userinfo;
+#endif
- if (rc == 1)
- {
- /* host_user already set by reference, so just return. */
- goto handle_return;
- }
+static int
+cvs_pam_conv(int num_msg,
+ const struct pam_message **msg,
+ struct pam_response **resp,
+ void *appdata_ptr)
+{
+ int i;
+ struct pam_response *response;
+ struct cvs_pam_userinfo *ui = (struct cvs_pam_userinfo *)appdata_ptr;
+
+#if SOLARIS2 == 260
+ if(!ui)
+ ui = global_userinfo;
+#endif
- assert (rc == 0);
+ if (!ui || !ui->username || !ui->password || !msg || !resp)
+ return PAM_CONV_ERR;
- if (!system_auth)
- {
- /* Note that the message _does_ distinguish between the case in
- which we check for a system password and the case in which
- we do not. It is a real pain to track down why it isn't
- letting you in if it won't say why, and I am not convinced
- that the potential information disclosure to an attacker
- outweighs this. */
- printf ("error 0 no such user %s in CVSROOT/passwd\n", username);
+ response = malloc(num_msg * sizeof(struct pam_response));
+ if (!response)
+ return PAM_CONV_ERR;
+ for (i = 0; i < num_msg; i++){
+ response[i].resp_retcode = 0;
+ response[i].resp = 0;
+ switch(msg[i]->msg_style) {
+ case PAM_PROMPT_ECHO_ON:
+ response[i].resp = strdup(ui->username);
+ break;
+ case PAM_PROMPT_ECHO_OFF:
+ response[i].resp = strdup(ui->password);
+ break;
+ default:
+ if(response)
+ free(response);
+ return PAM_CONV_ERR;
+ }
+ }
+
+ *resp = response;
+ return PAM_SUCCESS;
+}
+
+static int
+check_system_password (username, password)
+ char *username, *password;
+{
+ pam_handle_t *pamh = NULL;
+ int retval;
+ struct cvs_pam_userinfo ui = { username, password };
+ struct pam_conv conv = { cvs_pam_conv, (void *)&ui };
- error_exit ();
- }
+#if SOLARIS2 == 260
+ global_userinfo = &ui;
+#endif
- /* No cvs password found, so try /etc/passwd. */
+ retval = pam_start(PAM_SERVICENAME, username, &conv, &pamh);
+
+ if (retval == PAM_SUCCESS)
+ retval = pam_authenticate(pamh, 0);
+
+ if (retval == PAM_SUCCESS)
+ retval = pam_acct_mgmt(pamh, 0);
+ if (pam_end(pamh,retval) != PAM_SUCCESS) {
+ printf("E Fatal error, aborting.\n
+ pam failed to release authenticator\n");
+ error_exit ();
+ }
+
+ return (retval == PAM_SUCCESS); /* indicate success */
+}
+#else
+static int
+check_system_password (username, password)
+ char *username, *password;
+{
+ char *found_passwd = NULL;
+ struct passwd *pw;
#ifdef HAVE_GETSPNAM
{
struct spwd *spw;
@@ -5637,32 +5686,74 @@
/* user exists and has a password */
if (strcmp (found_passwd, crypt (password, found_passwd)) == 0)
{
- host_user = xstrdup (username);
+ return 1;
}
else
{
- host_user = NULL;
#ifdef LOG_AUTHPRIV
syslog (LOG_AUTHPRIV | LOG_NOTICE,
"password mismatch for %s: %s vs. %s", username,
crypt(password, found_passwd), found_passwd);
#endif
+ return 0;
}
- goto handle_return;
}
if (password && *password)
+ return 1;
+
+ return 0;
+}
+#endif
+
+/* Return a hosting username if password matches, else NULL. */
+static char *
+check_password (username, password, repository)
+ char *username, *password, *repository;
+{
+ int rc;
+ char *host_user = NULL;
+
+ /* First we see if this user has a password in the CVS-specific
+ password file. If so, that's enough to authenticate with. If
+ not, we'll check /etc/passwd. */
+
+ rc = check_repository_password (username, password, repository,
+ &host_user);
+
+ if (rc == 2)
+ return NULL;
+
+ if (rc == 1)
{
- /* user exists and has no system password, but we got
- one as parameter */
- host_user = xstrdup (username);
+ /* host_user already set by reference, so just return. */
goto handle_return;
}
- /* user exists but has no password at all */
- host_user = NULL;
+ assert (rc == 0);
+
+ if (!system_auth)
+ {
+ /* Note that the message _does_ distinguish between the case in
+ which we check for a system password and the case in which
+ we do not. It is a real pain to track down why it isn't
+ letting you in if it won't say why, and I am not convinced
+ that the potential information disclosure to an attacker
+ outweighs this. */
+ printf ("error 0 no such user %s in CVSROOT/passwd\n", username);
+
+ error_exit ();
+ }
+
+ /* No cvs password found, so try /etc/passwd. */
+ if ( check_system_password(username, password) )
+ host_user = xstrdup (username);
+ else
+ host_user = NULL;
+
#ifdef LOG_AUTHPRIV
- syslog (LOG_AUTHPRIV | LOG_NOTICE,
+ if (!host_user)
+ syslog (LOG_AUTHPRIV | LOG_NOTICE,
"login refused for %s: user has no password", username);
#endif
- patch for pam authentication in cvs,
Brian Murphy <=
- Re: patch for pam authentication in cvs, Brian Murphy, 2003/04/11
- Re: patch for pam authentication in cvs, Larry Jones, 2003/04/11
- Re: patch for pam authentication in cvs, Brian Murphy, 2003/04/11
- Re: patch for pam authentication in cvs, Kevin Wang, 2003/04/11
- Re: patch for pam authentication in cvs, Brian Murphy, 2003/04/11
- Re: patch for pam authentication in cvs, Derek Robert Price, 2003/04/14
- Re: patch for pam authentication in cvs, Brian Murphy, 2003/04/15
- Re: patch for pam authentication in cvs, Larry Jones, 2003/04/11
- Re: patch for pam authentication in cvs, Kevin Wang, 2003/04/11