GRSTx509MakeProxyFileName() etc
authorAndrew McNab <andrew.mcnab@manchester.ac.uk>
Tue, 8 Feb 2005 10:26:44 +0000 (10:26 +0000)
committerAndrew McNab <andrew.mcnab@manchester.ac.uk>
Tue, 8 Feb 2005 10:26:44 +0000 (10:26 +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/grst-delegation.c
org.gridsite.core/src/grst_x509.c

index f778a33..fd3935f 100644 (file)
@@ -1,3 +1,9 @@
+* Tue Feb 8 2005 Andrew McNab <Andrew.McNab@man.ac.uk>
+- Include GRSTx509MakeProxyFileName() and 
+  GRSTx509StringToChain() (code to used hashes in cached
+  proxy file names.)
+* Tue Feb 8 2005 Andrew McNab <Andrew.McNab@man.ac.uk>
+- ==== GridSite version 1.1.5 ====
 * Tue Dec 14 2004 Andrew McNab <Andrew.McNab@man.ac.uk>
 - Patch from Daniel Kouril <kouril@ics.muni.cz> to allow
   switching Globus vs system OpenSSL libraries/headers.
index 117c61e..87062a2 100644 (file)
@@ -1,4 +1,4 @@
 MAJOR_VERSION=1
 MINOR_VERSION=1.1
-PATCH_VERSION=1.1.4
+PATCH_VERSION=1.1.5
 VERSION=$(PATCH_VERSION)
index febda2c..c2d7729 100644 (file)
@@ -252,6 +252,8 @@ char *GRSTx509FindProxyFileName(void);
 int GRSTx509MakeProxyCert(char **, FILE *, char *, char *, char *, int);
 char *GRSTx509CachedProxyKeyFind(char *, char *, char *);
 int GRSTx509MakeProxyRequest(char **, char *, char *, char *);
+int GRSTx509StringToChain(STACK_OF(X509) **, char *);
+char *GRSTx509MakeProxyFileName(char *, STACK_OF(X509) *);
 int GRSTx509CacheProxy(char *, char *, char *, char *);
 
 #define GRST_HEADFILE   "gridsitehead.txt"
index 12d1755..a5e8430 100644 (file)
@@ -1,4 +1,4 @@
 #Thu Jan 13 03:09:57 CET 2005
-module.version=1.1.4
+module.version=1.1.5
 module.build=134
 module.age=3
index 2a8a9b2..c8f8185 100644 (file)
@@ -141,6 +141,8 @@ int main(int argn, char *argv[])
   char      *docroot, *method, *request, *p, *client_dn, *user_dn,
             *delegation_id, *reqtxt, *proxydir;
   struct soap soap;
+
+chdir("/var/tmp");
   
   method  = getenv("REQUEST_METHOD");
   if (strcmp(method, "POST") == 0)
index 37b60e6..0e43705 100644 (file)
@@ -875,7 +875,7 @@ int GRSTx509MakeProxyCert(char **proxychain, FILE *debugfp,
 {
   char *ptr, *certchain;
   int i, subjAltName_pos, ncerts;
-  long serial = 1, ptrlen;
+  long serial = 2796, ptrlen;
   EVP_PKEY *pkey, *CApkey;
   const EVP_MD *digest;
   X509 *certs[GRST_MAX_CHAIN_LEN];
@@ -1278,7 +1278,7 @@ int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir,
   const EVP_MD          *digest;
   struct stat      statbuf;
 
-  if ((keypair = RSA_generate_key(GRST_KEYSIZE, 3, NULL, NULL)) == NULL)
+  if ((keypair = RSA_generate_key(GRST_KEYSIZE, 65537, NULL, NULL)) == NULL)
                                                                return 1;
   asprintf(&prvkeyfile, "%s/.XXXXXX", proxydir);
           
@@ -1329,6 +1329,143 @@ int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir,
   return 0;
 }
 
+/// 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)
+{   
+  STACK_OF(X509_INFO) *sk=NULL;
+  BIO *certbio;
+  X509_INFO *xi;
+
+  *certstack = sk_X509_new_null();
+  if (*certstack == NULL) return GRST_RET_FAILED;
+
+  certbio = BIO_new_mem_buf(certstring, -1);
+  
+  if (!(sk=PEM_X509_INFO_read_bio(certbio, NULL, NULL, NULL)))
+    {
+      BIO_free(certbio);
+      sk_X509_INFO_free(sk);
+      sk_X509_free(*certstack);
+      return GRST_RET_FAILED;
+    }
+      
+  while (sk_X509_INFO_num(sk))
+       {
+         xi=sk_X509_INFO_shift(sk);
+         if (xi->x509 != NULL)
+           {
+             sk_X509_push(*certstack, xi->x509);
+             xi->x509=NULL;
+           }
+         X509_INFO_free(xi);
+       }
+       
+   if (!sk_X509_num(*certstack))
+     {
+       BIO_free(certbio);
+       sk_X509_INFO_free(sk);
+       sk_X509_free(*certstack);
+       return GRST_RET_FAILED;
+     }
+
+   BIO_free(certbio);
+   sk_X509_INFO_free(sk);
+   
+   return GRST_RET_OK;
+}
+
+/// 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)
+{ 
+  int        i, depth, prevIsCA = 1, IsCA, hash_name_len, delegation_id_len,
+                 der_name_len;
+  unsigned char *der_name, hash_name[EVP_MAX_MD_SIZE],
+                 hash_delegation_id[EVP_MAX_MD_SIZE],
+                 filename[34];
+  X509_NAME *subject_name;
+  X509      *cert;
+  const EVP_MD *m;
+  EVP_MD_CTX ctx;
+
+  depth = sk_X509_num(certstack);  
+  
+  for (i=depth-1; i >= 0; --i)
+        /* loop through the proxy chain starting at CA end */
+     {
+       if (cert = sk_X509_value(certstack, i))
+         {
+           IsCA = (GRSTx509IsCA(cert) == GRST_RET_OK);
+
+           if (prevIsCA && !IsCA) /* the full certificate of the user */
+             {
+               break;
+             }
+         }
+     }
+
+  if (i < 0) return NULL; /* not found: something wrong with the chain */
+
+  if ((subject_name = X509_get_subject_name(cert)) == NULL) return NULL;
+  
+  der_name_len = i2d_X509_NAME(X509_get_subject_name(cert), NULL);
+  if (der_name_len == 0) return NULL;
+  
+  der_name = malloc(der_name_len);  
+  if (!i2d_X509_NAME(X509_get_subject_name(cert), &der_name))
+    {
+      free(der_name);
+      return NULL;
+    }
+  
+  OpenSSL_add_all_digests();
+  
+  m = EVP_sha1();
+  if (m == NULL)
+    {
+      free(der_name);
+      return NULL;
+    }
+
+  EVP_DigestInit(&ctx, m);
+  EVP_DigestUpdate(&ctx, der_name, der_name_len);
+  EVP_DigestFinal(&ctx, hash_name, &hash_name_len);
+
+  EVP_DigestInit(&ctx, m);
+  EVP_DigestUpdate(&ctx, delegation_id, strlen(delegation_id));
+  EVP_DigestFinal(&ctx, hash_delegation_id, &delegation_id_len);
+
+  /* lots of nasty hard coded numbers: 
+     "8bytes/16chars delegation ID" + "-" + "8bytes/16chars DN" */
+
+  for (i=0; i <=7; ++i)
+   sprintf(&filename[i*2], "%02x", hash_delegation_id[i]);
+   
+  filename[16] = '-';
+  
+  for (i=0; i <=7; ++i)
+   sprintf(&filename[17 + i*2], "%02x", hash_name[i]);
+   
+  return strdup(filename);
+}
+
 /// 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
@@ -1339,39 +1476,43 @@ int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir,
 int GRSTx509CacheProxy(char *proxydir, char *delegation_id, 
                                        char *user_dn, char *proxychain)
 {
-  int   fd, c, len = 0, i;
-  char *cert, *upcertfile, *prvkeyfile, *p;
+  int   c, len = 0, i;
+  char *cert, *upcertfile, *upcertpath, *prvkeyfile, *p;
   FILE *ifp, *ofp;
+  STACK_OF(X509) *certstack;
     
   prvkeyfile = GRSTx509CachedProxyKeyFind(proxydir, delegation_id, user_dn);
 
   if (prvkeyfile == NULL)  
     {
-      free(proxydir);
       return GRST_RET_FAILED;
     }
         
   if ((ifp = fopen(prvkeyfile, "r")) == NULL) 
     {
       free(prvkeyfile);
-      free(proxydir);
       return GRST_RET_FAILED;
     }
 
-  if (asprintf(&upcertfile, "%s/XXXXXX", proxydir) == -1) 
+  if (GRSTx509StringToChain(&certstack, proxychain) != GRST_RET_OK)
                                                     return GRST_RET_FAILED;
 
-  if ((fd = mkstemp(upcertfile)) == -1)
+  upcertfile = GRSTx509MakeProxyFileName(delegation_id, certstack);
+
+  if (upcertfile == NULL)
     {
-      fclose(ifp);
       free(prvkeyfile);
-      free(upcertfile);
+      sk_X509_free(certstack);
       return GRST_RET_FAILED;
     }
     
-  if ((ofp = fdopen(fd, "w")) == NULL)
+  asprintf(&upcertpath, "%s/%s", proxydir, upcertfile);  
+  ofp = fopen(upcertpath, "w");
+  chmod(upcertpath, S_IRUSR | S_IWUSR);
+  free(upcertpath);
+
+  if (ofp == NULL)
     {
-      close(fd);
       fclose(ifp);
       free(prvkeyfile);
       free(upcertfile);