Added renewal_core library exporting calls to perform actual renewal
authorDaniel Kouřil <kouril@ics.muni.cz>
Fri, 11 Aug 2006 13:43:41 +0000 (13:43 +0000)
committerDaniel Kouřil <kouril@ics.muni.cz>
Fri, 11 Aug 2006 13:43:41 +0000 (13:43 +0000)
org.glite.security.proxyrenewal/Makefile
org.glite.security.proxyrenewal/interface/renewal_core.h [new file with mode: 0644]
org.glite.security.proxyrenewal/src/renewal_core.c [new file with mode: 0644]
org.glite.security.proxyrenewal/src/renewal_core_compat.c [new file with mode: 0644]

index 3730746..d011319 100644 (file)
@@ -73,20 +73,28 @@ INSTALL:=libtool --mode=install install
 
 DAEMONOBJ:=renewd.o renew.o common.o commands.o api.o voms.o
 LIBOBJ:=api.o common.o
+LIB_CORE_OBJS := renewal_core.o voms.o renewal_core_compat.o
 CLIENTOBJ:=client.o
 
 THRLIBOBJ:=${LIBOBJ:.o=.thr.o}
 LIBLOBJ:=${LIBOBJ:.o=.lo}
 THRLIBLOBJ:=${LIBOBJ:.o=.thr.lo}
 
+LIB_CORE_NOTHR_OBJS := ${LIB_CORE_OBJS}
+LIB_CORE_NOTHR_LOBJS := ${LIB_CORE_OBJS:.o=.lo}
+LIB_CORE_THR_OBJS := ${LIB_CORE_OBJS:.o=.thr.o}
+LIB_CORE_THR_LOBJS := ${LIB_CORE_OBJS:.o=.thr.lo}
+
 LIB:=libglite_security_proxyrenewal_${nothrflavour}.la
 THRLIB:=libglite_security_proxyrenewal_${thrflavour}.la
+LIB_CORE_NOTHR := libglite_security_proxyrenewal_core_${nothrflavour}.la
+LIB_CORE_THR := libglite_security_proxyrenewal_core_${thrflavour}.la
 
 DAEMON:=glite-proxy-renewd
 CLIENT:=glite-proxy-renew
 
 default: all
-compile all: ${LIB} ${THRLIB} ${DAEMON} ${CLIENT}
+compile all: ${LIB} ${THRLIB} ${LIB_CORE_NOTHR} ${DAEMON} ${CLIENT}
 
 ${LIB}: ${LIBOBJ}
        ${LINK} -o $@ ${LIBLOBJ} -rpath ${glite_location}/lib ${JOBIDLIB}
@@ -95,13 +103,16 @@ ${LIB}: ${LIBOBJ}
 ${THRLIB}: ${THRLIBOBJ}
        ${LINK} -o $@ ${THRLIBLOBJ} -rpath ${glite_location}/lib
 
+${LIB_CORE_NOTHR}: ${LIB_CORE_NOTHR_OBJS}
+       ${LINK} -o $@ ${LIB_CORE_NOTHR_OBJS} -rpath ${glite_location}/lib ${MYPROXY_LIB} -L${glite_location}/lib -lvomsc_${nothrflavour}
+
 ${DAEMON}: ${DAEMONOBJ}
        ${LINK} -o $@ ${DAEMONOBJ} ${JOBIDLIB} ${MYPROXY_LIB} -lvomsc -lglobus_gss_assist_${nothrflavour} ${GLOBUS_LIBS} 
 
 ${CLIENT}: ${CLIENTOBJ} ${LIB}
        ${LINK} -o $@ ${CLIENTOBJ} ${LIB} ${GLOBUS_LIBS}
 
-${THRLIBOBJ}: %.thr.o: %.c
+${THRLIBOBJ} ${LIB_CORE_THR_OBJS}: %.thr.o: %.c
        ${COMPILE} ${GLOBUSTHRINC} -o $@ -c $<
 
 %.o: %.c
