More VOMS merging
authorAndrew McNab <andrew.mcnab@manchester.ac.uk>
Mon, 24 Apr 2006 21:53:02 +0000 (21:53 +0000)
committerAndrew McNab <andrew.mcnab@manchester.ac.uk>
Mon, 24 Apr 2006 21:53:02 +0000 (21:53 +0000)
org.gridsite.core/CHANGES
org.gridsite.core/VERSION
org.gridsite.core/doc/mod_gridsite.8
org.gridsite.core/interface/gridsite.h
org.gridsite.core/project/configure.properties.xml
org.gridsite.core/project/version.properties
org.gridsite.core/src/Makefile
org.gridsite.core/src/grst_admin_gacl.c
org.gridsite.core/src/grst_x509.c
org.gridsite.core/src/mod_gridsite.c

index 606171f..b91fa74 100644 (file)
@@ -1,3 +1,12 @@
+* Mon Apr 24 2006 Andrew McNab <Andrew.McNab@man.ac.uk>
+- Reworked SSL session caching: passcodes directory now
+  because /var/www/sessions by default, and also used
+  to cache credentials according to SSL Session ID.
+- Patch from Alberto di Meglio <alberto.di.meglio@cern.ch>
+  to allow use of relocated httpd include files.
+- Use dist for building tar balls
+* Mon Apr 24 2006 Andrew McNab <Andrew.McNab@man.ac.uk>
+- ==== GridSite version 1.1.18.1 ====
 * Fri Mar 31 2006 Andrew McNab <Andrew.McNab@man.ac.uk>
 - Final tidy up for gLite 3.1
 * Fri Mar 31 2006 Andrew McNab <Andrew.McNab@man.ac.uk>
index 0b56d61..788cbe5 100644 (file)
@@ -1,4 +1,4 @@
 MAJOR_VERSION=1
 MINOR_VERSION=1.1
-PATCH_VERSION=1.1.18
+PATCH_VERSION=1.1.18.1
 VERSION=$(PATCH_VERSION)
index 1577633..cfbea3f 100644 (file)
@@ -171,10 +171,12 @@ Sets the port to use for the unencrypted HTTP component of GridHTTP
 HTTPS->HTTP transfers. The same setting will be used for all virtual hosts
 which support GridHTTP. (Default: 777)
 
