Sync
authorAndrew McNab <andrew.mcnab@manchester.ac.uk>
Tue, 5 Sep 2006 22:53:19 +0000 (22:53 +0000)
committerAndrew McNab <andrew.mcnab@manchester.ac.uk>
Tue, 5 Sep 2006 22:53:19 +0000 (22:53 +0000)
org.gridsite.core/CHANGES
org.gridsite.core/VERSION
org.gridsite.core/interface/gridsite.h
org.gridsite.core/project/version.properties
org.gridsite.core/src/Makefile
org.gridsite.core/src/grst_err.c
org.gridsite.core/src/grst_x509.c
org.gridsite.core/src/htproxyput.c
org.gridsite.core/src/mod_gridsite.c

index 89892bd..6e48ce5 100644 (file)
@@ -1,3 +1,6 @@
+* Mon Jul 17 2006 Andrew McNab <Andrew.McNab@man.ac.uk>
+- Add Shibboleth handling from Joseph Dada's branch to
+  mod_gridsite in main GridSite tree.
 * Tue Jun 27 2006 Andrew McNab <Andrew.McNab@man.ac.uk>
 - Merge delegation services back into core.
 - Add OCSP options
index 721f6a3..1800f41 100644 (file)
@@ -1,4 +1,4 @@
 MAJOR_VERSION=1
 MINOR_VERSION=1.3
-PATCH_VERSION=1.3.1
+PATCH_VERSION=1.3.2
 VERSION=$(PATCH_VERSION)
index 014d5bf..ab150b1 100644 (file)
@@ -143,7 +143,7 @@ struct GRSTasn1TagList { char treecoords[GRST_ASN1_MAXCOORDLEN+1];
                          int  tag; } ;
 
 typedef struct { int    type;          /* CA, user, proxy, VOMS, ... */
-                 int    status;                /* unchecked, bad sig, bad time */
+                 int    errors;                /* unchecked, bad sig, bad time */
                  char   *ca;           /* Cert CA DN, or VOMS issuer CA */
                  char   *dn;           /* Cert DN, or VOMS issuer DN */
                  char   *value;                /* VOMS FQAN or NULL */
@@ -154,10 +154,22 @@ typedef struct { int    type;             /* CA, user, proxy, VOMS, ... */
                  void   *raw;          /* X509 or VOMS Extension object */
                  void   *next; } GRSTx509Cert;
 
+#define GRST_CERT_BAD_FORMAT 1
+#define GRST_CERT_BAD_CHAIN  2
+#define GRST_CERT_BAD_SIG    4
+#define GRST_CERT_BAD_TIME   8
+#define GRST_CERT_BAD_OCSP  16
+
+#define GRST_CERT_TYPE_CA    1
+#define GRST_CERT_TYPE_EEC   2
+#define GRST_CERT_TYPE_PROXY 3
+#define GRST_CERT_TYPE_VOMS  4
+
+/* a chain of certs, starting from the first CA */
 typedef struct { GRSTx509Cert *firstcert; } GRSTx509Chain;
 
 int GRSTx509CertLoad(GRSTx509Cert *, X509 *);
-int GRSTx509ChainLoad(GRSTx509Chain *, STACK_OF(X509) *, X509 *);
+int GRSTx509ChainLoadCheck(GRSTx509Chain **, STACK_OF(X509) *, X509 *, char *);
 int GRSTx509ChainFree(GRSTx509Chain *);
 
 #define GRST_HTTP_PORT         777
index 83e3d4d..c145572 100644 (file)
@@ -173,27 +173,27 @@ gsexec:   gsexec.c gsexec.h
        gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
            -o gsexec gsexec.c
 
-urlencode: urlencode.c libgridsite.a
+urlencode: urlencode.c libgridsite.so.$(VERSION)
        gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
             -o urlencode urlencode.c -L. \
             -I/usr/kerberos/include \
             -lgridsite
 
-htcp: htcp.c libgridsite.a
+htcp: htcp.c libgridsite.so.$(VERSION)
        gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
            -o htcp htcp.c -L. \
            -I/usr/kerberos/include \
             `curl-config --cflags` `curl-config --libs` \
             -lgridsite
 
-gridsite-copy.cgi: gridsite-copy.c libgridsite.a
+gridsite-copy.cgi: gridsite-copy.c libgridsite.so.$(VERSION)
        gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
            -o gridsite-copy.cgi gridsite-copy.c -L. \
            -I/usr/kerberos/include \
             `curl-config --cflags` `curl-config --libs` \
             -lgridsite
 
-mod_gridsite.so: mod_gridsite.c mod_ssl-private.h libgridsite.a
+mod_gridsite.so: mod_gridsite.c mod_ssl-private.h libgridsite.so.$(VERSION)
        gcc -g $(MYCFLAGS) -shared -Wl,-soname=gridsite_module \
            -I/usr/kerberos/include \
            -I/usr/include/libxml2 \
@@ -209,13 +209,13 @@ real-gridsite-admin.cgi: grst_admin_main.c grst_admin_gacl.c \
             -I/usr/kerberos/include \
             -DVERSION=\"$(VERSION)\" -lgridsite -lssl -lcrypto -lxml2 -lz -lm
 
-findproxyfile: findproxyfile.c libgridsite.a
+findproxyfile: findproxyfile.c libgridsite.so.$(VERSION)
        gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) $(MYLDFLAGS) \
             -o findproxyfile findproxyfile.c -L. \
             -I/usr/kerberos/include -lgridsite \
             -lssl -lcrypto -lxml2 -lz -lm
 
