This commit was manufactured by cvs2svn to create branch 'glite-security-
authorcvs2svn <admin@example.com>
Wed, 16 Mar 2005 13:41:34 +0000 (13:41 +0000)
committercvs2svn <admin@example.com>
Wed, 16 Mar 2005 13:41:34 +0000 (13:41 +0000)
proxyrenewal_branch_1_0_0_RC1'.

Cherrypick from master 2005-03-16 13:41:33 UTC Daniel KouĊ™il <kouril@ics.muni.cz> 'Don't use hard-wired configuration values for VOMS setting. Let the VOMS library choose default values instead.':
    org.glite.security.proxyrenewal/src/acstack.h
    org.glite.security.proxyrenewal/src/newformat.h
    org.glite.security.proxyrenewal/src/voms.c

org.glite.security.proxyrenewal/src/acstack.h [new file with mode: 0755]
org.glite.security.proxyrenewal/src/newformat.h [new file with mode: 0755]
org.glite.security.proxyrenewal/src/voms.c [new file with mode: 0644]

diff --git a/org.glite.security.proxyrenewal/src/acstack.h b/org.glite.security.proxyrenewal/src/acstack.h
new file mode 100755 (executable)
index 0000000..a833a31
--- /dev/null
@@ -0,0 +1,79 @@
+/*********************************************************************
+ *
+ * Authors: Vincenzo Ciaschini - Vincenzo.Ciaschini@cnaf.infn.it 
+ *
+ * Copyright (c) 2002, 2003 INFN-CNAF on behalf of the EU DataGrid.
+ * For license conditions see LICENSE file or
+ * http://www.edg.org/license.html
+ *
+ * Parts of this code may be based upon or even include verbatim pieces,
+ * originally written by other people, in which case the original header
+ * follows.
+ *
+ *********************************************************************/
+#ifndef _ACSTACK_H
+#define _ACSTACK_H
+
+#include <openssl/asn1.h>
+#include <openssl/stack.h>
+#include <openssl/safestack.h>
+
+#define IMPL_STACK(type) \
+   DECLARE_STACK_OF(type) \
+   STACK_OF(type) *sk_##type##_new (int (*cmp)(const type * const *, const type * const *)) \
+       { return sk_new ( (int (*)(const char * const *, const char * const *))cmp);} \
+   STACK_OF(type) *sk_##type##_new_null () { return sk_new_null(); } \
+   void   sk_##type##_free (STACK_OF(type) *st) { sk_free(st); } \
+   int    sk_##type##_num (const STACK_OF(type) *st) { return sk_num(st); } \
+   type  *sk_##type##_value (const STACK_OF(type) *st, int i) { return (type *)sk_value(st, i); } \
+   type  *sk_##type##_set (STACK_OF(type) *st, int i, type *val) { return ((type *)sk_set(st, i, (char *)val)); } \
+   void   sk_##type##_zero (STACK_OF(type) *st) { sk_zero(st);} \
+   int    sk_##type##_push (STACK_OF(type) *st, type *val) { return sk_push(st, (char *)val); } \
+   int    sk_##type##_unshift (STACK_OF(type) *st, type *val) { return sk_unshift(st, (char *)val); } \
+   int    sk_##type##_find (STACK_OF(type) *st, type *val) { return sk_find(st, (char *)val); } \
+   type  *sk_##type##_delete (STACK_OF(type) *st, int i) { return (type *)sk_delete(st, i); } \
+   type  *sk_##type##_delete_ptr (STACK_OF(type) *st, type *ptr) { return (type *)sk_delete_ptr(st, (char *)ptr); } \
+   int    sk_##type##_insert (STACK_OF(type) *st, type *val, int i) { return sk_insert(st, (char *)val, i); } \
+   int (*sk_##type##_set_cmp_func (STACK_OF(type) *st, int (*cmp)(const type * const *, const type * const *)))(const type * const *, const type * const *) \
+       { return (int ((*)(const type * const *, const type * const *)))sk_set_cmp_func (st, (int (*)(const char * const *, const char * const *))cmp); } \
+   STACK_OF(type) *sk_##type##_dup (STACK_OF(type) *st) { return sk_dup(st); } \
+   void   sk_##type##_pop_free (STACK_OF(type) *st, void (*func)(type *)) { sk_pop_free(st, (void (*)(void *))func); } \
+   type  *sk_##type##_shift (STACK_OF(type) *st) { return (type *)sk_shift(st); } \
+   type  *sk_##type##_pop (STACK_OF(type) *st) { return (type *)sk_pop(st); } \
+   void   sk_##type##_sort (STACK_OF(type) *st) { sk_sort(st); } \
+   STACK_OF(type) *d2i_ASN1_SET_OF_##type (STACK_OF(type) **st, unsigned char **pp, long length, type *(*d2ifunc)(), void (*freefunc)(type *), int ex_tag, int ex_class) \
+       { return d2i_ASN1_SET(st, pp, length, (char *(*)())d2ifunc, (void (*)(void *))freefunc, ex_tag, ex_class); } \
+   int i2d_ASN1_SET_OF_##type (STACK_OF(type) *st, unsigned char **pp, int (*i2dfunc)(), int ex_tag, int ex_class, int is_set) \
+       { return i2d_ASN1_SET(st, pp, i2dfunc, ex_tag, ex_class, is_set); }  \
+   unsigned char *ASN1_seq_pack_##type (STACK_OF(type) *st, int (*i2d)(), unsigned char **buf, int *len) { return ASN1_seq_pack(st, i2d, buf, len); } \
+   STACK_OF(type) *ASN1_seq_unpack_##type (unsigned char *buf, int len, type *(*d2i)(), void (*freefunc)(type *)) \
+       { return ASN1_seq_unpack(buf, len, (char *(*)())d2i, (void (*)(void *))freefunc); }
+
+
+#define DECL_STACK(type) \
+   DECLARE_STACK_OF(type) \
+   extern STACK_OF(type) *sk_##type##_new (int (*)(const type * const *, const type * const *)); \
+   extern STACK_OF(type) *sk_##type##_new_null (); \
+   extern void   sk_##type##_free (STACK_OF(type) *); \
+   extern int    sk_##type##_num (const STACK_OF(type) *); \
+   extern type  *sk_##type##_value (const STACK_OF(type) *, int); \
+   extern type  *sk_##type##_set (STACK_OF(type) *, int, type *); \
+   extern void   sk_##type##_zero (STACK_OF(type) *); \
+   extern int    sk_##type##_push (STACK_OF(type) *, type *); \
+   extern int    sk_##type##_unshift (STACK_OF(type) *, type *); \
+   extern int    sk_##type##_find (STACK_OF(type) *, type *); \
+   extern type  *sk_##type##_delete (STACK_OF(type) *, int); \
+   extern type  *sk_##type##_delete_ptr (STACK_OF(type) *, type *); \
+   extern int    sk_##type##_insert (STACK_OF(type) *, type *, int); \
+   extern int (*sk_##type##_set_cmp_func (STACK_OF(type) *, int (*)(const type * const *, const type * const *)))(const type * const *, const type * const *); \
+   extern STACK_OF(type) *sk_##type##_dup (STACK_OF(type) *); \
+   extern void   sk_##type##_pop_free (STACK_OF(type) *, void (*)(type *)); \
+   extern type  *sk_##type##_shift (STACK_OF(type) *); \
+   extern type  *sk_##type##_pop (STACK_OF(type) *); \
+   extern void   sk_##type##_sort (STACK_OF(type) *); \
+   extern STACK_OF(type) *d2i_ASN1_SET_OF_##type (STACK_OF(type) **, unsigned char **, long, type *(*)(), void (*)(type *), int, int); \
+   extern int i2d_ASN1_SET_OF_##type (STACK_OF(type) *, unsigned char **, int (*)(), int, int, int); \
+   extern unsigned char *ASN1_seq_pack_##type (STACK_OF(type) *, int (*)(), unsigned char **, int *); \
+   extern STACK_OF(type) *ASN1_seq_unpack_##type (unsigned char *, int, type *(*)(), void (*)(type *)) ;
+
+#endif
diff --git a/org.glite.security.proxyrenewal/src/newformat.h b/org.glite.security.proxyrenewal/src/newformat.h
new file mode 100755 (executable)
index 0000000..0efeb7e
--- /dev/null
@@ -0,0 +1,195 @@
+/*********************************************************************
+ *
+ * Authors: Vincenzo Ciaschini - Vincenzo.Ciaschini@cnaf.infn.it 
+ *
+ * Copyright (c) 2002, 2003 INFN-CNAF on behalf of the EU DataGrid.
+ * For license conditions see LICENSE file or
+ * http://www.edg.org/license.html
+ *
+ * Parts of this code may be based upon or even include verbatim pieces,
+ * originally written by other people, in which case the original header
+ * follows.
+ *
+ *********************************************************************/
+#ifndef _NEW_FORMAT_H
+#define _NEW_FORMAT_H
+#include <openssl/evp.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1_mac.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/stack.h>
+#include <openssl/safestack.h>
+
+#include "acstack.h"
+#if 0
+static STACK_OF(CRYPT_EX_DATA_FUNS) *AC_meth = NULL;
+
+static AC_METHOD meth = {
+  (int (*)())  i2d_AC,
+  (char *(*)())d2i_AC,
+  (char *(*)())AC_new,
+  (void (*)()) AC_free};
+a
+ASN1_METHOD *AC_asn1_meth(void)
+{
+  return &meth;
+}
+#endif
+
+typedef struct ACDIGEST {
+  ASN1_ENUMERATED *type;
+  ASN1_OBJECT     *oid;
+  X509_ALGOR      *algor;
+  ASN1_BIT_STRING *digest;
+} AC_DIGEST;
+
+typedef struct ACIS {
+  STACK_OF(GENERAL_NAME) *issuer;
+  ASN1_INTEGER  *serial;
+  ASN1_BIT_STRING *uid;
+} AC_IS;
+
+typedef struct ACFORM {
+  STACK_OF(GENERAL_NAME) *names;
+  AC_IS         *is;
+  AC_DIGEST     *digest;
+} AC_FORM;
+
+typedef struct ACACI {
+  STACK_OF(GENERAL_NAME) *names;
+  AC_FORM       *form;
+} AC_ACI;
+
+typedef struct ACHOLDER {
+  AC_IS         *baseid;
+  STACK_OF(GENERAL_NAMES) *name;
+  AC_DIGEST     *digest;
+} AC_HOLDER;
+
+typedef struct ACVAL {
+  ASN1_GENERALIZEDTIME *notBefore;
+  ASN1_GENERALIZEDTIME *notAfter;
+} AC_VAL;
+
+typedef struct asn1_string_st AC_IETFATTRVAL;
+
+typedef struct ACIETFATTR {
+  STACK_OF(GENERAL_NAMES)   *names;
+  STACK_OF(AC_IETFATTRVAL) *values;
+} AC_IETFATTR;
+
+typedef struct ACTARGET {
+  GENERAL_NAME *name;
+  GENERAL_NAME *group;
+  AC_IS        *cert;
+} AC_TARGET;
+typedef struct ACTARGETS {
+  STACK_OF(AC_TARGET) *targets;
+} AC_TARGETS;
+
+typedef struct ACATTR {
+  ASN1_OBJECT           *type;
+  STACK_OF(AC_IETFATTR) *ietfattr;
+} AC_ATTR;
+
+typedef struct ACINFO {
+  ASN1_INTEGER             *version;
+  AC_HOLDER                *holder;
+  AC_FORM                  *form;
+  X509_ALGOR               *alg;
+  ASN1_INTEGER             *serial;
+  AC_VAL                   *validity;
+  STACK_OF(AC_ATTR)        *attrib;
+  ASN1_BIT_STRING          *id;
+  STACK_OF(X509_EXTENSION) *exts;
+} AC_INFO;
+
+typedef struct ACC {
+  AC_INFO         *acinfo;
+  X509_ALGOR      *sig_alg;
+  ASN1_BIT_STRING *signature;
+} AC;
+
+typedef struct ACSEQ {
+  STACK_OF(AC) *acs;
+} AC_SEQ;
+
+DECL_STACK(AC_TARGET)
+DECL_STACK(AC_TARGETS)
+DECL_STACK(AC_IETFATTR)
+DECL_STACK(AC_IETFATTRVAL)
+DECL_STACK(AC_ATTR)
+DECL_STACK(AC);
+DECL_STACK(AC_INFO);
+DECL_STACK(AC_VAL);
+DECL_STACK(AC_HOLDER);
+DECL_STACK(AC_ACI);
+DECL_STACK(AC_FORM);
+DECL_STACK(AC_IS);
+DECL_STACK(AC_DIGEST);
+
+extern int i2d_AC_ATTR(AC_ATTR *a, unsigned char **pp);
+extern AC_ATTR *d2i_AC_ATTR(AC_ATTR **a, unsigned char **p, long length);
+extern AC_ATTR *AC_ATTR_new();
+extern void AC_ATTR_free(AC_ATTR *a);
+extern int i2d_AC_IETFATTR(AC_IETFATTR *a, unsigned char **pp);
+extern AC_IETFATTR *d2i_AC_IETFATTR(AC_IETFATTR **a, unsigned char **p, long length);
+extern AC_IETFATTR *AC_IETFATTR_new();
+extern void AC_IETFATTR_free (AC_IETFATTR *a);
+extern int i2d_AC_IETFATTRVAL(AC_IETFATTRVAL *a, unsigned char **pp);
+extern AC_IETFATTRVAL *d2i_AC_IETFATTRVAL(AC_IETFATTRVAL **a, unsigned char **pp, long length);
+extern AC_IETFATTRVAL *AC_IETFATTRVAL_new();
+extern void AC_IETFATTRVAL_free(AC_IETFATTRVAL *a);
+extern int i2d_AC_DIGEST(AC_DIGEST *a, unsigned char **pp);
+extern AC_DIGEST *d2i_AC_DIGEST(AC_DIGEST **a, unsigned char **pp, long length);;
+extern AC_DIGEST *AC_DIGEST_new(void);
+extern void AC_DIGEST_free(AC_DIGEST *a);
+extern int i2d_AC_IS(AC_IS *a, unsigned char **pp);
+extern AC_IS *d2i_AC_IS(AC_IS **a, unsigned char **pp, long length);
+extern AC_IS *AC_IS_new(void);
+extern void AC_IS_free(AC_IS *a);
+extern int i2d_AC_FORM(AC_FORM *a, unsigned char **pp);
+extern AC_FORM *d2i_AC_FORM(AC_FORM **a, unsigned char **pp, long length);
+extern AC_FORM *AC_FORM_new(void);
+extern void AC_FORM_free(AC_FORM *a);
+extern int i2d_AC_ACI(AC_ACI *a, unsigned char **pp);
+extern AC_ACI *d2i_AC_ACI(AC_ACI **a, unsigned char **pp, long length);
+extern AC_ACI *AC_ACI_new(void);
+extern void AC_ACI_free(AC_ACI *a);
+
+extern int i2d_AC_HOLDER(AC_HOLDER *a, unsigned char **pp);
+extern AC_HOLDER *d2i_AC_HOLDER(AC_HOLDER **a, unsigned char **pp, long length);
+extern AC_HOLDER *AC_HOLDER_new(void);
+extern void AC_HOLDER_free(AC_HOLDER *a);
+
+/* new AC_VAL functions by Valerio */
+extern int i2d_AC_VAL(AC_VAL *a, unsigned char **pp);
+extern AC_VAL *d2i_AC_VAL(AC_VAL **a, unsigned char **pp, long length);
+extern AC_VAL *AC_VAL_new(void);
+extern void AC_VAL_free(AC_VAL *a);
+/* end*/
+
+extern int i2d_AC_INFO(AC_INFO *a, unsigned char **pp);
+extern AC_INFO *d2i_AC_INFO(AC_INFO **a, unsigned char **p, long length);
+extern AC_INFO *AC_INFO_new(void);
+extern void AC_INFO_free(AC_INFO *a);
+extern int i2d_AC(AC *a, unsigned char **pp) ;
+extern AC *d2i_AC(AC **a, unsigned char **pp, long length);
+extern AC *AC_new(void);
+extern void AC_free(AC *a);
+extern int i2d_AC_TARGETS(AC_TARGETS *a, unsigned char **pp) ;
+extern AC_TARGETS *d2i_AC_TARGETS(AC_TARGETS **a, unsigned char **pp, long length);
+extern AC_TARGETS *AC_TARGETS_new(void);
+extern void AC_TARGETS_free(AC_TARGETS *a);
+extern int i2d_AC_TARGET(AC_TARGET *a, unsigned char **pp) ;
+extern AC_TARGET *d2i_AC_TARGET(AC_TARGET **a, unsigned char **pp, long length);
+extern AC_TARGET *AC_TARGET_new(void);
+extern void AC_TARGET_free(AC_TARGET *a);
+extern int i2d_AC_SEQ(AC_SEQ *a, unsigned char **pp) ;
+extern AC_SEQ *d2i_AC_SEQ(AC_SEQ **a, unsigned char **pp, long length);
+extern AC_SEQ *AC_SEQ_new(void);
+extern void AC_SEQ_free(AC_SEQ *a);
+
+#endif
diff --git a/org.glite.security.proxyrenewal/src/voms.c b/org.glite.security.proxyrenewal/src/voms.c
new file mode 100644 (file)
index 0000000..70e6b4f
--- /dev/null
@@ -0,0 +1,288 @@
+#include "renewal_locl.h"
+#include "renewd_locl.h"
+
+#include <string.h>
+#include <openssl/x509.h>
+
+#include "glite/security/voms/voms_apic.h"
+
+#include "newformat.h"
+
+char * Decode(const char *, int, int *);
+char **listadd(char **, char *, int);
+
+static int
+generate_proxy(globus_gsi_cred_handle_t cur_proxy,
+               X509_EXTENSION *voms_extension, const char *new_file)
+{
+   globus_result_t result;
+   globus_gsi_proxy_handle_t proxy_handle = NULL;
+   globus_gsi_cred_handle_t proxy = NULL;
+   EVP_PKEY *cur_proxy_priv_key = NULL;
+   X509 *new_cert = NULL;
+   X509 *voms_cert = NULL;
+   globus_gsi_cert_utils_cert_type_t proxy_type;
+
+   result = globus_gsi_proxy_handle_init(&proxy_handle, NULL);
+   if (result) {
+      fprintf(stderr, "globus_gsi_proxy_handle_init() failed\n");
+      goto end;
+   }
+
+   result = globus_gsi_cred_get_key(cur_proxy, &cur_proxy_priv_key);
+   if (result) {
+      fprintf(stderr, "globus_gsi_cred_get_key() failed\n");
+      goto end;
+   }
+
+   /* Create and sign a new proxy */
+   result = globus_gsi_cred_get_cert_type(cur_proxy, &proxy_type);
+   if (result) {
+      fprintf(stderr, "globus_gsi_cred_get_cert_type() failed\n");
+      goto end;
+   }
+
+   result = globus_gsi_proxy_handle_set_type(proxy_handle, proxy_type);
+   if (result) {
+      fprintf(stderr, "globus_gsi_proxy_handle_set_type() failed\n");
+      goto end;
+   }
+
+   result = globus_gsi_proxy_create_signed(proxy_handle, cur_proxy, &proxy);
+   if (result) {
+      fprintf(stderr, "globus_gsi_proxy_handle_init() failed\n");
+      goto end;
+   }
+
+   /* Get the new proxy */
+   result = globus_gsi_cred_get_cert(proxy, &new_cert);
+   if (result) {
+      fprintf(stderr, "globus_gsi_cred_get_cert() failed\n");
+      goto end;
+   }
+
+   /* The Globus API doesn't allow to store custom X.509 extensions */
+   voms_cert = X509_dup(new_cert);
+   if (voms_cert->cert_info->extensions == NULL)
+      voms_cert->cert_info->extensions = sk_X509_EXTENSION_new_null();
+   sk_X509_EXTENSION_push(voms_cert->cert_info->extensions, voms_extension);
+
+   /* Openssl ensures that memory containing old signature structures is unallocated */
+#if 0
+   X509_sign(voms_cert, cur_proxy_priv_key, proxy_handle->attrs->signing_algorithm);
+#else
+   X509_sign(voms_cert, cur_proxy_priv_key, EVP_md5());
+#endif
+
+   /* And put the cert back, older one is unallocated by the function */
+   result = globus_gsi_cred_set_cert(proxy, voms_cert);
+   if (result) {
+      fprintf(stderr, "globus_gsi_cred_set_cert() failed\n");
+      goto end;
+   }
+
+   result = globus_gsi_cred_write_proxy(proxy, (char *)new_file);
+
+end:
+
+   return 0;
+}
+
+static int
+my_VOMS_Export(void *buf, int buf_len, X509_EXTENSION **extension)
+{
+   AC *ac = NULL;
+   unsigned char *p, *pp;
+   AC **voms_attrs = NULL;
+
+   p = pp = buf;
+   ac = d2i_AC(NULL, &p, buf_len+1);
+   if (ac == NULL) {
+      fprintf(stderr, "d2i_AC() failed\n");
+      return 1;
+   }
+
+   voms_attrs = (AC **)listadd((char **)voms_attrs, (char *)ac, sizeof(AC *));
+
+   *extension = X509V3_EXT_conf_nid(NULL, NULL, OBJ_txt2nid("acseq"),
+                                  (char*)voms_attrs);
+   return 0;
+}
+
+static int
+create_voms_command(struct vomsdata *vd, struct voms **voms_cert, char **command)
+{
+   int voms_error, ret;
+   struct data **attribs;
+
+#if 0
+   VOMS_ResetOrder(vd, &voms_error);
+   for (i = 2; i < argc; i++) {
+      ret = VOMS_Ordering(argv[i], vd, &voms_error);
+      if (ret == 0) {
+        fprintf(stderr, "VOMS_Ordering() failed\n"); 
+        return 1;
+      }
+   }
+#endif
+
+   if (voms_cert == NULL || *voms_cert == NULL || (*voms_cert)->std == NULL) {
+      fprintf(stderr, "Invalid VOMS certificate\n");
+      return 1;
+   }
+
+   attribs = (*voms_cert)->std;
+
+   if (strcmp (attribs[0]->role, "NULL") == 0 )
+      ret = asprintf(command, "G%s", attribs[0]->group);
+   else
+      ret = asprintf(command, "B%s:%s", attribs[0]->group, attribs[0]->role);
+
+end:
+
+   return 0;
+}
+
+static int
+renew_voms_cert(struct vomsdata *vd, struct voms **voms_cert, 
+                char **buf, size_t *buf_len)
+{
+   int voms_error = 0, i, ret, voms_version;
+   struct contactdata **voms_contacts = NULL;
+   char *command = NULL;
+
+   voms_contacts = VOMS_FindByVO(vd, (*voms_cert)->voname, NULL, NULL, &voms_error);
+
+   if (voms_contacts == NULL) {
+      fprintf(stderr, "VOMS_FindByVO() failed\n");
+      return 1;
+   }
+
+   ret = create_voms_command(vd, voms_cert, &command);
+
+   /* XXX iterate over all servers on the list on errors */
+   ret = VOMS_ContactRaw(voms_contacts[0]->host, voms_contacts[0]->port,
+                        voms_contacts[0]->contact, command, 
+                        (void**) buf, buf_len, &voms_version,
+                        vd, &voms_error);
+   if (ret == 0) {
+      fprintf(stderr, "VOMS_Contact() failed\n");
+      return 1;
+   }
+
+   VOMS_DeleteContacts(voms_contacts);
+
+   if (command)
+      free(command);
+
+   return 0;
+}
+
+int
+renew_voms_certs(const char *cur_file, const char *new_file)
+{
+   globus_gsi_cred_handle_t cur_proxy = NULL;
+   struct vomsdata *vd = NULL;
+   struct voms **voms_cert = NULL;
+   int voms_err, ret;
+   X509 *cert = NULL;
+   STACK_OF(X509) *chain = NULL;
+   char *buf = NULL;
+   size_t buf_len;
+   X509_EXTENSION *extension = NULL;
+   char *old_env_proxy = getenv("X509_USER_PROXY");
+
+   setenv("X509_USER_PROXY", cur_file, 1);
+
+   ret = load_proxy(cur_file, &cert, NULL, &chain, &cur_proxy);
+   if (ret)
+      goto end;
+
+   vd = VOMS_Init(NULL, NULL);
+   if (vd == NULL) {
+      fprintf(stderr, "VOMS_Init() failed\n");
+      return 1;
+   }
+
+   ret = VOMS_Retrieve(cert, chain, RECURSE_CHAIN, vd, &voms_err);
+   if (ret == 0) {
+      if (voms_err == VERR_NOEXT) {
+        /* no VOMS cred, no problem; continue */
+        fprintf(stderr, "No VOMS attributes found in proxy %s\n", cur_file);
+        ret = 0;
+        goto end;
+      } else {
+        fprintf(stderr, "Cannot get VOMS certificate(s) from proxy");
+        ret = 1;
+        goto end;
+      }
+   }
+
+   /* XXX make sure this loop can really work for multiple voms certificates
+    * embedded in the proxy */
+   for (voms_cert = vd->data; voms_cert && *voms_cert; voms_cert++) {
+      char *tmp, *ptr;
+      size_t tmp_len;
+
+      ret = renew_voms_cert(vd, voms_cert, &tmp, &tmp_len);
+      if (ret)
+        goto end;
+      ptr = realloc(buf, buf_len + tmp_len);
+      if (ptr == NULL) {
+         ret = ENOMEM;
+         goto end;
+      }
+      buf = ptr;
+      memcpy(buf + buf_len, tmp, tmp_len);
+      buf_len += tmp_len;
+   }
+
+   if (buf == NULL) {
+      /* no extension renewed, return */
+      ret = 0;
+      goto end;
+   }
+
+   ret = my_VOMS_Export(buf, buf_len, &extension);
+   if (ret)
+      goto end;
+
+   ret = generate_proxy(cur_proxy, extension, new_file);
+
+end:
+#if 0
+   if (ret)
+      unlink(new_file);
+#endif
+   (old_env_proxy) ? setenv("X509_USER_PROXY", old_env_proxy, 1) :
+                    unsetenv("X509_USER_PROXY");
+
+   VOMS_Destroy(vd);
+
+   return ret;
+}
+
+#if 0
+int
+main(int argc, char *argv[])
+{
+   int ret;
+   const char *current_proxy = "/tmp/x509up_u11930";
+   const char *renewed_proxy = "/tmp/proxy";
+
+   if (argc > 1)
+      current_proxy = argv[1];
+   if (argc > 2)
+      renewed_proxy = argv[2];
+
+   if (globus_module_activate(GLOBUS_GSI_PROXY_MODULE) != GLOBUS_SUCCESS ||
+       globus_module_activate(GLOBUS_GSI_CERT_UTILS_MODULE) != GLOBUS_SUCCESS) {
+       fprintf(stderr, "[%d]: Unable to initialize Globus modules\n", getpid());
+       return 1;
+   }
+
+   ret = renew_voms_certs(current_proxy, renewed_proxy);
+
+   return 0;
+}
+#endif