bug-cvs
[Top][All Lists]
Advanced

[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;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]