bug-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

GSSAPI + pserver + systemauth=no


From: jomarqua
Subject: GSSAPI + pserver + systemauth=no
Date: Tue, 17 Sep 2002 22:58:56 -0400 (EDT)

CVS'ers

        I noticed during my attempts to configure cvs 1.11.1p1 using
gssapi authentication and systemauth=no that it did not work as one might
expect from the documentation.

        I am attaching a patch that changes the behavior - such that
gssapi authentication is now subject to the systemauth configuration and
the CVSROOT/passwd file.  (This includes support for virtual users via the
passwd file remapping of usernames.)

I submit this for suggestions on how to make it better - i am concerned
about the addition of a new function gssapi_check_password() - i feel that
there should be a better method of integrating this functionality with the
normal check_password function.  If anyone has sugegstions about how to
better clean that up, I would be delighted to resubmit this patch with
modifications to the News file, and other suggestions in the HACKING file.


Thanks ever so much for a fabulous product!

-VaiX

--------------SNIP--------------

diff -rU 5 cvs-1.11.2/src/client.c j.cvs2/src/client.c
--- cvs-1.11.2/src/client.c     Thu Aug  9 16:27:26 2001
+++ j.cvs2/src/client.c Tue Sep 17 20:05:27 2002
@@ -4236,10 +4236,18 @@
     str = "BEGIN GSSAPI REQUEST\012";

     if (send (sock, str, strlen (str), 0) < 0)
        error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));

+    if (send (sock, current_parsed_root->directory, strlen 
(current_parsed_root->directory), 0) < 0)
+       error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
+
+    str = "\012";
+
+    if (send (sock, str, strlen (str), 0) < 0)
+       error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
+
     if (strlen (hostinfo->h_name) > BUFSIZE - 5)
        error (1, 0, "Internal error: hostname exceeds length of buffer");
     sprintf (buf, "cvs@%s", hostinfo->h_name);
     tok_in.length = strlen (buf);
     tok_in.value = buf;
diff -rU 5 cvs-1.11.2/src/server.c j.cvs2/src/server.c
--- cvs-1.11.2/src/server.c     Tue Mar 19 14:15:45 2002
+++ j.cvs2/src/server.c Tue Sep 17 20:03:37 2002
@@ -31,11 +31,11 @@
 #   include <krb5.h>

 /* We need this to wrap data.  */
 static gss_ctx_id_t gcontext;

-static void gserver_authenticate_connection PROTO((void));
+static void gserver_authenticate_connection PROTO((char *));

 /* Whether we are already wrapping GSSAPI communication.  */
 static int cvs_gssapi_wrapping;

 #   ifdef ENCRYPTION
@@ -5437,10 +5437,11 @@
     fp = CVS_FOPEN (filename, "r");
     if (fp == NULL)
     {
        if (!existence_error (errno))
            error (0, errno, "cannot open %s", filename);
+           error (0, errno, "cannot open %s", filename);
        return 0;
     }

     /* Look for a relevant line -- one with this user's name. */
     namelen = strlen (username);
@@ -5674,10 +5675,55 @@
     }

     return host_user;
 }

+
+
+
+/* Return a hosting username if password matches, else NULL. */
+static char *
+gssapi_check_password (username, password, repository)
+    char *username, *password, *repository;
+{
+
+
+    int rc;
+        char *host_user = NULL;
+
+           /* We see if this user has a password in the CVS-specific
+            *        password file.  If so, that's enough to authenticate 
with.  */
+
+           rc = check_repository_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;
+                   }
+     if (rc == 0 )
+       error (1, 0, "GSSAPI authentication failed");
+
+
+handle_return:
+        if (host_user)
+           {
+            /* Set CVS_Username here, in allocated space.
+            *            It might or might not be the same as host_user. */
+            CVS_Username = xmalloc (strlen (username) + 1);
+            strcpy (CVS_Username, username);
+        }
+
+    return host_user;
+}
+
 #endif /* AUTH_SERVER_SUPPORT */

 #if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)

 /* Read username and password from client (i.e., stdin).
@@ -5774,11 +5820,28 @@
        ;
     else if (strcmp (tmp, "BEGIN GSSAPI REQUEST\n") == 0)
     {
 #ifdef HAVE_GSSAPI
        free (tmp);
-       gserver_authenticate_connection ();
+
+       getline_safe (&repository, &repository_allocated, stdin, PATH_MAX);
+       strip_trailing_newlines (repository);
+
+       if (!root_allow_ok (repository))
+       {
+       printf ("error 0 %s: no such repository\n", repository);
+#ifdef HAVE_SYSLOG_H
+       syslog (LOG_DAEMON | LOG_NOTICE, "login refused for %s", repository);
+#endif
+       goto i_hate_you;
+    }
+
+
+       gserver_authenticate_connection (repository);
+
+
+
        return;
 #else
        error (1, 0, "GSSAPI authentication not supported by this server");
 #endif
     }
@@ -5980,21 +6043,26 @@
 /* Authenticate a GSSAPI connection.  This is called from
    pserver_authenticate_connection, and it handles success and failure
    the same way.  */

 static void
-gserver_authenticate_connection ()
+gserver_authenticate_connection (repository)
+
+               char *repository;
+
 {
     char hostname[MAXHOSTNAMELEN];
     struct hostent *hp;
     gss_buffer_desc tok_in, tok_out;
     char buf[1024];
     OM_uint32 stat_min, ret;
     gss_name_t server_name, client_name;
     gss_cred_id_t server_creds;
     int nbytes;
     gss_OID mechid;
+    char *host_user = NULL;
+

     gethostname (hostname, sizeof hostname);
     hp = gethostbyname (hostname);
     if (hp == NULL)
        error (1, 0, "can't get canonical hostname");
@@ -6051,20 +6119,38 @@
        We could instead use an authentication to access mapping.  */
     {
        krb5_context kc;
        krb5_principal p;
        gss_buffer_desc desc;
+

        krb5_init_context (&kc);
        if (gss_display_name (&stat_min, client_name, &desc,
-                             &mechid) != GSS_S_COMPLETE
+                             &mechid) != GSS_S_COMPLETE
            || krb5_parse_name (kc, ((gss_buffer_t) &desc)->value, &p) != 0
-           || krb5_aname_to_localname (kc, p, sizeof buf, buf) != 0
-           || krb5_kuserok (kc, p, buf) != TRUE)
+           || krb5_aname_to_localname (kc, p, sizeof buf, buf) != 0 )
        {
            error (1, 0, "access denied");
        }
+
+       parse_config (repository);
+
+       if ( system_auth  && krb5_kuserok (kc, p, buf) != TRUE )
+       {
+           error (1, 0, "access denied");
+        }
+
+       if ( ! system_auth )
+       {
+          host_user = gssapi_check_password (buf, "", repository);
+
+          if (   host_user == NULL )
+          {
+              error (1, 0, "access denied");
+          }
+       }
+
        krb5_free_principal (kc, p);
        krb5_free_context (kc);
     }

     if (tok_out.length != 0)
@@ -6077,11 +6163,15 @@
            || (fwrite (tok_out.value, 1, tok_out.length, stdout)
                != tok_out.length))
            error (1, errno, "fwrite failed");
     }

-    switch_to_user (buf);
+
+    if ( system_auth )
+       switch_to_user (buf);
+    else
+       switch_to_user (host_user);

     printf ("I LOVE YOU\n");
     fflush (stdout);
 }







reply via email to

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