-.IP "GridSiteOnetimesDir path"
-Location of authentication cookies directory, relative to ServerRoot.
-Used by GridHTTP to record the credentials obtained via HTTPS,
-and available to the corresponding HTTP request. (Default: /var/www/onetimes)
+.IP "GridSiteSessionsDir path"
+Location of authentication cookies and SSL session credentials directory,
+relative to ServerRoot. Used by GridHTTP to record the credentials obtained
+via HTTPS, and available to the corresponding HTTP request or subsequent
+HTTPS requests following a session restart.
+(Default: /var/www/sessions)
 
 .IP "GridSiteACLFormat GACL|XACML"
 Format to use when writing .gacl files. (Both formats are automatically
index caa3a14..d9473a8 100644 (file)
@@ -289,11 +289,8 @@ char *GRSTx509CachedProxyFind(char *, char *, char *);
 char *GRSTx509FindProxyFileName(void);
 int GRSTx509MakeProxyCert(char **, FILE *, char *, char *, char *, int);
 char *GRSTx509CachedProxyKeyFind(char *, char *, char *);
-int GRSTx509ProxyDestroy(char *, char *, char *);
-int GRSTx509ProxyGetTimes(char *, char *, char *, time_t *, time_t *);
 int GRSTx509MakeProxyRequest(char **, char *, char *, char *);
 int GRSTx509StringToChain(STACK_OF(X509) **, char *);
-char *GRSTx509MakeDelegationID(void);
 char *GRSTx509MakeProxyFileName(char *, STACK_OF(X509) *);
 int GRSTx509CacheProxy(char *, char *, char *, char *);
 
index 1ce854c..8baac92 100644 (file)
@@ -4,6 +4,6 @@
 
        <project name="configure options">
         <property name="build.make.arguments"
-               value="prefix=${stage.abs.dir} GSOAPDIR=${ext.gsoap.subdir} OPENSSL_GLOBUS_FLAGS=-I${with.globus.prefix}/include/${with.globus.dbg.nothr.flavor} OPENSSL_GLOBUS_LIBS=-L${with.globus.prefix}/lib/ FLAVOR_GLOBUS_EXT=_${with.globus.dbg.nothr.flavor} HTTPD_FLAGS=-I${with.httpd.prefix}/include/httpd"/>
+               value='prefix=${stage.abs.dir} GSOAPDIR=${ext.gsoap.subdir} OPENSSL_GLOBUS_FLAGS=-I${with.globus.prefix}/include/${with.globus.dbg.nothr.flavor} OPENSSL_GLOBUS_LIBS=-L${with.globus.prefix}/lib/ FLAVOR_GLOBUS_EXT=_${with.globus.dbg.nothr.flavor} HTTPD_FLAGS="-I${with.httpd.prefix:-/usr}/include/httpd"' />
        </project>
 
index b451378..47a93a3 100644 (file)
@@ -1,2 +1,2 @@
-module.version=1.1.18
-module.age=1_etics
+module.version=1.1.18.1
+module.age=1
index 2247b23..2109007 100644 (file)
@@ -1,6 +1,6 @@
 #
 #   Andrew McNab and Shiv Kaushal, University of Manchester.
-#   Copyright (c) 2002-5. All rights reserved.
+#   Copyright (c) 2002-6. All rights reserved.
 #
 #   Redistribution and use in source and binary forms, with or
 #   without modification, are permitted provided that the following
@@ -44,12 +44,8 @@ ifndef prefix
 export prefix=/usr/local
 endif
 
-ifndef HTTPD_FLAGS
-export HTTPD_FLAGS=-I/usr/include/httpd
-endif
-
 ifndef MYCFLAGS
-export MYCFLAGS=-I. -I../interface $(HTTPD_FLAGS) -I/usr/include/apr-0 -I/opt/glite/include -fPIC
+export MYCFLAGS=-I. -I../interface $(HTTPD_FLAGS) -I/usr/include/httpd -I/usr/include/apr-0 -I/opt/glite/include -fPIC
 endif
 
 ifndef MYLDFLAGS
@@ -206,6 +202,7 @@ showx509exts: showx509exts.c libgridsite.a
             -lssl -lcrypto -lxml2 -lz -lm
  
 apidoc:
+       date
        doxygen Doxyfile
        mkdir -p ../doc/doxygen
        cp -f doxygen/*.html doxygen/*.css doxygen/*.png ../doc/doxygen
@@ -285,25 +282,25 @@ install: apidoc
 
 # source files tarball
 dist:
-       mkdir -p ../gridsite-$(PATCH_VERSION)/src \
-                 ../gridsite-$(PATCH_VERSION)/doc \
-                 ../gridsite-$(PATCH_VERSION)/interface
+       mkdir -p ../dist/gridsite-$(PATCH_VERSION)/src \
+                 ../dist/gridsite-$(PATCH_VERSION)/doc \
+                 ../dist/gridsite-$(PATCH_VERSION)/interface
        cp -f ../VERSION ../README ../LICENSE ../CHANGES ../INSTALL \
-                 ../gridsite-$(PATCH_VERSION)
+                 ../dist/gridsite-$(PATCH_VERSION)
        cp -f Makefile grst*.c htcp.c \
                  urlencode.c findproxyfile.c gaclexample.c mod_gridsite.c \
                  grst_admin.h mod_ssl-private.h \
                  gsexec.c gsexec.h gridsite-copy.c \
                  roffit gridsite.spec \
                  Doxyfile doxygen.css doxyheader.html \
-                 ../gridsite-$(PATCH_VERSION)/src
+                 ../dist/gridsite-$(PATCH_VERSION)/src
        cp -f ../doc/*.html ../doc/*.1 ../doc/*.8 ../doc/*.conf ../doc/*.sh \
-              ../doc/*.wsdl ../gridsite-$(PATCH_VERSION)/doc
+              ../doc/*.wsdl ../dist/gridsite-$(PATCH_VERSION)/doc
        cp -f ../interface/*.h \
-                 ../gridsite-$(PATCH_VERSION)/interface
-       cd .. ; tar zcvf gridsite-$(PATCH_VERSION).src.tar.gz \
+                 ../dist/gridsite-$(PATCH_VERSION)/interface
+       cd ../dist ; tar zcvf ../gridsite-$(PATCH_VERSION).src.tar.gz \
                  gridsite-$(PATCH_VERSION)
-       rm -Rf ../gridsite-$(PATCH_VERSION)
+       rm -Rf ../dist/gridsite-$(PATCH_VERSION)
 
 
 # binary tarball distribution for htcp users
index 2cb517a..bdcccbd 100644 (file)
@@ -188,8 +188,9 @@ void new_entry_form(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm,char *help_u
   GRSTgaclEntry *entry;
   GRSTgaclNamevalue* namevalue;
 
-  if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
 
+  if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+  entry = GRSTgaclEntryNew(); 
   StartHTML(&bp, dir_uri, dir_path);
   StartForm(&bp, dir_uri, dir_path, admin_file, timestamp, "new_entry");
   GRSThttpPrintf (&bp, "<font size=\"4\"><b>NEW ENTRY IN ACL FOR %s </b></font></p>\n", dir_uri);
@@ -831,7 +832,7 @@ void GRSTgaclCredTableEnd(GRSTgaclEntry* entry, int entry_no, int admin, int tim
 
   if (strcmp(cmd, "add_cred_form")==0 ||strcmp(cmd, "del_cred_sure")==0) show_perms=0; else show_perms=1;
   if (strcmp(cmd, "edit_entry_form")==0 || strcmp(cmd, "new_entry_form")==0) edit_perms=1; else edit_perms=0;
-  if (strcmp(cmd, "new_entry_form")==0) blank_perms=1; else blank_perms=0;
+  if (strcmp(cmd, "new_entry_form")==0)  blank_perms=1; else blank_perms=0;
 
   // If showing the last row is not required then exit
   if (show_perms==0){GRSThttpPrintf (bp,"</table><br>\n"); return;}
@@ -842,7 +843,7 @@ void GRSTgaclCredTableEnd(GRSTgaclEntry* entry, int entry_no, int admin, int tim
 
   GRSThttpPrintf (bp, "</td>\n<td>&nbsp;</td><td align=left>");
 
-  if (blank_permsentry->allowed=entry->denied=GRST_PERM_NONE;
+  if (blank_perms==1)entry->allowed=entry->denied=GRST_PERM_NONE;
 
   // Show Permissions - will produce a list or a list of check boxes depending on whether the permissions are to be edited or not
   GRSThttpPrintf (bp, "<b>Allowed:</b>  ");
index a41f248..71ab3fd 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2002-6, Andrew McNab, University of Manchester
+   Copyright (c) 2002-5, Andrew McNab, University of Manchester
    All rights reserved.
 
    Redistribution and use in source and binary forms, with or
@@ -38,7 +38,6 @@
 #include <stdio.h>
 #include <unistd.h>       
 #include <stdlib.h>
-#include <stdarg.h>
 #include <time.h>
 #include <stdarg.h>
 #include <dirent.h>
@@ -545,7 +544,7 @@ int GRSTx509ParseVomsExt(int *lastcred, int maxcreds, size_t credlen,
         if (actime2 < time2_time) time2_time = actime2;
 
         time(&time_now);
-        if ((time1_time > time_now + 300) || (time2_time < time_now))
+        if ((time1_time > time_now) || (time2_time < time_now)) 
                continue; /* expiration isnt invalidity ...? */
 
         for (i=1; ; ++i)
@@ -583,7 +582,7 @@ int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen,
                          char *creds, X509 *usercert, STACK_OF(X509) *certstack,
                          char *vomsdir)
 {
-   int  i, j, vomsfound=0;
+   int  i, j;
    char s[80];
    unsigned char  *ucuser;
    X509_EXTENSION *ex;
@@ -617,14 +616,11 @@ int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen,
 
            if (strcmp(s, GRST_VOMS_OID) == 0) /* a VOMS extension */
              {
-               vomsfound=1;
                GRSTx509ParseVomsExt(lastcred, maxcreds, credlen, creds,
                                  uctime1_time, uctime2_time,
                                  ex, ucuser, vomsdir);
              }
          }
-
-      if (vomsfound) return GRST_RET_OK;
     }
 
    return GRST_RET_OK;