-showx509exts: showx509exts.c libgridsite.a
+showx509exts: showx509exts.c libgridsite.so.$(VERSION)
        gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) $(MYLDFLAGS) \
             -o showx509exts showx509exts.c -L. \
             -I/usr/kerberos/include \
@@ -271,25 +271,26 @@ endif
 DelegationService.wsdl: delegation.h
        $(GSOAPDIR)/bin/soapcpp2 -c delegation.h
 
-gridsite-delegation.cgi: grst-delegation.c delegation.h DelegationService.wsdl
+gridsite-delegation.cgi: grst-delegation.c delegation.h \
+                         DelegationService.wsdl libgridsite.so.$(VERSION)
        gcc -g $(MYCFLAGS) $(MYLDFLAGS) -o gridsite-delegation.cgi \
             grst-delegation.c \
             -I/usr/kerberos/include -I. -I$(GSOAPDIR)/include \
             -I$(GRIDSITEDIR)/include \
-            -DVERSION=\"$(VERSION)\" -L$(GSOAPDIR)/lib \
+            -DVERSION=\"$(VERSION)\" -L. -L$(GSOAPDIR)/lib \
             -L$(GRIDSITEDIR)/lib \
             soapC.c soapServer.c -lgsoap \
             -lgridsite -lcurl -lz -lssl -lcrypto -lxml2 -lm
 
-htproxyput: htproxyput.c delegation.h DelegationService.wsdl
+htproxyput: htproxyput.c delegation.h DelegationService.wsdl libgridsite.so.$(VERSION)
        gcc -g $(MYCFLAGS) $(MYLDFLAGS) -o htproxyput \
             htproxyput.c \
             -I/usr/kerberos/include -I. \
             -g -DVERSION=\"$(VERSION)\" \
             -I$(GSOAPDIR)/include \
             -I$(GRIDSITEDIR)/include \
-            -DWITH_OPENSSL -L$(GSOAPDIR)/lib \
-            $(STDSOAP2) -L$(GRIDSITEDIR)/lib \
+            -DWITH_OPENSSL -L. -L$(GSOAPDIR)/lib \
+            $(STDSOAP2) \
             soapC.c soapClient.c -lgsoapssl \
             -lgridsite -lcurl -lz -lssl -lcrypto -lxml2 -lm
         
index 5c541b5..8d1e2cb 100644 (file)
@@ -37,7 +37,5 @@
 
 #include "gridsite.h"
 
-/* Little piece of GRSTerror in GRSTgacl */
-
 void (*GRSTerrorLogFunc)(char *, int, int, char *, ...) = NULL;
 
index fe2905a..c93564e 100644 (file)
@@ -161,6 +161,177 @@ int GRSTx509IsCA(X509 *cert)
    else return GRST_RET_FAILED;
 }   
 
