bug-cvs
[Top][All Lists]
Advanced

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

PROPOSAL: Defer ACL GSSAPI auth until CVSROOT protocol element


From: James E Jurach Jr.
Subject: PROPOSAL: Defer ACL GSSAPI auth until CVSROOT protocol element
Date: Tue, 02 Jul 2002 02:19:33 -0500

PURPOSE:  Implement repository-specific GSSAPI authentication to access mapping

PROPOSAL:  Defer ACL-based GSSAPI auth until CVSROOT directory protocol element

OVERVIEW:  We want to control access authorization to the cvs repository
through an access control list ("k5login") within the repository's CVSROOT
directory, rather than through krb5_kuserok() and hence getpwnam() and
/etc/passwd.

One problem with this approach is while with the passcode pserver mechanism
passes the CVSROOT directory as a part of its protocol, the GSSAPI
mechanism does not pass this information, and at the time of
authentication, the CVSROOT directory is not known.  We suggest deferring
the authorization until the CVSROOT protocol element occurs.

IMPLEMENTATION: a #define to src/cvs.h added for CVSROOTADM_K5LOGIN, and a
moderate change to the gssapi-specific code in src/server.c

PATCH:

Index: ccvs/ChangeLog
===================================================================
RCS file: /cvs/ccvs/ChangeLog,v
retrieving revision 1.649
diff -u -3 -r1.649 ChangeLog
--- ccvs/ChangeLog      28 Jun 2002 18:52:30 -0000      1.649
+++ ccvs/ChangeLog      2 Jul 2002 07:11:35 -0000
@@ -1,3 +1,14 @@
+2002-07-02  James Jurach  <address@hidden>
+
+       * src/server.c:  begin to store GSSAPI principal name in global
+       CVS_Principal variable.  defer newly implemented simple authentication
+       to access mapping authorization until CVSROOT directory protocol
+       element is called in order for this access mapping to be associated
+       with the repository (i.e. limit access to repository to principals
+       listed in "CVSROOT/k5login")
+
+       * src/cvs.h: add definition of CVSROOTADM_K5LOGIN
+
 2002-06-28  Derek Price  <address@hidden>
 
        * INSTALL (Building [on] other platforms): Don't reference the Mac
Index: ccvs/NEWS
===================================================================
RCS file: /cvs/ccvs/NEWS,v
retrieving revision 1.107
diff -u -3 -r1.107 NEWS
--- ccvs/NEWS   22 May 2002 15:40:23 -0000      1.107
+++ ccvs/NEWS   2 Jul 2002 07:11:37 -0000
@@ -1,5 +1,11 @@
 Changes since 1.11.2:
 
+* GSSAPI pserver authentication now supports an authorization list at
+CVSROOT/k5login.  When the file exists, cvs authorization is no longer
+based on krb5_kuserok() (and hence getpwnam()), but rather on the presence
+of the connecting GSSAPI principal name inside this list of principals
+contained within this file.
+
 * We've standardized on Automake version 1.6 and Autoconf version 2.53.
 They are cleaner, less bug prone, and will hopfully allow me to start updating
 sanity.sh to use Autotest and Autoshell.  Again, this should only really affect
Index: ccvs/src/cvs.h
===================================================================
RCS file: /cvs/ccvs/src/cvs.h,v
retrieving revision 1.232
diff -u -3 -r1.232 cvs.h
--- ccvs/src/cvs.h      24 May 2002 21:59:19 -0000      1.232
+++ ccvs/src/cvs.h      2 Jul 2002 07:11:38 -0000
@@ -194,6 +194,9 @@
 #define CVSROOTADM_USERS       "users"
 #define CVSROOTADM_READERS     "readers"
 #define CVSROOTADM_WRITERS     "writers"
+#ifdef HAVE_GSSAPI
+#define CVSROOTADM_K5LOGIN     "k5login"
+#endif
 #define CVSROOTADM_PASSWD      "passwd"
 #define CVSROOTADM_CONFIG      "config"
 
Index: ccvs/src/server.c
===================================================================
RCS file: /cvs/ccvs/src/server.c,v
retrieving revision 1.275
diff -u -3 -r1.275 server.c
--- ccvs/src/server.c   18 Jun 2002 13:35:28 -0000      1.275
+++ ccvs/src/server.c   2 Jul 2002 07:11:41 -0000
@@ -34,6 +34,8 @@
 static gss_ctx_id_t gcontext;
 
 static void gserver_authenticate_connection PROTO((void));
+static void gserver_authorize_connection PROTO((void));
+static void gserver_principal_to_user PROTO((char *princ, int len, char *buf));
 
 /* Whether we are already wrapping GSSAPI communication.  */
 static int cvs_gssapi_wrapping;
@@ -45,6 +47,10 @@
    multiple instances of that buffer in the communication stream.  */
 int cvs_gssapi_encrypt;
 #   endif
+
+/* Store the GSSAPI principal here. */
+static char *CVS_Principal = NULL;
+
 # endif        /* HAVE_GSSAPI */
 #endif /* defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) */
 
@@ -811,6 +817,14 @@
     (void) putenv (env);
     /* do not free env, as putenv has control of it */
 #endif