@@ -814,7 +810,7 @@ static void mpcerror(FILE *debugfp, char *msg)
  */
 
 int GRSTx509MakeProxyCert(char **proxychain, FILE *debugfp, 
-                          char *reqtxt, char *cert, char *key, int minutes)
+                           char *reqtxt, char *cert, char *key, int minutes)
 {
   char *ptr, *certchain;
   int i, subjAltName_pos, ncerts;
@@ -1198,33 +1194,18 @@ char *GRSTx509CachedProxyKeyFind(char *proxydir, char *delegation_id,
   return keyfile;
 }
 
-static void mkdir_printf(mode_t mode, char *fmt, ...)
-{
-  int   ret;
-  char *path;
-  va_list ap;
-  
-  va_start(ap, fmt);
-  vasprintf(&path, fmt, ap);
-  va_end(ap);
-
-  ret = mkdir(path, mode);
-
-  free(path);
-}
-
 /// 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
+ *  is PEM encoded, and the key is stored in proxydir as temporary file
+ *  with a filename like .XXXXXX
  */ 
 
 int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir, 
                              char *delegation_id, char *user_dn)
 {
-  int              i;
-  char            *docroot, *prvkeyfile, *ptr, *user_dn_enc;
+  int              i, fd;
+  char            *docroot, *reqfile, *prvkeyfile, *ptr;
   size_t           ptrlen;
   FILE            *fp;
   RSA             *keypair;
@@ -1233,51 +1214,28 @@ int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir,
   EVP_PKEY        *pkey;
   X509_REQ        *certreq;
   BIO             *reqmem;
-  const EVP_MD    *digest;
+  const EVP_MD          *digest;
   struct stat      statbuf;
 
-  if (strcmp(user_dn, "cache") == 0) return GRST_RET_FAILED;
-    
-  user_dn_enc = GRSThttpUrlEncode(user_dn);
-
-  /* create directories if necessary */
-
-  mkdir_printf(S_IRUSR | S_IWUSR | S_IXUSR, 
-               "%s/cache",       proxydir);
-  mkdir_printf(S_IRUSR | S_IWUSR | S_IXUSR, 
-               "%s/cache/%s",    proxydir, user_dn_enc);
-  mkdir_printf(S_IRUSR | S_IWUSR | S_IXUSR, 
-               "%s/cache/%s/%s", proxydir, user_dn_enc, delegation_id);
-
-  /* make the new proxy private key */
-
-  asprintf(&prvkeyfile, "%s/cache/%s/%s/userkey.pem",
-           proxydir, user_dn_enc, delegation_id);
-
-  if (prvkeyfile == NULL)  
-    {
-      free(user_dn_enc);
-      return GRST_RET_FAILED;
-    }
-        
   if ((keypair = RSA_generate_key(GRST_KEYSIZE, 65537, NULL, NULL)) == NULL)
                                                                return 1;
+  asprintf(&prvkeyfile, "%s/.XXXXXX", proxydir);
           
-  if ((fp = fopen(prvkeyfile, "w")) == NULL) return 2;
-  
-  chmod(prvkeyfile, S_IRUSR | S_IWUSR);
-  free(prvkeyfile);
-  free(user_dn_enc);
-
+  fd = mkstemp(prvkeyfile);
+    
+  if ((fp = fdopen(fd, "w")) == NULL) return 1;
+                               
+  fprintf(fp, "%s\n%s\n", delegation_id, user_dn);
+    
   if (!PEM_write_RSAPrivateKey(fp, keypair, NULL, NULL, 0, NULL, NULL))
-                               return 3;
+                               return 1;
   
-  if (fclose(fp) != 0) return 4;
+  if (fclose(fp) != 0) return 1;
   
   /* now create the certificate request */
 
   certreq = X509_REQ_new();
-  if (certreq == NULL) return 5;
+  if (certreq == NULL) return 1;
 
   OpenSSL_add_all_algorithms();
 
@@ -1310,110 +1268,6 @@ int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir,
   return 0;
 }
 