+int GRSTx509ChainFree(GRSTx509Chain *chain)
+{
+   GRSTx509Cert *grst_cert;
+
+   if (chain == NULL) return GRST_RET_OK;
+   
+// delete the various stuff in the chain members....      
+
+   return GRST_RET_OK;
+}
+
+/// 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)
+{
+   X509 *cert;                  /* Points to the current cert in the loop */
+   int depth = 0;               /* Depth of cert chain */
+   int chain_errors = 0;       /* records previous errors */
+   int first_non_ca;
+   size_t len,len2;             /* Lengths of issuer and cert DN */
+   int IsCA;                    /* Holds whether cert is allowed to sign */
+   int prevIsCA;                /* Holds whether previous cert in chain is 
+                                   allowed to sign */
+   int prevIsLimited;          /* previous cert was proxy and limited */
+   int i,j;                     /* Iteration variables */
+   char *cert_DN;               /* Pointer to current-certificate-in-chain's 
+                                   DN */
+   char *issuer_DN;             /* Pointer to 
+                                   issuer-of-current-cert-in-chain's DN */
+   char *proxy_part_DN;         /* Pointer to end part of current-cert-in-chain
+                                   maybe eg "/CN=proxy" */
+   time_t now;
+   GRSTx509Cert *grst_cert, *new_grst_cert;
+   
+   GRSTerrorLog(GRST_LOG_DEBUG, "GRSTx509ChainLoadCheck() starts");
+printf("GRSTx509ChainLoadCheck() starts");
+
+   time(&now);
+
+   first_non_ca = 0; /* set to something predictable if things fail */
+   /* Set necessary preliminary values */
+   IsCA          = TRUE;           /* =prevIsCA - start from a CA */
+   prevIsLimited = 0;
+
+   /* Get the client cert chain */
+   if (certstack != NULL) 
+     depth = sk_X509_num(certstack); /* How deep is that chain? */
+   
+printf("depth=%d\n", depth);
+
+   if ((depth == 0) && (lastcert == NULL)) 
+     {
+       *chain = NULL;
+       return GRST_RET_FAILED;
+     }
+
+   *chain = malloc(sizeof(GRSTx509Chain));
+   bzero(*chain, sizeof(GRSTx509Chain));
+       
+   /* Check the client chain */
+   for (i = depth - 1; i >= (lastcert == NULL) ? 0 : -1; --i) 
+      /* loop through client-presented chain starting at CA end */
+      {
+        prevIsCA=IsCA;
+
+        new_grst_cert = malloc(sizeof(GRSTx509Cert));
+        bzero(new_grst_cert, sizeof(GRSTx509Cert));
+        new_grst_cert->errors = chain_errors;
+        
+        if (i == depth - 1) (*chain)->firstcert = new_grst_cert;
+        else grst_cert->next = new_grst_cert;
+
+        /* Check for X509 certificate and point to it with 'cert' */
+        if (i < 0) cert = lastcert;
+        else cert = sk_X509_value(certstack, i);
+
+        if (cert != NULL)
+          {
+            /* we check times and record if invalid */
+          
+            if (now <
+           GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(cert)),0))
+                new_grst_cert->errors |= GRST_CERT_BAD_TIME;
+                
+            if (now > 
+           GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(cert)),0))
+                new_grst_cert->errors |= GRST_CERT_BAD_TIME;
+
+            /* If any forebear certificate is not allowed to sign we must 
+               assume all decendents are proxies and cannot sign either */
+            if (prevIsCA)
+              {
+                /* always treat the first cert (from the CA files) as a CA */
+                if (i == depth - 1) IsCA = TRUE;
+                /* check if this cert is valid CA for signing certs */
+                else IsCA = (GRSTx509IsCA(cert) == GRST_RET_OK);
+                
+                if (!IsCA) first_non_ca = i;
+              } 
+            else 
+              {
+                IsCA = FALSE; 
+                /* Force proxy check next iteration. Important because I can
+                   sign any CA I create! */
+              }
+            cert_DN   = X509_NAME_oneline(X509_get_subject_name(cert),NULL,0);
+            issuer_DN = X509_NAME_oneline(X509_get_issuer_name(cert),NULL,0);
+            len       = strlen(cert_DN);
+            len2      = strlen(issuer_DN);
+
+            if (!prevIsCA)
+              {
+                /* issuer didn't have CA status, so this is (at best) a proxy:
+                   check for bad proxy extension*/
+
+                if (prevIsLimited) /* we reject proxies of limited proxies! */
+                  {
+                    new_grst_cert->errors  |= GRST_CERT_BAD_CHAIN;
+                    chain_errors |= GRST_CERT_BAD_CHAIN;
+                  }
+              
+                /* User not allowed to sign shortened DN */
+                if (len2 > len) 
+                  {
+                    new_grst_cert->errors  |= GRST_CERT_BAD_CHAIN;
+                    chain_errors |= GRST_CERT_BAD_CHAIN;
+                  }
+                  
+                /* Proxy subject must begin with issuer. */
+                if (strncmp(cert_DN, issuer_DN, len2) != 0) 
+                  {
+                    new_grst_cert->errors  |= GRST_CERT_BAD_CHAIN;
+                    chain_errors |= GRST_CERT_BAD_CHAIN;
+                  }
+
+                /* Set pointer to end of base DN in cert_DN */
+                proxy_part_DN = &cert_DN[len2];
+
+                /* First attempt at support for Old and New style GSI
+                   proxies: /CN=anything is ok for now */
+                if (strncmp(proxy_part_DN, "/CN=", 4) != 0)
+                  {
+                    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 ... */
+              } 
+          }
+      }
+
+   return GRST_RET_OK; /* this is also GRST_RET_OK, of course - by choice */
+}
+
 /// Check certificate chain for GSI proxy acceptability.
 /**
  *  Returns X509_V_OK/GRST_RET_OK if valid; OpenSSL X509 errors otherwise.
index d1f0d87..b6dd179 100644 (file)
@@ -73,6 +73,7 @@ http://www.gridpp.ac.uk/authz/gridsite/
 #define HTPROXY_TIME           3
 #define HTPROXY_UNIXTIME       4
 #define HTPROXY_MAKE           5
+#define HTPROXY_INFO           6
 
 void printsyntax(char *argv0)
 {
@@ -85,6 +86,20 @@ void printsyntax(char *argv0)
   fprintf(stderr, "%s [options] URL\n"
           "(Version: %s)\n", p, VERSION);
 }
+
+void htproxy_logfunc(char *file, int line, int level, char *fmt, ...)
+{
+  char *mesg;
+  va_list ap;
+
+  va_start(ap, fmt);
+  vasprintf(&mesg, fmt, ap);
+  va_end(ap);
+
+  fprintf(stderr, "%s(%d) %s\n", file, line, mesg);
+
+  free(mesg);
+}
   
 int main(int argc, char *argv[])
 {
@@ -93,7 +108,7 @@ int main(int argc, char *argv[])
         *executable, *keytxt, *proxychain, *ptr;
   struct ns__putProxyResponse *unused;
   struct tm *finish_tm;
-  int    option_index, c, noverify = 0, i, 
+  int    option_index, c, noverify = 0, i, ret,
          method = HTPROXY_PUT, verbose = 0, fd, minutes;
   struct soap soap_get, soap_put;
   struct ns__getProxyReqResponse        getProxyReqResponse;
@@ -105,6 +120,8 @@ int main(int argc, char *argv[])
   STACK_OF(X509) *x509_certstack;
   X509   *x509_cert;
   BIO    *certmem;
+  GRSTx509Chain *grst_chain = NULL;
+  GRSTx509Cert  *grst_cert = NULL;
   long   ptrlen;
   struct stat statbuf;
   struct passwd *userpasswd; 
@@ -121,6 +138,7 @@ int main(int argc, char *argv[])
                                         {"renew",       0, 0, 0},
                                         {"unixtime",   0, 0, 0},
                                         {"make",       0, 0, 0},
+                                        {"info",       0, 0, 0},
                                         {0, 0, 0, 0}  };
 
   if (argc == 1)
@@ -150,8 +168,13 @@ int main(int argc, char *argv[])
              else if (option_index == 10) method          = HTPROXY_RENEW;
              else if (option_index == 11) method          = HTPROXY_UNIXTIME;
              else if (option_index == 12) method          = HTPROXY_MAKE;
+             else if (option_index == 13) method          = HTPROXY_INFO;
            }
-         else if (c == 'v') ++verbose;
+         else if (c == 'v') 
+                {
+                  GRSTerrorLogFunc = htproxy_logfunc;
+                  ++verbose;
+                }
        }
 
   executable = rindex(argv[0], '/');
@@ -164,8 +187,10 @@ int main(int argc, char *argv[])
   else if (strcmp(executable, "htproxyunixtime") == 0) 
                                                     method = HTPROXY_UNIXTIME;
   else if (strcmp(executable, "htproxymake") == 0)  method = HTPROXY_MAKE;
+  else if (strcmp(executable, "htproxyinfo") == 0)  method = HTPROXY_INFO;
 
-  if ((method != HTPROXY_MAKE) && (optind + 1 != argc))
+  if ((method != HTPROXY_MAKE) && 
+      (method != HTPROXY_INFO) && (optind + 1 != argc))
     {
       fprintf(stderr, "Must specify a delegation service URL!\n");
       return 1;
@@ -201,7 +226,7 @@ int main(int argc, char *argv[])
              expiry too to avoid suprises when we try to use it ... */
 
           if (stat(cert, &statbuf) == 0) key = cert;