+
+#ifdef HAVE_GSSAPI
+    /* GSSAPI Authorization was deferred until now, because of the
+       potential presence of the k5login ACL file. */
+    if (CVS_Principal) {
+      gserver_authorize_connection();
+    }
+#endif
 }
 
 static int max_dotdot_limit = 0;
@@ -6003,11 +6017,13 @@
     struct hostent *hp;
     gss_buffer_desc tok_in, tok_out;
     char buf[1024];
+    char username[1024];
     OM_uint32 stat_min, ret;
     gss_name_t server_name, client_name;
     gss_cred_id_t server_creds;
     int nbytes;
     gss_OID mechid;
+    gss_buffer_desc desc;
 
     gethostname (hostname, sizeof hostname);
     hp = gethostbyname (hostname);
@@ -6062,25 +6078,20 @@
        error (1, 0, "could not verify credentials");
     }
 
-    /* FIXME: Use Kerberos v5 specific code to authenticate to a user.
-       We could instead use an authentication to access mapping.  */
-    {
-       krb5_context kc;
-       krb5_principal p;
-       gss_buffer_desc desc;
-
-       krb5_init_context (&kc);
+    /* Acquire the principal name. */
        if (gss_display_name (&stat_min, client_name, &desc,
-                             &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)
-       {
-           error (1, 0, "access denied");
-       }
-       krb5_free_principal (kc, p);
-       krb5_free_context (kc);
-    }
+                         &mechid) != GSS_S_COMPLETE)
+      error (1, 0, "gss_display_name failed");
+
+    if (CVS_Principal != NULL)
+      free(CVS_Principal);
+    CVS_Principal = xstrdup(((gss_buffer_t)&desc)->value);
+
+    /* Map the principal name to a username. */
+    gserver_principal_to_user(CVS_Principal,sizeof username, username);
+
+    /* FIXME: GSSAPI auth does not contain repository and CVSROOT directory is
+       undefined.  Defer until Root protocol element to do authorization. */
 
     if (tok_out.length != 0)
     {
@@ -6094,10 +6105,102 @@
            error (1, errno, "fwrite failed");
     }
 
-    switch_to_user (buf);
+    switch_to_user (username);
 
     printf ("I LOVE YOU\n");
     fflush (stdout);
+}
+
+static void
+gserver_principal_to_user (char *princstr, int len, char *buf)
+{
+  krb5_context kc;
+  krb5_principal princ;
+  int authorized = 0;
+
+  krb5_init_context (&kc);
+
+  /* FIXME: principal-to-username mapping is Kerberos v5 specific */
+
+  if (krb5_parse_name(kc, princstr, &princ) != 0)
+    error (1, 0, "krb5_parse_name(%s) failed", princstr);
+  if (krb5_aname_to_localname(kc, princ, len, buf) != 0)
+    error (1, 0, "krb5_aname_to_localname(%s) failed", buf);
+
+  krb5_free_principal (kc, princ);
+  krb5_free_context (kc);
+}
+
+static void
+gserver_authorize_connection ()
+{
+  int flen;
+  char *fname;
+  FILE *fp;
+  int authorized = 0;
+
+  /* Find GSSAPI principal in authentication to access mapping. */
+
+  flen = strlen (current_parsed_root->directory)
+    + strlen (CVSROOTADM)
+    + strlen (CVSROOTADM_K5LOGIN)
+    + 3;
+      
+  fname = xmalloc (flen);
+  (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
+                 CVSROOTADM, CVSROOTADM_K5LOGIN);
+
+  fp = fopen (fname, "r");
+  if (fp != NULL) {
+    char *linebuf = NULL;
+    int num_red = 0;
+    size_t linebuf_len = 0;
+
+    while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0) {
+         
+      /* Chop newline by hand, for strcmp()'s sake. */
+      if (linebuf[num_red - 1] == '\n')
+       linebuf[num_red - 1] = '\0';
+
+      if (strcmp (linebuf, CVS_Principal) == 0) {
+       authorized = 1;
+       break;
+      }
+    }
+
+    if (linebuf)
+      free (linebuf);
+
+    if (num_red < 0 && !feof (fp))
+      error (0, errno, "cannot read %s", fname);
+    if (fclose (fp) < 0)
+      error (0, errno, "cannot close %s", fname);
+
+  } else if (system_auth) {
+    /* FIXME: if authentication to access mapping is unavailable,
+       default to Kerberos v5 specific authorization */
+    krb5_context kc;
+    krb5_principal princ;
+    krb5_init_context (&kc);
+
+    if (krb5_parse_name(kc, CVS_Principal, &princ) != 0)
+      error (1, 0, "krb5_parse_name(%s) failed", CVS_Principal);
+
+    if (krb5_kuserok (kc, princ, CVS_Username) == TRUE)
+      authorized = 1;
+
+    krb5_free_principal (kc, princ);
+    krb5_free_context (kc);
+
+  } else { /* No SystemAuth and no k5login?  allow all users in KDC .. */
+
+    authorized = 1;
+  }
+
+  free (fname);
+
+  if (! authorized)
+    error (1, 0, "gssapi access denied for %s", CVS_Principal);
 }
 
 #endif /* HAVE_GSSAPI */



reply via email to

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