-/// 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)
-{
-  int              ret = GRST_RET_OK;
-  char            *docroot, *filename, *user_dn_enc;
-
-  if (strcmp(user_dn, "cache") == 0) return GRST_RET_FAILED;
-    
-  user_dn_enc = GRSThttpUrlEncode(user_dn);
-
-  /* private key */
-  
-  asprintf(&filename, "%s/%s/%s/userkey.pem",
-           proxydir, user_dn_enc, delegation_id);
-
-  if (filename == NULL)  
-    {
-      free(user_dn_enc);
-      return GRST_RET_FAILED;
-    }
-
-  if (unlink(filename) != 0) ret = GRST_RET_NO_SUCH_FILE;  
-  free(filename);
-
-  /* cert chain */
-  
-  asprintf(&filename, "%s/%s/%s/usercert.pem",
-           proxydir, user_dn_enc, delegation_id);
-
-  if (filename == NULL)  
-    {
-      free(user_dn_enc);
-      return GRST_RET_FAILED;
-    }
-
-  if (unlink(filename) != 0) ret = GRST_RET_NO_SUCH_FILE;  
-  free(filename);
-
-  /* voms file */
-  
-  asprintf(&filename, "%s/%s/%s/voms.attributes",
-           proxydir, user_dn_enc, delegation_id);
-
-  if (filename == NULL)  
-    {
-      free(user_dn_enc);
-      return GRST_RET_FAILED;
-    }
-
-  unlink(filename);
-  free(filename);
-  
-  return ret;
-}
-
-/// 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)
-{
-  char  *docroot, *filename, *user_dn_enc;
-  FILE  *fp;
-  X509  *cert;
-
-  if (strcmp(user_dn, "cache") == 0) return GRST_RET_FAILED;
-    
-  user_dn_enc = GRSThttpUrlEncode(user_dn);
-
-  /* cert chain */
-  
-  asprintf(&filename, "%s/%s/%s/usercert.pem",
-           proxydir, user_dn_enc, delegation_id);
-           
-  free(user_dn_enc);
-
-  if (filename == NULL) return GRST_RET_FAILED;
-
-  fp = fopen(filename, "r");
-  free(filename);
-  
-  if (fp == NULL) return GRST_RET_NO_SUCH_FILE;
-
-  cert = PEM_read_X509(fp, NULL, NULL, NULL);
-
-  fclose(fp);
-  
-  *start  = GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(cert)),0);
-  *finish = GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(cert)),0);
-
-  X509_free(cert);
-  
-  return GRST_RET_OK;
-}
-
 /// Create a stack of X509 certificate from a PEM-encoded string
 /**
  *  Creates a dynamically allocated stack of X509 certificate objects
@@ -1467,47 +1321,6 @@ int GRSTx509StringToChain(STACK_OF(X509) **certstack, char *certstring)
    return GRST_RET_OK;
 }
 
-/// 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)
-{ 
-  unsigned char hash_delegation_id[EVP_MAX_MD_SIZE];        
-  int  size_needed = 0, i, delegation_id_len;
-  char cred_name[14], *cred_value, *delegation_id;
-  const EVP_MD *m;
-  EVP_MD_CTX ctx;
-
-  OpenSSL_add_all_digests();
-
-  m = EVP_sha1();
-  if (m == NULL) return NULL;
-
-  EVP_DigestInit(&ctx, m);
-
-  for (i=0; i <= 999; ++i)
-     {
-       snprintf(cred_name, sizeof(cred_name), "GRST_CRED_%d", i);       
-       if ((cred_value = getenv(cred_name)) == NULL) break;
-       
-       EVP_DigestUpdate(&ctx, cred_value, strlen(cred_value));
-     }
-     
-  EVP_DigestFinal(&ctx, hash_delegation_id, &delegation_id_len);
-
-  delegation_id = malloc(17);
-
-  for (i=0; i <=7; ++i)
-   sprintf(&delegation_id[i*2], "%02x", hash_delegation_id[i]);
-
-  delegation_id[16] = '\0';
-
-  return delegation_id;
-}
-
 /// 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
@@ -1586,6 +1399,8 @@ char *GRSTx509MakeProxyFileName(char *delegation_id,
 
   filename[16] = '-';
 
+
+
   EVP_DigestInit(&ctx, m);
   EVP_DigestUpdate(&ctx, buf, der_name_len);
   EVP_DigestFinal(&ctx, hash_name, &hash_name_len);
@@ -1599,91 +1414,103 @@ char *GRSTx509MakeProxyFileName(char *delegation_id,
 /// 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.
+ *  private key with the same delegation ID and user DN is appended to
+ *  make a valid proxy file, and the temporary private key file deleted.
  */
 
 int GRSTx509CacheProxy(char *proxydir, char *delegation_id, 
                                        char *user_dn, char *proxychain)
 {
-  int   c, len = 0, i, ret;
-  char *user_dn_enc, *upcertfile, *upcertpath, *userkeyfile, *cachekeyfile, 
-       *p, *ptr;
+  int   c, len = 0, i;
+  char *upcertfile, *upcertpath, *prvkeyfile, *p, *ptr;
   FILE *ifp, *ofp;
-
-  if (strcmp(user_dn, "cache") == 0) return GRST_RET_FAILED;
+  STACK_OF(X509) *certstack;
+  BIO  *certmem;
+  X509 *cert;
+  long  ptrlen;
     
-  user_dn_enc = GRSThttpUrlEncode(user_dn);
+  prvkeyfile = GRSTx509CachedProxyKeyFind(proxydir, delegation_id, user_dn);
 
-  /* create directories if necessary */
-
-  mkdir_printf(S_IRUSR | S_IWUSR | S_IXUSR, 
-               "%s/%s",    proxydir, user_dn_enc);
-  mkdir_printf(S_IRUSR | S_IWUSR | S_IXUSR, 
-               "%s/%s/%s", proxydir, user_dn_enc, delegation_id);
-
-  /* move the new proxy private key */
-
-  asprintf(&cachekeyfile, "%s/cache/%s/%s/userkey.pem",
-           proxydir, user_dn_enc, delegation_id);
-
-  if (cachekeyfile == NULL)  
+  if (prvkeyfile == NULL)  
     {
-      free(user_dn_enc);
       return GRST_RET_FAILED;
     }
         
-  asprintf(&userkeyfile, "%s/%s/%s/userkey.pem",
-           proxydir, user_dn_enc, delegation_id);
-
-  if (userkeyfile == NULL)  
+  if ((ifp = fopen(prvkeyfile, "r")) == NULL) 
     {
-      free(cachekeyfile);
-      free(user_dn_enc);
+      free(prvkeyfile);
       return GRST_RET_FAILED;
     }
 
-  ret = rename(cachekeyfile, userkeyfile);
-  chmod(userkeyfile, S_IRUSR | S_IWUSR);
+//  fprintf(stderr, "\n\n\n\n PROXYCHAIN = \n %s", proxychain);
+  if (GRSTx509StringToChain(&certstack, proxychain) != GRST_RET_OK)
+                                                    return GRST_RET_FAILED;
 
-  free(cachekeyfile);
-  free(userkeyfile);
-  
-  if (ret != 0)
-    {
-      free(user_dn_enc);
-      return GRST_RET_FAILED;
-    }
-
-  /* write out the proxy certificate chain */
-
-  asprintf(&upcertfile, "%s/%s/%s/usercert.pem",
-           proxydir, user_dn_enc, delegation_id);
+  upcertfile = GRSTx509MakeProxyFileName(delegation_id, certstack);
 
   if (upcertfile == NULL)
     {
-      free(user_dn_enc);
+      free(prvkeyfile);
+      sk_X509_free(certstack);
       return GRST_RET_FAILED;
     }
     
-  ofp = fopen(upcertfile, "w");
+  asprintf(&upcertpath, "%s/%s", proxydir, upcertfile);  
+  ofp = fopen(upcertpath, "w");
+  chmod(upcertpath, S_IRUSR | S_IWUSR);
+  free(upcertpath);
+
   if (ofp == NULL)
     {
-      free(user_dn_enc);
+      fclose(ifp);
+      free(prvkeyfile);
       free(upcertfile);
       return GRST_RET_FAILED;
     }
+
+  fprintf(ofp, "%s\n%s\n", delegation_id, user_dn);
+  /* write out the most recent proxy by itself */
+  if (cert = sk_X509_value(certstack, 0))
+    {
+      certmem = BIO_new(BIO_s_mem());
+      if (PEM_write_bio_X509(certmem, cert) == 1)
+        {
+          ptrlen = BIO_get_mem_data(certmem, &ptr);
+          fwrite(ptr, 1, ptrlen, ofp);               
+        }
+             
+      BIO_free(certmem);           
+    }         
   
-  chmod(upcertfile, S_IRUSR | S_IWUSR);
+  /* insert proxy private key */
+  
+  while ((c = fgetc(ifp)) != EOF) fputc(c, ofp);
+  unlink(prvkeyfile);
+  free(prvkeyfile);
 
-  free(user_dn_enc);
-  free(upcertfile);
+  for (i=1; i <= sk_X509_num(certstack) - 1; ++i)
+        /* loop through the proxy chain starting at 2nd most recent proxy */
+     {
+       if (cert = sk_X509_value(certstack, i))
+         {
+           certmem = BIO_new(BIO_s_mem());
+           if (PEM_write_bio_X509(certmem, cert) == 1)
+             {
+               ptrlen = BIO_get_mem_data(certmem, &ptr);
+               fwrite(ptr, 1, ptrlen, ofp);
+             }
+             
+           BIO_free(certmem);           
+         }         
+     }
 
-  if ((fwrite(proxychain, sizeof (char), strlen(proxychain), ofp) !=
-      strlen(proxychain)) || (fclose(ofp) != 0))
-    {      
-      return GRST_RET_FAILED;
-    }
+  sk_X509_free(certstack);
+  free(upcertfile);
+  
+  if (fclose(ifp) != 0) return GRST_RET_FAILED;
+  if (fclose(ofp) != 0) return GRST_RET_FAILED;
   
 /* should also check validity of proxy cert to avoid suprises? */
       
index 3404939..4fbcfbe 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2003-5, Andrew McNab and Shiv Kaushal, 
+   Copyright (c) 2003-6, Andrew McNab and Shiv Kaushal, 
    University of Manchester. All rights reserved.
 
    Redistribution and use in source and binary forms, with or
@@ -92,7 +92,6 @@
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 
-
 #include "mod_ssl-private.h"
 
 #include "gridsite.h"
 #define UNSET -1
 #endif
 
+#define GRST_SESSIONS_DIR "/var/www/sessions"
+
 module AP_MODULE_DECLARE_DATA gridsite_module;
 
 #define GRST_SITECAST_GROUPS 32
@@ -117,7 +118,7 @@ struct sitecast_alias
    These are assigned default values in create_gridsite_srv_config() */
 
 int                    gridhttpport = 0;
-char                    *passcodesdir = NULL;
+char                    *sessionsdir = NULL;
 char                   *sitecastdnlists = NULL;
 struct sitecast_group  sitecastgroups[GRST_SITECAST_GROUPS+1];
 struct sitecast_alias  sitecastaliases[GRST_SITECAST_ALIASES];
@@ -143,7 +144,6 @@ typedef struct
    char                        *headfile;
    char                        *footfile;
    int                 gridhttp;
-   int                 soap2cgi;
    char                        *aclformat;
    char                        *execmethod;
    char                        *delegationuri;
@@ -151,251 +151,6 @@ typedef struct
    apr_fileperms_t     diskmode;
 }  mod_gridsite_dir_cfg; /* per-directory config choices */
 
