1.6 stuff, deprecate Compact Credentials, AURIs etc etc.
authorAndrew McNab <andrew.mcnab@manchester.ac.uk>
Thu, 24 May 2007 13:01:54 +0000 (13:01 +0000)
committerAndrew McNab <andrew.mcnab@manchester.ac.uk>
Thu, 24 May 2007 13:01:54 +0000 (13:01 +0000)
org.gridsite.core/src/Makefile
org.gridsite.core/src/gaclexample.c
org.gridsite.core/src/grst_admin_gacl.c
org.gridsite.core/src/grst_gacl.c
org.gridsite.core/src/grst_x509.c
org.gridsite.core/src/grst_xacml.c
org.gridsite.core/src/htproxyput.c
org.gridsite.core/src/mod_gridsite.c

index e95abd5..a926168 100644 (file)
@@ -60,7 +60,7 @@ endif
 
 build: apidoc build-lib \
        htcp gridsite-copy.cgi mod_gridsite.so \
-       urlencode findproxyfile real-gridsite-admin.cgi gsexec
+       urlencode findproxyfile gsexec # real-gridsite-admin.cgi
 
 build-lib: libgridsite_globus.so.$(VERSION) libgridsite_globus.a \
            libgridsite.so.$(VERSION) libgridsite.a 
@@ -209,6 +209,12 @@ mod_gridsite.so: mod_gridsite.c mod_ssl-private.h libgridsite.so.$(VERSION)
            -DVERSION=\"$(VERSION)\" -o mod_gridsite.so \
            mod_gridsite.c $(MYLDFLAGS) -lxml2 -lm -lz -lgridsite
 
+mod_gridsite_example.so: mod_gridsite_example.c 
+       gcc -g -shared -Wl,-soname=gridsite_example_module \
+          -I/usr/include/httpd -I/usr/include/apr-0 \
+           -DVERSION=\"$(VERSION)\" -o mod_gridsite_example.so \
+           mod_gridsite_example.c 
+
 real-gridsite-admin.cgi: grst_admin_main.c grst_admin_gacl.c \
                          grst_admin_file.c grst_admin.h
        gcc -g $(MYCFLAGS) $(MYLDFLAGS) -o real-gridsite-admin.cgi \
@@ -253,12 +259,12 @@ apidoc:
           > $$i.html ; done
 
 gaclexample: gaclexample.c libgridsite.a
-       gcc -g -o gaclexample gaclexample.c -I. -L. \
+       gcc -g -o gaclexample gaclexample.c -I../interface -L. \
             -I/usr/kerberos/include -lgridsite \
             -lssl -lcrypto -lxml2 -lz -lm
            
 xacmlexample: xacmlexample.c libgridsite.a
-       gcc -g -o xacmlexample xacmlexample.c -I. -L. \
+       gcc -g -o xacmlexample xacmlexample.c -I../interface -L. \
             -I/usr/kerberos/include -lgridsite \
             -lssl -lcrypto -lxml2 -lz -lm
 #
@@ -338,6 +344,7 @@ install: apidoc install-lib
                  $(prefix)/share/man/man1 \
                  $(prefix)/share/man/man8 \
                  $(prefix)/lib/httpd/modules \
+                 mod_gridsite_example.c \
                  $(prefix)/share/doc/gridsite-$(MINOR_VERSION)
        cp -f ../interface/gridsite.h $(prefix)/include
        cp -f ../interface/gridsite-gacl.h $(prefix)/include
@@ -441,7 +448,7 @@ dist:
        cp -f ../VERSION ../README ../LICENSE ../CHANGES ../INSTALL \
                  ../dist/gridsite-$(PATCH_VERSION)
        cp -f Makefile grst*.c htcp.c slashgrid.c slashgrid.init \
-                 urlencode.c findproxyfile.c gaclexample.c mod_gridsite.c \
+                 urlencode.c findproxyfile.c gaclexample.c mod_gridsite*.c \
                  htproxyput.c grst_admin.h mod_ssl-private.h \
                  gsexec.c gsexec.h gridsite-copy.c delegation.h \
                  roffit make-gridsite-spec \
index 5ad29b7..32aaaa4 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2002-3, Andrew McNab, University of Manchester
+   Copyright (c) 2002-7, Andrew McNab, University of Manchester
    All rights reserved.
 
    Redistribution and use in source and binary forms, with or
@@ -61,9 +61,7 @@ int main()
 
   /* build up an ACL, starting with a credential */
 
-  cred = GRSTgaclCredNew("person");
-
-  GRSTgaclCredAddValue(cred, "dn", "/O=Grid/CN=Mr Grid Person");
+  cred = GRSTgaclCredCreate("dn:", "/O=Grid/CN=Mr Grid Person");
   
   /* create an entry to put it in */ 
    
@@ -75,11 +73,10 @@ int main()
 
   /* add another credential */
   
-  cred = GRSTgaclCredNew("dn-list");
-  GRSTgaclCredAddValue(cred, "url", "example-dn-list");
+  cred = GRSTgaclCredCreate("https://example-dn-list", NULL); /* DN List */
   GRSTgaclEntryAddCred(entry, cred);
 
-  fp = fopen("example-dn-list", "w");
+  fp = fopen("https%3A%2F%2Fexample-dn-list", "w");
   fputs("/O=Grid/CN=Mr Grid Person\n", fp);
   fclose(fp);  
  
@@ -93,7 +90,7 @@ int main()
 
   perm0 = GRST_PERM_READ | GRST_PERM_WRITE;
   
-  printf("test perm should be %d\n", perm0);
+  printf("\n**** perm should be %d in the following tests! ****\n\n", perm0);
 
   /* create a new ACL and add the entry to it */
   
@@ -103,9 +100,10 @@ int main()
 
   /* create a GRSTgaclUser to compare with the ACL */
 
-  usercred = GRSTgaclCredNew("person");
-  
+  /* old style cred creation: use GRSTgaclCredCreate as above now */
+  usercred = GRSTgaclCredNew("person"); 
   GRSTgaclCredAddValue(usercred, "dn", "/O=Grid/CN=Mr Grid Person");
+  /* end of old style cred creation */
    
   user = GRSTgaclUserNew(usercred);
   
@@ -116,7 +114,7 @@ int main()
     
   perm1 = GRSTgaclAclTestUser(acl1, user);
 
-  printf("test /O=Grid/CN=Mr Grid Person in acl = %d\n", perm1);
+  printf("test /O=Grid/CN=Mr Grid Person in acl, perm = %d\n", perm1);
 
   /* print and save the whole ACL */
 
@@ -138,7 +136,7 @@ int main()
 
   perm2 = GRSTgaclAclTestUser(acl2, user);
 
-  printf("test /O=Grid/CN=Mr Grid Person in acl = %d\n", perm2);
+  printf("test /O=Grid/CN=Mr Grid Person in acl, perm = %d\n", perm2);
 
   if (perm1 != perm0) return 1;
   if (perm2 != perm0) return 2;
index bdcccbd..6bce4fb 100644 (file)
@@ -43,6 +43,8 @@
 extern char *grst_perm_syms[];
 extern int grst_perm_vals[];
 
+                                  
+
 #include "grst_admin.h"
 
 // CGI GACL Editor interface functions
index c2c4ecd..539a44e 100644 (file)
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
 #include <unistd.h>              
 #include <string.h>
 #include <dirent.h>
+#include <fcntl.h>
 #include <ctype.h>
 
 #ifndef _GNU_SOURCE
@@ -71,7 +73,7 @@ GRSTgaclPerm grst_perm_vals[] =  {   GRST_PERM_NONE,
                                      GRST_PERM_WRITE,
                                      GRST_PERM_ADMIN,
                                      -1                };
-                                 
+
 int GRSTgaclInit(void)
 {
   xmlInitParser();
@@ -92,37 +94,80 @@ GRSTgaclAcl *GRSTxacmlAclParse(xmlDocPtr, xmlNodePtr, GRSTgaclAcl *);
  * Functions to manipulate GRSTgaclCred structures *
  *                                             */
 
-GRSTgaclCred *GRSTgaclCredNew(char *type)
+GRSTgaclCred *GRSTgaclCredCreate(char *auri_prefix, char *auri_suffix)
 /*
-    GRSTgaclCredNew - allocate a new GRSTgaclCred structure, and return
-                      it's pointer or NULL on (malloc) error.
+    GRSTgaclCredCreate - allocate a new GRSTgaclCred structure, and return
+                         it's pointer or NULL on (malloc) error.
 */
 {
+  int           i;
+  char         *auri;
   GRSTgaclCred *newcred; 
 
-  if (type == NULL) return NULL;
+  if      ((auri_prefix != NULL) && (auri_suffix == NULL))
+   auri = strdup(auri_prefix);
+  else if ((auri_prefix == NULL) && (auri_suffix != NULL))
+   auri = strdup(auri_suffix);
+  else if ((auri_prefix != NULL) && (auri_suffix != NULL))
+   asprintf(&auri, "%s%s", auri_prefix, auri_suffix);
+  else return NULL;
+
+  for (i=0; (auri[i] != '\0') && isspace(auri[i]); ++i) ; /* leading space */
+
+  for (i=strlen(auri) - 1; (i >= 0) && isspace(auri[i]); --i)
+                                           auri[i]='\0'; /* trailing space */
 
   newcred = malloc(sizeof(GRSTgaclCred));
-  if (newcred == NULL) return NULL;
+  if (newcred == NULL) 
+    {
+      free(auri);
+      return NULL;
+    }
   
-  newcred->type       = strdup(type);
+  newcred->auri       = auri;
   newcred->delegation = 0;
-  newcred->firstname  = NULL;
+  newcred->nist_loa   = 0;
+  newcred->notbefore  = 0;
+  newcred->notafter   = 0;
   newcred->next       = NULL;
 
   return newcred;
 }
 
-int GRSTgaclCredAddValue(GRSTgaclCred *cred, char *rawname, char *rawvalue)
+GRSTgaclCred *GRSTgaclCredNew(char *type)
+/*
+    GRSTgaclCredNew - allocate a new GRSTgaclCred structure, and return
+                      it's pointer or NULL on (malloc) error.
+*/
+{
+  if (type == NULL) return NULL;
+  
+  if ((strcmp(type, "person" ) == 0) ||
+      (strcmp(type, "voms"   ) == 0) ||
+      (strcmp(type, "dn-list") == 0) ||
+      (strcmp(type, "dns"    ) == 0) ||
+      (strcmp(type, "level"  ) == 0)) return GRSTgaclCredCreate("", NULL);
+      
+  if (strcmp(type, "any-user") == 0) 
+       return GRSTgaclCredCreate("gacl:", "any-user");
+                                  
+  if (strcmp(type, "auth-user") == 0) 
+       return GRSTgaclCredCreate("gacl:", "auth-user");
+
+  return NULL;
+}
+
+int GRSTgaclCredAddValue(GRSTgaclCred *cred, char *name, char *rawvalue)
 /*
     GRSTgaclCredAddValue - add a name/value pair to a GRSTgaclCred
 */
 {
   int                i;
-  char              *name, *value;
-  GRSTgaclNamevalue *p;
+  char              *value;
 
-  name  = strdup(rawname);
+  if ((cred == NULL) || (cred->auri == NULL)) return 0;
+  free(cred->auri);
+  cred->auri = NULL;
 
   /* no leading or trailing space in value */
 
@@ -130,42 +175,41 @@ int GRSTgaclCredAddValue(GRSTgaclCred *cred, char *rawname, char *rawvalue)
   while ((*value != '\0') && isspace(*value)) ++value;
 
   value = strdup(value);
-
   for (i=strlen(value) - 1; (i >= 0) && isspace(value[i]); --i) value[i]='\0';
-  
-  if (cred->firstname == NULL) 
+
+  if (strcmp(name, "dn") == 0)
     {
-      cred->firstname = malloc(sizeof (GRSTgaclNamevalue));
-      (cred->firstname)->name  = name;
-      (cred->firstname)->value = value;
-      (cred->firstname)->next  = NULL;
+      asprintf(&(cred->auri), "dn:%s", value);
+      free(value);
+      return 1;
     }
-  else
+  else if (strcmp(name, "fqan") == 0)
     {
-      p = cred->firstname; 
-  
-      while (p->next != NULL) p = (GRSTgaclNamevalue *) p->next;
-  
-      p->next = malloc(sizeof(GRSTgaclNamevalue));
-      ((GRSTgaclNamevalue *) p->next)->name  = name;
-      ((GRSTgaclNamevalue *) p->next)->value = value;
-      ((GRSTgaclNamevalue *) p->next)->next  = NULL;
-    } 
-  
-  return 1;
-}
-
-static int GRSTgaclNamevalueFree(GRSTgaclNamevalue *p)
-{
-  if (p == NULL) return 1;
-  
-  if (p->next  != NULL) 
-        GRSTgaclNamevalueFree((GRSTgaclNamevalue *) p->next);
-  if (p->name  != NULL) free(p->name);
-  if (p->value != NULL) free(p->value);
-  free(p);
-  
-  return 1;
+      asprintf(&(cred->auri), "fqan:%s", value);
+      free(value);
+      return 1;
+    }
+  else if (strcmp(name, "url") == 0)
+    {
+      asprintf(&(cred->auri), "%s", value);
+      free(value);
+      return 1;
+    }
+  else if (strcmp(name, "hostname") == 0)
+    {
+      asprintf(&(cred->auri), "dns:%s", value);
+      free(value);
+      return 1;
+    }
+  else if (strcmp(name, "nist-loa") == 0)
+    {
+      asprintf(&(cred->auri), "nist-loa:%s", value);
+      free(value);
+      return 1;
+    }
+    
+  free(value);  
+  return 0;
 }
 
 int GRSTgaclCredFree(GRSTgaclCred *cred)
