Sync
authorAndrew McNab <andrew.mcnab@manchester.ac.uk>
Thu, 29 Jun 2006 08:48:28 +0000 (08:48 +0000)
committerAndrew McNab <andrew.mcnab@manchester.ac.uk>
Thu, 29 Jun 2006 08:48:28 +0000 (08:48 +0000)
org.gridsite.core/src/grst_x509.c
org.gridsite.core/src/htproxyput.c
org.gridsite.core/src/mod_gridsite.c

index 31a89c9..fe2905a 100644 (file)
@@ -1121,13 +1121,88 @@ static void mkdir_printf(mode_t mode, char *fmt, ...)
   free(path);
 }
 
+/// 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)
+{
+  int              i;
+  char            *ptr;
+  size_t           ptrlen;
+  RSA             *keypair;
+  X509_NAME       *subject;
+  X509_NAME_ENTRY *ent;
+  EVP_PKEY        *pkey;
+  X509_REQ        *certreq;
+  BIO             *reqmem, *keymem;
+  const EVP_MD    *digest;
+  struct stat      statbuf;
+
+  /* create key pair and put it in a PEM string */
+
+  if ((keypair = RSA_generate_key(GRST_KEYSIZE, 65537, NULL, NULL)) == NULL)
+                                                               return 1;
+
+  keymem = BIO_new(BIO_s_mem());
+  if (!PEM_write_bio_RSAPrivateKey(keymem, keypair, NULL, NULL, 0, NULL, NULL))
+    {
+      BIO_free(keymem);
+      return 3;
+    }
+
+  ptrlen = BIO_get_mem_data(keymem, &ptr);
+  
+  *keytxt = malloc(ptrlen + 1);
+  memcpy(*keytxt, ptr, ptrlen);
+  (*keytxt)[ptrlen] = '\0';
+
+  BIO_free(keymem);
+  
+  /* now create the certificate request */
+
+  certreq = X509_REQ_new();
+
+  OpenSSL_add_all_algorithms();
+
+  pkey = EVP_PKEY_new();
+  EVP_PKEY_assign_RSA(pkey, keypair);
+
+  X509_REQ_set_pubkey(certreq, pkey);
+  
+  subject = X509_NAME_new();
+  ent = X509_NAME_ENTRY_create_by_NID(NULL, OBJ_txt2nid("organizationName"), 
+                                      MBSTRING_ASC, "Dummy", -1);
+  X509_NAME_add_entry (subject, ent, -1, 0);
+  X509_REQ_set_subject_name (certreq, subject);
+  
+  digest = EVP_md5();
+  X509_REQ_sign(certreq, pkey, digest);
+
+  reqmem = BIO_new(BIO_s_mem());
+  PEM_write_bio_X509_REQ(reqmem, certreq);
+  ptrlen = BIO_get_mem_data(reqmem, &ptr);
+  
+  *reqtxt = malloc(ptrlen + 1);
+  memcpy(*reqtxt, ptr, ptrlen);
+  (*reqtxt)[ptrlen] = '\0';
+
+  BIO_free(reqmem);
+
+  X509_REQ_free(certreq);
+  
+  return 0;
+}
+
 /// 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)
 {
index cf52474..d1f0d87 100644 (file)
@@ -55,6 +55,10 @@ http://www.gridpp.ac.uk/authz/gridsite/
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+
 #include <getopt.h>
 
 #include <gridsite.h>
@@ -68,6 +72,7 @@ http://www.gridpp.ac.uk/authz/gridsite/
 #define HTPROXY_DESTROY                2
 #define HTPROXY_TIME           3
 #define HTPROXY_UNIXTIME       4
+#define HTPROXY_MAKE           5
 
 void printsyntax(char *argv0)
 {
@@ -85,10 +90,10 @@ int main(int argc, char *argv[])
 {
   char  *delegation_id = "", *reqtxt, *certtxt, *valid = NULL, 
         *cert = NULL, *key = NULL, *capath = NULL, *keycert, timestr[81],
-        *executable;
+        *executable, *keytxt, *proxychain, *ptr;
   struct ns__putProxyResponse *unused;
   struct tm *finish_tm;
-  int    option_index, c, noverify = 0, 
+  int    option_index, c, noverify = 0, i, 
          method = HTPROXY_PUT, verbose = 0, fd, minutes;
   struct soap soap_get, soap_put;
   struct ns__getProxyReqResponse        getProxyReqResponse;
@@ -97,6 +102,10 @@ int main(int argc, char *argv[])
   struct ns__destroyResponse            destroyResponse;
   struct ns__getTerminationTimeResponse getTerminationTimeResponse;
   FILE   *ifp, *ofp;
+  STACK_OF(X509) *x509_certstack;
+  X509   *x509_cert;
+  BIO    *certmem;
+  long   ptrlen;
   struct stat statbuf;
   struct passwd *userpasswd; 
   struct option long_options[] = {      {"verbose",     0, 0, 'v'},
@@ -111,6 +120,7 @@ int main(int argc, char *argv[])
                                         {"put",         0, 0, 0},
                                         {"renew",       0, 0, 0},
                                         {"unixtime",   0, 0, 0},
+                                        {"make",       0, 0, 0},
                                         {0, 0, 0, 0}  };
 
   if (argc == 1)
@@ -139,16 +149,11 @@ int main(int argc, char *argv[])
              else if (option_index ==  9) method          = HTPROXY_PUT;
              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 (c == 'v') ++verbose;
        }
 
-  if (optind + 1 != argc)
-    {
-      fprintf(stderr, "Must specify a delegation service URL!\n");
-      return 1;
-    }
-
   executable = rindex(argv[0], '/');
   if (executable != NULL) executable++;
   else                    executable = argv[0];
@@ -158,6 +163,13 @@ int main(int argc, char *argv[])
   else if (strcmp(executable, "htproxytime") == 0)  method = HTPROXY_TIME;
   else if (strcmp(executable, "htproxyunixtime") == 0) 
                                                     method = HTPROXY_UNIXTIME;
+  else if (strcmp(executable, "htproxymake") == 0)  method = HTPROXY_MAKE;
+
+  if ((method != HTPROXY_MAKE) && (optind + 1 != argc))
+    {
+      fprintf(stderr, "Must specify a delegation service URL!\n");
+      return 1;
+    }
 
   if ((method == HTPROXY_RENEW) && (delegation_id[0] == '\0'))
     {
@@ -177,12 +189,14 @@ int main(int argc, char *argv[])
   else if ((cert != NULL) && (key == NULL)) key = cert;
   else if ((cert == NULL) && (key == NULL))
     {
-      cert = getenv("X509_USER_PROXY");
+      if (method != HTPROXY_MAKE) cert = getenv("X509_USER_PROXY");
+
       if (cert != NULL) key = cert;
       else
         {
-          asprintf(&(cert), "/tmp/x509up_u%d", geteuid());
-                                                                                
+          if (method != HTPROXY_MAKE) 
+               asprintf(&(cert), "/tmp/x509up_u%d", geteuid());
+
           /* one fine day, we will check the proxy file for 
              expiry too to avoid suprises when we try to use it ... */
 
@@ -421,6 +435,61 @@ int main(int argc, char *argv[])
         
       return 0;
     }  
+  else if (method == HTPROXY_MAKE)
+    {
+      if (GRSTx509CreateProxyRequest(&reqtxt, &keytxt, NULL) != GRST_RET_OK)
+        {
+          fprintf(stderr, "Failed to create internal proxy cert request\n");
+          return 1;
+        }
+      
+      if (GRSTx509MakeProxyCert(&proxychain, NULL, reqtxt, cert, key, minutes)
+            != GRST_RET_OK)
+        {
+          fprintf(stderr, "Failed to sign internal proxy cert request\n");
+          return 2;
+        }
+        
+      if (GRSTx509StringToChain(&x509_certstack, proxychain) != GRST_RET_OK)
+        {
+          fprintf(stderr, "Failed to convert internal proxy chain\n");
+          return 3;
+        }
+                                
+      if (x509_cert = sk_X509_value(x509_certstack, 0))
+        {
+          certmem = BIO_new(BIO_s_mem());
+          if (PEM_write_bio_X509(certmem, x509_cert) == 1)
+            {
+              ptrlen = BIO_get_mem_data(certmem, &ptr);
+              fwrite(ptr, 1, ptrlen, stdout);
+            }
+                                                          
+          BIO_free(certmem);
+        }
+                                                                    
+      fputs(keytxt, stdout);
+
+      for (i=1; i <= sk_X509_num(x509_certstack) - 1; ++i)
+        /* loop through the proxy chain starting at 2nd most recent proxy */
+         {
+           if (x509_cert = sk_X509_value(x509_certstack, i))
+             {
+               certmem = BIO_new(BIO_s_mem());
+               if (PEM_write_bio_X509(certmem, x509_cert) == 1)
+                 {
+                   ptrlen = BIO_get_mem_data(certmem, &ptr);
+                   fwrite(ptr, 1, ptrlen, stdout);
+                 }
+
+               BIO_free(certmem);
+             }
+         }
+
+      sk_X509_free(x509_certstack);
+      
+      return 0;
+    }
 
   /* weirdness */
 }
index 8c8fb7e..4fb177b 100644 (file)
@@ -823,11 +823,10 @@ int http_gridhttp(request_rec *r, mod_gridsite_dir_cfg *conf)
 
 int http_put_method(request_rec *r, mod_gridsite_dir_cfg *conf)
 {
-  char        buf[2048];
+  char        buf[2048], *filename;
   size_t      block_length, length_sent;
   int         retcode, stat_ret;
   apr_file_t *fp;
-  apr_int32_t open_flag;
   struct stat statbuf;
   int       has_range = 0, is_done = 0;
   apr_off_t range_start, range_end, range_length, length_to_send;
@@ -872,23 +871,29 @@ int http_put_method(request_rec *r, mod_gridsite_dir_cfg *conf)
            else return OK;
          }
     
-       open_flag = APR_WRITE | APR_CREATE | APR_BUFFERED;
+       filename = r->filename;
+
+       if (apr_file_open(&fp, filename, APR_WRITE | APR_CREATE | APR_BUFFERED,
+            conf->diskmode, r->pool) != 0) return HTTP_INTERNAL_SERVER_ERROR;
     }
-  else open_flag = APR_WRITE | APR_CREATE | APR_BUFFERED | APR_TRUNCATE;
+  else /* use temporary file if not a partial transfer */ 
+    {
+      filename = apr_psprintf(r->pool, "%s.tmpXXXXXX", r->filename);
 
-  if (apr_file_open(&fp, r->filename, open_flag,
-      conf->diskmode, r->pool) != 0) return HTTP_INTERNAL_SERVER_ERROR;
-   
+      if (apr_file_mktemp(&fp, filename, 
+                    APR_CREATE | APR_WRITE | APR_BUFFERED | APR_EXCL, r->pool)
+                    != APR_SUCCESS) return HTTP_INTERNAL_SERVER_ERROR;
+    }
+       
   /* we force the permissions, rather than accept any existing ones */
 
-  apr_file_perms_set(r->filename, conf->diskmode);
+  apr_file_perms_set(filename, conf->diskmode);
 
   if (has_range)
     {
       if (apr_file_seek(fp, APR_SET, &range_start) != 0) 
         {
           retcode = HTTP_INTERNAL_SERVER_ERROR;
-          //break;
           return retcode;
         }
 
@@ -925,7 +930,15 @@ int http_put_method(request_rec *r, mod_gridsite_dir_cfg *conf)
       ap_set_content_type(r, "text/html");
     }
 
-  if (apr_file_close(fp) != 0) return HTTP_INTERNAL_SERVER_ERROR;
+  if ((apr_file_close(fp) != 0) || (retcode == HTTP_INTERNAL_SERVER_ERROR))
+    {
+      if (strcmp(filename, r->filename) != 0) remove(filename);
+      return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+  if ((strcmp(filename, r->filename) != 0) &&
+      (apr_file_rename(filename, r->filename, r->pool) != 0))
+      return HTTP_FORBIDDEN; /* best guess as to the problem ... */
 
   if ((retcode == OK) && (stat_ret != 0))
     {