-typedef struct
-{
-  xmlDocPtr doc;
-//  char *outbuffer;
-} soap2cgi_ctx; /* store per-request context for Soap2cgi in/out filters */
-
-static const char Soap2cgiFilterName[]="Soap2cgiFilter";
-
-static void mod_gridsite_soap2cgi_insert(request_rec *r)
-{
-    mod_gridsite_dir_cfg *conf;
-    soap2cgi_ctx     *ctx;
-    
-    conf = (mod_gridsite_dir_cfg *) ap_get_module_config(r->per_dir_config,
-                                                      &gridsite_module);
-                                                      
-    if (conf->soap2cgi) 
-      {
-        ctx = (soap2cgi_ctx *) malloc(sizeof(soap2cgi_ctx));        
-        ctx->doc = NULL;
-        
-        ap_add_output_filter(Soap2cgiFilterName, ctx, r, r->connection);
-
-        ap_add_input_filter(Soap2cgiFilterName, NULL, r, r->connection);
-      }
-}
-
-xmlNodePtr find_one_child(xmlNodePtr parent_node, char *name)
-{
-    xmlNodePtr cur;
-
-    for (cur = parent_node->children; cur != NULL; cur = cur->next)
-       {
-         if ((cur->type == XML_ELEMENT_NODE) &&
-             (strcmp(cur->name, name) == 0)) return cur;
-       }
-
-    return NULL;
-}
-
-int add_one_node(xmlDocPtr doc, char *line)
-{
-    char *p, *name, *aftername, *attrname = NULL, *value = NULL;
-    xmlNodePtr cur, cur_child;
-
-    cur = xmlDocGetRootElement(doc);
-
-    p = index(line, '=');
-    if (p == NULL) return 1;
-
-    *p = '\0';
-    value = &p[1];
-
-    name = line;
-
-    while (1) /* go through each .-deliminated segment of line[] */
-         {
-           if ((p = index(name, '.')) != NULL)
-             {
-               *p = '\0';
-               aftername = &p[1];
-             }
-           else aftername = &name[strlen(name)];
-
-           if ((p = index(name, '_')) != NULL)
-             {
-               *p = '\0';
-               attrname = &p[1];
-             }
-
-           cur_child = find_one_child(cur, name);
-
-           if (cur_child == NULL)
-                    cur_child = xmlNewChild(cur, NULL, name, NULL);
-
-           cur = cur_child;
-
-           name = aftername;
-
-           if (attrname != NULL)
-             {
-               xmlSetProp(cur, attrname, value);
-               return 0;
-             }
-
-           if (*name == '\0')
-             {
-               xmlNodeSetContent(cur, value);
-               return 0;
-             }             
-         }
-}
-
-static apr_status_t mod_gridsite_soap2cgi_out(ap_filter_t *f,
-                                              apr_bucket_brigade *bbIn)
-{
-    char        *p, *name, *outbuffer;
-    request_rec *r = f->r;
-    conn_rec    *c = r->connection;
-    apr_bucket         *bucketIn, *pbktEOS;
-    apr_bucket_brigade *bbOut;
-
-    const char *data;
-    apr_size_t len;
-    char *buf;
-    apr_size_t n;
-    apr_bucket *pbktOut;
-
-    soap2cgi_ctx *ctx;
-    xmlNodePtr   root_node = NULL;
-    xmlBufferPtr buff;
-
-    ctx = (soap2cgi_ctx *) f->ctx;
-
-// LIBXML_TEST_VERSION;
-
-    bbOut = apr_brigade_create(r->pool, c->bucket_alloc);
-
-    if (ctx->doc == NULL)
-      {
-        ctx->doc = xmlNewDoc("1.0");
-             
-        root_node = xmlNewNode(NULL, "Envelope");
-        xmlDocSetRootElement(ctx->doc, root_node);
-                                                                                
-        xmlNewChild(root_node, NULL, "Header", NULL);
-        xmlNewChild(root_node, NULL, "Body",   NULL);
-      }
-    
-    apr_brigade_pflatten(bbIn, &outbuffer, &len, r->pool);
-       
-    /* split up buffer and feed each line to add_one_node() */
-    
-    name = outbuffer;
-    
-    while (*name != '\0')
-         {
-           p = index(name, '\n');
-           if (p != NULL) 
-             {
-               *p = '\0';
-               ++p;             
-             }
-           else p = &name[strlen(name)]; /* point to final NUL */
-           
-           add_one_node(ctx->doc, name);
-           
-           name = p;
-         }
-
-    APR_BRIGADE_FOREACH(bucketIn, bbIn)
-       {
-         if (APR_BUCKET_IS_EOS(bucketIn))
-           {
-             /* write out XML tree we have built */
-
-             buff = xmlBufferCreate();
-             xmlNodeDump(buff, ctx->doc, root_node, 0, 0);
-
-// TODO: simplify/reduce number of copies or libxml vs APR buffers?
-
-             buf = (char *) xmlBufferContent(buff);
-
-             pbktOut = apr_bucket_heap_create(buf, strlen(buf), NULL, 
-                                              c->bucket_alloc);
-
-             APR_BRIGADE_INSERT_TAIL(bbOut, pbktOut);
-       
-             xmlBufferFree(buff);
-
-             pbktEOS = apr_bucket_eos_create(c->bucket_alloc);
-             APR_BRIGADE_INSERT_TAIL(bbOut, pbktEOS);
-
-             continue;
-           }
-       }
-       
-    return ap_pass_brigade(f->next, bbOut);
-}
-
-static apr_status_t mod_gridsite_soap2cgi_in(ap_filter_t *f,
-                                             apr_bucket_brigade *pbbOut,
-                                             ap_input_mode_t eMode,
-                                             apr_read_type_e eBlock,
-                                             apr_off_t nBytes)
-{
-    request_rec *r = f->r;
-    conn_rec *c = r->connection;
-//    CaseFilterInContext *pCtx;
-    apr_status_t ret;
-
-#ifdef NEVERDEFINED
-
-    ret = ap_get_brigade(f->next, pCtx->pbbTmp, eMode, eBlock, nBytes);    
-    if (!(pCtx = f->ctx)) {
-        f->ctx = pCtx = apr_palloc(r->pool, sizeof *pCtx);
-        pCtx->pbbTmp = apr_brigade_create(r->pool, c->bucket_alloc);
-    }
-    if (APR_BRIGADE_EMPTY(pCtx->pbbTmp)) {
-        ret = ap_get_brigade(f->next, pCtx->pbbTmp, eMode, eBlock, nBytes);
-        if (eMode == AP_MODE_EATCRLF || ret != APR_SUCCESS)
-            return ret;
-    }
-    while(!APR_BRIGADE_EMPTY(pCtx->pbbTmp)) {
-        apr_bucket *pbktIn = APR_BRIGADE_FIRST(pCtx->pbbTmp);
-        apr_bucket *pbktOut;
-        const char *data;
-        apr_size_t len;
-        char *buf;
-        int n;
-        /* It is tempting to do this...
-         * APR_BUCKET_REMOVE(pB);
-         * APR_BRIGADE_INSERT_TAIL(pbbOut,pB);
-         * and change the case of the bucket data, but that would be wrong
-         * for a file or socket buffer, for example...
-         */
-                                                                                
-        if(APR_BUCKET_IS_EOS(pbktIn)) {
-            APR_BUCKET_REMOVE(pbktIn);
-            APR_BRIGADE_INSERT_TAIL(pbbOut, pbktIn);
-            break;
-        }
-                                                                                
-        ret=apr_bucket_read(pbktIn, &data, &len, eBlock);
-        if(ret != APR_SUCCESS)
-            return ret;
-                                                                                
-        buf = malloc(len);
-        for(n=0 ; n < len ; ++n)
-            buf[n] = apr_toupper(data[n]);
-                                                                                
-        pbktOut = apr_bucket_heap_create(buf, len, 0, c->bucket_alloc);
-        APR_BRIGADE_INSERT_TAIL(pbbOut, pbktOut);
-        apr_bucket_delete(pbktIn);
-    }
-#endif
-                                                                                
-    return APR_SUCCESS;
-}
-
 
 /*
  * dav_parse_range() is based on modules/dav/main/mod_dav.c from Apache
@@ -594,7 +349,7 @@ char *make_admin_footer(request_rec *r, mod_gridsite_dir_cfg *conf,
 void delegation_header(request_rec *r, mod_gridsite_dir_cfg *conf){
 
   apr_table_add(r->headers_out,
-                apr_pstrdup(r->pool, "Grst-Delegation-Service"),
+                apr_pstrdup(r->pool, "Proxy-Delegation-Service"),
                 apr_psprintf(r->pool,"https://%s%s", r->hostname, conf->delegationuri));
   return;
 
@@ -986,9 +741,9 @@ int http_gridhttp(request_rec *r, mod_gridsite_dir_cfg *conf)
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                "Generated GridHTTP passcode %016llx", gridauthcookie);
 
-    filetemplate = apr_psprintf(r->pool, "%s/%016llxXXXXXX", 
+    filetemplate = apr_psprintf(r->pool, "%s/passcode-%016llxXXXXXX", 
      ap_server_root_relative(r->pool,
-     passcodesdir),
+     sessionsdir),
      gridauthcookie);
 
     if (apr_file_mktemp(&fp, 
@@ -1028,7 +783,7 @@ int http_gridhttp(request_rec *r, mod_gridsite_dir_cfg *conf)
     
     /* send redirection header back to client */
        
