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)
{
#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>
#define HTPROXY_DESTROY 2
#define HTPROXY_TIME 3
#define HTPROXY_UNIXTIME 4
+#define HTPROXY_MAKE 5
void printsyntax(char *argv0)
{
{
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;
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'},
{"put", 0, 0, 0},
{"renew", 0, 0, 0},
{"unixtime", 0, 0, 0},
+ {"make", 0, 0, 0},
{0, 0, 0, 0} };
if (argc == 1)
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];
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'))
{
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 ... */
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 */
}
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;
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;
}
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))
{