-          else
+          else if (method != HTPROXY_INFO)
             {
               cert = getenv("X509_USER_CERT");
               key  = getenv("X509_USER_KEY");
@@ -230,7 +255,8 @@ int main(int argc, char *argv[])
   if (verbose) fprintf(stderr, "key=%s\ncert=%s\ncapath=%s\n",
                        key, cert, capath);
 
-  if (strcmp(key, cert) != 0) /* we have to concatenate for gSOAP */
+  if ((key != NULL) && (cert != NULL) &&
+      (strcmp(key, cert) != 0)) /* we have to concatenate for gSOAP */
     {
       keycert = strdup("/tmp/.XXXXXX");
         
@@ -490,7 +516,91 @@ int main(int argc, char *argv[])
       
       return 0;
     }
+  else if (method == HTPROXY_INFO)
+    {
+      if (cert != NULL) 
+        {
+          if (verbose) fprintf(stderr, "Getting proxy info from %s\n", cert);
+    
+          ifp = fopen(cert, "r");
+          if (ifp == NULL)
+            {
+              fprintf(stderr, "Failed to open proxy file\n");
+              return 2;              
+            }
+        }
+      else  
+        {
+          if (verbose) fprintf(stderr, "Getting proxy info from stdin\n");
+          ifp = stdin;
+        }
+      
+      ptrlen = 4096;
+      ptr = malloc(ptrlen);
+      i = 0;
+      
+      while ((c = fgetc(ifp)) != EOF)
+           {
+             ptr[i] = c;
+             ++i;
+             
+             if (i >= ptrlen) 
+               {
+                 ptrlen += 4096;
+                 ptr = realloc(ptr, ptrlen);
+               }
+           }
+           
+      ptr[i] = '\0';
+      if (cert != NULL) fclose(ifp);
+      
+      if ((GRSTx509StringToChain(&x509_certstack, ptr) != GRST_RET_OK) ||
+          (x509_certstack == NULL))
+        {
+          fprintf(stderr, "Failed to parse proxy file for certificate chain\n");
+          free(ptr);
+          return 2;
+        }
+        
+// fprintf(stderr, "%s\n", ptr);
 
+      free(ptr);
+
+      if (verbose) fprintf(stderr, "Parsing certificate chain\n");
+      
+      ret = GRSTx509ChainLoadCheck(&grst_chain, x509_certstack, NULL, capath);
+      
+      if ((ret != GRST_RET_OK) || 
+          (grst_chain == NULL) || (grst_chain->firstcert == NULL))
+        {
+          fprintf(stderr, "Failed parsing certificate chain\n");
+          return 3;
+        }
+      
+      grst_cert = grst_chain->firstcert;
+
+// printf("%lu\n", grst_cert);
+// printf("%lu\n", grst_cert->type);
+// printf("%lu\n", grst_cert->dn);
+// printf("%lu\n", grst_cert->next);
+       
+// printf("before for\n");      
+      for (i=0; 
+      grst_cert != NULL; 
+      grst_cert = grst_cert->next)
+         {
+// printf("inside for %i\n", grst_cert == NULL);         
+
+           printf("%d %d %s\n", i, grst_cert->type, grst_cert->dn);
+           printf("%lu\n", grst_cert->next);
+
+           grst_cert = grst_cert->next;
+           ++i;             
+         }
+      
+
+      GRSTx509ChainFree(grst_chain);
+    }
   /* weirdness */
 }
 