-    cookievalue = rindex(filetemplate, '/');
+    cookievalue = rindex(filetemplate, '-');
     if (cookievalue != NULL) ++cookievalue;
     else cookievalue = filetemplate;
        
@@ -1646,8 +1401,8 @@ static void *create_gridsite_srv_config(apr_pool_t *p, server_rec *s)
       {
         gridhttpport = GRST_HTTP_PORT;
       
-        passcodesdir = apr_pstrdup(p, "/var/www/onetimes");
-                                      /* GridSiteOnetimesDir dir-path   */
+        sessionsdir = apr_pstrdup(p, GRST_SESSIONS_DIR);
+                                      /* GridSiteSessionsDir dir-path   */
 
         sitecastdnlists = NULL;
 
@@ -1706,7 +1461,6 @@ static void *create_gridsite_dir_config(apr_pool_t *p, char *path)
                /* GridSiteHeadFile and GridSiteFootFile  file name */
 
         conf->gridhttp      = 0;     /* GridSiteGridHTTP      on/off       */
-        conf->soap2cgi      = 0;     /* GridSiteSoap2cgi      on/off       */
        conf->aclformat     = apr_pstrdup(p, "GACL");
                                      /* GridSiteACLFormat     gacl/xacml   */
        conf->delegationuri = NULL;  /* GridSiteDelegationURI URI-value    */
@@ -1742,7 +1496,6 @@ static void *create_gridsite_dir_config(apr_pool_t *p, char *path)
         conf->headfile      = NULL;  /* GridSiteHeadFile      file name    */
         conf->footfile      = NULL;  /* GridSiteFootFile      file name    */
         conf->gridhttp      = UNSET; /* GridSiteGridHTTP      on/off       */
-        conf->soap2cgi      = UNSET; /* GridSiteSoap2cgi      on/off       */
        conf->aclformat     = NULL;  /* GridSiteACLFormat     gacl/xacml   */
        conf->delegationuri = NULL;  /* GridSiteDelegationURI URI-value    */
        conf->execmethod    = NULL;  /* GridSiteExecMethod */
@@ -1823,9 +1576,6 @@ static void *merge_gridsite_dir_config(apr_pool_t *p, void *vserver,
     if (direct->gridhttp != UNSET) conf->gridhttp = direct->gridhttp;
     else                           conf->gridhttp = server->gridhttp;
         
-    if (direct->soap2cgi != UNSET) conf->soap2cgi = direct->soap2cgi;
-    else                           conf->soap2cgi = server->soap2cgi;
-
     if (direct->aclformat != NULL) conf->aclformat = direct->aclformat;
     else                           conf->aclformat = server->aclformat;
 
@@ -1856,12 +1606,20 @@ static const char *mod_gridsite_take1_cmds(cmd_parms *a, void *cfg,
     int   n, i;
     char *p;
   
-    if (strcasecmp(a->cmd->name, "GridSiteOnetimesDir") == 0)
+    if (strcasecmp(a->cmd->name, "GridSiteSessionsDir") == 0)
+    {
+      if (a->server->is_virtual)
+       return "GridSiteSessionsDir cannot be used inside a virtual server";
+    
+      sessionsdir = apr_pstrdup(a->pool, parm);
+    }
+/* GridSiteOnetimesDir is deprecated in favour of GridSiteSessionsDir */
+    else if (strcasecmp(a->cmd->name, "GridSiteOnetimesDir") == 0)
     {
       if (a->server->is_virtual)
        return "GridSiteOnetimesDir cannot be used inside a virtual server";
     
-      passcodesdir = apr_pstrdup(a->pool, parm);
+      sessionsdir = apr_pstrdup(a->pool, parm);
     }
     else if (strcasecmp(a->cmd->name, "GridSiteGridHTTPport") == 0)
     {
@@ -2122,10 +1880,6 @@ static const char *mod_gridsite_flag_cmds(cmd_parms *a, void *cfg,
 
       ((mod_gridsite_dir_cfg *) cfg)->gridhttp = flag;
     }
-    else if (strcasecmp(a->cmd->name, "GridSiteSoap2cgi") == 0)
-    {
-      ((mod_gridsite_dir_cfg *) cfg)->soap2cgi = flag;
-    }
 
     return NULL;
 }
@@ -2177,6 +1931,9 @@ static const command_rec mod_gridsite_cmds[] =
                  NULL, OR_FILEINFO, "on or off"),
     AP_INIT_TAKE1("GridSiteGridHTTPport", mod_gridsite_take1_cmds,
                    NULL, RSRC_CONF, "GridHTTP port"),
+    AP_INIT_TAKE1("GridSiteSessionsDir", mod_gridsite_take1_cmds,
+                 NULL, RSRC_CONF, "directory with GridHTTP passcodes and SSL session creds"),
+/* GridSiteOnetimesDir is deprecated in favour of GridSiteSessionsDir */
     AP_INIT_TAKE1("GridSiteOnetimesDir", mod_gridsite_take1_cmds,
                  NULL, RSRC_CONF, "directory with GridHTTP passcodes"),
 
@@ -2189,9 +1946,6 @@ static const command_rec mod_gridsite_cmds[] =
     AP_INIT_TAKE2("GridSiteCastAlias", mod_gridsite_take2_cmds,
                  NULL, RSRC_CONF, "URL and local path mapping"),
 
-    AP_INIT_FLAG("GridSiteSoap2cgi", mod_gridsite_flag_cmds,
-                 NULL, OR_FILEINFO, "on or off"),
-
     AP_INIT_TAKE1("GridSiteACLFormat", mod_gridsite_take1_cmds,
                  NULL, OR_FILEINFO, "format to save access control lists in"),
 
@@ -2235,22 +1989,108 @@ static int mod_gridsite_first_fixups(request_rec *r)
     return DECLINED;
 }  
 
-void GRST_creds_to_conn(conn_rec *conn, 
+
+int GRST_get_session_id(SSL *ssl, char *session_id, size_t len)
+{
+   int          i;
+   SSL_SESSION *session;
+
+   if (((session = SSL_get_session(ssl)) == NULL) ||
+       (session->session_id_length == 0)) return GRST_RET_FAILED;
+   
+   if (2 * session->session_id_length + 1 > len) return GRST_RET_FAILED;
+
+   for (i=0; i < (int) session->session_id_length; ++i)
+    sprintf(&(session_id[i*2]), "%02X", (unsigned char) session->session_id[i]);
+
+   session_id[i*2] = '\0';
+   
+   return GRST_RET_OK;
+}
+
+int GRST_load_ssl_creds(SSL *ssl, conn_rec *conn)
+{
+   char session_id[(SSL_MAX_SSL_SESSION_ID_LENGTH+1)*2], *sessionfile = NULL,
+        line[512], *p;
+   apr_file_t  *fp = NULL;
+   int i;
+      
+   if (GRST_get_session_id(ssl, session_id, sizeof(session_id)) != GRST_RET_OK)
+     return GRST_RET_FAILED;
+   
+   sessionfile = apr_psprintf(conn->pool, "%s/sslcreds-%s",
+                         ap_server_root_relative(conn->pool, sessionsdir),
+                         session_id);
+
+   if (apr_file_open(&fp, sessionfile, APR_READ, 0, conn->pool) != APR_SUCCESS)
+       return GRST_RET_FAILED;
+   
+   while (apr_file_gets(line, sizeof(line), fp) == APR_SUCCESS)
+        {
+          if (sscanf(line, "GRST_CRED_%d=", &i) == 1)
+            {
+              p = index(line, '=');
+
+              apr_table_setn(conn->notes,
+                         apr_psprintf(conn->pool, "GRST_CRED_%d", i),
+                         apr_pstrdup(conn->pool, &p[1]));
+            }
+        }
+        
+   apr_file_close(fp);
+
+   /* connection notes created by GRST_save_ssl_creds() are now reloaded */
+   apr_table_set(conn->notes, "GRST_save_ssl_creds", "yes");
+
+   return GRST_RET_OK;
+}
+
+/*
+    Save result of GRSTx509CompactCreds() 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)
 {
-   int i, lastcred;
-   const int maxcreds = 99;
+   int          i, lastcred;
+   const int    maxcreds = 99;
    const size_t credlen = 1024;
-   char creds[maxcreds][credlen+1], envname[14];
+   char         creds[maxcreds][credlen+1], envname[14], *tempfile = NULL,
+               *sessionfile, session_id[(SSL_MAX_SSL_SESSION_ID_LENGTH+1)*2];
+   apr_file_t  *fp = NULL;
+   SSL         *ssl;
+   SSLConnRec  *sslconn;
+
+   /* check if already done */
 
    if ((certstack != NULL) && (conn->notes != NULL) &&
-       (apr_table_get(conn->notes, "GRST_creds_to_conn") != NULL)) return;
+       (apr_table_get(conn->notes, "GRST_save_ssl_creds") != NULL)) return;
 
-   /* Put result of GRSTx509CompactCreds() into connection notes */
+   /* we at least need to say we've been run */
 
-   apr_table_set(conn->notes, "GRST_creds_to_conn", "yes");
+   apr_table_set(conn->notes, "GRST_save_ssl_creds", "yes");
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, conn->base_server,
-                                            "set GRST_creds_to_conn");
+                                            "set GRST_save_ssl_creds");
+
+   sslconn = (SSLConnRec *)ap_get_module_config(conn->conn_config,&ssl_module);
+
+   if ((sslconn != NULL) && 
+       ((ssl = sslconn->ssl) != NULL) &&
+       (GRST_get_session_id(ssl,session_id,sizeof(session_id)) == GRST_RET_OK))
+     {
+       sessionfile = apr_psprintf(conn->pool, "%s/sslcreds-%s",
+                         ap_server_root_relative(conn->pool, sessionsdir),
+                         session_id);
+
+       tempfile = apr_pstrcat(conn->pool, 
+                          ap_server_root_relative(conn->pool, sessionsdir), 
+                          "/tmp-XXXXXX", NULL);
+   
+       if ((tempfile != NULL) && (tempfile[0] != '\0'))
+               apr_file_mktemp(&fp, tempfile, 
+                               APR_CREATE | APR_WRITE | APR_EXCL, conn->pool);
+     }
 
    if (GRSTx509CompactCreds(&lastcred, maxcreds, credlen, (char *) creds,
                           certstack, GRST_VOMS_DIR, peercert) == GRST_RET_OK)