@@ -129,13 +140,13 @@ distbin:
 
 install:
        -mkdir -p ${PREFIX}/bin ${PREFIX}/lib ${PREFIX}/include/glite/security/proxyrenewal ${PREFIX}/share/doc/${package}-${version} ${PREFIX}/etc/init.d
-       ${INSTALL} -m 644 ${LIB} ${THRLIB} ${PREFIX}/lib
+       ${INSTALL} -m 644 ${LIB} ${THRLIB} ${LIB_CORE_NOTHR} ${PREFIX}/lib
        ${INSTALL} -m 755 ${DAEMON} ${CLIENT} ${PREFIX}/bin
        ${INSTALL} -m 644 ${top_srcdir}/LICENSE ${PREFIX}/share/doc/${package}-${version}
-       cd ${top_srcdir}/interface && ${INSTALL} -m 644 renewal.h ${PREFIX}/include/glite/security/proxyrenewal
+       cd ${top_srcdir}/interface && ${INSTALL} -m 644 renewal.h renewal_core.h ${PREFIX}/include/glite/security/proxyrenewal
 
        ${INSTALL} -m 755 ${top_srcdir}/config/startup ${PREFIX}/etc/init.d/glite-proxy-renewald
 
 
 clean:
-       $(RM) $(LIB) $(DAEMON) $(CLIENT) *.o core 
+       $(RM) $(LIB) ${LIB_CORE_NOTHR} $(DAEMON) $(CLIENT) *.o core 
diff --git a/org.glite.security.proxyrenewal/interface/renewal_core.h b/org.glite.security.proxyrenewal/interface/renewal_core.h
new file mode 100644 (file)
index 0000000..8348963
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef RENEWAL_CORE_H
+#define RENEWAL_CORE_H
+
+#ident "$Id$"
+
+#include <sys/syslog.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+       GLITE_RENEWAL_LOG_NONE,
+       GLITE_RENEWAL_LOG_STDOUT,
+       GLITE_RENEWAL_LOG_SYSLOG,
+} glite_renewal_log_dst;
+
+typedef struct glite_renewal_core_context_data {
+  int log_level;
+  glite_renewal_log_dst log_dst;
+  char *err_message;
+  char *voms_conf;
+} glite_renewal_core_context_data;
+
+typedef struct glite_renewal_core_context_data *glite_renewal_core_context;
+
+/**
+ * This cal initializes the context and sets default values
+ */
+int
+glite_renewal_core_init_ctx(glite_renewal_core_context *context);
+
+/**
+ * This call frees the context and all memory used by the context
+ */
+int
+glite_renewal_core_destroy_ctx(glite_renewal_core_context context);
+
+/**
+ * This call tries to renew the proxy certificate using the MyProxy
+ * repository. If VOMS attributes are present in the proxy they are renewed
+ * as well.
+ * \param context IN: context with authentication information
+ * \param myproxy_server IN: hostname of the myproxy repository
+ * \param myproxy_port IN: TCP port of the myproxy repository, if 0 the
+ * default value will be used
+ * \param current_proxy IN: filename with the proxy to renew
+ * \param new_proxy OUT: filename with the renewed proxy, the caller is
+ * responsible for removing the file when it's not needed.
+ */
+int
+glite_renewal_core_renew(glite_renewal_core_context context,
+                        const char *myproxy_server,
+                        unsigned int myproxy_port,
+                        const char *current_proxy,
+                        char **new_proxy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RENEWAL_CORE_H */
diff --git a/org.glite.security.proxyrenewal/src/renewal_core.c b/org.glite.security.proxyrenewal/src/renewal_core.c
new file mode 100644 (file)
index 0000000..3bd2d1d
--- /dev/null
@@ -0,0 +1,283 @@
+#include <myproxy.h>
+#include <myproxy_delegation.h>
+
+#include "renewal_core.h"
+#include "renewal_locl.h"
+#include "renewd_locl.h"
+
+static const char rcsid[] = "$Id$";
+
+int
+glite_renewal_load_proxy(glite_renewal_core_context ctx, const char *cur_file, X509 **cert, EVP_PKEY **priv_key,
+           STACK_OF(X509) **chain, globus_gsi_cred_handle_t *cur_proxy)
+{
+   globus_result_t result;
+   globus_gsi_cred_handle_t proxy = NULL;
+   int ret;
+
+   result = globus_gsi_cred_handle_init(&proxy, NULL);
+   if (result) {
+      fprintf(stderr, "globus_gsi_cred_handle_init() failed\n");
+      goto end;
+   }
+
+   result = globus_gsi_cred_read_proxy(proxy, (char *) cur_file);
+   if (result) {
+      fprintf(stderr, "globus_gsi_cred_read_proxy() failed\n");
+      goto end;
+   }
+
+   if (cert) {
+      result = globus_gsi_cred_get_cert(proxy, cert);
+      if (result) {
+        fprintf(stderr, "globus_gsi_cred_get_cert() failed\n");
+        goto end;
+      }
+   }
+
+   if (priv_key) {
+      result = globus_gsi_cred_get_key(proxy, priv_key);
+      if (result) {
+        fprintf(stderr, "globus_gsi_cred_get_key() failed\n");
+        goto end;
+      }
+   }
+
+   if (chain) {
+      result = globus_gsi_cred_get_cert_chain(proxy, chain);
+      if (result) {
+        fprintf(stderr, "globus_gsi_cred_get_cert_chain() failed\n");
+        goto end;
+      }
+   }
+
+   if (cur_proxy) {
+      *cur_proxy = proxy;
+      proxy = NULL;
+   }
+
+   ret = 0;
+   
+end:
+   if (proxy)
+      globus_gsi_cred_handle_destroy(proxy);
+   if (result)
+      ret = EDG_WLPR_ERROR_GENERIC;
+
+   return ret;
+}
+
+int
+glite_renewal_get_proxy_base_name(glite_renewal_core_context ctx, const char *file, char **name)
+{
+   X509 *cert = NULL;
+   EVP_PKEY *key = NULL;
+   STACK_OF(X509) *chain = NULL;
+   X509_NAME *subject = NULL;
+   int ret;
+   globus_result_t result;
+
+   ret = glite_renewal_load_proxy(ctx, file, &cert, &key, &chain, NULL);
+   if (ret)
+      return ret;
+
+   subject = X509_NAME_dup(X509_get_subject_name(cert));
+
+   sk_X509_insert(chain, cert, 0);
+   cert = NULL;
+
+   result = globus_gsi_cert_utils_get_base_name(subject, chain);
+   if (result) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot get subject name from proxy %s", file);
+      ret = EDG_WLPR_ERROR_SSL; /* XXX ??? */
+      goto end;
+   }
+
+   *name = X509_NAME_oneline(subject, NULL, 0);
+   ret = 0;
+
+end:
+   if (cert)
+      X509_free(cert);
+   if (key)
+      EVP_PKEY_free(key);
+   if (chain)
+      sk_X509_pop_free(chain, X509_free);
+   if (subject)
+      X509_NAME_free(subject);
+
+   return ret;
+}
+
+int
+glite_renewal_core_renew(glite_renewal_core_context ctx,
+                         const char * myproxy_server,
+                        unsigned int myproxy_port,
+                         const char *current_proxy,
+                         char **new_proxy)
+{
+   char tmp_proxy[FILENAME_MAX];
+   int tmp_fd;
+   int ret = -1;
+   char *p;
+   const char *server = NULL;
+   myproxy_socket_attrs_t *socket_attrs;
+   myproxy_request_t      *client_request;
+   myproxy_response_t     *server_response;
+   char *renewed_proxy;
+   int voms_exts;
+
+   socket_attrs = malloc(sizeof(*socket_attrs));
+   memset(socket_attrs, 0, sizeof(*socket_attrs));
+
+   client_request = malloc(sizeof(*client_request));
+   memset(client_request, 0, sizeof(*client_request));
+
+   server_response = malloc(sizeof(*server_response));
+   memset(server_response, 0, sizeof(*server_response));
+
+   myproxy_set_delegation_defaults(socket_attrs, client_request);
+
+   glite_renewal_log(ctx, LOG_DEBUG, "Trying to renew proxy in %s", current_proxy);
+
+   snprintf(tmp_proxy, sizeof(tmp_proxy), "%s.myproxy.XXXXXX", current_proxy);
+   tmp_fd = mkstemp(tmp_proxy);
+   if (tmp_fd == -1) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot create temporary file (%s)",
+                   strerror(errno));
+      return errno;
+   }
+
+   ret = glite_renewal_get_proxy_base_name(ctx, current_proxy, &client_request->username);
+   if (ret)
+      goto end;
+
+   voms_exts = glite_renewal_check_voms_attrs(ctx, current_proxy);
+
+   client_request->proxy_lifetime = 60 * 60 * DGPR_RETRIEVE_DEFAULT_HOURS;
+
+   server = (myproxy_server) ? myproxy_server : socket_attrs->pshost;
+   if (server == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "No myproxy server specified");
+      ret = EINVAL;
+      goto end;
+   }
+   socket_attrs->pshost = strdup(server);
+
+   socket_attrs->psport = (myproxy_port) ? myproxy_port : MYPROXY_SERVER_PORT;
+
+   verror_clear();
+   ret = myproxy_get_delegation(socket_attrs, client_request, (char *) current_proxy,
+                               server_response, tmp_proxy);
+   if (ret == 1) {
+      ret = EDG_WLPR_ERROR_MYPROXY;
+      glite_renewal_log(ctx, LOG_ERR, "Error contacting MyProxy server for proxy %s: %s",
+                  current_proxy, verror_get_string());
+      verror_clear();
+      goto end;
+   }
+
+   renewed_proxy = tmp_proxy;
+
+   if (voms_exts) {
+      char tmp_voms_proxy[FILENAME_MAX];
+      int tmp_voms_fd;
+      
+      snprintf(tmp_voms_proxy, sizeof(tmp_voms_proxy), "%s.voms.XXXXXX",
+              current_proxy);
+      tmp_voms_fd = mkstemp(tmp_voms_proxy);
+      if (tmp_voms_fd == -1) {
+        glite_renewal_log(ctx, LOG_ERR, "Cannot create temporary file (%s)",
+                     strerror(errno));
+        ret = errno;
+        goto end;
+      }
+
+      ret = glite_renewal_renew_voms_creds(ctx, current_proxy, renewed_proxy, tmp_voms_proxy);
+      close(tmp_voms_fd);
+      if (ret) {
+        unlink(tmp_voms_proxy);
+        goto end;
+      }
+
+      renewed_proxy = tmp_voms_proxy;
+      unlink(tmp_proxy);
+   }
+
+   if (new_proxy)
+      *new_proxy = strdup(renewed_proxy);
+
+   ret = 0;
+
+end:
+   if (socket_attrs->socket_fd)
+      close(socket_attrs->socket_fd);
+   close(tmp_fd);
+   if (ret)
+      unlink(tmp_proxy);
+   myproxy_free(socket_attrs, client_request, server_response);
+
+   return ret;
+}
+
+int
+glite_renewal_core_init_ctx(glite_renewal_core_context *context)
+{
+   glite_renewal_core_context p = NULL;
+
+   *context = NULL;
+
+   p = calloc(1, sizeof(*p));
+   if (p == NULL)
+      return ENOMEM;
+
+   p->log_level = LOG_ERR;
+   p->log_dst = GLITE_RENEWAL_LOG_SYSLOG;
+
+   *context = p;
+   return 0;
+}
+
+int
+glite_renewal_core_destroy_ctx(glite_renewal_core_context context)
+{
+   if (context == NULL)
+      return 0;
+   if (context->err_message);
+      free(context->err_message);
+   free(context);
+   return 0;
+}
+
+void
+glite_renewal_log(glite_renewal_core_context context, int dbg_level, const char *format, ...)
+{
+   va_list ap;
+
+   if (context->err_message) {
+      free(context->err_message);
+      context->err_message = NULL;
+   }
+   
+   /* cannot handle the %m format argument specific for syslog() */
+   va_start(ap, format);
+   vasprintf(&context->err_message, format, ap);
+   va_end(ap);
+
+   if (dbg_level > context->log_level)
+      return;
+
+   switch (context->log_dst) {
+      case GLITE_RENEWAL_LOG_STDOUT:
+        printf("%s\n", context->err_message);
+        break;
+      case GLITE_RENEWAL_LOG_SYSLOG:
+        syslog(dbg_level, "%s", context->err_message);
+        break;
+      case GLITE_RENEWAL_LOG_NONE:
+      default:
+        break;
+   }
+
+   return;
+}
diff --git a/org.glite.security.proxyrenewal/src/renewal_core_compat.c b/org.glite.security.proxyrenewal/src/renewal_core_compat.c
new file mode 100644 (file)
index 0000000..80c50f2
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * This is a "glue" file containing various pieces that are needed to build
+ * separated renewal_core library.
+ */
+
+#include <glite/security/voms/voms_apic.h>
+
+#include "renewal_core.h"
+#include "renewal_locl.h"
+#include "renewd_locl.h"
+
+char *vomsconf = NULL;
+static glite_renewal_core_context saved_ctx = NULL;
+
+/* Wrapper calling renew_voms_creds() from voms.o */
+int
+glite_renewal_renew_voms_creds(glite_renewal_core_context ctx, const char *cur_file, const char *renewed_file, const char *new_file)
+{
+   int ret;
+
+   vomsconf = ctx->voms_conf;
+   saved_ctx = ctx;
+   ret = renew_voms_creds(cur_file, renewed_file, new_file);
+   saved_ctx = NULL;
+
+   return ret;
+}
+
+/* This is called from voms.o, normaly it sits in renew.o, which we don't want
+ * to add to the renewal_core lib. */
+int
+load_proxy(const char *cur_file, X509 **cert, EVP_PKEY **priv_key,
+           STACK_OF(X509) **chain, globus_gsi_cred_handle_t *cur_proxy)
+{
+   assert(saved_ctx != NULL);
+
+   return glite_renewal_load_proxy(saved_ctx, cur_file, cert, priv_key, chain, cur_proxy);
+}
+
+/* This is called from voms.o */
+void
+edg_wlpr_Log(int dbg_level, const char *format, ...)
+{
+   char *str;
+   va_list ap;
+
+   assert(saved_ctx != NULL);
+
+   va_start(ap, format);
+   vasprintf(&str, format, ap);
+   va_end(ap);
+
+   glite_renewal_log(saved_ctx, dbg_level, "%s", str);
+   free(str);
+}
+
+/* A new call not implemented in 3.0 version of voms.o */
+int
+glite_renewal_check_voms_attrs(glite_renewal_core_context ctx, const char *proxy)
+{
+   int ret, voms_err, present;
+   X509 *cert = NULL;
+   STACK_OF(X509) *chain = NULL;
+   struct vomsdata *vd = NULL;
+
+   ret = glite_renewal_load_proxy(ctx, proxy, &cert, NULL, &chain, NULL);
+   if (ret)
+      return 0;
+
+   vd = VOMS_Init(NULL, NULL);
+   if (vd == NULL) {
+      present = 0;
+      goto end;
+   }
+
+   ret = VOMS_Retrieve(cert, chain, RECURSE_CHAIN, vd, &voms_err);
+   if (ret == 0) {
+      present = 0;
+      goto end;
+   }
+
+   present = 1;
+
+end:
+   if (cert)
+      X509_free(cert);
+   if (chain)
+      sk_X509_pop_free(chain, X509_free);
+   if (vd)
+      VOMS_Destroy(vd);
+
+   return present;
+}