index 1f32160..449e0db 100644 (file)
@@ -1,6 +1,6 @@
 /*
-   Copyright (c) 2003-6, Andrew McNab and Shiv Kaushal, 
-   University of Manchester. All rights reserved.
+   Copyright (c) 2003-6, 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
    without modification, are permitted provided that the following
@@ -2072,6 +2072,19 @@ static const command_rec mod_gridsite_cmds[] =
     {NULL}
 };
 
+/*  Blank unset these HTTP headers, to prevent injection attacks.
+    This is run before mod_shib's check_user_id hook, which may
+    legitimately create such headers.                           */
+
+static int mod_gridsite_check_user_id(request_rec *r)
+{
+    ap_table_unset(r->headers_in, "User-Distinguished-Name");
+    ap_table_unset(r->headers_in, "Nist-LoA");
+    ap_table_unset(r->headers_in, "VOMS-Attribute");
+
+    return DECLINED; /* ie carry on processing request */
+}
+
 static int mod_gridsite_first_fixups(request_rec *r)
 {
     mod_gridsite_dir_cfg *conf;
@@ -2289,6 +2302,7 @@ static int mod_gridsite_perm_handler(request_rec *r)
                 *gridauthpasscode = NULL, *cookiefile, oneline[1025], *key_i,
                 *destination = NULL, *destination_uri = NULL, *querytmp, 
                 *destination_prefix = NULL, *destination_translated = NULL;
+    char        *vomsAttribute, *loa;
     const char  *content_type;
     time_t       now, notbefore, notafter;
     apr_table_t *env;
@@ -2314,6 +2328,49 @@ static int mod_gridsite_perm_handler(request_rec *r)
                return DECLINED; /* if not turned on, look invisible */
 
     env = r->subprocess_env;
+    
+    /* Get the user's attributes from Shibboleth and set up user credential
+       based on the attributes if authentication has been carried out using
+       a Shibboleth Identity Provider.*/
+
+    /* Get DN from a Shibboleth attribute */
+    if (vomsAttribute == NULL)
+      {
+        dn = (char *) apr_table_get(r->headers_in, "User-Distinguished-Name");
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "DN: %s", dn);
+      }                                            
+#if 0                                                                    
+    /* Get the NIST LoA attribute */
+    loa = (char *) apr_table_get(r->headers_in, "nist-loa");
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Nist-LoA: %d", loa);
+#endif
+    /* Set up user credential based on the DN and LoA attributes */
+                                  
+    if (dn != NULL)
+      {
+        cred = GRSTgaclCredNew("person");
+        GRSTgaclCredAddValue(cred, "dn", dn);
+        user = GRSTgaclUserNew(cred);
+        cred = GRSTgaclCredNew("level");
+#if 0
+        GRSTgaclCredAddValue(cred, "nist-loa", loa);
+#endif
+        GRSTgaclCredAddValue(cred, "nist-loa", "2"); /* hardcoded for now */
+        GRSTgaclUserAddCred(user, cred);
+      }
+
+    vomsAttribute = (char *) apr_table_get(r->headers_in, "VOMS-Attribute");
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, 
+                 "VOMS-Attribute: %s", vomsAttribute);
+            
+    /* Set up user credential based on VOMS Attribute */
+    if (vomsAttribute != NULL)
+      {
+        cred = GRSTgaclCredNew("voms");
+        GRSTgaclCredAddValue(cred, "fqan", vomsAttribute);
+        if (user == NULL) user = GRSTgaclUserNew(cred);
+        else GRSTgaclUserAddCred(user, cred);
+      }
 
     p = (char *) apr_table_get(r->subprocess_env, "HTTPS");
     if ((p != NULL) && (strcmp(p, "on") == 0)) ishttps = 1;
@@ -3349,6 +3406,9 @@ static void register_hooks(apr_pool_t *p)
     ap_hook_post_config(mod_gridsite_server_post_config, NULL, NULL, 
                                                               APR_HOOK_LAST);
     ap_hook_child_init(mod_gridsite_child_init, NULL, NULL, APR_HOOK_MIDDLE);
+    
+    ap_hook_check_user_id(mod_gridsite_check_user_id, NULL, NULL, 
+                                                      APR_HOOK_REALLY_FIRST);
 
     ap_hook_fixups(mod_gridsite_first_fixups,NULL,NULL,APR_HOOK_FIRST);