@@ -2264,10 +2104,18 @@ void GRST_creds_to_conn(conn_rec *conn,
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, conn->base_server,
                                       "store GRST_CRED_%d=%s", i, creds[i]);
 
+            if (fp != NULL) apr_file_printf(fp, "GRST_CRED_%d=%s\n",
+                                                i, creds[i]);
           }
                                    
        /* free remaining dup'd certs? */
-     }     
+     }
+     
+   if (fp != NULL)
+     {
+       apr_file_close(fp);
+       apr_file_rename(tempfile, sessionfile, conn->pool);
+     }
 }
 
 static int mod_gridsite_perm_handler(request_rec *r)
@@ -2314,19 +2162,19 @@ static int mod_gridsite_perm_handler(request_rec *r)
     p = (char *) apr_table_get(r->subprocess_env, "HTTPS");
     if ((p != NULL) && (strcmp(p, "on") == 0)) ishttps = 1;
 
-    /* do we need/have per-connection (SSL) cred variable(s)? */
-    
+    /* reload per-connection (SSL) cred variables? */
+
     sslconn = (SSLConnRec *) ap_get_module_config(r->connection->conn_config, 
                                                   &ssl_module);
-
-    if ((sslconn != NULL) && (sslconn->ssl != NULL) &&
+    if ((sslconn != NULL) && 
+        (sslconn->ssl != NULL) &&
+        (sslconn->ssl->session != NULL) &&
         (r->connection->notes != NULL) &&
-        (apr_table_get(r->connection->notes, "GRST_creds_to_conn") == NULL))
+        (apr_table_get(r->connection->notes, "GRST_save_ssl_creds") == NULL))
       {
-        certstack = SSL_get_peer_cert_chain(sslconn->ssl);
-        peercert  = SSL_get_peer_certificate(sslconn->ssl);
-      
-        GRST_creds_to_conn(r->connection, certstack, peercert);
+        if (GRST_load_ssl_creds(sslconn->ssl, r->connection) == GRST_RET_OK)        
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                         "Restored SSL session data from session cache file");
       }
 
     proxylevel = ((mod_gridsite_dir_cfg *) cfg)->gsiproxylimit + 1;