@@ -176,8 +220,7 @@ int GRSTgaclCredFree(GRSTgaclCred *cred)
 {
   if (cred == NULL) return 1;
 
-  GRSTgaclNamevalueFree(cred->firstname);  
-  if (cred->type != NULL) free(cred->type);
+  if (cred->auri != NULL) free(cred->auri);
   free(cred);
   
   return 1;
@@ -259,18 +302,12 @@ int GRSTgaclCredPrint(GRSTgaclCred *cred, FILE *fp)
 */
 {
   char              *q;
-  GRSTgaclNamevalue *p;
 
-  if (cred->firstname != NULL)
+  if (cred->auri != NULL)
     {
-      fprintf(fp, "<%s>\n", cred->type);
-    
-      p = cred->firstname;
-      
-      do { 
-           fprintf(fp, "<%s>", p->name);
+      fprintf(fp, "<cred>\n<auri>");
 
-            for (q=p->value; *q != '\0'; ++q)
+      for (q=cred->auri; *q != '\0'; ++q)
               if      (*q == '<')  fputs("&lt;",   fp);
               else if (*q == '>')  fputs("&gt;",   fp);
               else if (*q == '&')  fputs("&amp;" , fp);
@@ -278,15 +315,16 @@ int GRSTgaclCredPrint(GRSTgaclCred *cred, FILE *fp)
               else if (*q == '"')  fputs("&quot;", fp);
               else                 fputc(*q, fp);
 
-           fprintf(fp, "</%s>\n", p->name);
-
-           p = (GRSTgaclNamevalue *) p->next;
-         
-         } while (p != NULL);
-
-      fprintf(fp, "</%s>\n", cred->type);
+      fprintf(fp, "</auri>\n");
+      
+      if (cred->nist_loa > 0) 
+            fprintf(fp, "<nist-loa>%d</nist-loa>\n", cred->nist_loa);
+      
+      if (cred->delegation > 0) 
+            fprintf(fp, "<delegation>%d</delegation>\n", cred->delegation);
+      
+      fprintf(fp, "</cred>\n");
     }
-  else fprintf(fp, "<%s/>\n", cred->type);
   
   return 1;  
 }
@@ -523,7 +561,7 @@ int GRSTgaclAclPrint(GRSTgaclAcl *acl, FILE *fp)
 {
   GRSTgaclEntry *entry;
   
-  fputs("<gacl version=\"0.0.1\">\n", fp);
+  fputs("<gacl version=\"0.9.0\">\n", fp);
   
   for (entry = acl->firstentry; entry != NULL; entry = entry->next)
                                             GRSTgaclEntryPrint(entry, fp);
@@ -562,13 +600,51 @@ static GRSTgaclCred *GRSTgaclCredParse(xmlNodePtr cur)
                     returning it as a pointer or NULL on error.
 */
 {
-  xmlNodePtr  cur2;
-  GRSTgaclCred   *cred;
-  
-  cred = GRSTgaclCredNew((char *) cur->name);
+  xmlNodePtr    cur2;
+  GRSTgaclCred *cred = NULL;
+  /* generic AURI creds first */
+
+  if (strcmp((char *) cur->name, "cred") == 0)
+    {
+      for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
+         {
+           if (!xmlIsBlankNode(cur2) &&
+               (strcmp((char *) cur2->name, "auri") == 0))               
+             {
+               if (cred != NULL) /* multiple AURI */
+                 {
+                   GRSTgaclCredFree(cred);
+                   cred = NULL;
+                   return NULL;
+                 }
+
+               cred = GRSTgaclCredCreate((char *) xmlNodeGetContent(cur2),NULL);
+             }
+         }
+         
+      if (cred == NULL) return NULL;
+      
+      for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
+         {
+           if (xmlIsBlankNode(cur2)) continue;
+           
+           if (strcmp((char *) cur2->name, "nist-loa") == 0)
+             {
+               cred->nist_loa = atoi((char *) xmlNodeGetContent(cur2));
+             }
+           else if (strcmp((char *) cur2->name, "delegation") == 0)
+             {
+               cred->delegation = atoi((char *) xmlNodeGetContent(cur2));
+             }
+         }
+    
+      return cred;
+    }
   
-  cred->firstname = NULL;
-  cred->next      = NULL;
+  /* backwards compatibility */
+
+  cred = GRSTgaclCredNew((char *) cur->name); 
   
   for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
      {
@@ -827,9 +903,11 @@ GRSTgaclUser *GRSTgaclUserNew(GRSTgaclCred *cred)
   
   user = malloc(sizeof(GRSTgaclUser));
   
-  if (user != NULL) user->firstcred = cred;
-  
-  user->dnlists = NULL;
+  if (user != NULL)   
+    { 
+      user->firstcred = cred;
+      user->dnlists   = NULL;
+    }
   
   return user;
 }
@@ -839,7 +917,7 @@ int GRSTgaclUserFree(GRSTgaclUser *user)
   if (user == NULL) return 1;
   
   if (user->firstcred != NULL) GRSTgaclCredsFree(user->firstcred);
-
+  
   if (user->dnlists != NULL) free(user->dnlists);
   
   free(user);
@@ -873,124 +951,64 @@ int GRSTgaclUserAddCred(GRSTgaclUser *user, GRSTgaclCred *cred)
 int GRSTgaclUserHasCred(GRSTgaclUser *user, GRSTgaclCred *cred)
 /* test if the user has the given credential */
 {
+  int                nist_loa = 999;
   GRSTgaclCred      *crediter;
-  GRSTgaclNamevalue *usernamevalue, *crednamevalue;
 
-  if (cred == NULL) return 0;
+  if ((cred == NULL) || (cred->auri == NULL)) return 0;
 
-  if (strcmp(cred->type, "any-user") == 0) return 1;
+  if (strcmp(cred->auri, "any-user:") == 0) return 1;
   
-  if (user == NULL) return 0;
+  if ((user == NULL) || (user->firstcred == NULL)) return 0;
   
-  if (strcmp(cred->type, "dn-list") == 0) 
-    {
-      if ((cred->firstname == NULL) ||
-          (strcmp((cred->firstname)->name, "url") != 0) ||
-          ((cred->firstname)->next != NULL))                 return 0;
-      
-      return GRSTgaclDNlistHasUser((cred->firstname)->value, user);
-    }
-
-  if (strcmp(cred->type, "dns") == 0)
-    {
-      if ((user->firstcred == NULL) ||
-          ((user->firstcred)->firstname == NULL) ||
-          (cred->firstname == NULL) ||
-          (strcmp((cred->firstname)->name, "hostname") != 0) ||
-          ((cred->firstname)->next != NULL)) return 0;
-      
+  if (strncmp(cred->auri, "dns:", 4) == 0)
+    {      
       for (crediter=user->firstcred; 
            crediter != NULL; 
            crediter = crediter->next)
-        if (strcmp(crediter->type, "dns") == 0) 
-          {            
-            if ((crediter->firstname == NULL) ||
-              (strcmp((crediter->firstname)->name, "hostname") != 0)) return 0;
-               
-            return (fnmatch((cred->firstname)->value, 
-                            (crediter->firstname)->value, FNM_CASEFOLD) == 0);
-          }
-          
+        if ((crediter->auri != NULL) &&
+            (strncmp(crediter->auri, "dns:", 4) == 0))
+          return (fnmatch(cred->auri, crediter->auri, FNM_CASEFOLD) == 0);
            
       return 0;    
     }
     
-  if (strcmp(cred->type, "auth-user") == 0)
+  if (strcmp(cred->auri, "gacl:auth-user") == 0)
     {
-      if ((user->firstcred == NULL) ||
-          ((user->firstcred)->firstname == NULL)) return 0;
-      
       for (crediter=user->firstcred; 
            crediter != NULL; 
            crediter = crediter->next)
-        if (strcmp(crediter->type, "person") == 0) return 1;
+        if ((crediter->auri != NULL) &&
+            (strncmp(crediter->auri, "dn:", 3) == 0)) return 1;
                 
       return 0;    
     }
   
-  if (strcmp(cred->type, "level") == 0)
+  if (sscanf(cred->auri, "nist-loa:%d", &nist_loa) == 1)
     {
-      if ((user->firstcred == NULL) ||
-          ((user->firstcred)->firstname == NULL)) return 0;
-      
       for (crediter=user->firstcred; 
            crediter != NULL; 
            crediter = crediter->next)
-        if (strcmp(crediter->type, "level") == 0) 
-          {
-            if (atoi(user->firstcred->firstname->value) 
-                        >= atoi(crediter->firstname->value)) return 1;
+        if ((crediter->auri != NULL) &&
+            (strncmp(crediter->auri, "dn:", 3) == 0) &&
+            (crediter->nist_loa >= nist_loa)) return 1;
 
-            return 0;
-          } 
-                
       return 0;    
     }
 
+// can remove this once we preload DN Lists etc as AURIs?
+  if ((strncmp(cred->auri, "http:",  5) == 0) ||
+      (strncmp(cred->auri, "https:", 6) == 0))
+    {      
+      return GRSTgaclDNlistHasUser(cred->auri, user);
+    }
+
+  /* generic AURI = AURI test */
+
   for (crediter=user->firstcred; crediter != NULL; crediter = crediter->next)
-       {
-         if (strcmp(crediter->type, cred->type) != 0) continue;
-         
-         if ((crediter->firstname == NULL) && 
-             (cred->firstname     == NULL)) return 1;
-         
-         if ((crediter->firstname == NULL) || 
-             (cred->firstname     == NULL)) continue;
-             
-         usernamevalue = crediter->firstname;
-         crednamevalue = cred->firstname;
-         
-         for (;;)
-            {
-              if (strcmp(usernamevalue->name,crednamevalue->name) != 0) break;
-
-              if (strcmp(cred->type, "person") == 0)
-                {
-                  if (GRSTx509NameCmp(usernamevalue->value, 
-                                      crednamevalue->value) != 0) break;
-                }
-/*
-              else if (strcmp(cred->type, "level") == 0)
-                {
-                  if (atoi(usernamevalue->value) 
-                        < atoi(crednamevalue->value)) break;
-                }              
-*/
-              else if (strcmp(usernamevalue->value,
-                              crednamevalue->value) != 0) break;
-              
-              /* ok if cred list runs out before user's cred list */
-              if (crednamevalue->next == NULL) return 1;
-
-              /* but not ok if more names to match which user doesn't have */
-              if (usernamevalue->next == NULL) break;
-             
-              crednamevalue = (GRSTgaclNamevalue *) crednamevalue->next;
-              usernamevalue = (GRSTgaclNamevalue *) usernamevalue->next;
-            }
-       }
-         
-  return 0;
+     if ((crediter->auri != NULL) &&
+         (strcmp(crediter->auri, cred->auri) == 0)) return 1;
+           
+  return 0;    
 }
 
 GRSTgaclCred *GRSTgaclUserFindCredtype(GRSTgaclUser *user, char *type)
@@ -1004,7 +1022,18 @@ GRSTgaclCred *GRSTgaclUserFindCredtype(GRSTgaclUser *user, char *type)
 
   while (cred != NULL)
        {
-         if (strcmp(cred->type, type) == 0) return cred;
+         if ((strcmp(type, "person") == 0) &&       
+             (strncmp(cred->auri, "dn:", 3) == 0)) return cred;
+
+         if ((strcmp(type, "voms") == 0) &&       
+             (strncmp(cred->auri, "fqan:", 5) == 0)) return cred;
+
+         if ((strcmp(type, "dns") == 0) &&
+             (strncmp(cred->auri, "dns:", 4) == 0)) return cred;
+
+         if ((strcmp(type, "dn-list") == 0) &&
+             ((strncmp(cred->auri, "http:",  5) == 0) || 
+              (strncmp(cred->auri, "https:", 6) == 0))) return cred;
          
          cred = cred->next;       
        }
@@ -1014,12 +1043,150 @@ GRSTgaclCred *GRSTgaclUserFindCredtype(GRSTgaclUser *user, char *type)
 
 int GRSTgaclUserSetDNlists(GRSTgaclUser *user, char *dnlists)
 {
-  if ((user == NULL) || (dnlists == NULL)) return 0;
-
   if (user->dnlists != NULL) free(user->dnlists);
 
-  user->dnlists = strdup(dnlists);
+  if (dnlists == NULL) user->dnlists = NULL;
+  else                 user->dnlists = strdup(dnlists);
+
+  return GRSTgaclUserLoadDNlists(user, dnlists);
+}
+
+static void recurse4dnlists(GRSTgaclUser *user, char *dir,
+                            int recurse_level, GRSTgaclCred *dn_cred)
+/* try to find file[] in dir[]. try subdirs if not found. 
+   return full path to first found version or NULL on failure */
+{
+  int            fd, linestart, i;
+  char          *fullfilename, *mapped, *q, *s;
+  size_t         dn_len;
+  struct stat    statbuf;
+  DIR           *dirDIR;
+  struct dirent *file_ent;
+  GRSTgaclCred  *cred;
+
+  if (recurse_level >= GRST_RECURS_LIMIT) return;
+
+  dn_len = strlen(dn_cred->auri) - 3;
 
+  /* search this directory */
+  
+  dirDIR = opendir(dir);
+  
+  if (dirDIR == NULL) return;
+  
+  while ((file_ent = readdir(dirDIR)) != NULL)
+       {
+         if (file_ent->d_name[0] == '.') continue;
+       
+         asprintf(&fullfilename, "%s/%s", dir, file_ent->d_name);
+
+         GRSTerrorLog(GRST_LOG_DEBUG, "recurse4dnlists opens %s", fullfilename);
+
+         if ((fd = open(fullfilename, O_RDONLY)) < 0)
+           ;
+         else if (fstat(fd, &statbuf) != 0)
+           ;
+         else if (S_ISDIR(statbuf.st_mode))
+           recurse4dnlists(user, fullfilename, recurse_level + 1, dn_cred);
+         else if ((S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) &&
+                  ((mapped = mmap(NULL, statbuf.st_size, 
+                               PROT_READ, MAP_PRIVATE, fd, 0)) != MAP_FAILED))
+           {  
+             linestart = 0;
+             
+             while (linestart + dn_len <= statbuf.st_size)
+                  {
+                    GRSTerrorLog(GRST_LOG_DEBUG, "recurse4dnlists at %ld in %s", 
+                          linestart, fullfilename);
+
+                    for (i=0; 
+                         (linestart + i < statbuf.st_size) && (i < dn_len);
+                         ++i)
+                       if (mapped[linestart + i] != dn_cred->auri[3+i]) break;
+
+                    GRSTerrorLog(GRST_LOG_DEBUG, "recurse4dnlists at %d %d %d %d", 
+                          linestart, i, dn_len, statbuf.st_size);
+
+                    if ((i == dn_len) && 
+                        ((linestart+i == statbuf.st_size) ||
+                         (mapped[linestart+i] == '\n') ||
+                         (mapped[linestart+i] == '\r')))  /* matched */                    
+                      {                        
+                        s = GRSThttpUrlDecode(file_ent->d_name);                    
+                        cred = GRSTgaclCredCreate(s, NULL);
+                        GRSTerrorLog(GRST_LOG_DEBUG, 
+                                     "recurse4dnlists adds %s", s);
+                        free(s);
+                    
+                        GRSTgaclCredSetNotBefore(cred,  dn_cred->notbefore);
+                        GRSTgaclCredSetNotAfter(cred,   dn_cred->notafter);
+                        GRSTgaclCredSetDelegation(cred, dn_cred->delegation);
+                        GRSTgaclCredSetNistLoa(cred,    dn_cred->nist_loa);
+
+                        GRSTgaclUserAddCred(user, cred);
+                        break;
+                      }                    
+                      
+                    linestart += i;
+
+                    while ((linestart < statbuf.st_size) &&
+                           (mapped[linestart] != '\n') && 
+                           (mapped[linestart] != '\r')) ++linestart;
+
+                    while ((linestart < statbuf.st_size) &&
+                           ((mapped[linestart] == '\n') || 
+                            (mapped[linestart] == '\r'))) ++linestart;
+                  }
+             
+             munmap(mapped, statbuf.st_size);
+           }
+
+         if (fd < 0) close(fd);
+         free(fullfilename);
+       }
+  
+  closedir(dirDIR);  
+}
+
+int GRSTgaclUserLoadDNlists(GRSTgaclUser *user, char *dnlists)
+/*
+    Examine DN Lists for attributes belonging to this user and
+    add them to *user as additional credentials.
+*/
+{
+  char *dn_lists_dirs, *dn_list_ptr, *filename, *dirname, *dn = NULL;
+  GRSTgaclCred *dn_cred;
+
+  /* check for DN Lists */
+
+  if (dnlists == NULL) dnlists = getenv("GRST_DN_LISTS");
+
+  if (dnlists == NULL) dnlists = GRST_DN_LISTS;
+  
+  if (*dnlists == '\0') return 1; /* Didn't ask for anything: that's ok */
+  
+  /* find this user's (first) DN */
+  
+  if (user == NULL) return 1; /* No user! */
+
+  for (dn_cred = user->firstcred; dn_cred != NULL; dn_cred = dn_cred->next)
+     { 
+       if (strncmp(dn_cred->auri, "dn:", 3) == 0) break;
+     }
+     
+  if (dn_cred == NULL) return 1; /* User has no DN! */
+
+  /* look through DN List files */
+  
+  dn_lists_dirs = strdup(dnlists); /* we need to keep this for free() later! */
+  dn_list_ptr   = dn_lists_dirs;   /* copy, for naughty function strsep()    */
+
+  while ((dirname = strsep(&dn_list_ptr, ":")) != NULL)
+       {
+         recurse4dnlists(user, dirname, 0, dn_cred);
+       }
+       
+  free(dn_lists_dirs);
   return 1;
 }
 
@@ -1110,10 +1277,8 @@ int GRSTgaclDNlistHasUser(char *listurl, GRSTgaclUser *user)
          
                 while (cred != NULL)                  
                      {
-                       if ((strcmp(cred->type, "person") == 0)          && 
-                           (cred->firstname != NULL)                    &&
-                           (strcmp("dn", (cred->firstname)->name) == 0) &&
-                 (GRSTx509NameCmp(line, (cred->firstname)->value) == 0))
+                       if ((strncmp(cred->auri, "dn:", 3) == 0) &&
+                           (GRSTx509NameCmp(line, &(cred->auri[3])) == 0))
                          {
                            fclose(fp);
                            free(dn_lists_dirs);
@@ -1157,7 +1322,7 @@ GRSTgaclPerm GRSTgaclAclTestUser(GRSTgaclAcl *acl, GRSTgaclUser *user)
      
        for (cred = entry->firstcred; cred != NULL; cred = cred->next)
              if (!GRSTgaclUserHasCred(user, cred)) flag = 0;
-             else if (strcmp(cred->type, "any-user") != 0) onlyanyuser = 0;
+             else if (strcmp(cred->auri, "any-user:") != 0) onlyanyuser = 0;
 
        if (!flag) continue; /* flag false if a subtest failed */
 
@@ -1200,7 +1365,7 @@ GRSTgaclPerm GRSTgaclAclTestexclUser(GRSTgaclAcl *acl, GRSTgaclUser *user)
      
        for (cred = entry->firstcred; cred != NULL; cred = cred->next)
           {
-            if (strcmp(cred->type, "person") != 0)
+            if (strncmp(cred->auri, "dn:", 3) != 0)
              /* if we ever add support for other person-specific credentials,
                 they must also be recognised here */
               {
index 99741d3..5ab98e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2002-6, Andrew McNab, University of Manchester
+   Copyright (c) 2002-7, Andrew McNab, University of Manchester
    All rights reserved.
 
    Redistribution and use in source and binary forms, with or
 
 /// Compare X509 Distinguished Name strings
 int GRSTx509NameCmp(char *a, char *b)
-/**
- *  This function attempts to do with string representations what
- *  would ideally be done with OIDs/values. In particular, we equate
- *  "/Email=" == "/emailAddress=" to deal with this important change
- *  between OpenSSL 0.9.6 and 0.9.7. 
- *  Other than that, it is currently the same as ordinary strcasecmp(3)
- *  (for consistency with EDG/LCG/EGEE gridmapdir case insensitivity.)
- */
+///
+/// This function attempts to do with string representations what
+/// would ideally be done with OIDs/values. In particular, we equate
+/// "/Email=" == "/emailAddress=" to deal with this important change
+/// between OpenSSL 0.9.6 and 0.9.7. 
+/// Other than that, it is currently the same as ordinary strcasecmp(3)
+/// (for consistency with EDG/LCG/EGEE gridmapdir case insensitivity.)
 {
    int   ret;
    char *aa, *bb, *p;
@@ -110,17 +109,15 @@ int GRSTx509NameCmp(char *a, char *b)
 
 
 /// Check critical extensions
-/**
- *  Returning GRST_RET_OK if all of extensions are known to us or 
- *  OpenSSL; GRST_REF_FAILED otherwise.   
- *
- *  Since this function relies on functionality (X509_supported_extension)
- *  introduced in 0.9.7, then we do nothing and report an error 
- *  (GRST_RET_FAILED) if one of the associated defines 
- *  (X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) is absent.
- */
-
 int GRSTx509KnownCriticalExts(X509 *cert)
+///
+/// Returning GRST_RET_OK if all of extensions are known to us or 
+/// OpenSSL; GRST_REF_FAILED otherwise.   
+///
+/// Since this function relies on functionality (X509_supported_extension)
+/// introduced in 0.9.7, then we do nothing and report an error 
+/// (GRST_RET_FAILED) if one of the associated defines 
+/// (X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) is absent.
 {
    int  i;
    char s[80];
@@ -147,11 +144,9 @@ int GRSTx509KnownCriticalExts(X509 *cert)
 }
 
 /// Check if certificate can be used as a CA to sign standard X509 certs
-/*
- *  Return GRST_RET_OK if true; GRST_RET_FAILED if not.
- */
-
 int GRSTx509IsCA(X509 *cert)
+///
+/// Return GRST_RET_OK if true; GRST_RET_FAILED if not.
 {
    int idret, purpose_id;
 
@@ -191,14 +186,12 @@ int GRSTx509ChainFree(GRSTx509Chain *chain)
 }
 
 /// Check a specific signature against a specific (VOMS) cert
-/*
- *  Returns GRST_RET_OK if signature is ok, other values if not.
- */
-
 static int GRSTx509VerifySig(time_t *time1_time, time_t *time2_time,
                              unsigned char *txt, int txt_len,
                              unsigned char *sig, int sig_len, 
                              X509 *cert)
+///
+/// Returns GRST_RET_OK if signature is ok, other values if not.
 {   
    int            ret;
    EVP_PKEY      *prvkey;
@@ -241,15 +234,13 @@ static int GRSTx509VerifySig(time_t *time1_time, time_t *time2_time,
 }
 
 /// Check the signature of the VOMS attributes
-/*
- *  Returns GRST_RET_OK if signature is ok, other values if not.
- */
-
 static int GRSTx509VerifyVomsSig(time_t *time1_time, time_t *time2_time,
                                  unsigned char *asn1string, 
                                  struct GRSTasn1TagList taglist[], 
                                  int lasttag,
                                  char *vomsdir, int acnumber)
+///
+/// Returns GRST_RET_OK if signature is ok, other values if not.
 {   
 #define GRST_ASN1_COORDS_VOMS_DN   "-1-1-%d-1-3-1-1-1-%%d-1-%%d"
 #define GRST_ASN1_COORDS_VOMS_INFO "-1-1-%d-1"
@@ -375,15 +366,13 @@ static int GRSTx509VerifyVomsSig(time_t *time1_time, time_t *time2_time,
 }
 
 /// Get the VOMS attributes in the given extension
-/*
- *  Add any VOMS credentials found into the chain. Always returns GRST_RET_OK
- *  - even for invalid credentials, which are flagged in errors field
- */
-
 static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert, 
                          time_t time1_time, time_t time2_time,
                          X509_EXTENSION *ex, 
                          char *ucuserdn, char *vomsdir)
+///
+/// Add any VOMS credentials found into the chain. Always returns GRST_RET_OK
+/// - even for invalid credentials, which are flagged in errors field
 {
 #define MAXTAG 500
 #define GRST_ASN1_COORDS_FQAN    "-1-1-%d-1-7-1-2-1-2-%d"
@@ -399,7 +388,6 @@ static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert,
    int                lasttag=-1, itag, i, acnumber = 1, chain_errors = 0;
    struct GRSTasn1TagList taglist[MAXTAG+1];
    time_t             actime1 = 0, actime2 = 0, time_now;
-   GRSTx509Cert      *new_grst_cert;
 
    asn1data   = X509_EXTENSION_get_data(ex);
    asn1string = ASN1_STRING_data(asn1data);
@@ -465,8 +453,8 @@ static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert,
                  *grst_cert = (*grst_cert)->next;
                  bzero(*grst_cert, sizeof(GRSTx509Cert));
                
-                 (*grst_cert)->start  = time1_time;
-                 (*grst_cert)->finish = time2_time;
+                 (*grst_cert)->notbefore = time1_time;
+                 (*grst_cert)->notafter  = time2_time;
                  asprintf(&((*grst_cert)->value), "%.*s",
                           taglist[itag].length,
                           &asn1string[taglist[itag].start+
@@ -485,20 +473,18 @@ static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert,
 }
 
 /// Check certificate chain for GSI proxy acceptability.
-/**
- *  Returns GRST_RET_OK if valid; OpenSSL X509 errors otherwise.
- *
- *  The GridSite version handles old and new style Globus proxies, and
- *  proxies derived from user certificates issued with "X509v3 Basic
- *  Constraints: CA:FALSE" (eg UK e-Science CA)
- *
- *  TODO: we do not yet check ProxyCertInfo and ProxyCertPolicy extensions
- *        (although via GRSTx509KnownCriticalExts() we can accept them.)
- */
-
 int GRSTx509ChainLoadCheck(GRSTx509Chain **chain, 
                            STACK_OF(X509) *certstack, X509 *lastcert,
                            char *capath, char *vomsdir)
+///
+/// Returns GRST_RET_OK if valid; OpenSSL X509 errors otherwise.
+///
+/// The GridSite version handles old and new style Globus proxies, and
+/// proxies derived from user certificates issued with "X509v3 Basic
+/// Constraints: CA:FALSE" (eg UK e-Science CA)
+///
+/// TODO: we do not yet check ProxyCertInfo and ProxyCertPolicy extensions
+///       (although via GRSTx509KnownCriticalExts() we can accept them.)
 {
    X509 *cert;                  /* Points to the current cert in the loop */
    X509 *cacert = NULL;         /* The CA root cert */
@@ -560,6 +546,8 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain,
        fclose(fp);
        if (cacert != NULL) 
         GRSTerrorLog(GRST_LOG_DEBUG, " Loaded CA root cert from file");
+       else
+        GRSTerrorLog(GRST_LOG_DEBUG, " Failed to load CA root cert file");
      }
 
    *chain = malloc(sizeof(GRSTx509Chain));
@@ -602,28 +590,44 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain,
               {
                 /* if first cert does not claim to be a self-signed copy 
                    of a CA root cert in the store, we check the signature */
-              
-                ret = X509_check_issued(cacert, cert);
 
-                GRSTerrorLog(GRST_LOG_DEBUG, 
+                if (cacert == NULL)
+                  {
+                    chain_errors |= GRST_CERT_BAD_CHAIN;
+                    ret = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
+                  }
+                else 
+                  {
+                    ret = X509_check_issued(cacert, cert);
+
+                    GRSTerrorLog(GRST_LOG_DEBUG, 
                              "Cert sig check %d returns %d", i, ret);
 
-                if (ret != X509_V_OK) 
+                    if (ret != X509_V_OK) 
                              new_grst_cert->errors |= GRST_CERT_BAD_SIG;
+                  }
               }
             else if ((i == depth - 2) && (subjecthash == issuerhash))
               {
                 /* first cert claimed to be a self-signed copy of a CA root
                 cert in the store, we check the signature of the second
                 cert, using OUR copy of the CA cert DIRECT from the store */
-              
-                ret = X509_check_issued(cacert, cert);
 
-                GRSTerrorLog(GRST_LOG_DEBUG, 
+                if (cacert == NULL)
+                  {
+                    chain_errors |= GRST_CERT_BAD_CHAIN;
+                    ret = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
+                  }
+                else 
+                  {
+                    ret = X509_check_issued(cacert, cert);
+                
+                    GRSTerrorLog(GRST_LOG_DEBUG, 
                              "Cert sig check %d returns %d", i, ret);
                 
-                if (ret != X509_V_OK)
+                    if (ret != X509_V_OK)
                              new_grst_cert->errors |= GRST_CERT_BAD_SIG;
+                  }
               }
             else if (i < depth - 1)
               {
@@ -645,17 +649,17 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain,
 
             new_grst_cert->serial = (int) ASN1_INTEGER_get(
                                X509_get_serialNumber(cert));
-            new_grst_cert->start  = GRSTasn1TimeToTimeT(
+            new_grst_cert->notbefore = GRSTasn1TimeToTimeT(
                                ASN1_STRING_data(X509_get_notBefore(cert)), 0);
-            new_grst_cert->finish = GRSTasn1TimeToTimeT(
+            new_grst_cert->notafter  = GRSTasn1TimeToTimeT(
                                ASN1_STRING_data(X509_get_notAfter(cert)), 0);
           
             /* we check times and record if invalid */
           
-            if (now < new_grst_cert->start)
+            if (now < new_grst_cert->notbefore)
                  new_grst_cert->errors |= GRST_CERT_BAD_TIME;
 
-            if (now > new_grst_cert->finish)
+            if (now > new_grst_cert->notafter)
                  new_grst_cert->errors |= GRST_CERT_BAD_TIME;
 
             new_grst_cert->dn = X509_NAME_oneline(X509_get_subject_name(cert),NULL,0);
@@ -683,14 +687,19 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain,
                     new_grst_cert->type = GRST_CERT_TYPE_EEC;
                     first_non_ca = i;
                     ucuserdn = new_grst_cert->dn;
+                    new_grst_cert->delegation 
+                       = (lastcert == NULL) ? i : i + 1;
                   }
               } 
             else 
               {
                 new_grst_cert->type = GRST_CERT_TYPE_PROXY;
-                IsCA = FALSE; 
+
+                IsCA = FALSE;
                 /* Force proxy check next iteration. Important because I can
                    sign any CA I create! */
+
+                new_grst_cert->delegation = (lastcert == NULL) ? i : i + 1;
               }
 
             if (!prevIsCA)
@@ -728,7 +737,7 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain,
                     new_grst_cert->errors  |= GRST_CERT_BAD_CHAIN;
                     chain_errors |= GRST_CERT_BAD_CHAIN;
                   }
-                                         
+
                 if (strncmp(proxy_part_DN, "/CN=limited proxy", 17) == 0)
                         prevIsLimited = 1; /* ready for next cert ... */
 
@@ -740,11 +749,12 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain,
                      if (strcmp(s, GRST_VOMS_OID) == 0) /* a VOMS extension */
                        {
                          GRSTx509ChainVomsAdd(&grst_cert, 
-                                              new_grst_cert->start,
-                                              new_grst_cert->finish,                                              
+                                              new_grst_cert->notbefore,
+                                              new_grst_cert->notafter,                                              
                                               ex,
                                               ucuserdn, 
                                               vomsdir);
+                         grst_cert->delegation = (lastcert == NULL) ? i : i+1;
                        }
                    }
                         
@@ -760,24 +770,22 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain,
 }
 
 /// Check certificate chain for GSI proxy acceptability.
-/**
- *  Returns X509_V_OK/GRST_RET_OK if valid; OpenSSL X509 errors otherwise.
- *
- *  Inspired by GSIcheck written by Mike Jones, SVE, Manchester Computing,
- *  The University of Manchester.
- *
- *  The GridSite version handles old and new style Globus proxies, and
- *  proxies derived from user certificates issued with "X509v3 Basic
- *  Constraints: CA:FALSE" (eg UK e-Science CA)
- *
- *  We do not check chain links between certs here: this is done by
- *  GRST_check_issued/X509_check_issued in mod_ssl's ssl_engine_init.c
- *
- *  TODO: we do not yet check ProxyCertInfo and ProxyCertPolicy extensions
- *        (although via GRSTx509KnownCriticalExts() we can accept them.)
- */
-
 int GRSTx509CheckChain(int *first_non_ca, X509_STORE_CTX *ctx)
+///
+/// Returns X509_V_OK/GRST_RET_OK if valid; OpenSSL X509 errors otherwise.
+///
+/// Inspired by GSIcheck written by Mike Jones, SVE, Manchester Computing,
+/// The University of Manchester.
+///
+/// The GridSite version handles old and new style Globus proxies, and
+/// proxies derived from user certificates issued with "X509v3 Basic
+/// Constraints: CA:FALSE" (eg UK e-Science CA)
+///
+/// We do not check chain links between certs here: this is done by
+/// GRST_check_issued/X509_check_issued in mod_ssl's ssl_engine_init.c
+///
+/// TODO: we do not yet check ProxyCertInfo and ProxyCertPolicy extensions
+///       (although via GRSTx509KnownCriticalExts() we can accept them.)
 {
    STACK_OF(X509) *certstack;   /* Points to the client's cert chain */
    X509 *cert;                  /* Points to the client's cert */
@@ -927,11 +935,6 @@ int GRSTx509CheckChain(int *first_non_ca, X509_STORE_CTX *ctx)
 }
 
 /// Example VerifyCallback routine
-
-/**
- *   
- */
-
 int GRSTx509VerifyCallback (int ok, X509_STORE_CTX *ctx)
 {
    int errnum   = X509_STORE_CTX_get_error(ctx);
@@ -966,15 +969,13 @@ int GRSTx509VerifyCallback (int ok, X509_STORE_CTX *ctx)
 }
 
 /// Get the VOMS attributes in the given extension
-/*
- *  Puts any VOMS credentials found into the Compact Creds string array
- *  starting at *creds. Always returns GRST_RET_OK - even for invalid
- *  credentials, which are just ignored.
- */
-
 int GRSTx509ParseVomsExt(int *lastcred, int maxcreds, size_t credlen, 
                          char *creds, time_t time1_time, time_t time2_time,
                          X509_EXTENSION *ex, char *ucuserdn, char *vomsdir)
+///
+/// Puts any VOMS credentials found into the Compact Creds string array
+/// starting at *creds. Always returns GRST_RET_OK - even for invalid
+/// credentials, which are just ignored.
 {
 #define MAXTAG 500
 #define GRST_ASN1_COORDS_FQAN    "-1-1-%d-1-7-1-2-1-2-%d"
@@ -1052,14 +1053,12 @@ int GRSTx509ParseVomsExt(int *lastcred, int maxcreds, size_t credlen,
 }
 
 /// Get the VOMS attributes in the extensions to the given cert stack
-/*
- *  Puts any VOMS credentials found into the Compact Creds string array
- *  starting at *creds. Always returns GRST_RET_OK.
- */
-
 int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen, 
                          char *creds, X509 *usercert, STACK_OF(X509) *certstack,
                          char *vomsdir)
+///
+/// Puts any VOMS credentials found into the Compact Creds string array
+/// starting at *creds. Always returns GRST_RET_OK.
 {
    int  i, j;
    char s[80];
@@ -1106,11 +1105,9 @@ int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen,
 }
 
 /// Turn a Compact Cred line into a GRSTgaclCred object
-/**
- *  Returns pointer to created GRSTgaclCred or NULL or failure.
- */
 GRSTgaclCred *GRSTx509CompactToCred(char *grst_cred)
+///
+/// Returns pointer to created GRSTgaclCred or NULL or failure.
 {
    int       delegation;
    char     *p;
@@ -1167,16 +1164,14 @@ GRSTgaclCred *GRSTx509CompactToCred(char *grst_cred)
 }
 
 /// Get the credentials in an X509 cert/GSI proxy, including any VOMS
-/**
- *  Credentials are placed in Compact Creds string array at *creds.
- * 
- *  Function returns GRST_RET_OK on success, or GRST_RET_FAILED if
- *  some inconsistency found in certificate.
- */
 int GRSTx509CompactCreds(int *lastcred, int maxcreds, size_t credlen, 
                          char *creds, STACK_OF(X509) *certstack, char *vomsdir, 
                          X509 *peercert)
+///
+/// Credentials are placed in Compact Creds string array at *creds.
+///
+/// Function returns GRST_RET_OK on success, or GRST_RET_FAILED if
+/// some inconsistency found in certificate.
 {   
    int   i, j, delegation = 0;
    char  credtemp[credlen+1];
@@ -1252,12 +1247,10 @@ int GRSTx509CompactCreds(int *lastcred, int maxcreds, size_t credlen,
 }
 
 /// Find proxy file name of the current user
-/**
- *  Return a string with the proxy file name or NULL if not present.
- *  This function does not check if the proxy has expired.
- */
 char *GRSTx509FindProxyFileName(void)
+///
+/// Return a string with the proxy file name or NULL if not present.
+/// This function does not check if the proxy has expired.
 {
   char *p;
   
@@ -1282,14 +1275,12 @@ static void mpcerror(FILE *debugfp, char *msg)
 }
 
 /// Make a GSI Proxy chain from a request, certificate and private key
-/**
- *  The proxy chain is returned in *proxychain. If debugfp is non-NULL,
- *  errors are output to that file pointer. The proxy will expired in
- *  the given number of minutes starting from the current time.
- */
-
 int GRSTx509MakeProxyCert(char **proxychain, FILE *debugfp, 
                           char *reqtxt, char *cert, char *key, int minutes)
+///
+/// The proxy chain is returned in *proxychain. If debugfp is non-NULL,
+/// errors are output to that file pointer. The proxy will expired in
+/// the given number of minutes starting from the current time.
 {
   char *ptr, *certchain;
   int i, subjAltName_pos, ncerts;
@@ -1518,18 +1509,15 @@ int GRSTx509MakeProxyCert(char **proxychain, FILE *debugfp,
 }
 
 /// Find a proxy file in the proxy cache
-/**
- *  Returns the full path and file name of proxy file associated
- *  with given delegation ID and user DN.
- */
-
 char *GRSTx509CachedProxyFind(char *proxydir, char *delegation_id, 
                               char *user_dn)
-/* 
-    Return a pointer to a malloc'd string with the full path of the 
-    proxy file corresponding to the given delegation_id, or NULL
-    if not found.
-*/
+///
+/// Returns the full path and file name of proxy file associated
+/// with given delegation ID and user DN.
+///
+/// Return a pointer to a malloc'd string with the full path of the 
+/// proxy file corresponding to the given delegation_id, or NULL
+/// if not found.
 {
   char *user_dn_enc, *proxyfile;
   struct stat statbuf;
@@ -1551,18 +1539,15 @@ char *GRSTx509CachedProxyFind(char *proxydir, char *delegation_id,
 }
 
 /// Find a temporary proxy private key file in the proxy cache
-/**
- *  Returns the full path and file name of the private key file associated
- *  with given delegation ID and user DN.
- */
-
 char *GRSTx509CachedProxyKeyFind(char *proxydir, char *delegation_id, 
                                  char *user_dn)
-/* 
-    Return a pointer to a malloc'd string with the full path of the 
-    private proxy key corresponding to the given delegation_id, or NULL
-    if not found.
-*/
+///
+/// Returns the full path and file name of the private key file associated
+/// with given delegation ID and user DN.
+///
+/// Return a pointer to a malloc'd string with the full path of the 
+/// private proxy key corresponding to the given delegation_id, or NULL
+/// if not found.
 {
   char *user_dn_enc, *prvkeyfile;
   struct stat statbuf;
@@ -1599,12 +1584,10 @@ static void mkdir_printf(mode_t mode, char *fmt, ...)
 }
 
 /// Create a X.509 request for a GSI proxy and its private key
-/**
- *  Returns GRST_RET_OK on success, non-zero otherwise. Request string
- *  and private key are PEM encoded strings
- */ 
 int GRSTx509CreateProxyRequest(char **reqtxt, char **keytxt, char *ocspurl)
+///
+/// Returns GRST_RET_OK on success, non-zero otherwise. Request string
+/// and private key are PEM encoded strings
 {
   int              i;
   char            *ptr;
@@ -1674,14 +1657,12 @@ int GRSTx509CreateProxyRequest(char **reqtxt, char **keytxt, char *ocspurl)
 }
 
 /// Make and store a X.509 request for a GSI proxy
-/**
- *  Returns GRST_RET_OK on success, non-zero otherwise. Request string
- *  is PEM encoded, and the key is stored in the temporary cache under
- *  proxydir
- */ 
 int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir, 
                              char *delegation_id, char *user_dn)
+///
+/// Returns GRST_RET_OK on success, non-zero otherwise. Request string
+/// is PEM encoded, and the key is stored in the temporary cache under
+/// proxydir
 {
   int              i;
   char            *docroot, *prvkeyfile, *ptr, *user_dn_enc;
@@ -1771,13 +1752,11 @@ int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir,
 }
 
 /// Destroy stored GSI proxy files
-/**
- *  Returns GRST_RET_OK on success, non-zero otherwise.
- *  (Including GRST_RET_NO_SUCH_FILE if the private key or cert chain
- *   were not found.)
- */ 
-
 int GRSTx509ProxyDestroy(char *proxydir, char *delegation_id, char *user_dn)
+///
+/// Returns GRST_RET_OK on success, non-zero otherwise.
+/// (Including GRST_RET_NO_SUCH_FILE if the private key or cert chain
+///  were not found.)
 {
   int              ret = GRST_RET_OK;
   char            *docroot, *filename, *user_dn_enc;
@@ -1818,13 +1797,11 @@ int GRSTx509ProxyDestroy(char *proxydir, char *delegation_id, char *user_dn)
 }
 
 /// Get start and finish validity times of stored GSI proxy file
-/**
- *  Returns GRST_RET_OK on success, non-zero otherwise.
- *  (Including GRST_RET_NO_SUCH_FILE if the cert chain was not found.)
- */ 
-
 int GRSTx509ProxyGetTimes(char *proxydir, char *delegation_id, char *user_dn, 
                           time_t *start, time_t *finish)
+///
+/// Returns GRST_RET_OK on success, non-zero otherwise.
+/// (Including GRST_RET_NO_SUCH_FILE if the cert chain was not found.)
 {
   char  *docroot, *filename, *user_dn_enc;
   FILE  *fp;
@@ -1859,15 +1836,12 @@ int GRSTx509ProxyGetTimes(char *proxydir, char *delegation_id, char *user_dn,
 }
 
 /// Create a stack of X509 certificate from a PEM-encoded string
-/**
- *  Creates a dynamically allocated stack of X509 certificate objects
- *  by walking through the PEM-encoded X509 certificates.
- *
- *  Returns GRST_RET_OK on success, non-zero otherwise.
- *
- */
-
 int GRSTx509StringToChain(STACK_OF(X509) **certstack, char *certstring)
+///
+/// Creates a dynamically allocated stack of X509 certificate objects
+/// by walking through the PEM-encoded X509 certificates.
+///
+/// Returns GRST_RET_OK on success, non-zero otherwise.
 {   
   STACK_OF(X509_INFO) *sk=NULL;
   BIO *certbio;
@@ -1912,12 +1886,10 @@ int GRSTx509StringToChain(STACK_OF(X509) **certstack, char *certstring)
 }
 
 /// Returns a Delegation ID based on hash of GRST_CRED_0, ...
-/**
- *  Returns a malloc'd string with Delegation ID made by SHA1-hashing the
- *  values of the compact credentials exported by mod_gridsite
- */
-
 char *GRSTx509MakeDelegationID(void)
+///
+/// Returns a malloc'd string with Delegation ID made by SHA1-hashing the
+/// values of the compact credentials exported by mod_gridsite
 { 
   unsigned char hash_delegation_id[EVP_MAX_MD_SIZE];        
   int  size_needed = 0, i, delegation_id_len;
@@ -1954,17 +1926,15 @@ char *GRSTx509MakeDelegationID(void)
 
 #if 0
 /// Return the short file name for the given delegation_id and user_dn
-/**
- *  Returns a malloc'd string with the short file name (no paths) that
- *  derived from the hashed delegation_id and user_dn
- *
- *  File name is SHA1_HASH(DelegationID)+"-"+SHA1_HASH(DN) where DN
- *  is DER encoded version of user_dn with any trailing CN=proxy removed
- *  Hashes are the most significant 8 bytes, in lowercase hexadecimal.
- */
-
 char *GRSTx509MakeProxyFileName(char *delegation_id,
                                 STACK_OF(X509) *certstack)
+///
+/// Returns a malloc'd string with the short file name (no paths) that
+/// derived from the hashed delegation_id and user_dn
+///
+/// File name is SHA1_HASH(DelegationID)+"-"+SHA1_HASH(DN) where DN
+/// is DER encoded version of user_dn with any trailing CN=proxy removed
+/// Hashes are the most significant 8 bytes, in lowercase hexadecimal.
 { 
   int        i, depth, prevIsCA = 1, IsCA, hash_name_len, delegation_id_len,
                  der_name_len;
@@ -2043,14 +2013,12 @@ char *GRSTx509MakeProxyFileName(char *delegation_id,
 #endif
 
 /// Store a GSI proxy chain in the proxy cache, along with the private key
-/**
- *  Returns GRST_RET_OK on success, non-zero otherwise. The existing
- *  private key with the same delegation ID and user DN is moved out of
- *  the temporary cache.
- */
-
 int GRSTx509CacheProxy(char *proxydir, char *delegation_id, 
                                        char *user_dn, char *proxychain)
+///
+/// Returns GRST_RET_OK on success, non-zero otherwise. The existing
+/// private key with the same delegation ID and user DN is moved out of
+/// the temporary cache.
 {
   int   c, len = 0, i, ret;
   char *user_dn_enc, *p, *ptr, *prvkeyfile, *proxyfile;
index c4c88ee..2ced7ff 100644 (file)
@@ -101,7 +101,6 @@ static GRSTgaclCred *GRSTxacmlCredParse(xmlNodePtr cur)
 
   cred = GRSTgaclCredNew((char *) xmlNodeGetContent(attr_des->properties->children));
 
-  cred->firstname = NULL;
   cred->next      = NULL;
 
   //Assumed that there is only one name/value pair per credential
@@ -405,20 +404,14 @@ int GRSTxacmlCredPrint(GRSTgaclCred *cred, FILE *fp)
    GRSTxacmlCredPrint - print a credential and any name-value pairs is contains in XACML form
 */
 {
-  char              *q;
-  GRSTgaclNamevalue *p;
+  char *q;
 
-  if (cred->firstname != NULL)
+  if (cred->auri != NULL)
     {
-
-      p = cred->firstname;
-
-      do {
-
           fputs("\t\t\t\t<Subject>\n", fp);
           fputs("\t\t\t\t\t<SubjectMatch MatchId=\"urn:oasis:names:tc:xacml:1.0:function:string-equal\">\n", fp);
           fputs("\t\t\t\t\t\t<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">", fp);
-           for (q=p->value; *q != '\0'; ++q)
+           for (q=cred->auri; *q != '\0'; ++q)
               if      (*q == '<')  fputs("&lt;",   fp);
               else if (*q == '>')  fputs("&gt;",   fp);
               else if (*q == '&')  fputs("&amp;" , fp);
@@ -431,14 +424,11 @@ int GRSTxacmlCredPrint(GRSTgaclCred *cred, FILE *fp)
 
           fputs("\t\t\t\t\t\t<SubjectAttributeDesignator\n", fp);
           fputs("\t\t\t\t\t\t\tAttributeId=", fp);
-          fprintf(fp, "\"%s\"\n", cred->type);
+          fprintf(fp, "\"cred\"\n");
           fputs("\t\t\t\t\t\t\tDataType=", fp);
-           fprintf(fp, "\"%s\"/>\n", p->name);
+           fprintf(fp, "\"auri\"/>\n");
           fputs("\t\t\t\t\t</SubjectMatch>\n", fp);
           fputs("\t\t\t\t</Subject>\n", fp);
-           p = (GRSTgaclNamevalue *) p->next;
-         } while (p != NULL);
-
     }
     else fputs("\t\t\t\t<AnySubject/>\n", fp);
 
index 688b509..1078953 100644 (file)
@@ -591,7 +591,7 @@ int main(int argc, char *argv[])
                   (grst_cert->type == GRST_CERT_TYPE_VOMS) 
                     ? grst_cert->value : grst_cert->dn);
  
-           printf(" Status  : %d ( %s%s%s%s%s%s)\n", grst_cert->errors,
+           printf(" Status     : %d ( %s%s%s%s%s%s)\n", grst_cert->errors,
                  (grst_cert->errors == 0) ? "OK " : "",
                  (grst_cert->errors & GRST_CERT_BAD_FORMAT) ? "BAD_FORMAT ":"",
                  (grst_cert->errors & GRST_CERT_BAD_CHAIN)  ? "BAD_CHAIN ":"",
@@ -599,18 +599,19 @@ int main(int argc, char *argv[])
                  (grst_cert->errors & GRST_CERT_BAD_TIME)   ? "BAD_TIME ":"",
                  (grst_cert->errors & GRST_CERT_BAD_OCSP)   ? "BAD_OCSP ":"");
 
-           printf(" Start   : %s", ctime(&(grst_cert->start)));
-           printf(" Finish  : %s", ctime(&(grst_cert->finish)));
+           printf(" Start      : %s",   ctime(&(grst_cert->notbefore)));
+           printf(" Finish     : %s",   ctime(&(grst_cert->notafter)));
+           printf(" Delegation : %d\n", grst_cert->delegation);
 
            if (grst_cert->type == GRST_CERT_TYPE_VOMS)
              {
-               printf(" User DN : %s\n", grst_cert->dn);
-               printf(" VOMS DN : %s\n\n", grst_cert->issuer);
+               printf(" User DN    : %s\n", grst_cert->dn);
+               printf(" VOMS DN    : %s\n\n", grst_cert->issuer);
              }
            else
              {
-               printf(" Serial  : %d\n", grst_cert->serial);
-               printf(" Issuer  : %s\n\n", grst_cert->issuer);              
+               printf(" Serial     : %d\n", grst_cert->serial);
+               printf(" Issuer     : %s\n\n", grst_cert->issuer);              
              }
          }
       
index 16febab..fcbb7d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2003-6, Andrew McNab, Shiv Kaushal, Joseph Dada,
+   Copyright (c) 2003-7, Andrew McNab, Shiv Kaushal, Joseph Dada,
    and Yibiao Li, University of Manchester. All rights reserved.
 
    Redistribution and use in source and binary forms, with or
@@ -216,7 +216,7 @@ char *make_admin_footer(request_rec *r, mod_gridsite_dir_cfg *conf,
 */
 {
     char     *out, *https, *p, *dn = NULL, *file = NULL, *permstr = NULL, 
-             *temp, modified[99], *dir_uri, *grst_cred_0 = NULL;
+             *temp, modified[99], *dir_uri, *grst_cred_auri_0 = NULL;
     GRSTgaclPerm  perm = GRST_PERM_NONE;
     struct tm mtime_tm;
     time_t    mtime_time;
@@ -263,26 +263,16 @@ char *make_admin_footer(request_rec *r, mod_gridsite_dir_cfg *conf,
     out = apr_pstrcat(r->pool, out, "<hr><small>", NULL);
 
     if (r->connection->notes != NULL)
-         grst_cred_0 = (char *) 
-                       apr_table_get(r->connection->notes, "GRST_CRED_0");
+      {
+        grst_cred_auri_0 = (char *) 
+                  apr_table_get(r->connection->notes, "GRST_CRED_AURI_0");
+      }                       
 
-    if ((grst_cred_0 != NULL) && 
-        (strncmp(grst_cred_0, "X509USER ", sizeof("X509USER")) == 0))
+    if ((grst_cred_auri_0 != NULL) && 
+        (strncmp(grst_cred_auri_0, "dn:", 3) == 0))
       {
-         p = index(grst_cred_0, ' ');
-         if (p != NULL)
-           {
-             p = index(++p, ' ');
-             if (p != NULL)
-               {
-                 p = index(++p, ' ');
-                 if (p != NULL)
-                   {
-                     p = index(++p, ' ');
-                     if (p != NULL) dn = p;
-                   }
-               }
-           }
+         dn = &grst_cred_auri_0[3];
+         if (dn[0] == '\0') dn = NULL;
       }
   
     if (dn != NULL) 
@@ -779,13 +769,21 @@ int http_gridhttp(request_rec *r, mod_gridsite_dir_cfg *conf)
 
     for (i=0; ; ++i)
        {
-         envname_i = apr_psprintf(r->pool, "GRST_CRED_%d", i);
+         envname_i = apr_psprintf(r->pool, "GRST_CRED_AURI_%d", i);
+         if (grst_cred_i = (char *)
+                           apr_table_get(r->connection->notes, envname_i))
+           {
+             apr_file_printf(fp, "%s=%s\n", envname_i, grst_cred_i);
+           }
+         else break; /* GRST_CRED_AURI_i are numbered consecutively */
+
+         envname_i = apr_psprintf(r->pool, "GRST_CRED_VALID_%d", i);
          if (grst_cred_i = (char *)
                            apr_table_get(r->connection->notes, envname_i))
            {
              apr_file_printf(fp, "%s=%s\n", envname_i, grst_cred_i);
            }
-         else break; /* GRST_CRED_i are numbered consecutively */
+         else break; /* GRST_CRED_VALID_i are numbered consecutively */
        }
 
     if (apr_file_close(fp) != APR_SUCCESS) 
@@ -2161,16 +2159,27 @@ int GRST_load_ssl_creds(SSL *ssl, conn_rec *conn)
    
    while (apr_file_gets(line, sizeof(line), fp) == APR_SUCCESS)
         {
-          if (sscanf(line, "GRST_CRED_%d=", &i) == 1)
+          if (sscanf(line, "GRST_CRED_AURI_%d=", &i) == 1)
             {
+              if ((p = index(line, '\n')) != NULL) *p = '\0';              
               p = index(line, '=');
 
               apr_table_setn(conn->notes,
-                         apr_psprintf(conn->pool, "GRST_CRED_%d", i),
+                         apr_psprintf(conn->pool, "GRST_CRED_AURI_%d", i),
+                         apr_pstrdup(conn->pool, &p[1]));
+            }
+          else if (sscanf(line, "GRST_CRED_VALID_%d=", &i) == 1)
+            {
+              if ((p = index(line, '\n')) != NULL) *p = '\0';              
+              p = index(line, '=');
+
+              apr_table_setn(conn->notes,
+                         apr_psprintf(conn->pool, "GRST_CRED_VALID_%d", i),
                          apr_pstrdup(conn->pool, &p[1]));
             }
           else if (sscanf(line, "GRST_OCSP_URL_%d=", &i) == 1)
             {
+              if ((p = index(line, '\n')) != NULL) *p = '\0';              
               p = index(line, '=');
 
               apr_table_setn(conn->notes,
@@ -2188,25 +2197,23 @@ int GRST_load_ssl_creds(SSL *ssl, conn_rec *conn)
 }
 
 /*
-    Save result of GRSTx509CompactCreds() into connection notes, and
-    write out in an SSL session creds file.
+    Save result of AURIs and validity info from chain into connection notes,
+    and write out in an SSL session creds file.
 */
 
-void GRST_save_ssl_creds(conn_rec *conn, 
-                        STACK_OF(X509) *certstack, X509 *peercert)
+void GRST_save_ssl_creds(conn_rec *conn, GRSTx509Chain *grst_chain)
 {
    int          i, lastcred;
-   const int    maxcreds = 99;
-   const size_t credlen = 1024;
-   char         creds[maxcreds][credlen+1], envname[14], *tempfile = NULL,
+   char         envname[14], *tempfile = NULL,
                *sessionfile, session_id[(SSL_MAX_SSL_SESSION_ID_LENGTH+1)*2];
    apr_file_t  *fp = NULL;
    SSL         *ssl;
    SSLConnRec  *sslconn;
+   GRSTx509Cert  *grst_cert = NULL;
 
    /* check if already done */
 
-   if ((certstack != NULL) && (conn->notes != NULL) &&
+   if ((grst_chain != NULL) && (conn->notes != NULL) &&
        (apr_table_get(conn->notes, "GRST_save_ssl_creds") != NULL)) return;
 
    /* we at least need to say we've been run */
@@ -2234,27 +2241,67 @@ void GRST_save_ssl_creds(conn_rec *conn,
                                APR_CREATE | APR_WRITE | APR_EXCL, conn->pool);
      }
 
-   if (GRSTx509CompactCreds(&lastcred, maxcreds, credlen, (char *) creds,
-                          certstack, GRST_VOMS_DIR, peercert) == GRST_RET_OK)
-     {
-       for (i=0; i <= lastcred; ++i)
+   grst_cert = grst_chain->firstcert;
+   
+   for (i=0; grst_cert != NULL; grst_cert = grst_cert->next)
+      {
+        if (grst_cert->type == GRST_CERT_TYPE_VOMS)
           {
             apr_table_setn(conn->notes,
-                                 apr_psprintf(conn->pool, "GRST_CRED_%d", i),
-                                 apr_pstrdup(conn->pool, creds[i]));
+                   apr_psprintf(conn->pool, "GRST_CRED_AURI_%d", i),
+                   apr_pstrcat(conn->pool, "fqan:", grst_cert->value, NULL));
+
+            if (fp != NULL) apr_file_printf(fp, "GRST_CRED_AURI_%d=fqan:%s\n",
+                                                i, grst_cert->value);
+
+            apr_table_setn(conn->notes,
+                   apr_psprintf(conn->pool, "GRST_CRED_VALID_%d", i),
+                   apr_psprintf(conn->pool, 
+                      "notbefore=%ld notafter=%ld delegation=%d nist-loa=%d", 
+                      grst_cert->notbefore,
+                      grst_cert->notafter, 0, 0));
+
+            if (fp != NULL) apr_file_printf(fp, 
+  "GRST_CRED_VALID_%d=notbefore=%ld notafter=%ld delegation=%d nist-loa=%d\n",
+                                            i, grst_cert->notbefore,
+                                               grst_cert->notafter, 0, 0);
 
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, conn->base_server,
-                                      "store GRST_CRED_%d=%s", i, creds[i]);
+                      "store GRST_CRED_AURI_%d=fqan:%s", i, grst_cert->value);
 
-            if (fp != NULL) apr_file_printf(fp, "GRST_CRED_%d=%s\n",
-                                                i, creds[i]);
+            ++i;
           }
-                                   
-       /* free remaining dup'd certs? */
-     }
+        else if ((grst_cert->type == GRST_CERT_TYPE_EEC) ||
+                 (grst_cert->type == GRST_CERT_TYPE_PROXY))
+          {
+            apr_table_setn(conn->notes,
+                   apr_psprintf(conn->pool, "GRST_CRED_AURI_%d", i),
+                   apr_pstrcat(conn->pool, "dn:", grst_cert->dn, NULL));
 
-   /* this needs to be merged into compactcreds in grst_x509? */
+            if (fp != NULL) apr_file_printf(fp, "GRST_CRED_AURI_%d=dn:%s\n",
+                                                i, grst_cert->dn);
+
+            apr_table_setn(conn->notes,
+                   apr_psprintf(conn->pool, "GRST_CRED_VALID_%d", i),
+                   apr_psprintf(conn->pool, 
+                      "notbefore=%ld notafter=%ld delegation=%d nist-loa=%d", 
+                      grst_cert->notbefore,
+                      grst_cert->notafter, 0, 0));
+
+            if (fp != NULL) apr_file_printf(fp, 
+  "GRST_CRED_VALID_%d=notbefore=%ld notafter=%ld delegation=%d nist-loa=%d\n",
+                                            i, grst_cert->notbefore,
+                                               grst_cert->notafter, 0, 0);
+
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, conn->base_server,
+                      "store GRST_CRED_AURI_%d=dn:%s", i, grst_cert->dn);
 
+            ++i;
+          }
+      }
+
+   /* this needs to be merged into grst_x509? */
+#if 0
    if (ocspmodes != NULL)
    {
      int   j;
@@ -2292,7 +2339,7 @@ void GRST_save_ssl_creds(conn_rec *conn,
              }
         }   
    }
-         
+#endif
    /* end of bit that needs to go into grst_x509 */
      
    if (fp != NULL)
@@ -2383,14 +2430,15 @@ static int mod_gridsite_perm_handler(request_rec *r)
     We also publish environment variables here if requested by GridSiteEnv.
 */
 {
-    int          retcode = DECLINED, i, n, file_is_acl = 0,
-                 destination_is_acl = 0, proxylevel, ishttps = 0;
-    char        *dn, *p, envname[14], *grst_cred_0 = NULL, *dir_path, 
-                *remotehost, s[99], *grst_cred_i, *cookies, *file, *https,
+    int          retcode = DECLINED, i, n, file_is_acl = 0, cc_delegation,
+                 destination_is_acl = 0, ishttps = 0, nist_loa, delegation;
+    char        *dn, *p, envname1[30], envname2[30], 
+                *grst_cred_auri_0 = NULL, *dir_path, 
+                *remotehost, s[99], *grst_cred_auri_i, *cookies, *file, *https,
                 *gridauthpasscode = NULL, *cookiefile, oneline[1025], *key_i,
                 *destination = NULL, *destination_uri = NULL, *querytmp, 
                 *destination_prefix = NULL, *destination_translated = NULL,
-                *aclpath = NULL;
+                *aclpath = NULL, *grst_cred_valid_0 = NULL, *grst_cred_valid_i;
     char        *vomsAttribute = NULL, *loa;
     const char  *content_type;
     time_t       now, notbefore, notafter;
@@ -2448,15 +2496,12 @@ static int mod_gridsite_perm_handler(request_rec *r)
                                   
     if (dn != NULL)
       {
-        cred = GRSTgaclCredNew("person");
-        GRSTgaclCredAddValue(cred, "dn", dn);
-        user = GRSTgaclUserNew(cred);
-        cred = GRSTgaclCredNew("level");
+        cred = GRSTgaclCredCreate("dn:", dn);
 
-        if (loa != NULL) GRSTgaclCredAddValue(cred, "nist-loa", loa);
-        else GRSTgaclCredAddValue(cred, "nist-loa", "2");
+        if (loa != NULL) GRSTgaclCredSetNistLoa(cred, atoi(loa));
+        else GRSTgaclCredSetNistLoa(cred, 2);
 
-        GRSTgaclUserAddCred(user, cred);
+        user = GRSTgaclUserNew(cred);
       }
             
     /* Set up user credential based on VOMS Attribute from Shibboleth? */
@@ -2467,8 +2512,7 @@ static int mod_gridsite_perm_handler(request_rec *r)
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, 
                  "VOMS-Attribute: %s", vomsAttribute);
 
-        cred = GRSTgaclCredNew("voms");
-        GRSTgaclCredAddValue(cred, "fqan", vomsAttribute);
+        cred = GRSTgaclCredCreate("fqan:", vomsAttribute);
         if (user == NULL) user = GRSTgaclUserNew(cred);
         else GRSTgaclUserAddCred(user, cred);
       }
@@ -2492,67 +2536,152 @@ static int mod_gridsite_perm_handler(request_rec *r)
                          "Restored SSL session data from session cache file");
       }
 
-    proxylevel = ((mod_gridsite_dir_cfg *) cfg)->gsiproxylimit + 1;
+    delegation = ((mod_gridsite_dir_cfg *) cfg)->gsiproxylimit + 1;
     
     if ((user == NULL) && 
         (r->connection->notes != NULL) &&
-        ((grst_cred_0 = (char *) 
-            apr_table_get(r->connection->notes, "GRST_CRED_0")) != NULL) &&
-        (sscanf(grst_cred_0, "X509USER %*d %*d %d ", &proxylevel) == 1) &&
-        (proxylevel <= ((mod_gridsite_dir_cfg *) cfg)->gsiproxylimit))
+        ((grst_cred_auri_0 = (char *) 
+         apr_table_get(r->connection->notes, "GRST_CRED_AURI_0")) != NULL) &&
+        (strncmp(grst_cred_auri_0, "dn:", 3) == 0) &&
+        ((grst_cred_valid_0 = (char *) 
+         apr_table_get(r->connection->notes, "GRST_CRED_VALID_0")) != NULL) &&
+        (sscanf(grst_cred_valid_0, 
+                "notbefore=%ld notafter=%ld delegation=%d nist-loa=%d", 
+                &notbefore, &notafter, &delegation, &nist_loa) == 4) &&
+        (delegation <= ((mod_gridsite_dir_cfg *) cfg)->gsiproxylimit))
       {
-        apr_table_setn(env, "GRST_CRED_0", grst_cred_0);
-                                    
-        cred_0 = GRSTx509CompactToCred(grst_cred_0);
+        cred_0 = GRSTgaclCredCreate(grst_cred_auri_0, NULL);
         if (cred_0 != NULL)
           {
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
-                         "Using identity %s from SSL/TLS", grst_cred_0);
+                         "Using identity %s from SSL/TLS", grst_cred_auri_0);
+
+            GRSTgaclCredSetNotBefore( cred_0, notbefore);
+            GRSTgaclCredSetNotAfter(  cred_0, notafter);
+            GRSTgaclCredSetDelegation(cred_0, delegation);
+
+            if (delegation == 0) GRSTgaclCredSetNistLoa(cred_0, 3);
+            else                 GRSTgaclCredSetNistLoa(cred_0, 2);
 
             user = GRSTgaclUserNew(cred_0);
 
-            /* check for VOMS GRST_CRED_i too */
+            /* check for VOMS etc in GRST_CRED_AURI_i too */
   
             for (i=1; ; ++i)
                {
-                 snprintf(envname, sizeof(envname), "GRST_CRED_%d", i);
-                 if (grst_cred_i = (char *) 
-                                   apr_table_get(r->connection->notes,envname))
+                 snprintf(envname1, sizeof(envname1), "GRST_CRED_AURI_%d", i);
+                 snprintf(envname2, sizeof(envname2), "GRST_CRED_VALID_%d", i);
+
+                 if ((grst_cred_auri_i = (char *) 
+                         apr_table_get(r->connection->notes,envname1)) &&
+                     (grst_cred_valid_i = (char *) 
+                         apr_table_get(r->connection->notes,envname2)))
                    { 
-                     if (((mod_gridsite_dir_cfg *) cfg)->envs)
-                              apr_table_setn(env,
-                                             apr_pstrdup(r->pool, envname),
-                                             grst_cred_i);
-                                    
-                     if (cred = GRSTx509CompactToCred(grst_cred_i))
-                                        GRSTgaclUserAddCred(user, cred);
+                     cred = GRSTgaclCredCreate(grst_cred_auri_i, NULL);
+                     if (cred != NULL) 
+                       {
+                         notbefore  = 0;
+                         notafter   = 0;
+                         delegation = 0;
+                         nist_loa   = 0;
+                       
+                         sscanf(grst_cred_valid_i, 
+                       "notbefore=%ld notafter=%ld delegation=%d nist-loa=%d", 
+                                &notbefore, &notafter, &delegation, &nist_loa);
+                        
+                         GRSTgaclCredSetNotBefore( cred, notbefore);
+                         GRSTgaclCredSetNotAfter(  cred, notafter);
+                         GRSTgaclCredSetDelegation(cred, delegation);
+                         GRSTgaclCredSetDelegation(cred, nist_loa);
+
+                         GRSTgaclUserAddCred(user, cred);
+                       }
                    }
-                 else break; /* GRST_CRED_i are numbered consecutively */
+                 else break; /* GRST_CRED_AURI_i are numbered consecutively */
                }
-
-            cred = GRSTgaclCredNew("level");
-            if (proxylevel == 0) GRSTgaclCredAddValue(cred, "nist-loa", "3");
-            else                 GRSTgaclCredAddValue(cred, "nist-loa", "2");
-            GRSTgaclUserAddCred(user, cred);
           }
       }
 
     if ((user != NULL) && ((mod_gridsite_dir_cfg *) cfg)->dnlists)
-          GRSTgaclUserSetDNlists(user, ((mod_gridsite_dir_cfg *) cfg)->dnlists);
+          GRSTgaclUserLoadDNlists(user, ((mod_gridsite_dir_cfg *) cfg)->dnlists);
 
     /* add DNS credential */
     
     remotehost = (char *) ap_get_remote_host(r->connection,
                                   r->per_dir_config, REMOTE_DOUBLE_REV, NULL);
     if ((remotehost != NULL) && (*remotehost != '\0'))
-      {            
-        cred = GRSTgaclCredNew("dns");
-        GRSTgaclCredAddValue(cred, "hostname", remotehost);
+      {
+        cred = GRSTgaclCredCreate("dns:", remotehost);
+
+        if (user == NULL) user = GRSTgaclUserNew(cred);
+        else              GRSTgaclUserAddCred(user, cred);
+      }
+
+    /* add IP credential */
+    
+    remotehost = (char *) ap_get_remote_host(r->connection,
+                                  r->per_dir_config, REMOTE_DOUBLE_REV, NULL);
+    if ((remotehost != NULL) && (*remotehost != '\0'))
+      {
+        cred = GRSTgaclCredCreate("ip:", r->connection->remote_ip);
 
         if (user == NULL) user = GRSTgaclUserNew(cred);
         else              GRSTgaclUserAddCred(user, cred);
       }
 
+    /* write contents of user to per-request environment variables */
+
+    if (((mod_gridsite_dir_cfg *) cfg)->envs && (user != NULL))
+      {    
+        cred = user->firstcred;
+        
+        /* old-style Compact Credentials have the same delegation level
+           for all credentials. eg Using EEC delegation=0; using 1st GSI
+           Proxy then delegation=1 for X509USER _and_ GSIPROXY credentials. 
+           So we remember the delegation level of any X509USER here */
+        if (cred != NULL) cc_delegation = cred->delegation;
+      
+        for (i=0; (cred != NULL) && (cred->auri != NULL); ++i)
+             {                                    
+               if (strncmp(cred->auri, "dn:", 3) == 0)
+                 {
+                   apr_table_setn(env, 
+                                  apr_psprintf(r->pool, "GRST_CRED_%d", i),
+                                  apr_psprintf(r->pool, 
+                                               "%s %ld %ld %d %s",
+                                               (i=0) ? "X509USER" : "GSIPROXY",
+                                               cred->notbefore,
+                                               cred->notafter,
+                                               cc_delegation, 
+                                               &(cred->auri[3])));
+                 }
+               else if (strncmp(cred->auri, "fqan:", 5) == 0)
+                 {
+                   apr_table_setn(env, 
+                                  apr_psprintf(r->pool, "GRST_CRED_%d", i),
+                                  apr_psprintf(r->pool, 
+                                                  "VOMS %ld %ld 0 %s",
+                                                  notbefore, notafter, 
+                                                  &(cred->auri[5])));
+                 }
+
+               apr_table_setn(env,
+                              apr_psprintf(r->pool, "GRST_CRED_AURI_%d", i),
+                              apr_pstrdup(r->pool, cred->auri));
+
+               apr_table_setn(env, 
+                              apr_psprintf(r->pool, "GRST_CRED_VALID_%d", i),
+                              apr_psprintf(r->pool,
+                       "notbefore=%ld notafter=%ld delegation=%d nist-loa=%d",
+                                           cred->notbefore,
+                                           cred->notafter,
+                                           cred->delegation,
+                                           cred->nist_loa));
+                 
+               cred = cred->next;
+             }    
+      }
+
     /* check for Destination: header and evaluate if present */
 
     if ((destination = (char *) apr_table_get(r->headers_in,
@@ -2601,13 +2730,26 @@ static int mod_gridsite_perm_handler(request_rec *r)
           }
       }
     
-    /* this checks for NULL arguments itself */
-    if (GRSTgaclDNlistHasUser(((mod_gridsite_dir_cfg *) cfg)->adminlist, user))
-      {
-        perm = GRST_PERM_ALL;
-        if (destination_translated != NULL) destination_perm = GRST_PERM_ALL;
+    if ((((mod_gridsite_dir_cfg *) cfg)->adminlist != NULL) && (user != NULL))
+      {    
+        cred = user->firstcred;
+      
+        while ((cred != NULL) && (cred->auri != NULL))
+             {
+               if (strcmp(((mod_gridsite_dir_cfg *) cfg)->adminlist,
+                          cred->auri) == 0)
+                 {
+                   perm = GRST_PERM_ALL;
+                   if (destination_translated != NULL) 
+                          destination_perm = GRST_PERM_ALL;
+                   break;
+                 }
+                 
+               cred = cred->next;
+             }    
       }
-    else
+    
+    if (perm != GRST_PERM_ALL) /* cannot improve on perfection... */
       {
         if (((mod_gridsite_dir_cfg *) cfg)->aclpath != NULL)
           {
@@ -2965,11 +3107,12 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
    int returned_ok;
    int first_non_ca;
    STACK_OF(X509) *certstack;
+   GRSTx509Chain *grst_chain;
 
    /*
     * GSI Proxy user-cert-as-CA handling:
     * we skip Invalid CA errors at this stage, since we will check this
-    * again at errdepth=0 for the full chain using GRSTx509CheckChain
+    * again at errdepth=0 for the full chain using GRSTx509ChainLoadCheck
     */
    if (errnum == X509_V_ERR_INVALID_CA)
      {
@@ -3017,7 +3160,11 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
     * CAs or, failing that, GSI-proxy validity using GRSTx509CheckChain.
     */
      {
-        errnum = GRSTx509CheckChain(&first_non_ca, ctx);
+        certstack = (STACK_OF(X509) *) X509_STORE_CTX_get_chain(ctx);
+
+        errnum = GRSTx509ChainLoadCheck(&grst_chain, certstack, NULL,
+                                        "/etc/grid-security/certificates", 
+                                        "/etc/grid-security/vomsdir");
 
         if (errnum != X509_V_OK)
           {
@@ -3031,13 +3178,13 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
         else 
           {
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Valid certificate"
-                                   " chain reported by GRSTx509CheckChain()");
+                              " chain reported by GRSTx509ChainLoadCheck()");
 
-            /* Put result of GRSTx509CompactCreds() into connection notes */
-            if ((certstack = 
-                  (STACK_OF(X509) *) X509_STORE_CTX_get_chain(ctx)) != NULL)
-             GRST_save_ssl_creds(conn, certstack, NULL);
+            /* Put result of GRSTx509ChainLoadCheck into connection notes */
+            GRST_save_ssl_creds(conn, grst_chain);
           }
+          
+        GRSTx509ChainFree(grst_chain);
      }
 
    return returned_ok;
@@ -3451,6 +3598,23 @@ static int mod_gridsite_server_post_config(apr_pool_t *pPool,
 
    return OK;
 }
+
+static server_rec *mod_gridsite_log_func_server;
+static void mod_gridsite_log_func(char *file, int line, int level,
+                                                    char *fmt, ...)
+{
+   char *mesg;
+   va_list ap;
+
+   va_start(ap, fmt);
+   vasprintf(&mesg, fmt, ap);
+   va_end(ap);
+
+   ap_log_error(file, line, level, 
+                0, mod_gridsite_log_func_server, "%s", mesg);
+   
+   free(mesg);
+}
       
 static void mod_gridsite_child_init(apr_pool_t *pPool, server_rec *pServer)
 {
@@ -3461,6 +3625,8 @@ static void mod_gridsite_child_init(apr_pool_t *pPool, server_rec *pServer)
    SSLSrvConfigRec *sc = ap_get_module_config(pServer->module_config, 
                                                         &ssl_module);          
    GRSTgaclInit();
+   mod_gridsite_log_func_server = pServer;
+   GRSTerrorLogFunc = mod_gridsite_log_func;
 
    /* expire old ssl creds files */
                                     
@@ -3552,7 +3718,7 @@ static void register_hooks(apr_pool_t *p)
 
     ap_hook_fixups(mod_gridsite_first_fixups,NULL,NULL,APR_HOOK_FIRST);
     
-    ap_hook_fixups(mod_gridsite_perm_handler,NULL,NULL,APR_HOOK_REALLY_LAST);
+    ap_hook_fixups(mod_gridsite_perm_handler,NULL,NULL,APR_HOOK_LAST);
     
     ap_hook_handler(mod_gridsite_handler, NULL, NULL, APR_HOOK_FIRST);