[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: PAM awareness
From: |
Brian Murphy |
Subject: |
Re: PAM awareness |
Date: |
Sun, 27 Jun 2004 03:18:31 +0200 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Debian/1.6-5 |
Derek Robert Price wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Brian Murphy wrote:
This is not enough, I have a patch which adds pam session management
functionality
so that things set by pam modules are set in the running session
(for example
extra groups)
The patch is here:
http://lists.gnu.org/archive/html/bug-cvs/2003-10/msg00307.html
Does this patch need to be committed, Brian, or is it unfinished?
Does it deserve documentation or does it provide functionality users
will expect from a PAM enabled application?
Derek
The PAM support is incomplete without it, some things which PAM modules can
do are unsupported by CVS without the patch. The patch was in response to a
request from someone who used a PAM module which allocated group permissions
to the user which were then ignored by CVS.
The attached patch makes PAM support complete in that it supports all PAM
functionality.
The contrib directory does not include a "pam" subdirectory with the
configuration
files for linux and solaris, at least in the released version (1.12.9).
These should
also be updated to match the documentation.
ChangeLog
cvs.texinfo:
Added documentation for the now required session configuration for PAM.
server.c:
pamh: new global static to hold the pam handle.
server: close the PAM session so that logging works properly
switch_to_user: opens a PAM session and gets credentials from PAM
so that PAM modules can change group
permissions.
get the username from PAM so that PAM modules
can modify the final local username
cvs_pam_conv: changed the assertions to allow PAM to output text
to the user.
check_system_password renamed to check_pam_password
check_pam_password:
changed argument type for username so that PAM
modules
can modify the username under authentication.
setting a terminal so some PAM modules which
expect it to
be set work, it is set to the pam servicename
which defaults
to the binary name.
Set the username from PAM after authentication
if a module
has changed it.
check_password: calls check_pam_password if PAM is enabled otherwise
calls check_system_password
/Brian
diff -b -r -u cvs-1.12.9/doc/cvs.texinfo cvs-1.12.9.mine/doc/cvs.texinfo
--- cvs-1.12.9/doc/cvs.texinfo 2004-05-19 23:38:31.000000000 +0200
+++ cvs-1.12.9.mine/doc/cvs.texinfo 2004-06-27 02:59:43.000000000 +0200
@@ -2571,7 +2571,7 @@
flexibility about how @sc{cvs} users are authenticated but
no more security than other methods. See below for more.}
-CVS needs an "auth" and "account" module in the
+CVS needs an "auth", "account" and "session" module in the
PAM configuration file. A typical PAM configuration
would therefore have the following lines
in @file{/etc/pam.conf} to emulate the standard @sc{cvs}
@@ -2580,6 +2580,7 @@
@example
cvs auth required pam_unix.so
cvs account required pam_unix.so
+cvs session required pam_unix.so
@end example
The the equivalent @file{/etc/pam.d/cvs} would contain
@@ -2587,6 +2588,7 @@
@example
auth required pam_unix.so
account required pam_unix.so
+session required pam_unix.so
@end example
Some systems require a full path to the module so that
diff -b -r -u cvs-1.12.9/src/server.c cvs-1.12.9.mine/src/server.c
--- cvs-1.12.9/src/server.c 2004-06-09 16:52:39.000000000 +0200
+++ cvs-1.12.9.mine/src/server.c 2004-06-27 02:53:40.000000000 +0200
@@ -112,6 +112,12 @@
# endif /* AUTH_SERVER_SUPPORT */
+#ifdef HAVE_PAM
+# include <security/pam_appl.h>
+
+static pam_handle_t *pamh = NULL;
+#endif
+
/* While processing requests, this buffer accumulates data to be sent to
the client, and then once we are in do_cvs_command, we use it
@@ -5340,6 +5346,28 @@
error (0, 0, "Dying gasps received from client.");
}
+#ifdef HAVE_PAM
+ {
+ int retval;
+
+ retval = pam_close_session(pamh, 0);
+#ifdef HAVE_SYSLOG_H
+ if (retval != PAM_SUCCESS)
+ syslog (LOG_DAEMON | LOG_ERR,
+ "PAM close session error: %s",
+ pam_strerror(pamh, retval));
+#endif
+
+ retval = pam_end (pamh, retval);
+#ifdef HAVE_SYSLOG_H
+ if (retval != PAM_SUCCESS)
+ syslog (LOG_DAEMON | LOG_ERR,
+ "PAM failed to release authenticator, error: %s",
+ pam_strerror(pamh, retval));
+#endif
+ }
+#endif
+
/* server_cleanup() will be called on a normal exit and close the buffers
* explicitly.
*/
@@ -5353,6 +5381,22 @@
switch_to_user (const char *cvs_username, const char *username)
{
struct passwd *pw;
+#ifdef HAVE_PAM
+ int retval;
+ char *pam_stage = "open session";
+
+ retval = pam_open_session(pamh, 0);
+ if (retval == PAM_SUCCESS) {
+ pam_stage = "get pam user";
+ retval = pam_get_item(pamh, PAM_USER, (const void **)&username);
+ }
+
+ if (retval != PAM_SUCCESS) {
+ printf("E PAM %s error: %s\n", pam_stage,
+ pam_strerror(pamh, retval));
+ exit (EXIT_FAILURE);
+ }
+#endif
pw = getpwnam (username);
if (pw == NULL)
@@ -5398,6 +5442,15 @@
}
#endif /* HAVE_INITGROUPS */
+#ifdef HAVE_PAM
+ retval = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+ if (retval != PAM_SUCCESS) {
+ printf("E PAM reestablish credentials error: %s\n",
+ pam_strerror(pamh, retval));
+ exit (EXIT_FAILURE);
+ }
+#endif
+
#ifdef SETXID_SUPPORT
/* honor the setgid bit iff set*/
if (getgid() != getegid())
@@ -5641,8 +5694,6 @@
#ifdef HAVE_PAM
-# include <security/pam_appl.h>
-
struct cvs_pam_userinfo {
char *username;
char *password;
@@ -5656,7 +5707,7 @@
struct pam_response *response;
struct cvs_pam_userinfo *ui = (struct cvs_pam_userinfo *)appdata_ptr;
- assert (ui && ui->username && ui->password && msg && resp);
+ assert (msg && resp);
response = xmalloc(num_msg * sizeof (struct pam_response));
memset(response, 0, num_msg * sizeof (struct pam_response));
@@ -5667,10 +5718,12 @@
{
/* PAM wants a username */
case PAM_PROMPT_ECHO_ON:
+ assert (ui && ui->username);
response[i].resp = xstrdup (ui->username);
break;
/* PAM wants a password */
case PAM_PROMPT_ECHO_OFF:
+ assert (ui && ui->password);
response[i].resp = xstrdup (ui->password);
break;
case PAM_ERROR_MSG:
@@ -5699,18 +5752,21 @@
return PAM_CONV_ERR;
}
-
-
static int
-check_system_password (char *username, char *password)
+check_pam_password (char **username, char *password)
{
- pam_handle_t *pamh = NULL;
int retval, err;
- struct cvs_pam_userinfo ui = { username, password };
+ struct cvs_pam_userinfo ui = { *username, password };
struct pam_conv conv = { cvs_pam_conv, (void *)&ui };
char *pam_stage = "start";
- retval = pam_start (PAM_SERVICE_NAME, username, &conv, &pamh);
+ retval = pam_start (PAM_SERVICE_NAME, *username, &conv, &pamh);
+
+ /* sets a dummy tty name which pam modules can check for */
+ if (retval == PAM_SUCCESS) {
+ pam_stage = "set dummy tty";
+ retval = pam_set_item(pamh, PAM_TTY, PAM_SERVICE_NAME);
+ }
if (retval == PAM_SUCCESS) {
pam_stage = "authenticate";
@@ -5722,20 +5778,18 @@
retval = pam_acct_mgmt (pamh, 0);
}
+ if (retval == PAM_SUCCESS) {
+ pam_stage = "get pam user";
+ retval = pam_get_item(pamh, PAM_USER, (const void **)username);
+ }
+
if (retval != PAM_SUCCESS)
printf ("E PAM %s error: %s\n", pam_stage, pam_strerror(pamh, retval));
- if ((err = pam_end (pamh, retval)) != PAM_SUCCESS)
- {
- printf ("E Fatal error, aborting.\n"
- "pam failed to release authenticator\n"
- "PAM error %s\n", pam_strerror (NULL, err));
- exit (EXIT_FAILURE);
- }
-
return retval == PAM_SUCCESS; /* indicate success */
}
-#else
+#endif
+
static int
check_system_password (char *username, char *password)
{
@@ -5800,7 +5854,6 @@
#endif
return 1;
}
-#endif
@@ -5841,7 +5894,11 @@
}
/* No cvs password found, so try /etc/passwd. */
+#ifdef HAVE_PAM
+ if ( check_pam_password(&username, password) )
+#else
if ( check_system_password(username, password) )
+#endif
host_user = xstrdup (username);
else
host_user = NULL;