@@ -2497,9 +2345,9 @@ static int mod_gridsite_perm_handler(request_rec *r)
 
     if ((gridauthpasscode != NULL) && (gridauthpasscode[0] != '\0')) 
       {
-        cookiefile = apr_psprintf(r->pool, "%s/%s",
+        cookiefile = apr_psprintf(r->pool, "%s/passcode-%s",
                  ap_server_root_relative(r->pool,
-                 passcodesdir),
+                 sessionsdir),
                  gridauthpasscode);
                                       
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
@@ -2830,7 +2678,7 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
             /* Put result of GRSTx509CompactCreds() into connection notes */
             if ((certstack = 
                   (STACK_OF(X509) *) X509_STORE_CTX_get_chain(ctx)) != NULL)
-             GRST_creds_to_conn(conn, certstack, NULL);
+             GRST_save_ssl_creds(conn, certstack, NULL);
           }
      }
 
@@ -3182,6 +3030,7 @@ static int mod_gridsite_server_post_config(apr_pool_t *pPool,
    server_rec      *this_server;
    apr_proc_t      *procnew = NULL;
    apr_status_t     status;
+   char            *path;
    const char *userdata_key = "sitecast_init";
 
    apr_pool_userdata_get((void **) &procnew, userdata_key, 
@@ -3257,13 +3106,60 @@ static int mod_gridsite_server_post_config(apr_pool_t *pPool,
                       "Set mod_ssl verify callbacks to GridSite wrappers");
           }
       }
-      
+
+   /* create sessions directory if necessary */
+
+   path = ap_server_root_relative(pPool, sessionsdir);
+   apr_dir_make_recursive(path, APR_UREAD | APR_UWRITE | APR_UEXECUTE, pPool);
+   chown(path, unixd_config.user_id, unixd_config.group_id);
+
    return OK;
 }
       
 static void mod_gridsite_child_init(apr_pool_t *pPool, server_rec *pServer)
 {
+   apr_time_t cutoff_time;
+   apr_dir_t *dir;
+   char *filename;
+   apr_finfo_t finfo;
+   SSLSrvConfigRec *sc = ap_get_module_config(pServer->module_config, 
+                                                        &ssl_module);          
    GRSTgaclInit();
+
+   /* expire old ssl creds files */
+                                    
+   if (sc != NULL) // && sc->enabled)
+     {
+       cutoff_time = apr_time_now() 
+                      - apr_time_from_sec(sc->session_cache_timeout);
+
+       ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServer,
+                        "Cutoff time for ssl creds cache: %ld", 
+                        (long) apr_time_sec(cutoff_time));
+
+       if (apr_dir_open(&dir, 
+           ap_server_root_relative(pPool, sessionsdir), pPool) == APR_SUCCESS)
+         {
+           while (apr_dir_read(&finfo, 
+                        APR_FINFO_CTIME | APR_FINFO_NAME, dir) == APR_SUCCESS)
+                {
+                  if ((finfo.ctime < cutoff_time) &&
+                      (strncmp(finfo.name, "sslcreds-", 9) == 0))
+                    {
+                      filename = apr_pstrcat(pPool, 
+                                   ap_server_root_relative(pPool, sessionsdir),
+                                   "/", finfo.name, NULL);
+                    
+                      ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServer,
+                        "Remove %s from ssl creds cache", filename);
+
+                      apr_file_remove(filename, pPool);
+                    }
+                }
+
+           apr_dir_close(dir);
+         }       
+     }
 }
 
 static int mod_gridsite_handler(request_rec *r)
@@ -3309,17 +3205,6 @@ static ap_unix_identity_t *mod_gridsite_get_suexec_id_doer(const request_rec *r)
 
 static void register_hooks(apr_pool_t *p)
 {
-    /* set up the Soap2cgi input and output filters */
-
-    ap_hook_insert_filter(mod_gridsite_soap2cgi_insert, NULL, NULL,
-                          APR_HOOK_MIDDLE);
-
-    ap_register_output_filter(Soap2cgiFilterName, mod_gridsite_soap2cgi_out,
-                              NULL, AP_FTYPE_RESOURCE);
-
-//    ap_register_input_filter(Soap2cgiFilterName, mod_gridsite_soap2cgi_in,
-//                              NULL, AP_FTYPE_RESOURCE);
-
     /* config and handler stuff */
 
     ap_hook_post_config(mod_gridsite_server_post_config, NULL, NULL,