Moving files to proper locations
authorZdeněk Šustr <sustr4@cesnet.cz>
Mon, 4 Oct 2010 09:53:36 +0000 (09:53 +0000)
committerZdeněk Šustr <sustr4@cesnet.cz>
Mon, 4 Oct 2010 09:53:36 +0000 (09:53 +0000)
24 files changed:
org.glite.px.proxyrenewal/LICENSE [new file with mode: 0644]
org.glite.px.proxyrenewal/Makefile [new file with mode: 0644]
org.glite.px.proxyrenewal/build.xml [new file with mode: 0755]
org.glite.px.proxyrenewal/config/startup [new file with mode: 0755]
org.glite.px.proxyrenewal/examples/renew_core.c [new file with mode: 0644]
org.glite.px.proxyrenewal/interface/renewal.h [new file with mode: 0644]
org.glite.px.proxyrenewal/interface/renewal_core.h [new file with mode: 0644]
org.glite.px.proxyrenewal/project/build.number [new file with mode: 0644]
org.glite.px.proxyrenewal/project/build.properties [new file with mode: 0644]
org.glite.px.proxyrenewal/project/configure.properties.xml [new file with mode: 0644]
org.glite.px.proxyrenewal/project/properties.xml [new file with mode: 0755]
org.glite.px.proxyrenewal/project/tar_exclude [new file with mode: 0644]
org.glite.px.proxyrenewal/project/taskdefs.xml [new file with mode: 0755]
org.glite.px.proxyrenewal/project/version.properties [new file with mode: 0644]
org.glite.px.proxyrenewal/src/api.c [new file with mode: 0644]
org.glite.px.proxyrenewal/src/client.c [new file with mode: 0644]
org.glite.px.proxyrenewal/src/commands.c [new file with mode: 0644]
org.glite.px.proxyrenewal/src/common.c [new file with mode: 0644]
org.glite.px.proxyrenewal/src/renew.c [new file with mode: 0644]
org.glite.px.proxyrenewal/src/renewal_core.c [new file with mode: 0644]
org.glite.px.proxyrenewal/src/renewal_locl.h [new file with mode: 0644]
org.glite.px.proxyrenewal/src/renewd.c [new file with mode: 0644]
org.glite.px.proxyrenewal/src/renewd_locl.h [new file with mode: 0644]
org.glite.px.proxyrenewal/src/voms.c [new file with mode: 0644]

diff --git a/org.glite.px.proxyrenewal/LICENSE b/org.glite.px.proxyrenewal/LICENSE
new file mode 100644 (file)
index 0000000..01b973b
--- /dev/null
@@ -0,0 +1,69 @@
+LICENSE file for EGEE Middleware
+================================
+
+Copyright (c) 2004 on behalf of the EU EGEE Project: 
+The European Organization for Nuclear Research (CERN), 
+Istituto Nazionale di Fisica Nucleare (INFN), Italy
+Datamat Spa, Italy
+Centre National de la Recherche Scientifique (CNRS), France
+CS Systeme d'Information (CSSI), France
+Royal Institute of Technology, Center for Parallel Computers (KTH-PDC), Sweden
+Universiteit van Amsterdam (UvA), Netherlands
+University of Helsinki (UH.HIP), Finlan
+University of Bergen (UiB), Norway
+Council for the Central Laboratory of the Research Councils (CCLRC), United Kingdom
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met: 
+
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+3. The end-user documentation included with the redistribution, if
+any, must include the following acknowledgment: "This product includes
+software developed by The EU EGEE Project (http://cern.ch/eu-egee/)."
+Alternatively, this acknowledgment may appear in the software itself, if
+and wherever such third-party acknowledgments normally appear.
+
+4. The names EGEE and the EU EGEE Project must not be
+used to endorse or promote products derived from this software without
+prior written permission. For written permission, please contact
+<email address>.
+
+5. You are under no obligation whatsoever to provide anyone with any
+bug fixes, patches, or upgrades to the features, functionality or
+performance of the Software ("Enhancements") that you may develop over
+time; however, if you choose to provide your Enhancements to The EU
+EGEE Project, or if you choose to otherwise publish or distribute your
+Enhancements, in source code form without contemporaneously requiring
+end users of The EU EGEE Proejct to enter into a separate written license
+agreement for such Enhancements, then you hereby grant The EU EGEE Project
+a non-exclusive, royalty-free perpetual license to install, use, copy,
+modify, prepare derivative works, incorporate into the EGEE Middleware
+or any other computer software, distribute, and sublicense your
+Enhancements or derivative works thereof, in binary and source code
+form (if any), whether developed by The EU EGEE Project or third parties.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL PROJECT OR ITS CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the EU EGEE Prject. For more information on The
+EU EGEE Project, please see http://cern.ch/eu-egee/. For more information on
+EGEE Middleware, please see http://egee-jra1.web.cern.ch/egee-jra1/
+
+
diff --git a/org.glite.px.proxyrenewal/Makefile b/org.glite.px.proxyrenewal/Makefile
new file mode 100644 (file)
index 0000000..24252c7
--- /dev/null
@@ -0,0 +1,167 @@
+#
+# Copyright (c) 2004 on behalf of the EU EGEE Project:
+# The European Organization for Nuclear Research (CERN),
+# Istituto Nazionale di Fisica Nucleare (INFN), Italy
+# Datamat Spa, Italy
+# Centre National de la Recherche Scientifique (CNRS), France
+# CS Systeme d'Information (CSSI), France
+# Royal Institute of Technology, Center for Parallel Computers (KTH-PDC), Sweden
+# Universiteit van Amsterdam (UvA), Netherlands
+# University of Helsinki (UH.HIP), Finland
+# University of Bergen (UiB), Norway
+# Council for the Central Laboratory of the Research Councils (CCLRC), United Kingdom
+#
+# Top Makefile file for the GLite Security Proxyrenewal module
+#
+# Authors: Ales Krenek <ljocha@ics.muni.cz>
+# Version info: $Id$
+# Release: $Name$
+#
+# Revision history:
+# $Log
+#
+
+# defaults
+top_srcdir=.
+builddir=build
+top_builddir=${top_srcdir}/${builddir}
+stagedir=.
+distdir=.
+globalprefix=glite
+lbprefix=lb
+package=glite-security-proxyrenewal
+version=0.0.0
+PREFIX=/opt/glite
+
+glite_location=$PREFIX
+globus_prefix=/opt/globus
+nothrflavour=gcc32
+thrflavour=gcc32pthr
+myproxy_prefix=$globus_prefix
+
+-include Makefile.inc
+
+VPATH:=${top_srcdir}/src:${top_srcdir}/examples
+
+GLOBUSINC:= -I${globus_prefix}/include/${nothrflavour} \
+       -I${globus_prefix}/include/${nothrflavour}/openssl
+
+GLOBUSTHRINC:= -I${globus_prefix}/include/${thrflavour} \
+       -I${globus_prefix}/include/${thrflavour}/openssl
+
+MYPROXYINC:= -I${myproxy_prefix}/include/${nothrflavour}
+MYPROXYTHRINC:= -I${myproxy_prefix}/include/${thrflavour}
+
+DEBUG:=-g -O0
+
+CFLAGS:= ${DEBUG} \
+       ${MYPROXYINC} \
+       -I${top_srcdir}/src -I${top_srcdir}/interface \
+       -I${glite_location}/include
+
+GLOBUS_LIBS:=-L${globus_prefix}/lib \
+       -lglobus_common_${nothrflavour} \
+       -lssl_${nothrflavour}
+
+MYPROXY_LIB_NOTHR :=-L${myproxy_prefix}/lib -lmyproxy_${nothrflavour}
+MYPROXY_LIB_THR:=-L${myproxy_prefix}/lib -lmyproxy_${thrflavour}
+
+offset=1
+version_info:=-version-info ${shell \
+       perl -e '$$,=":"; @F=split "\\.","${version}"; print $$F[0]+$$F[1]+${offset},$$F[2],$$F[1]' }
+
+COMPILE:=libtool --mode=compile ${CC} ${CFLAGS}
+LINK:=libtool --mode=link ${CC} ${LDFLAGS}
+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
+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
+
+VOMS_LIB_NOTHR := -L${glite_location}/lib -lvomsc_${nothrflavour}
+VOMS_LIB_THR := -L${glite_location}/lib -lvomsc_${thrflavour}
+
+DAEMON:=glite-proxy-renewd
+CLIENT:=glite-proxy-renew
+EXAMPLES := renew_core
+
+default: all
+compile all: ${LIB} ${THRLIB} ${LIB_CORE_NOTHR} ${DAEMON} ${CLIENT} 
+
+${LIB}: ${LIBOBJ}
+       ${LINK} ${version_info} -o $@ ${LIBLOBJ} -rpath ${glite_location}/lib
+
+${THRLIB}: ${THRLIBOBJ}
+       ${LINK} ${version_info} -o $@ ${THRLIBLOBJ} -rpath ${glite_location}/lib
+
+${LIB_CORE_NOTHR}: ${LIB_CORE_NOTHR_OBJS}
+       ${LINK} ${version_info} -o $@ ${LIB_CORE_NOTHR_LOBJS} -rpath ${glite_location}/lib ${MYPROXY_LIB_NOTHR} ${VOMS_LIB_NOTHR}
+
+${LIB_CORE_THR}: ${LIB_CORE_THR_OBJS}
+       ${LINK} ${version_info} -o $@ ${LIB_CORE_THR_LOBJS} -rpath ${glite_location}/lib ${MYPROXY_LIB_THR} ${VOMS_LIB_THR}
+
+${DAEMON}: ${DAEMONOBJ} ${LIB_CORE_NOTHR}
+       ${LINK} -o $@ ${DAEMONOBJ} ${LIB_CORE_NOTHR} 
+
+${CLIENT}: ${CLIENTOBJ} ${LIB}
+       ${LINK} -o $@ ${CLIENTOBJ} ${LIB} ${GLOBUS_LIBS}
+
+${THRLIBOBJ} ${LIB_CORE_THR_OBJS}: %.thr.o: %.c
+       ${COMPILE} ${GLOBUSTHRINC} -o $@ -c $<
+
+%.o: %.c
+       ${COMPILE} ${GLOBUSINC} -c $<
+
+${EXAMPLES}: %: %.o
+       ${LINK} -o $@ $< ${LIB_CORE_NOTHR}
+
+stage: compile
+       $(MAKE) install PREFIX=${stagedir}
+
+check:
+       echo No unit tests
+
+examples: ${EXAMPLES}
+
+dist: distsrc distbin
+
+distsrc:
+       mkdir -p ${top_srcdir}/${package}-${version}
+       cd ${top_srcdir} && GLOBIGNORE="${package}-${version}" && cp -Rf * ${package}-${version}
+       cd ${top_srcdir} && tar -czf ${distdir}/${package}-${version}_src.tar.gz --exclude-from=project/tar_exclude ${package}-${version}
+       rm -rf ${top_srcdir}/${package}-${version}
+
+distbin:
+       $(MAKE) install PREFIX=`pwd`/tmpbuilddir
+       cd tmpbuilddir && tar -czf ../${top_srcdir}/${distdir}/${package}-${version}_bin.tar.gz *
+       rm -rf tmpbuilddir
+
+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} ${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 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) ${THRLIB} ${LIB_CORE_NOTHR} ${LIB_CORE_THR} $(DAEMON) $(CLIENT) $(EXAMPLES) *.o *.lo core 
+
+.PHONY: default all compile examples check stage dist distsrc distbin install clean
diff --git a/org.glite.px.proxyrenewal/build.xml b/org.glite.px.proxyrenewal/build.xml
new file mode 100755 (executable)
index 0000000..ac94daf
--- /dev/null
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+       Copyright (c) 2004 on behalf of the EU EGEE Project: 
+       The European Organization for Nuclear Research (CERN), 
+       Istituto Nazionale di Fisica Nucleare (INFN), Italy
+       Datamat Spa, Italy
+       Centre National de la Recherche Scientifique (CNRS), France
+       CS Systeme d'Information (CSSI), France
+       Royal Institute of Technology, Center for Parallel Computers (KTH-PDC), Sweden
+       Universiteit van Amsterdam (UvA), Netherlands
+       University of Helsinki (UH.HIP), Finland
+       University of Bergen (UiB), Norway
+       Council for the Central Laboratory of the Research Councils (CCLRC), United Kingdom
+
+       Build file for the GLite LB Client module
+       
+       Authors: Ales Krenek <ljocha@ics.muni.cz>
+       Version info: $Id$
+       Release: $Name$
+
+       Revision history:
+       $Log$
+       Revision 1.1.1.1  2010/10/01 12:00:11  zsustr
+       Proxyrenewal module moved here from org.glite.security.proxyrenewal.
+
+       Revision 1.6  2006/03/08 17:07:31  dkouril
+       Merged changes from the release branch (between merge_rc1_src_1 and merge_rc1_src_2)
+
+       Revision 1.5  2005/05/26 15:18:36  zurek
+       inserted module.build.file
+       
+       Revision 1.4  2004/11/02 15:10:43  dkouril
+       RPM description
+       
+       Revision 1.3  2004/07/30 08:31:07  dimeglio
+       Changed default Ant target from compile to dist
+       
+       Revision 1.2  2004/07/12 16:18:37  dimeglio
+       Modified to use myproxy from the repository if available
+       
+       Revision 1.1.1.1  2004/07/09 10:16:25  akrenek
+       initial import
+       
+       Revision 1.2  2004/07/07 09:24:57  akrenek
+       thr/nonthr flavours used correctly
+       
+       Revision 1.3  2004/07/06 17:45:30  flammer
+       Update of classpath definitions, targets & configure file.
+       
+       Revision 1.2  2004/06/23 00:29:33  dimeglio
+       Added standard comments and handling of support files
+       
+-->
+
+<project name="proxyrenewal" default="dist">
+       
+       <!-- =========================================
+            Import properties (order is important)
+            ========================================= -->
+
+       <!-- import baseline & user properties -->
+       <import file="../org.glite/project/baseline.properties.xml" />
+
+       <!-- import component build properties,
+                       component properties &
+                       component common properties -->
+       <import file="./project/properties.xml"/>
+       
+       <!-- import subsystem build properties,
+                       subsystem properties &
+                       subsystem common properties -->
+       <import file="${subsystem.properties.file}"/>
+
+       <!-- import global build properties &
+                       global properties -->
+       <import file="${global.properties.file}" />
+               
+       <!-- =========================================
+                Load dependency property files (order is important)
+            ========================================= -->
+       <property file="${user.dependencies.file}"/>
+       <property file="${component.dependencies.file}" />
+       <property file="${subsystem.dependencies.file}" />
+       <property file="${global.dependencies.file}"/>
+       
+       <!-- =========================================
+                Load configure options (order is important)
+            ========================================= -->
+       <import file="${global.configure.options.file}"/>
+       <import file="${component.configure.options.file}"/>
+
+       <!-- =========================================
+                Import task definitions (order is important)
+            ========================================= -->
+       <import file="${subsystem.taskdefs.file}" />
+       <import file="${global.taskdefs.file}" />
+                       
+       <!-- =========================================
+                Load common targets
+            ========================================= -->
+       <import file="${global.targets-simple_make.file}" />
+
+       <!-- =========================================
+                Load version file 
+            ========================================= -->
+       <property file="${module.version.file}"/>
+               <property file="${module.build.file}"/>
+       <property file="${module.build.file}" />
+               
+       <!-- ==============================================
+                Local private targets
+            ============================================== -->
+       
+       <target name="localinit"
+               description="Module specific initialization tasks">
+               <antcall target="secmakefiles" />
+       </target>
+               
+       <target name="localcompile"
+               description="Module specific compile tasks">
+       </target>
+       
+       <target name="localclean"
+               description="Module specific cleaning tasks">
+       </target>
+
+       <!-- =========================================
+                RPM settings
+            ========================================= -->
+
+       <property name="build.package.summary" value="Proxy renewal daemon" />
+       <property name="build.package.description" value="The daemon is responsible for secure and controled way of periodical renewal&#xA;of users' proxy certificates. Its primary goal is to support long-time jobs&#xA;running on the grid. This package also contains a library and header file&#xA;that allow to develop C/C++ applications accessing the daemon." />
+       
+</project>             
diff --git a/org.glite.px.proxyrenewal/config/startup b/org.glite.px.proxyrenewal/config/startup
new file mode 100755 (executable)
index 0000000..26ba757
--- /dev/null
@@ -0,0 +1,80 @@
+#!/bin/sh
+
+GLITE_LOCATION=${GLITE_LOCATION:-/opt/glite}
+GLITE_LOCATION_VAR=${GLITE_LOCATION_VAR:-/opt/glite/var}
+
+[ -f /etc/glite.conf ] && . /etc/glite.conf
+[ -f $GLITE_LOCATION/etc/glite-wms.conf ] && . $GLITE_LOCATION/etc/glite-wms.conf
+[ -f $HOME/.glite.conf ] && . $HOME/.glite.conf
+
+PROXY_REPOSITORY="$GLITE_LOCATION_VAR/spool/glite-renewd"
+
+unset creds
+
+start()
+{
+       if test -z "$GLITE_USER" ;then
+               echo 'Error: GLITE_USER is not set'
+               echo FAILED
+               return 1
+       fi
+
+       [ -n "$GLITE_HOST_CERT" -a -n "$GLITE_HOST_KEY" ] &&
+               creds="-t $GLITE_HOST_CERT -k $GLITE_HOST_KEY"
+
+       if test -z "$creds"; then
+               if su - $GLITE_USER -c "test -r /etc/grid-security/hostkey.pem -a -r /etc/grid-security/hostcert.pem"; then
+                       echo "$0: WARNING: /etc/grid-security/hostkey.pem readable by $GLITE_USER"
+                       creds="-t /etc/grid-security/hostcert.pem -k /etc/grid-security/hostkey.pem"
+               fi
+       fi
+
+       [ -z "$creds" ] &&
+               echo $0: WARNING: No credentials specified. Using default lookup which is dangerous. >&2
+
+       # workaround for VOMS_FindByVO that seems to always require user's own VOMS config file (bug #7511)
+       user_voms_config=$HOME/.glite/vomses
+       if [ ! -f "$user_voms_config" ]; then
+               rm -f /tmp/renewal_vomses
+               su - $GLITE_USER -c "touch /tmp/renewal_vomses && chmod 644 /tmp/renewal_vomses"
+               user_voms_config=/tmp/renewal_vomses
+       fi
+
+       echo -n Starting ProxyRenewal Daemon: glite-proxy-renewd ...
+
+       if [ ! -d "$PROXY_REPOSITORY" ]; then
+               mkdir -p $PROXY_REPOSITORY || exit 1
+               chown $GLITE_USER $PROXY_REPOSITORY
+               chmod 0700 $PROXY_REPOSITORY
+       fi
+       
+       su - $GLITE_USER -c "VOMS_USERCONF=$user_voms_config \
+               $GLITE_LOCATION/bin/glite-proxy-renewd \
+               -r $PROXY_REPOSITORY $creds -A" && echo " done"
+}
+
+stop()
+{
+       echo -n "Stopping ProxyRenewal Daemon: glite-proxy-renewd ..."
+       killall glite-proxy-renewd
+       echo " done"
+}
+
+status()
+{
+       if netstat -an --unix | grep "^unix .* LISTEN.* /tmp/dgpr_renew_" >/dev/null 2>&1 ;then
+               echo glite-proxy-renewd running
+       else
+               echo glite-proxy-renewd not running
+               return 1
+       fi
+}
+
+case x$1 in
+       xstart) start;;
+       xstop)  stop;;
+       xrestart) stop; start;;
+       xstatus) status;;
+       x*)     echo usage: $0 start,stop,restart,status >&2
+               exit 1;;
+esac
diff --git a/org.glite.px.proxyrenewal/examples/renew_core.c b/org.glite.px.proxyrenewal/examples/renew_core.c
new file mode 100644 (file)
index 0000000..69518ea
--- /dev/null
@@ -0,0 +1,63 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <glite/security/proxyrenewal/renewal_core.h>
+
+static struct option const long_options[] = {
+   { "server",   required_argument, 0, 's' },
+   { "proxy",    required_argument, 0, 'p' },
+   { "help",     no_argument,       0, 'h' },
+   { NULL, 0, NULL, 0}
+};
+
+static char short_options[] = "s:p:h";
+
+int
+main(int argc, char *argv[])
+{
+   char *server = NULL;
+   char *proxy = NULL;
+   char *new_proxy = NULL;
+   extern int optind;
+   char arg;
+   glite_renewal_core_context ctx = NULL;
+   int ret;
+
+   while ((arg = getopt_long(argc, argv, short_options, long_options, NULL)) != EOF) {
+      switch(arg) {
+       case 's':
+          server = optarg; break;
+       case 'p':
+          proxy = optarg; break;
+       case 'h':
+          fprintf(stdout, "Usage: %s --server <myproxy server> --proxy <filename>\n", argv[0]);
+          exit(1);
+      }
+   }
+
+   if (server == NULL || proxy == NULL) {
+      fprintf(stderr, "both server and proxy parameters must be given\n");
+      exit(1);
+   }
+
+   ret = glite_renewal_core_init_ctx(&ctx);
+   if (ret) {
+      fprintf(stderr, "glite_renewal_core_init_ctx() failed\n");
+      exit(1);
+   }
+
+   ctx->log_dst = GLITE_RENEWAL_LOG_NONE;
+
+   ret = glite_renewal_core_renew(ctx, server, 0, proxy, &new_proxy);
+   if (ret) {
+      fprintf(stderr, "%s: glite_renewal_core_renew() failed: %s",
+              argv[0], ctx->err_message);
+      exit(1);
+   }
+
+   ret = glite_renewal_core_destroy_ctx(ctx);
+
+   printf("%s\n", new_proxy);
+
+   return 0;
+}
diff --git a/org.glite.px.proxyrenewal/interface/renewal.h b/org.glite.px.proxyrenewal/interface/renewal.h
new file mode 100644 (file)
index 0000000..e07a89f
--- /dev/null
@@ -0,0 +1,175 @@
+/**
+ * \file proxyrenewal/renewal.h
+ * \author Daniel Kouril
+ * \author Miroslav Ruda
+ * \brief  API for proxy renewal.
+ * \version 2.0
+ *
+ * General rules:
+ * - functions return 0 on success, nonzero on error, errror details can
+ *   be found via edg_wlpr_GetErrorText()
+ */
+
+#ifndef RENEWAL_H
+#define RENEWAL_H
+
+#ident "$Header$"
+
+#ifdef RENEWAL_HAVE_JOBID
+#include "glite/wmsutils/jobid/cjobid.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EDG_WLPR_FLAG_UNIQUE   1
+#define EDG_WLPR_FLAG_UPDATE   2
+
+typedef enum _edg_wlpr_ErrorCode {
+/**
+ * Base for proxy renewal specific code.
+ * Start sufficently high not to collide with standard errno. */
+ /* XXX see common/exception_codes.h */
+    EDG_WLPR_ERROR_BASE = 1900,
+    EDG_WLPR_ERROR_UNEXPECTED_EOF,
+    EDG_WLPR_ERROR_GENERIC,
+    EDG_WLPR_ERROR_PROTO_PARSE_ERROR,
+    EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND,
+    EDG_WLPR_ERROR_UNKNOWN_COMMAND,
+    EDG_WLPR_ERROR_SSL,
+    EDG_WLPR_ERROR_MYPROXY,
+    EDG_WLPR_PROXY_NOT_REGISTERED,
+    EDG_WLPR_PROXY_EXPIRED,
+    EDG_WLPR_ERROR_VOMS,
+    EDG_WLPR_ERROR_TIMEOUT,
+    EDG_WLPR_ERROR_ERRNO,
+} edg_wlpr_ErrorCode;
+
+/**
+ * Return a human readable string containg description of the errorcode
+ * \retval char* pointer to a error description
+ */
+const char *
+edg_wlpr_GetErrorText(int err_code);
+
+/**
+ * This function contacts the renewal daemon and registers the specified proxy
+ * for periodic renewal.
+ * \param filename IN: specification of the proxy to register.
+ * \param jdl IN: JDL of the job owing the proxy. The JDL is looked for a 
+ * myproxy server contact.
+ * \param flags IN: one of EDG_WLPR_FLAG_UNIQUE or EDG_WLPR_FLAG_UPDATE, or
+ * their bitwise OR.
+ * \param repository_filename OUT: filename of registered proxy in repository.
+ * \retval 0 success
+ * \retval nonzero on error. Human readable form of the error can be get via
+ * edg_wlpr_GetErrorText().
+ */
+int
+edg_wlpr_RegisterProxy(
+      const char * filename,
+      const char *jdl,
+      int flags,
+      char ** repository_filename
+);
+
+/**
+ * The same function as edg_wlpr_RegisterProxy() but information about the
+ * myproxy server and jobid are passed as parameters instead of in JDL.
+ */
+#ifdef RENEWAL_HAVE_JOBID
+int
+edg_wlpr_RegisterProxyExt(
+      const char * filename,
+      const char * server,
+      unsigned int port,
+      edg_wlc_JobId jobid,
+      int flags,
+      char ** repository_filename
+);
+#endif
+
+int
+glite_renewal_RegisterProxy(
+       const char * filename,
+       const char * server,
+       unsigned int port,
+       const char *jobid,
+       int flags,
+       char ** repository_filename
+);
+
+/**
+ * Unregister proxy from the renewal daemon.
+ * \param jobid IN: specification of job whose proxy shall be unregistered
+ * \param filename IN: (optional) specification of the proxy to unregister.
+ * \retval 0 success
+ * \retval nonzero on error. Human readable form of the error can be get via
+ * edg_wlpr_GetErrorText().
+ */
+#ifdef RENEWAL_HAVE_JOBID
+int
+edg_wlpr_UnregisterProxy(
+      edg_wlc_JobId jobid,
+      const char * repository_filename
+);
+#endif
+
+int
+glite_renewal_UnregisterProxy(
+       const char * jobid,
+       const char * repository_filename
+);
+
+/**
+ * Get a list of registered proxies maintained by the renewal daemon.
+ * \param count OUT: number of proxies
+ * \param list OUT: a list of filenames separated by '\n'
+ * specifying the registered proxies. 
+ * \warning The caller is responsible for freeing the data.
+ * \retval 0 success
+ * \retval nonzero on error. Human readable form of the error can be get via
+ * edg_wlpr_GetErrorText().
+ */
+int
+edg_wlpr_GetList(int *count, char **list);
+
+/**
+ * Get a status message about a proxy.
+ * The function contacts the renewal daemon and retrieve information it 
+ * maintains about the proxy.
+ * \param filename IN: specification of the proxy to query
+ * \param info OUT: status message.
+ * \warning The caller is responsible for freeing the data.
+ * \retval 0 success
+ * \retval nonzero on error. Human readable form of the error can be get via
+ * edg_wlpr_GetErrorText().
+ */
+int
+edg_wlpr_GetStatus(const char *repository_filename, char **info);
+
+/**
+ * For given jobid return registered proxy filename from repository
+ * \param jobid IN: specification of jobid
+ * \param repository_filename OUT: proxy regitered for given jobid
+ * \warning The caller is responsible for freeing the data.
+ * \retval 0 success
+ * \retval nonzero on error. Human readable form of the error can be get via
+ * edg_wlpr_GetErrorText().
+ */
+#ifdef RENEWAL_HAVE_JOBID
+int
+edg_wlpr_GetProxy(edg_wlc_JobId jobid, char **repository_filename);
+#endif
+
+int
+glite_renewal_GetProxy(
+       const char * jobid,
+       char **repository_filename);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RENEWAL_H */
diff --git a/org.glite.px.proxyrenewal/interface/renewal_core.h b/org.glite.px.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.px.proxyrenewal/project/build.number b/org.glite.px.proxyrenewal/project/build.number
new file mode 100644 (file)
index 0000000..1936771
--- /dev/null
@@ -0,0 +1 @@
+module.build=137
diff --git a/org.glite.px.proxyrenewal/project/build.properties b/org.glite.px.proxyrenewal/project/build.properties
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/org.glite.px.proxyrenewal/project/configure.properties.xml b/org.glite.px.proxyrenewal/project/configure.properties.xml
new file mode 100644 (file)
index 0000000..e7dcdbd
--- /dev/null
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+       Copyright (c) 2004 on behalf of the EU EGEE Project: 
+       The European Organization for Nuclear Research (CERN), 
+       Istituto Nazionale di Fisica Nucleare (INFN), Italy
+       Datamat Spa, Italy
+       Centre National de la Recherche Scientifique (CNRS), France
+       CS Systeme d'Information (CSSI), France
+       Royal Institute of Technology, Center for Parallel Computers (KTH-PDC), Sweden
+       Universiteit van Amsterdam (UvA), Netherlands
+       University of Helsinki (UH.HIP), Finland
+       University of Bergen (UiB), Norway
+       Council for the Central Laboratory of the Research Councils (CCLRC), United Kingdom
+
+       Configuration options for the GLite Security Proxyrenewal module
+       
+       Authors: Ales Krenek <ljocha@ics.muni.cz>
+    Version info: $Id$
+    Release: $Name$
+
+    Revision history:
+    $Log$
+    Revision 1.1.1.1  2010/10/01 12:00:12  zsustr
+    Proxyrenewal module moved here from org.glite.security.proxyrenewal.
+
+    Revision 1.4  2005/03/09 08:09:30  dkouril
+    Removed double dash from last CVS comment as ant seems to not like it.
+
+    Revision 1.3  2005/03/08 12:51:23  dkouril
+    - Removed unused code
+    - enabled (and partly rewritten) support for renewal of VOMS attributes
+    - internal VOMS headers added - they are necessary to work with ASN.1 encoded
+      VOMS attribures (hopefully new version of the VOMS API will provide better
+      support)
+
+    Revision 1.2  2004/07/12 16:18:37  dimeglio
+    Modified to use myproxy from the repository if available
+
+-->
+
+       <!-- ======================================================
+         Define extra properties here ...
+         ====================================================== -->
+        
+       <project name="Security Proxyrenewal configuration options">                                                                        
+               <target name="secmakefiles">
+                       <exec executable="ln" failonerror="true">
+                               <arg line="-fs ${component.dir}/Makefile ${module.build.dir}/Makefile"/>
+                       </exec>
+                       <echo file="${module.build.dir}/Makefile.inc">
+top_srcdir=..
+builddir=build
+stagedir=${stage.abs.dir}
+distdir=${dist.dir}
+globalprefix=${global.prefix}
+package=${module.package.name}
+PREFIX=${install.dir}
+version=${module.version}
+glite_location=${with.glite.location}
+globus_prefix=${with.globus.prefix}
+thrflavour=${with.globus.thr.flavor}
+nothrflavour=${with.globus.nothr.flavor}
+myproxy_prefix=${with.myproxy.prefix}
+                       </echo>
+           </target>
+       </project>
diff --git a/org.glite.px.proxyrenewal/project/properties.xml b/org.glite.px.proxyrenewal/project/properties.xml
new file mode 100755 (executable)
index 0000000..c2e72fb
--- /dev/null
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+       Copyright (c) 2004 on behalf of the EU EGEE Project: 
+       The European Organization for Nuclear Research (CERN), 
+       Istituto Nazionale di Fisica Nucleare (INFN), Italy
+       Datamat Spa, Italy
+       Centre National de la Recherche Scientifique (CNRS), France
+       CS Systeme d'Information (CSSI), France
+       Royal Institute of Technology, Center for Parallel Computers (KTH-PDC), Sweden
+       Universiteit van Amsterdam (UvA), Netherlands
+       University of Helsinki (UH.HIP), Finland
+       University of Bergen (UiB), Norway
+       Council for the Central Laboratory of the Research Councils (CCLRC), United Kingdom
+
+       Common build properties file for the Glite Security Proxyrenewal component
+       
+       Authors: Ales Krenek <ljocha@ics.muni.cz>
+       Version info: $Id$
+       Release: $Name$ 
+       
+       Revision history:
+       $Log$
+       Revision 1.1.1.1  2010/10/01 12:00:12  zsustr
+       Proxyrenewal module moved here from org.glite.security.proxyrenewal.
+
+       Revision 1.3  2004/07/16 14:56:56  flammer
+       Corrected input path of build.properties.
+
+       Revision 1.2  2004/07/12 16:18:37  dimeglio
+       Modified to use myproxy from the repository if available
+       
+-->
+
+<project name="Security Proxyrenewal component common properties">
+
+       <!-- Include build properties to allow overwriting 
+            of properties for subsystem                    -->
+       <property file="project/build.properties" />    
+
+       <!-- ======================================================
+          Define corresponding subsystem properties
+                ====================================================== -->
+
+       <!-- Subsystem name -->
+       <property name="subsystem.name" value="${security.subsystem.name}"/>
+               
+       <!-- Subsystem prefix -->
+       <property name="subsystem.prefix" value="${security.subsystem.prefix}"/>
+
+       <!-- ======================================================
+          Define component properties
+                ====================================================== -->
+                               
+       <!-- Component name prefix -->
+       <property name="component.prefix" value="proxyrenewal" />
+                       
+       <!-- ======================================================
+          Define general component properties
+                ====================================================== -->
+       
+       <import file="${component.general.properties.file}" />
+                                               
+       <!-- ======================================================
+                Define extra properties here ...
+                ====================================================== -->
+                
+                                                               
+</project>
diff --git a/org.glite.px.proxyrenewal/project/tar_exclude b/org.glite.px.proxyrenewal/project/tar_exclude
new file mode 100644 (file)
index 0000000..e1fcd1a
--- /dev/null
@@ -0,0 +1,10 @@
+tar_exclude
+CVS
+build.xml
+build
+build.properties
+properties.xml
+configure.properties.xml
+.cvsignore
+.project
+.cdtproject
diff --git a/org.glite.px.proxyrenewal/project/taskdefs.xml b/org.glite.px.proxyrenewal/project/taskdefs.xml
new file mode 100755 (executable)
index 0000000..13e894e
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project name="tasks and types definitions">
+</project>
diff --git a/org.glite.px.proxyrenewal/project/version.properties b/org.glite.px.proxyrenewal/project/version.properties
new file mode 100644 (file)
index 0000000..1441742
--- /dev/null
@@ -0,0 +1,2 @@
+module.version=1.3.0
+module.age=1
diff --git a/org.glite.px.proxyrenewal/src/api.c b/org.glite.px.proxyrenewal/src/api.c
new file mode 100644 (file)
index 0000000..a72d692
--- /dev/null
@@ -0,0 +1,550 @@
+#include "renewal.h"
+#include "renewal_locl.h"
+
+#ident "$Header$"
+
+#define SEPARATORS "\n"
+
+/* prototypes of static routines */
+static int
+encode_request(edg_wlpr_Request *request, char **msg);
+
+static int
+decode_response(const char *msg, const size_t msg_len, edg_wlpr_Response *response);
+
+static int
+do_connect(char *socket_name, struct timeval *timeout, int *sock);
+
+static int
+send_request(int sock, struct timeval *timeout, edg_wlpr_Request *request, edg_wlpr_Response *response);
+
+static int 
+encode_request(edg_wlpr_Request *request, char **msg)
+{
+   char *buf;
+   size_t buf_len;
+   int ret;
+
+   buf_len = EDG_WLPR_BUF_SIZE;
+   buf = malloc(buf_len);
+   if (buf == NULL)
+      return ENOMEM;
+   buf[0] = '\0';
+
+   ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_VERSION,
+                            EDG_WLPR_VERSION, SEPARATORS);
+   if (ret)
+      goto err;
+
+   ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_COMMAND,
+                            edg_wlpr_EncodeInt(request->command),
+                            SEPARATORS);
+   if (ret)
+      goto err;
+
+   if (request->myproxy_server) {
+      char host[1024];
+
+#if 0
+      snprintf(host, sizeof(host), "%s:%d", request->myproxy_server, 
+              (request->myproxy_port) ? request->myproxy_port : EDG_WLPR_MYPROXY_PORT); /* XXX let server decide ? */
+#else
+      snprintf(host, sizeof(host), "%s", request->myproxy_server);
+#endif
+      ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_MYPROXY_SERVER,
+                               host, SEPARATORS);
+      if (ret)
+        goto err;
+   }
+
+   if (request->proxy_filename) {
+      ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_PROXY,
+                               request->proxy_filename, SEPARATORS);
+      if (ret)
+        goto err;
+   }
+
+   if (request->jobid) {
+      ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_JOBID,
+                               request->jobid, SEPARATORS);
+      if (ret)
+        goto err;
+   }
+
+   if (request->entries) {
+      char **p = request->entries;
+      while (*p) {
+        ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_ENTRY,
+                                  *p, SEPARATORS);
+        if (ret)
+           goto err;
+        p++;
+      }
+   }
+
+   buf[strlen(buf)] = '\0';
+   *msg = buf;
+   return 0;
+
+err:
+   free(buf);
+   *msg = NULL;
+   return ret;
+}
+
+static int
+decode_response(const char *msg, const size_t msg_len, edg_wlpr_Response *response)
+{
+   int ret;
+   char *value = NULL;
+   /* char *p; */
+   int i;
+   int current_size = 0;
+
+   /* XXX add an ending zero '\0' */
+
+   assert(msg != NULL);
+   assert(response != NULL);
+
+   memset(response, 0, sizeof(*response));
+
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_VERSION, SEPARATORS,
+                          0, &response->version);
+   if (ret)
+      goto err;
+
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_RESPONSE, SEPARATORS,
+                          0, &value);
+   if (ret)
+      goto err;
+
+   ret = edg_wlpr_DecodeInt(value, (int *)(&response->response_code));
+   free(value);
+   if (ret)
+      goto err;
+
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_MYPROXY_SERVER,
+                          SEPARATORS, 0, &response->myproxy_server);
+   if (ret && ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND)
+      goto err;
+
+#if 0
+   response->myproxy_port = EDG_WLPR_MYPROXY_PORT; /* ??? */
+   if (response->myproxy_server && (p = strchr(response->myproxy_server, ':'))) {
+      int port;
+      *p = '\0';
+      port = atol(p+1); /* XXX */
+      response->myproxy_port = port;
+   }
+#endif
+
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_START_TIME, SEPARATORS, 
+                          0, &value);
+   if (ret && ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND)
+      goto err;
+   if (ret == 0) {
+      ret = edg_wlpr_DecodeInt(value, (int *)(&response->start_time));
+      free(value);
+      if (ret)
+         goto err;
+   }
+
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_END_TIME, SEPARATORS,
+                          0, &value);
+   if (ret && ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND)
+      goto err;
+   if (ret == 0) { 
+      ret = edg_wlpr_DecodeInt(value, (int *)(&response->end_time));
+      free(value);
+      if (ret)
+        goto err;
+   }
+
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_RENEWAL_TIME,
+                          SEPARATORS, 0, &value);
+   if (ret && ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND)
+      goto err;
+   if (ret == 0) {
+      ret = edg_wlpr_DecodeInt(value, (int *)(&response->next_renewal_time));
+      free(value);
+      if (ret)
+        goto err;
+   }
+
+   /* XXX Counter */
+
+   i = 0;
+   while ((ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_PROXY,
+                                  SEPARATORS, i, &value)) == 0) {
+      if (i >= current_size) {
+        char **tmp;
+
+        tmp = realloc(response->filenames, 
+                      (current_size + 16 + 1) * sizeof(*tmp));
+        if (tmp == NULL) {
+           ret = ENOMEM;
+           goto err;
+        }
+        response->filenames = tmp;
+        current_size += 16;
+      }
+      response->filenames[i] = value;
+      i++;
+   }
+   if (ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND)
+      goto err;
+   if (response->filenames)
+      response->filenames[i] = NULL;
+
+   return 0;
+
+err:
+   edg_wlpr_CleanResponse(response);
+
+   return ret;
+}
+
+static int
+do_connect(char *socket_name, struct timeval *timeout, int *sock)
+{
+   struct sockaddr_un my_addr;
+   int s;
+   int ret;
+   struct timeval before,after;
+   int sock_err;
+   socklen_t err_len;
+
+   assert(sock != NULL);
+   memset(&my_addr, 0, sizeof(my_addr));
+
+   s = socket(AF_UNIX, SOCK_STREAM, 0);
+   if (s == -1) {
+      return errno;
+   }
+
+   if (timeout) {
+      int flags = fcntl(s, F_GETFL, 0);
+      if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
+        return errno;
+   }
+
+   my_addr.sun_family = AF_UNIX;
+   strncpy(my_addr.sun_path, socket_name, sizeof(my_addr.sun_path));
+
+   ret = connect(s, (struct sockaddr *) &my_addr, sizeof(my_addr));
+   if (ret == -1) {
+      if (errno == EINPROGRESS) {
+        struct pollfd pollfds[1];
+
+        pollfds[0].fd = s;
+        pollfds[0].events = POLLOUT;
+        
+        gettimeofday(&before,NULL);
+        switch (poll(pollfds, 1, timeout->tv_sec*1000+timeout->tv_usec/1000)) {
+           case -1: close(s);
+                    return errno;
+           case 0: close(s);
+                   return EDG_WLPR_ERROR_TIMEOUT;
+        }
+        gettimeofday(&after,NULL);
+        if (edg_wlpr_DecrementTimeout(timeout, before, after)) {
+           close (s);
+           return EDG_WLPR_ERROR_TIMEOUT;
+        }
+
+        err_len = sizeof sock_err;
+        if (getsockopt(s,SOL_SOCKET,SO_ERROR,&sock_err,&err_len)) {
+           close(s);
+           return errno;
+        }
+        if (sock_err) {
+           close(s);
+           errno = sock_err;
+           return errno;
+        }
+      } else {
+        close(s);
+        return errno;
+      }
+   }
+
+   *sock = s;
+   return 0;
+}
+
+static int
+send_request(int sock, struct timeval *timeout, edg_wlpr_Request *request, edg_wlpr_Response *response)
+{
+   int ret;
+   char *buf = NULL;
+   size_t buf_len;
+
+   /* timeouts ?? */
+
+   ret = encode_request(request, &buf);
+   if (ret)
+      return ret;
+
+   ret = edg_wlpr_Write(sock, timeout, buf, strlen(buf) + 1);
+   free(buf);
+   if (ret)
+      return ret;
+
+   ret = edg_wlpr_Read(sock, timeout, &buf, &buf_len);
+   if (ret)
+      return ret;
+
+   ret = decode_response(buf, buf_len, response);
+   free(buf);
+   if (ret)
+      return ret;
+
+   return 0;
+}
+
+int
+edg_wlpr_RequestSend(edg_wlpr_Request *request, edg_wlpr_Response *response)
+{
+   char sockname[1024];
+   int ret;
+   int sock;
+   struct timeval timeout;
+   const char *s = NULL;
+   double d;
+
+   s = getenv("GLITE_PR_TIMEOUT");
+   d = s ? atof(s) : GLITE_PR_TIMEOUT_DEFAULT;
+   timeout.tv_sec = (long) d;
+   timeout.tv_usec = (long) ((d-timeout.tv_sec) * 1e6);
+
+   snprintf(sockname, sizeof(sockname), "%s%d",
+           DGPR_REG_SOCKET_NAME_ROOT, getuid());
+   ret = do_connect(sockname, &timeout, &sock);
+   if (ret)
+      return ret;
+
+   ret = send_request(sock, &timeout, request, response);
+
+   close(sock);
+   return ret;
+}
+
+int
+glite_renewal_RegisterProxy(const char *filename, const char * server,
+                            unsigned int port,
+                            const char *jobid, int flags,
+                            char **repository_filename)
+{
+   edg_wlpr_Request request;
+   edg_wlpr_Response response;
+   int ret;
+
+   memset(&request, 0, sizeof(request));
+   memset(&response, 0, sizeof(response));
+
+   if (jobid == NULL)
+      return EINVAL;
+
+   request.command = EDG_WLPR_COMMAND_REG;
+   request.myproxy_server = server;
+   request.proxy_filename = filename;
+   request.jobid = strdup(jobid);
+   if (request.jobid == NULL)
+      return ENOMEM;
+
+   ret = edg_wlpr_RequestSend(&request, &response);
+   free(request.jobid);
+   if (ret == 0 && response.response_code == 0 && repository_filename &&
+       response.filenames && response.filenames[0] )
+      *repository_filename = strdup(response.filenames[0]);
+
+   if (ret == 0)
+      ret = response.response_code;
+
+   edg_wlpr_CleanResponse(&response);
+   
+   return ret;
+}
+
+#ifdef RENEWAL_HAVE_JOBID
+int
+edg_wlpr_RegisterProxyExt(const char *filename, const char * server,
+                         unsigned int port,
+                          edg_wlc_JobId jobid, int flags,
+                         char **repository_filename)
+{
+   char *ji;
+   int ret;
+
+   ji = edg_wlc_JobIdUnparse(jobid);
+   if (ji == NULL)
+      return EINVAL;
+
+   ret = glite_renewal_RegisterProxy(filename, server, port, ji, flags,
+                                    repository_filename);
+   free(ji);
+   return ret;
+}
+#endif /* RENEWAL_HAVE_JOBID */
+
+#if 0
+int
+edg_wlpr_RegisterProxy(const char *filename, const char *jdl,
+                       int flags, char **repository_filename)
+{
+   char server[1024];
+   size_t server_len;
+   unsigned int port = 0;
+   char *p, *q;
+   
+   memset(server, 0, sizeof(server));
+   
+   /* parse JDL and find information about myproxy server */
+   p = strstr(jdl, JDL_MYPROXY);
+   if (p == NULL)
+      return 0; /* XXX */
+   q = strchr(p, '\n'); /* XXX */
+   if (q)
+      server_len = q - p;
+   else 
+      server_len = jdl + strlen(jdl) - p;
+   if (server_len >= sizeof(server))
+      return EINVAL; /* XXX */
+   strncmp(server, p, sizeof(server));
+
+   return (edg_wlpr_RegisterProxyExt(filename, server, port, NULL, flags, 
+                                    repository_filename));
+}
+#endif
+
+int
+glite_renewal_UnregisterProxy(const char *jobid, const char *repository_filename)
+{
+   edg_wlpr_Request request;
+   edg_wlpr_Response response;
+   int ret;
+
+   memset(&request, 0, sizeof(request));
+   memset(&response, 0, sizeof(response));
+
+   if (jobid == NULL)
+      return EINVAL;
+
+   request.command = EDG_WLPR_COMMAND_UNREG;
+   request.proxy_filename = repository_filename;
+   request.jobid = strdup(jobid);
+   if (request.jobid == NULL)
+      return ENOMEM;
+
+   ret = edg_wlpr_RequestSend(&request, &response);
+   free(request.jobid);
+   
+   if (ret == 0)
+      ret = response.response_code;
+   edg_wlpr_CleanResponse(&response);
+
+   return ret;
+}
+
+#ifdef RENEWAL_HAVE_JOBID
+int
+edg_wlpr_UnregisterProxy(edg_wlc_JobId jobid, const char *repository_filename)
+{
+   char *ji;
+   int ret;
+
+   ji = edg_wlc_JobIdUnparse(jobid);
+   if (ji == NULL)
+      return EINVAL;
+   ret = glite_renewal_UnregisterProxy(ji, repository_filename);
+   free(ji);
+   return ret;
+}
+#endif /* RENEWAL_HAVE_JOBID */
+
+int
+edg_wlpr_GetList(int *count, char **list)
+{
+   return ENOSYS; /* XXX */
+}
+
+int
+edg_wlpr_GetStatus(const char *filename, char **info)
+{
+   return ENOSYS; /* XXX */
+}
+
+static const char* const errTexts[] = {
+   "Unexpected EOF from peer",
+   "Generic error",
+   "Protocol parse error",
+   "Compulsory element not found in message",
+   "Unknown protocol command",
+   "SSL error",
+   "Error from Myproxy server",
+   "Proxy not registered",
+   "Proxy expired",
+   "VOMS error",
+   "Operation timed out",
+   "System error"
+};
+
+const char *
+edg_wlpr_GetErrorText(int code)
+{
+   return code ?
+           (code <= EDG_WLPR_ERROR_BASE ?
+                   strerror(code) :
+                   errTexts[code - EDG_WLPR_ERROR_BASE - 1]
+          ) :
+          NULL;
+}
+
+int
+glite_renewal_GetProxy(const char *jobid, char **repository_filename)
+{
+   edg_wlpr_Request request;
+   edg_wlpr_Response response;
+   int ret;
+
+   memset(&request, 0, sizeof(request));
+   memset(&response, 0, sizeof(response));
+
+   if (jobid == NULL)
+      return EINVAL;
+
+   request.command = EDG_WLPR_COMMAND_GET;
+   request.jobid = strdup(jobid);
+   if (request.jobid == NULL)
+      return ENOMEM;
+
+   ret = edg_wlpr_RequestSend(&request, &response);
+   free(request.jobid);
+
+   if (ret == 0 && response.response_code == 0 && repository_filename &&
+       response.filenames && response.filenames[0] )
+      *repository_filename = strdup(response.filenames[0]);
+   
+   if (ret == 0)
+      ret = response.response_code;
+   edg_wlpr_CleanResponse(&response);
+
+   return ret;
+}
+
+#ifdef RENEWAL_HAVE_JOBID
+int
+edg_wlpr_GetProxy(edg_wlc_JobId jobid, char **repository_filename)
+{
+   char *ji;
+   int ret;
+
+   ji = edg_wlc_JobIdUnparse(jobid);
+   if (ji == NULL)
+      return EINVAL;
+
+   ret = glite_renewal_GetProxy(ji, repository_filename);
+   free(ji);
+   return ret;
+}
+#endif /* RENEWAL_HAVE_JOBID */
diff --git a/org.glite.px.proxyrenewal/src/client.c b/org.glite.px.proxyrenewal/src/client.c
new file mode 100644 (file)
index 0000000..87efd78
--- /dev/null
@@ -0,0 +1,111 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include "renewal.h"
+
+static const char rcsid[] = "$Header$";
+
+static struct option const long_options[] = {
+   { "help",     no_argument,       0, 'h' },
+   { "version",  no_argument,       0, 'v' },
+   { "server",   required_argument, 0, 's' },
+   { "port",     required_argument, 0, 'p' },
+   { "file",     required_argument, 0, 'f' },
+   { "jobid",    required_argument, 0, 'j' },
+   { NULL, 0, NULL, 0}
+};
+
+static char short_options[] = "hvs:p:f:j:";
+
+static void
+usage(exit_code)
+{
+   fprintf(stdout, "Usage: edg-wl-renew [option] operation\n"
+          "\t-s myproxy_server [-p port] -f filename -j jobid start |\n"
+          "\t-j jobid [-f filename] stop |\n"
+          "\t-j jobid get\n"
+          "-h, --help                 display this help and exit\n"
+          "-v, --version              output version information and exit\n"
+          "-s, --server <fqdn>        address of myproxy server\n"
+          "-p, --port <num>           port of myproxy server\n"
+          "-f, --file <file>          filename with proxy\n"
+          "-j, --jobid <str>          datagrid jobid\n");
+   exit(exit_code);
+}
+
+int
+main(int argc, char *argv[])
+{
+   char *server = NULL;
+   int port = 0;
+   char *proxyfile = NULL;
+   char *jobid_str = NULL;
+   char *repository_filename = NULL;
+   int ret;
+   int arg;
+   extern int optind;
+
+   while ((arg = getopt_long(argc, argv,
+                            short_options, long_options, (int *) 0)) != EOF)
+      switch(arg) {
+        case 'h':
+           usage(0); break;
+        case 'v':
+           fprintf(stdout, "%s:\t%s\n", argv[0], rcsid); exit(0);
+        case 's':
+           server = strdup(optarg); break;
+        case 'p':
+           port = atoi(optarg); break;
+        case 'f':
+           proxyfile = strdup(optarg); break;
+        case 'j':
+           jobid_str = strdup(optarg); break;
+        default:
+           usage(1); break;
+      }
+
+   if (optind >= argc)
+      usage(1);
+
+   if (strcmp(argv[optind], "start") == 0) {
+      if (proxyfile == NULL || server == NULL || jobid_str == NULL)
+        usage(1);
+      ret = glite_renewal_RegisterProxy(proxyfile, server, port, jobid_str, 0,
+                                       &repository_filename);
+      if (ret) {
+        fprintf(stderr, "Registering proxy failed: %s\n",
+                edg_wlpr_GetErrorText(ret));
+        exit(1);
+      }
+      printf("%s\n", repository_filename);
+      free(repository_filename);
+      exit(0);
+   }
+   else if (strcmp(argv[optind], "stop") == 0) {
+      if (jobid_str == NULL)
+        usage(1);
+      ret = glite_renewal_UnregisterProxy(jobid_str, proxyfile);
+      if (ret) {
+        fprintf(stderr, "Unregistering proxy failed: %s\n",
+                edg_wlpr_GetErrorText(ret));
+        exit(1);
+      }
+   }
+   else if (strcmp(argv[optind], "get") == 0) {
+      if (jobid_str == NULL)
+        usage(1);
+      ret = glite_renewal_GetProxy(jobid_str, &proxyfile);
+      if (ret) {
+        fprintf(stderr, "GET request failed: %s\n",
+                edg_wlpr_GetErrorText(ret));
+        exit(1);
+      }
+      printf("%s\n", proxyfile);
+      free(proxyfile);
+   }
+   else 
+      usage(1);
+
+   return 0;
+}
diff --git a/org.glite.px.proxyrenewal/src/commands.c b/org.glite.px.proxyrenewal/src/commands.c
new file mode 100644 (file)
index 0000000..abc4809
--- /dev/null
@@ -0,0 +1,1256 @@
+#include "renewal_locl.h"
+#include "renewd_locl.h"
+
+#include "glite/security/voms/voms_apic.h"
+
+#ident "$Header$"
+
+#define SEPARATORS ",\n"
+#define RENEWAL_START_FRACTION 0.75 /* XXX */
+#define RENEWAL_MIN_LIFETIME (15 * 60)
+
+extern char *repository;
+extern time_t condor_limit;
+extern char *cadir;
+extern char *vomsdir;
+extern int voms_enabled;
+
+static char *
+strmd5(glite_renewal_core_context ctx, const char *s, unsigned char *digest);
+
+static int
+get_record_ext(glite_renewal_core_context ctx, FILE *fd, proxy_record *record, int *last_used_suffix);
+
+static int
+get_record(glite_renewal_core_context ctx, FILE *fd, proxy_record *record);
+
+static int
+store_record(glite_renewal_core_context ctx, char *basename, proxy_record *record);
+
+static int
+copy_file_content(glite_renewal_core_context ctx, FILE *in, FILE *out);
+
+static int
+copy_file(glite_renewal_core_context ctx, char *src, char *dst);
+
+static int
+get_base_filename(glite_renewal_core_context ctx, char *proxy_file, char **basefilename);
+
+int
+decode_record(glite_renewal_core_context ctx, char *line, proxy_record *record);
+
+int
+encode_record(glite_renewal_core_context ctx, proxy_record *record, char **line);
+
+static int
+open_metafile(glite_renewal_core_context ctx, char *proxy_file, FILE **fd);
+
+void
+free_record(glite_renewal_core_context ctx, proxy_record *record);
+
+static int
+realloc_prd_list(glite_renewal_core_context ctx, prd_list *list);
+
+/* make public: */
+static int
+edg_wlpr_GetTokenInt(glite_renewal_core_context ctx, const char *msg, const size_t msg_len,
+                     const char *key, const char *separators,
+                     int req_index, int *value);
+
+static void
+record_to_response(glite_renewal_core_context ctx, int status_code, proxy_record *record,
+                   edg_wlpr_Response *response);
+
+static int
+filename_to_response(glite_renewal_core_context ctx, char *filename, edg_wlpr_Response *response);
+
+
+
+
+static char *
+strmd5(glite_renewal_core_context ctx, const char *s, unsigned char *digest)
+{
+    MD5_CTX md5;
+    unsigned char   d[16];
+    int     i;
+    static char mbuf[33];
+
+    MD5_Init(&md5);
+    MD5_Update(&md5,s,strlen(s));
+    MD5_Final(d,&md5);
+
+    if (digest)
+       memcpy(digest,d,sizeof(d));
+    for (i=0; i<16; i++) {
+       int     dd = d[i] & 0x0f;
+       mbuf[2*i+1] = dd<10 ? dd+'0' : dd-10+'a';
+       dd = d[i] >> 4;
+       mbuf[2*i] = dd<10 ? dd+'0' : dd-10+'a';
+    }
+    mbuf[32] = 0;
+    return mbuf;
+}
+
+static int
+get_base_filename(glite_renewal_core_context ctx, char *proxy_file, char **basefilename)
+{
+   char *subject = NULL;
+   char file[FILENAME_MAX];
+   int ret;
+
+   assert(basefilename != NULL);
+
+   ret = glite_renewal_get_proxy_base_name(ctx, proxy_file, &subject);
+   if (ret)
+      goto end;
+
+   snprintf(file, sizeof(file), "%s/%s", repository, strmd5(ctx, subject, NULL));
+   *basefilename = strdup(file); /* XXX test ENOMEM */
+   ret = 0;
+   
+end:
+   if (subject)
+      free(subject);
+   return ret;
+}
+
+static int
+copy_file_content(glite_renewal_core_context ctx, FILE *in, FILE *out)
+{
+   char buf[1024];
+   size_t num;
+   int ret;
+
+   while (1) {
+      num = fread(buf, sizeof(*buf), sizeof(buf), in);
+      if ((ret = ferror(in))) {
+        glite_renewal_log(ctx, LOG_ERR, "Reading failed: %s", strerror(errno));
+        return ret;
+      }
+      num = fwrite(buf, sizeof(*buf), num, out);
+      if ((ret = ferror(in))) {
+        glite_renewal_log(ctx, LOG_ERR, "Writing failed: %s", strerror(errno));
+        return ret;
+      }
+      if (feof(in))
+        return 0;
+   }
+}
+
+/* return the time interval, after which the renewal should be started */
+static time_t
+get_delta(glite_renewal_core_context ctx, time_t current_time, time_t start_time, time_t end_time)
+{
+   time_t remaining_life;
+   time_t life_to_lose;
+   time_t limit;
+   time_t delta;
+
+   if (RENEWAL_MIN_LIFETIME > condor_limit) {
+     limit = RENEWAL_MIN_LIFETIME;
+   } else {
+     limit = condor_limit;
+   }
+
+   limit += RENEWAL_CLOCK_SKEW;
+
+   if (current_time + limit >= end_time) {
+     /* if the proxy is too short, renew it as soon as possible */
+
+     if (current_time + condor_limit > end_time ) {
+       glite_renewal_log(ctx, LOG_ERR, "Remaining proxy lifetime fell below the value of the Condor limit!");
+     }
+
+     return 0;
+   }
+
+   remaining_life = end_time - current_time;
+
+   /* renewal should gain the jobs an extra lifetime of
+      RENEWAL_START_FRACTION (default 3/4) of the new proxy's
+      lifetime. If the time remaining on the current proxy is already
+      small then the jobs may gain an extra lifetime of more than that.
+
+      In any case, a renewal will be scheduled to happen before the
+      lifetime limit.
+
+      'life_to_lose' is the lifetime that will be lost, ie the time that
+      will still remain on the current proxy when it is renewed
+   */
+
+   life_to_lose = (1.0-RENEWAL_START_FRACTION)*60*60*DGPR_RETRIEVE_DEFAULT_HOURS;
+
+   if (life_to_lose < limit) {
+     life_to_lose = limit;
+   }
+
+   delta = life_to_lose - limit;
+
+   while( remaining_life < (limit + delta) ) {
+     delta *= (1.0-RENEWAL_START_FRACTION);
+   }
+
+   life_to_lose = limit + delta;
+
+   return (remaining_life - life_to_lose);
+}
+
+int
+get_times(glite_renewal_core_context ctx, char *proxy_file, proxy_record *record)
+{
+   FILE *fd;
+   X509 *cert = NULL;
+   ASN1_UTCTIME *asn1_time = NULL;
+   int ret;
+   time_t current_time, start_time, end_time;
+
+   assert(record != NULL);
+   assert(proxy_file != NULL);
+
+   fd = fopen(proxy_file, "r");
+   if (fd == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Opening proxy file %s failed: %s",
+                  proxy_file, strerror(errno));
+      return errno;
+   }
+
+   cert = PEM_read_X509(fd, NULL, NULL, NULL);
+   if (cert == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot read X.509 certificate from %s",
+                  proxy_file);
+      ret = -1; /* XXX SSL_ERROR */
+      goto end;
+   }
+
+   asn1_time = ASN1_UTCTIME_new();
+   X509_gmtime_adj(asn1_time,0);
+   globus_gsi_cert_utils_make_time(X509_get_notAfter(cert), &end_time);
+   globus_gsi_cert_utils_make_time(X509_get_notBefore(cert), &start_time);
+   current_time = time(NULL);
+   ASN1_UTCTIME_free(asn1_time);
+   /* if (end_time - RENEWAL_CLOCK_SKEW < current_time) { Too short proxy } */
+   if (end_time + RENEWAL_CLOCK_SKEW < current_time) {
+      glite_renewal_log(ctx, LOG_ERR, "Expired proxy in %s", proxy_file);
+      ret = EDG_WLPR_PROXY_EXPIRED;
+      goto end;
+   }
+
+   /* Myproxy seems not to do check on expiration and return expired proxies
+      if credentials in repository are expired */
+   X509_free(cert);
+   cert = NULL;
+   while (1) {
+      time_t tmp_end;
+      /* see http://www.openssl.org/docs/crypto/pem.html section BUGS */
+      cert = PEM_read_X509(fd, NULL, NULL, NULL);
+      if (cert == NULL) {
+        if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) {
+           /* End of file reached. no error */
+           ERR_clear_error();
+           break;
+        }
+        glite_renewal_log(ctx, LOG_ERR, "Cannot read additional certificates from %s",
+                     proxy_file);
+        ret = -1; /* XXX SSL_ERROR */
+        goto end;
+      }
+      globus_gsi_cert_utils_make_time(X509_get_notAfter(cert), &tmp_end);
+      if (tmp_end + RENEWAL_CLOCK_SKEW < current_time) {
+        glite_renewal_log(ctx, LOG_ERR, "Expired proxy in %s", proxy_file);
+        ret = EDG_WLPR_PROXY_EXPIRED;
+        goto end;
+      }
+      X509_free(cert);
+      cert = NULL;
+   }
+
+   record->next_renewal = current_time + get_delta(ctx, current_time, start_time,
+                                                  end_time);
+   record->end_time = end_time;
+   ret = 0;
+
+end:
+   fclose(fd);
+   if (cert)
+      X509_free(cert);
+
+   return ret;
+}
+
+static int
+copy_file(glite_renewal_core_context ctx, char *src, char *dst)
+{
+   FILE *from = NULL;
+   FILE *tmp_to = NULL;
+   int tmp_fd;
+   char tmpfile[FILENAME_MAX];
+   int ret;
+
+   if (strcmp(src, dst) == 0)
+      return 0; 
+
+   from = fopen(src, "r");
+   if (from == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot open file %s for reading (%s)",
+                  src, strerror(errno));
+      return errno;
+   }
+
+   snprintf(tmpfile, sizeof(tmpfile), "%s.XXXXXX", dst);
+   tmp_fd = mkstemp(tmpfile);
+   if (tmp_fd == -1) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot create temporary file (%s)",
+                  strerror(errno));
+      ret = errno;
+      goto end;
+   }
+
+
+   tmp_to = fdopen(tmp_fd, "w");
+   if (tmp_to == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot associate stream with temporary file (%s)",
+                  strerror(errno));
+      unlink(tmpfile);
+      ret = errno;
+      goto end;
+   }
+
+   ret = copy_file_content(ctx, from, tmp_to);
+   fclose(tmp_to);
+   if (ret) {
+      goto end;
+   }
+
+   ret = rename(tmpfile, dst);
+   if (ret) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot replace repository file %s with temporary file (%s)",
+                  strerror(errno));
+      unlink(tmpfile);
+      ret = errno;
+      goto end;
+   }
+   tmp_to = NULL;
+      
+end:
+   fclose(from);
+   close(tmp_fd);
+   unlink(tmpfile);
+
+   return ret;
+}
+
+void
+free_record(glite_renewal_core_context ctx, proxy_record *record)
+{
+   int i;
+
+   if (record == NULL)
+      return;
+   if (record->myproxy_server)
+      free(record->myproxy_server);
+   if (record->jobids.val) {
+      for (i = 0; i < record->jobids.len; i++)
+        free(record->jobids.val[i]);
+      free(record->jobids.val);
+   }
+   memset(record, 0, sizeof(*record));
+}
+
+static int
+realloc_prd_list(glite_renewal_core_context ctx, prd_list *list)
+{
+   char **tmp;
+
+   tmp = realloc(list->val, (list->len + 1) * sizeof(*list->val));
+   if (tmp == NULL)
+      return ENOMEM;
+   list->val = tmp;
+   list->len++;
+   return 0;
+}
+
+static int
+get_jobids(glite_renewal_core_context ctx, const char *msg, const size_t msg_len, proxy_record *record)
+{
+   int index = 0;
+   int ret;
+   char *value;
+   char **tmp;
+
+   memset(&record->jobids, 0, sizeof(record->jobids));
+   while ((ret = edg_wlpr_GetToken(msg, msg_len, "jobid=", SEPARATORS,
+                                  index, &value)) == 0) {
+      tmp = realloc(record->jobids.val, (record->jobids.len + 1) * sizeof(*tmp));
+      if (tmp == NULL) {
+        ret = ENOMEM;
+        break;
+      }
+      record->jobids.val = tmp;
+      record->jobids.val[index] = value;
+      record->jobids.len++;
+      index++;
+   }
+   if (ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND) {
+      if (record->jobids.len)
+        free(record->jobids.val);
+      record->jobids.len = 0;
+      record->jobids.val = NULL;
+      return ret;
+   }
+
+   return 0;
+}
+
+static int
+edg_wlpr_GetTokenInt(glite_renewal_core_context ctx, const char *msg, const size_t msg_len,
+                     const char *key, const char *separators,
+                    int req_index, int *value)
+{
+   int ret;
+   char *str_value = NULL;
+
+   ret = edg_wlpr_GetToken(msg, msg_len, key, separators, req_index, &str_value);
+   if (ret)
+      return ret;
+
+   ret = edg_wlpr_DecodeInt(str_value, value);
+   free(str_value);
+   return ret;
+}
+
+int
+decode_record(glite_renewal_core_context ctx, char *line, proxy_record *record)
+{
+   /* line must be ended with '\0' */
+   int ret;
+   size_t len;
+
+   assert(line != NULL);
+   assert(record != NULL);
+
+   memset(record, 0, sizeof(*record));
+
+   len = strlen(line) + 1;
+
+   ret = edg_wlpr_GetTokenInt(ctx, line, len, "suffix=", SEPARATORS, 0,
+                             &record->suffix);
+   if (ret)
+      return ret;
+
+#if 0
+   ret = edg_wlpr_GetTokenInt(ctx, line, len, "counter=", SEPARATORS, 0, 
+                             &record->counter);
+   if (ret)
+      goto end;
+#endif
+
+   ret = edg_wlpr_GetTokenInt(ctx, line, len, "unique=", SEPARATORS, 0,
+                             &record->unique);
+   if (ret)
+      goto end;
+
+   ret = edg_wlpr_GetTokenInt(ctx, line, len, "voms_exts=", SEPARATORS, 0,
+                             &record->voms_exts);
+
+   ret = edg_wlpr_GetToken(line, len, "server=", SEPARATORS, 0,
+                          &record->myproxy_server);
+   if (ret)
+      goto end;
+
+   ret = edg_wlpr_GetTokenInt(ctx, line, len, "next_renewal=", SEPARATORS, 0,
+                             (int *)&record->next_renewal);
+   if (ret)
+      goto end;
+
+   ret = edg_wlpr_GetTokenInt(ctx, line, len, "end_time=", SEPARATORS, 0,
+                             (int *)&record->end_time);
+   if (ret)
+      goto end;
+
+   ret = get_jobids(ctx, line, len, record);
+   if (ret)
+      goto end;
+
+end:
+   if (ret)
+      free_record(ctx, record);
+
+   return ret;
+}
+
+int
+encode_record(glite_renewal_core_context ctx, proxy_record *record, char **line)
+{
+   char tmp_line[1024];
+   size_t jobids_len = 0;
+   int i;
+   
+   snprintf(tmp_line, sizeof(tmp_line), "suffix=%d, unique=%d, voms_exts=%d, server=%s, next_renewal=%ld, end_time=%ld",
+          record->suffix, record->unique, record->voms_exts,
+          (record->myproxy_server) ? record->myproxy_server : "",
+          record->next_renewal, record->end_time);
+   for (i = 0; i < record->jobids.len; i++)
+      /* alloc space for string ", jobid=<jobid>" */
+      jobids_len += 2 + strlen("jobid=") + strlen(record->jobids.val[i]);
+
+   *line = calloc(1, strlen(tmp_line) + jobids_len + 1);
+   if (*line == NULL)
+      return ENOMEM;
+
+   strcat(*line, tmp_line);
+   memset(tmp_line, 0, sizeof(tmp_line));
+
+   for (i = 0; i < record->jobids.len; i++) {
+      snprintf(tmp_line, sizeof(tmp_line), ", jobid=%s", record->jobids.val[i]);
+      strcat(*line, tmp_line);
+   }
+
+   return 0;
+}
+
+/* Get proxy record from the index file. If no suffix is defined return a free 
+   record with the smallest index */
+static int
+get_record_ext(glite_renewal_core_context ctx, FILE *fd, proxy_record *record, int *last_used_suffix)
+{
+   char line[1024];
+   int last_suffix = -1;
+   int ret;
+   char *p;
+   proxy_record tmp_record;
+   time_t current_time;
+   int line_num = 0;
+
+   assert(record != NULL);
+   memset(&tmp_record, 0, sizeof(tmp_record));
+
+   current_time = time(NULL);
+   while (fgets(line, sizeof(line), fd) != NULL) {
+      line_num++;
+      free_record(ctx, &tmp_record);
+      p = strchr(line, '\n');
+      if (p)
+        *p = '\0';
+      ret = decode_record(ctx, line, &tmp_record);
+      if (ret) {
+        glite_renewal_log(ctx, LOG_ERR, "Skipping invalid entry at line %d", line_num);
+        continue;
+      }
+      if (record->suffix >= 0) {
+        if (record->suffix == tmp_record.suffix) {
+           record->suffix = tmp_record.suffix;
+           record->jobids.len = tmp_record.jobids.len;
+           record->jobids.val = tmp_record.jobids.val;
+           record->unique = tmp_record.unique;
+           record->voms_exts = tmp_record.voms_exts;
+           if (record->myproxy_server)
+              free(record->myproxy_server);
+           record->myproxy_server = tmp_record.myproxy_server;
+           record->end_time = tmp_record.end_time;
+           record->next_renewal = tmp_record.next_renewal;
+           return 0;
+        } else
+           continue;
+      }
+      if (tmp_record.suffix > last_suffix)
+        last_suffix = tmp_record.suffix;
+
+      /* if no particular suffix was specified get the first free record 
+        available */
+      if (tmp_record.jobids.len >= MAX_PROXIES || tmp_record.unique || 
+         tmp_record.voms_exts)
+        continue;
+
+      if (tmp_record.jobids.len == 0) {
+        /* no jobs registered for this record, so use it initialized with the
+         * parameters (currently myproxy location) provided by user */
+        record->suffix = tmp_record.suffix;
+        record->next_renewal = record->end_time = 0;
+        free_record(ctx, &tmp_record);
+        return 0;
+      }
+
+      /* Proxies with VOMS attributes require a separate record, which is not
+       * shared with another proxies. The same applies it the unique flag was
+       * set by the caller */
+      if (record->voms_exts || record->unique)
+        continue;
+
+      if (tmp_record.jobids.len > 0 && record->myproxy_server &&
+         strcmp(record->myproxy_server, tmp_record.myproxy_server) != 0)
+        continue;
+
+      if (tmp_record.jobids.len > 0 &&
+          current_time + condor_limit + RENEWAL_CLOCK_SKEW > tmp_record.end_time) {
+
+        /* skip expired proxy (or ones that are going to expire soon),
+           leaving it untouched (it will be removed after next run of the 
+           renewal process) */
+
+        continue;
+      }
+
+      record->suffix = tmp_record.suffix;
+      record->jobids.len = tmp_record.jobids.len;
+      record->jobids.val = tmp_record.jobids.val;
+      record->unique = tmp_record.unique;
+      record->voms_exts = tmp_record.voms_exts;
+      if (record->myproxy_server)
+        free(record->myproxy_server);
+      record->myproxy_server = tmp_record.myproxy_server;
+      record->end_time = tmp_record.end_time;
+      record->next_renewal = tmp_record.next_renewal;
+      return 0;
+   }
+
+   if (last_used_suffix)
+      *last_used_suffix = last_suffix;
+
+   if (record->suffix >= 0) {
+      glite_renewal_log(ctx, LOG_DEBUG, "Requested suffix %d not found in meta file",
+                  record->suffix);
+   }
+
+   free_record(ctx, &tmp_record);
+
+   return EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND;
+}
+
+static int
+get_record(glite_renewal_core_context ctx, FILE *fd, proxy_record *record)
+{
+   return get_record_ext(ctx, fd, record, NULL);
+}
+
+static int
+store_record(glite_renewal_core_context ctx, char *basename, proxy_record *record)
+{
+   int stored = 0;
+   FILE *fd = NULL;
+   int temp;
+   char line[1024];
+   char *new_line = NULL;
+   int ret, i;
+   char *p;
+   proxy_record tmp_record;
+   char tmp_file[FILENAME_MAX];
+   char meta_file[FILENAME_MAX];
+   int line_num = 0;
+
+   assert (record != NULL);
+
+   memset(&tmp_record, 0, sizeof(tmp_record));
+
+   snprintf(meta_file, sizeof(meta_file), "%s.data", basename);
+   snprintf(tmp_file, sizeof(tmp_file), "%s.XXXXXX", meta_file);
+
+   temp = mkstemp(tmp_file);
+   if (temp < 0)
+      return errno;
+
+   fd = fopen(meta_file, "r");
+   if (fd == NULL) {
+      ret = errno;
+      goto end;
+   }
+   while (fgets(line, sizeof(line), fd) != NULL) {
+      line_num++;
+      free_record(ctx, &tmp_record);
+      p = strchr(line, '\n');
+      if (p)
+        *p = '\0';
+      ret = decode_record(ctx, line, &tmp_record);
+      if (ret) {
+        glite_renewal_log(ctx, LOG_ERR, "Removing invalid entry at line %d in %s", line_num, basename);
+        continue;
+      }
+      if (record->suffix == tmp_record.suffix &&
+         record->unique == tmp_record.unique) {
+        tmp_record.next_renewal = record->next_renewal;
+        tmp_record.end_time = record->end_time;
+        tmp_record.voms_exts = record->voms_exts;
+        if (tmp_record.myproxy_server != NULL)
+           free(tmp_record.myproxy_server);
+        tmp_record.myproxy_server = strdup(record->myproxy_server);
+        if (tmp_record.jobids.val) {
+           for (i = 0; i < tmp_record.jobids.len; i++)
+               free(tmp_record.jobids.val[i]);
+           free(tmp_record.jobids.val);
+        }
+        tmp_record.jobids.len = 0;
+        tmp_record.jobids.val = NULL;
+        for (i = 0; i < record->jobids.len; i++) {
+           realloc_prd_list(ctx, &tmp_record.jobids);
+           tmp_record.jobids.val[tmp_record.jobids.len - 1] = 
+              strdup(record->jobids.val[i]);
+        }
+        stored = 1;
+      }
+      ret = encode_record(ctx, &tmp_record, &new_line);
+      if (ret)
+        goto end;
+      dprintf(temp, "%s\n", new_line);
+      free(new_line);
+      new_line = NULL;
+   }
+   if (! stored) {
+      ret = encode_record(ctx, record, &new_line);
+      if (ret)
+        goto end;
+      ret = dprintf(temp, "%s\n", new_line);
+      free(new_line);
+      new_line = NULL;
+   }
+   fclose(fd); fd = NULL;
+   close(temp);
+
+   ret = rename(tmp_file, meta_file);
+   if (ret)
+      ret = errno;
+
+end:
+   free_record(ctx, &tmp_record);
+   if (fd)
+      fclose(fd);
+   close(temp);
+   return ret;
+}
+
+static int
+open_metafile(glite_renewal_core_context ctx, char *basename, FILE **fd)
+{
+   FILE *meta_fd;
+   char meta_filename[FILENAME_MAX];
+
+   snprintf(meta_filename, sizeof(meta_filename), "%s.data", basename);
+   meta_fd = fopen(meta_filename, "a+");
+   if (meta_fd == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Opening meta file %s failed (%s)",
+                  meta_filename, strerror(errno));
+      return errno;
+   }
+   rewind(meta_fd);
+   *fd = meta_fd;
+   glite_renewal_log(ctx, LOG_DEBUG, "Using meta file %s", meta_filename);
+   return 0;
+}
+
+static int
+filename_to_response(glite_renewal_core_context ctx, char *filename, edg_wlpr_Response *response)
+{
+   response->filenames = malloc(2 * sizeof(*response->filenames));
+   if (response->filenames == NULL) {
+      glite_renewal_log(ctx, LOG_DEBUG, "Not enough memory");
+      return errno;
+   }
+   response->filenames[0] = strdup(filename);
+   if (response->filenames[0] == NULL) {
+      glite_renewal_log(ctx, LOG_DEBUG, "Not enough memory");
+      free(response->filenames);
+      return errno;
+   }
+   response->filenames[1] = NULL;
+   return 0;
+}
+
+static void
+record_to_response(glite_renewal_core_context ctx, int status_code, proxy_record *record,
+                  edg_wlpr_Response *response)
+{
+   /* XXX Neni struktrura proxy_record zbytecna? Mohla by se pouzivat primo
+      edg_wlpr_Response? */
+   response->response_code = status_code; /* XXX chyba parsovatelna pres API */
+   if (status_code)
+      return;
+
+   if (response->myproxy_server) {
+      response->myproxy_server = strdup(record->myproxy_server);
+      if (response->myproxy_server == NULL) {
+        response->response_code = ENOMEM; /* XXX */
+        return;
+      }
+   }
+   response->end_time = record->end_time;
+   response->next_renewal_time = record->next_renewal;
+   /* XXX use jobid response->counter = record->counter; */
+}
+
+int
+check_proxyname(glite_renewal_core_context ctx, char *datafile, char *jobid, char **filename)
+{
+   proxy_record record;
+   FILE *meta_fd = NULL;
+   char line[1024];
+   char proxy[FILENAME_MAX];
+   char *p;
+   int ret, i;
+
+   memset(&record, 0, sizeof(record));
+
+   meta_fd = fopen(datafile, "r");
+   if (meta_fd == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot open meta file %s (%s)",
+                  datafile, strerror(errno));
+      return errno;
+   }
+
+   while (fgets(line, sizeof(line), meta_fd) != NULL) {
+      free_record(ctx, &record);
+      p = strchr(line, '\n');
+      if (p)
+        *p = '\0';
+      ret = decode_record(ctx, line, &record);
+      if (ret)
+        continue; /* XXX exit? */
+      for (i = 0; i < record.jobids.len; i++) {
+        if (strcmp(jobid, record.jobids.val[i]) == 0) {
+           snprintf(proxy, sizeof(proxy), "%s/%s", repository, datafile);
+           p = strrchr(proxy, '.');
+           sprintf(p, ".%d", record.suffix);
+           *filename = strdup(proxy);
+            free_record(ctx, &record);
+           fclose(meta_fd);
+           return 0;
+        }
+      }
+   }
+   free_record(ctx, &record);
+   fclose(meta_fd);
+   return EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND;
+}
+      
+int
+find_proxyname(glite_renewal_core_context ctx, char *jobid, char **filename)
+{
+   DIR *dir = NULL;
+   struct dirent *file;
+   int ret;
+   
+   chdir(repository);
+
+   dir = opendir(repository);
+   if (dir == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot open repository directory %s (%s)",
+                  repository, strerror(errno));
+      return errno;
+   }
+
+   while ((file = readdir(dir))) {
+      /* read files of format `md5sum`.data, where md5sum() is of fixed length
+        32 chars */
+      if (file->d_name == NULL || strlen(file->d_name) != 37 ||
+         strcmp(file->d_name + 32, ".data") != 0)
+        continue;
+      ret = check_proxyname(ctx, file->d_name, jobid, filename);
+      if (ret == 0) {
+        closedir(dir);
+        return 0;
+      }
+   }
+   closedir(dir);
+   glite_renewal_log(ctx, LOG_ERR, "Requested proxy is not registered");
+   return EDG_WLPR_PROXY_NOT_REGISTERED;
+}
+
+#ifdef NOVOMS
+int
+find_voms_cert(glite_renewal_core_context ctx, char *file, int *present)
+{
+       *present = 0;
+       return 0;
+}
+
+#else
+int
+find_voms_cert(glite_renewal_core_context ctx, char *file, int *present)
+{
+   struct vomsdata *voms_info = NULL;
+   STACK_OF(X509) *chain = NULL;
+   EVP_PKEY *privkey = NULL;
+   X509 *cert = NULL;
+   int ret, err;
+   
+   *present = 0;
+
+   voms_info = VOMS_Init(vomsdir, cadir);
+   if (voms_info == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "check_voms_cert(): Cannot initialize VOMS context (VOMS_Init() failed, probably voms dir was not specified)");
+      return EDG_WLPR_ERROR_VOMS;
+   }
+
+   ret = glite_renewal_load_proxy(ctx, file, &cert, &privkey, &chain, NULL);
+   if (ret) {
+      VOMS_Destroy(voms_info);
+      return ret;
+   }
+
+   ret = VOMS_Retrieve(cert, chain, RECURSE_CHAIN, voms_info, &err);
+   if (ret == 1) {
+      *present = 1;
+   }
+
+   VOMS_Destroy(voms_info);
+   X509_free(cert);
+   EVP_PKEY_free(privkey);
+   sk_X509_pop_free(chain, X509_free);
+   return 0;
+}
+#endif
+
+void
+register_proxy(glite_renewal_core_context ctx, edg_wlpr_Request *request, edg_wlpr_Response *response)
+{
+   proxy_record record;
+   int ret;
+   FILE *meta_fd = NULL;
+   int last_suffix;
+   char *basename = NULL;
+   char filename[FILENAME_MAX];
+
+   assert(request != NULL);
+   assert(response != NULL);
+
+   memset(&record, 0, sizeof(record));
+   memset(response, 0, sizeof(*response));
+   glite_renewal_log(ctx, LOG_DEBUG, "Registration request for %s", request->proxy_filename);
+
+   if (request->proxy_filename == NULL || request->jobid == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Registration request doesn't contain registration information");
+      return; /*  EINVAL; */
+   }
+   umask(0177);
+
+   ret = get_base_filename(ctx, request->proxy_filename, &basename);
+   if (ret)
+      goto end;
+
+   ret = open_metafile(ctx, basename, &meta_fd);
+   if (ret)
+      goto end;
+
+   if (voms_enabled)
+     ret = find_voms_cert(ctx, request->proxy_filename, &record.voms_exts);
+     /* ignore VOMS related error */
+
+   /* Find first free record */
+   record.suffix = -1;
+   record.myproxy_server = strdup(request->myproxy_server);
+   ret = get_record_ext(ctx, meta_fd, &record, &last_suffix);
+   fclose(meta_fd); meta_fd = NULL;
+   if (ret && ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND)
+      goto end;
+
+   if (ret == EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND || record.jobids.len == 0 || request->unique || record.voms_exts) {
+      /* create a new proxy file in the repository */
+      int suffix;
+
+      suffix = (record.jobids.len == 0 && record.suffix >= 0) ? 
+                record.suffix : last_suffix + 1;
+      snprintf(filename, sizeof(filename), "%s.%d", basename, suffix);
+      ret = copy_file(ctx, request->proxy_filename, filename);
+      if (ret)
+        goto end;
+      ret = get_times(ctx, filename, &record);
+      if (ret)
+        goto end;
+      record.suffix = suffix;
+      ret = realloc_prd_list(ctx, &record.jobids);
+      if (ret)
+        goto end;
+      record.jobids.val[record.jobids.len - 1] = strdup(request->jobid);
+      record.unique = request->unique;
+      glite_renewal_log(ctx, LOG_DEBUG, "Created a new proxy file in repository (%s)",
+                  filename);
+   } else {
+      ret = realloc_prd_list(ctx, &record.jobids);
+      if (ret)
+        goto end;
+      record.jobids.val[record.jobids.len - 1] = strdup(request->jobid);
+      snprintf(filename, sizeof(filename), "%s.%d", basename, record.suffix);
+      glite_renewal_log(ctx, LOG_DEBUG, "Inremented counter on %s", filename);
+   }
+
+   ret = store_record(ctx, basename, &record);
+
+end:
+   if (meta_fd) {
+      fclose(meta_fd);
+   }
+
+   if (basename)
+      free(basename);
+
+   if (ret == 0)
+      ret = filename_to_response(ctx, filename, response);
+   record_to_response(ctx, ret, &record, response);
+   free_record(ctx, &record);
+}
+
+void
+unregister_proxy(glite_renewal_core_context ctx, edg_wlpr_Request *request, edg_wlpr_Response *response)
+{
+   proxy_record record;
+   int ret, i, index;
+   FILE *meta_fd = NULL;
+   char *basename = NULL;
+   char *p;
+   struct stat stat_buf;
+
+   memset(&record, 0, sizeof(record));
+   glite_renewal_log(ctx, LOG_DEBUG, "Unregistration request for %s", request->jobid);
+
+   if (request->jobid == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Unregistration request doesn't contain needed information");
+      ret = EINVAL;
+      goto end;
+   }
+
+   if (request->proxy_filename == NULL) {
+      ret = find_proxyname(ctx, request->jobid, &request->proxy_filename);
+      if (ret)
+        goto end;
+   }
+
+   ret = get_base_filename(ctx, request->proxy_filename, &basename);
+   if (ret) {
+      goto end;
+   }
+
+   if (strncmp(request->proxy_filename, basename, strlen(basename) != 0)) {
+      glite_renewal_log(ctx, LOG_DEBUG, "Requested proxy %s is not from repository",
+                  request->proxy_filename);
+      ret = EDG_WLPR_PROXY_NOT_REGISTERED;
+      goto end;
+   }
+
+   p = strrchr(request->proxy_filename, '.');
+   if (p == NULL) {
+      glite_renewal_log(ctx, LOG_DEBUG, "Requested proxy %s is not from repository",
+                  request->proxy_filename);
+      ret = EDG_WLPR_PROXY_NOT_REGISTERED;
+      goto end;
+   }
+
+   ret = edg_wlpr_DecodeInt(p+1, &record.suffix);
+   if (ret) {
+      glite_renewal_log(ctx, LOG_DEBUG, "Requested proxy %s is not from repository",
+                 request->proxy_filename);
+      ret = EDG_WLPR_PROXY_NOT_REGISTERED;
+      goto end;
+   }
+
+   ret = open_metafile(ctx, basename, &meta_fd);
+   if (ret) {
+      /* fill in error response */
+      return;
+   }
+
+   ret = get_record(ctx, meta_fd, &record);
+   if (ret)
+      goto end;
+
+   ret = EDG_WLPR_PROXY_NOT_REGISTERED;
+   for (i = 0; i < record.jobids.len; i++)
+      if (strcmp(request->jobid, record.jobids.val[i]) == 0) {
+        ret = 0;
+        break;
+      }
+   if (ret) {
+      glite_renewal_log(ctx, LOG_DEBUG, "Requested proxy %s is not registered",
+                  request->proxy_filename);
+      goto end;
+   }
+
+   /* remove jobid from the list */
+   index = i;
+   free(record.jobids.val[i]);
+   record.jobids.len--;
+   for (i = index; i < record.jobids.len; i++)
+      record.jobids.val[i] = record.jobids.val[i+1];
+
+   if (record.jobids.len == 0) {
+      record.unique = 0;
+      record.voms_exts = 0;
+      record.end_time = 0;
+      record.next_renewal = 0;
+   }
+
+   ret = stat(request->proxy_filename, &stat_buf);
+   if (ret) {
+      glite_renewal_log(ctx, LOG_DEBUG, "Cannot stat file %s: (%s)",
+                  request->proxy_filename, strerror(errno));
+      ret = errno;
+      goto end;
+   }
+
+   ret = store_record(ctx, basename, &record);
+   if (ret)
+      goto end;
+
+   if (record.jobids.len == 0)
+      unlink(request->proxy_filename);
+
+end:
+   if (meta_fd) {
+      fclose(meta_fd);
+   }
+   if (basename)
+      free(basename);
+
+   if (ret == 0)
+      ret = filename_to_response(ctx, request->proxy_filename, response);
+   record_to_response(ctx, ret, &record, response);
+   free_record(ctx, &record);
+}
+
+void
+get_proxy(glite_renewal_core_context ctx, edg_wlpr_Request *request, edg_wlpr_Response *response)
+{
+   char *filename = NULL;
+   int ret;
+
+   memset(response, 0, sizeof(*response));
+
+   glite_renewal_log(ctx, LOG_DEBUG, "GET request for %s", request->jobid);
+   
+   if (request->jobid == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "GET request doesn't contain jobid specification");
+      ret = EINVAL;
+      goto end;
+   }
+
+   ret = find_proxyname(ctx, request->jobid, &filename);
+
+end:
+   if (ret == 0)
+      ret = filename_to_response(ctx, filename, response);
+   if (filename)
+      free(filename);
+   response->response_code = ret;
+}
+
+void
+update_db(glite_renewal_core_context ctx, edg_wlpr_Request *request, edg_wlpr_Response *response)
+{
+   FILE *fd = NULL;
+   int tmp_fd = -1;
+   int suffix = -1;
+   char tmp_file[FILENAME_MAX];
+   char cur_proxy[FILENAME_MAX];
+   char datafile[FILENAME_MAX];
+   char line[1024];
+   char *new_line = NULL;
+   char *basename, *proxy = NULL;
+   char **entry;
+   proxy_record record;
+   int ret;
+   char *p;
+   time_t current_time;
+
+   memset(&record, 0, sizeof(record));
+
+   glite_renewal_log(ctx, LOG_DEBUG, "UPDATE_DB request for %s", request->proxy_filename);
+
+   chdir(repository);
+   basename = request->proxy_filename;
+
+   snprintf(datafile, sizeof(datafile), "%s.data", basename);
+   fd = fopen(datafile, "r");
+   if (fd == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot open meta file %s (%s)",
+                  datafile, strerror(errno));
+      ret = errno;
+      return;
+   }
+
+   snprintf(tmp_file, sizeof(tmp_file), "%s.XXXXXX", datafile);
+   tmp_fd = mkstemp(tmp_file);
+   if (tmp_fd < 0) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot create temporary file (%s)",
+                  strerror(errno));
+      ret = errno;
+      goto end;
+   }
+
+   entry = request->entries;
+   if (entry) {
+      p = strchr(*entry, ':');
+      *p = '\0';
+      suffix = atoi(*entry);
+      proxy = p+1;
+   }
+
+   current_time = time(NULL);
+
+   while (fgets(line, sizeof(line), fd) != NULL) { 
+      free_record(ctx, &record);
+      p = strchr(line, '\n');
+      if (p)
+        *p = '\0';
+      ret = decode_record(ctx, line, &record);
+      if (ret)
+        goto end;
+      
+      if (record.suffix > suffix && entry && *entry) {
+        do {
+           entry++;
+           if (entry == NULL || *entry == NULL) {
+              suffix = -1;
+              break;
+           }
+           
+           p = strchr(*entry, ':');
+           suffix = atoi(*entry);
+           proxy = p+1;
+        } while (record.suffix > suffix);
+      }
+
+      if (record.suffix == suffix) {
+        snprintf(cur_proxy, sizeof(cur_proxy), "%s.%d", basename, suffix);
+        if (proxy == NULL || *proxy == '\0') {
+           /* if proxy isn't specified use file registered currently and
+            * reschedule renewal */
+           if (record.end_time < current_time) {
+              char *server;
+              /* remove file with expired proxy and clean the record in db */
+              unlink(cur_proxy);
+              server = strdup(record.myproxy_server);
+              free_record(ctx, &record);
+              record.suffix = suffix;
+              record.myproxy_server = server;
+              glite_renewal_log(ctx, LOG_WARNING, "Removed expired proxy %s", cur_proxy);
+           } else
+              get_times(ctx, cur_proxy, &record);
+        } else {
+           ret = get_times(ctx, proxy, &record);
+           (ret == 0) ? rename(proxy, cur_proxy) : unlink(proxy);
+        }
+      }
+      
+      ret = encode_record(ctx, &record, &new_line);
+      if (ret)
+        goto end;
+
+      dprintf(tmp_fd, "%s\n", new_line);
+      free(new_line);
+      new_line = NULL;
+   }
+   free_record(ctx, &record);
+
+   close(tmp_fd);
+   fclose(fd);
+
+   rename(tmp_file, datafile);
+
+   return;
+
+end:
+   if (fd)
+      fclose(fd);
+   unlink(tmp_file);
+   if (tmp_fd > 0)
+      close(tmp_fd);
+   free_record(ctx, &record);
+
+   return;
+}
diff --git a/org.glite.px.proxyrenewal/src/common.c b/org.glite.px.proxyrenewal/src/common.c
new file mode 100644 (file)
index 0000000..206bc2f
--- /dev/null
@@ -0,0 +1,322 @@
+#include "renewal_locl.h"
+
+#ident "$Header$"
+
+/* nread() and nwrite() never return partial data */
+static int
+nread(int sock, struct timeval *to, char *buf, size_t buf_len, size_t *read_len)
+{
+   int count;
+   size_t remain = buf_len;
+   char *cbuf = buf;
+   struct pollfd pollfds[1];
+   struct timeval before,after;
+   int ret;
+
+   if (to) {
+      gettimeofday(&before,NULL);
+   }
+
+   while (remain > 0) {
+      pollfds[0].fd = sock;
+      pollfds[0].events = POLLIN;
+      switch (poll(pollfds, 1, to ? (to->tv_sec*1000+to->tv_usec/1000) : INFTIM)) {
+        case 0:
+           ret = EDG_WLPR_ERROR_TIMEOUT;
+           goto end;
+        case -1:
+           ret = EDG_WLPR_ERROR_ERRNO;
+           goto end;
+      }
+      
+      count = read(sock, cbuf, remain);
+      if (count < 0) {
+        if (errno == EINTR)
+           continue;
+        else {
+           ret = EDG_WLPR_ERROR_ERRNO;
+           goto end;
+        }
+      } else
+        if (count == 0) {
+           *read_len = 0;
+           return 0;
+        }
+      cbuf += count;
+      remain -= count;
+   }
+   *read_len = buf_len;
+   ret = 0;
+
+end:
+   if (to) {
+      gettimeofday(&after,NULL);
+      edg_wlpr_DecrementTimeout(to, before, after);
+      if (to->tv_sec < 0) {
+        to->tv_sec = 0;
+        to->tv_usec = 0;
+      }
+   }
+
+   return ret;
+}
+
+static int
+nwrite(int sock, struct timeval *to, const char *buf, size_t buf_len)
+{
+   const char *cbuf = buf;
+   int count;
+   size_t remain = buf_len;
+   struct pollfd pollfds[1];
+   struct timeval before,after;
+   int ret;
+
+   if (to) {
+      gettimeofday(&before,NULL);
+   }
+
+   while (remain > 0) {
+      pollfds[0].fd = sock;
+      pollfds[0].events = POLLOUT;
+      switch (poll(pollfds, 1, to ? (to->tv_sec*1000+to->tv_usec/1000) : INFTIM)) {
+        case 0: ret = EDG_WLPR_ERROR_TIMEOUT;
+                goto end;
+        case -1: ret = EDG_WLPR_ERROR_ERRNO;
+                 goto end;
+      }
+                
+      count = write(sock, cbuf, remain);
+      if (count < 0) {
+        if (errno == EINTR)
+           continue;
+        else {
+           ret = EDG_WLPR_ERROR_ERRNO;
+           goto end;
+        }
+      }
+      cbuf += count;
+      remain -= count;
+   }
+   ret = 0;
+
+end:
+   if (to) {
+      gettimeofday(&after,NULL);
+      edg_wlpr_DecrementTimeout(to, before, after);
+      if (to->tv_sec < 0) {
+        to->tv_sec = 0;
+        to->tv_usec = 0;
+      }
+   }
+
+   return ret;
+}
+
+int
+edg_wlpr_Read(int sock, struct timeval *timeout, char **buf, size_t *buf_len)
+{
+   int ret;
+   unsigned char length[4];
+   size_t len;
+
+   ret = nread(sock, timeout, length, 4, &len);
+   if (ret) {
+      *buf_len = 0;
+      return ret;
+   }
+   if (len != 4) {
+      *buf_len = 0;
+      return EDG_WLPR_ERROR_UNEXPECTED_EOF; /* XXX vraci i kdyz peer spadne a zavre trubku */
+   }
+   *buf_len = (length[0] << 24) | 
+              (length[1] << 16) | 
+             (length[2] << 8 ) | 
+             (length[3] << 0);
+
+   *buf = malloc(*buf_len);
+   if (*buf == NULL)
+      return ENOMEM;
+
+   ret = nread(sock, timeout, *buf, *buf_len, &len);
+   if (ret)
+      return ret;
+
+   if (len != *buf_len) {
+      free(*buf);
+      *buf_len = 0;
+      return EDG_WLPR_ERROR_UNEXPECTED_EOF; /* XXX */
+   }
+
+   return 0;
+}
+
+int
+edg_wlpr_Write(int sock, struct timeval *timeout, char *buf, size_t buf_len)
+{
+   unsigned char length[4];
+   int ret;
+
+   length[0] = (buf_len >> 24) & 0xFF;
+   length[1] = (buf_len >> 16) & 0xFF;
+   length[2] = (buf_len >> 8)  & 0xFF;
+   length[3] = (buf_len >> 0)  & 0xFF;
+
+   if ((ret = nwrite(sock, timeout, length, 4)) != 0 ||
+       (ret = nwrite(sock, timeout, buf, buf_len)) != 0) 
+       return ret;
+   
+   return 0;
+}
+
+int
+edg_wlpr_GetToken(const char *msg, const size_t msg_len, 
+                  const char *key, const char *separators,
+                 int req_index, char **value)
+{
+   char *p;
+   size_t len;
+   int index;
+
+   assert(separators != NULL);
+
+   /* Add ending zero ? */
+
+   index = 0;
+   p = (char *)msg;
+   while (p && (p = strstr(p, key))) {
+     if (index == req_index)
+       break;
+     index++;
+     p += strlen(key);
+   }
+   if (p == NULL)
+      return EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND;
+
+   p = strchr(p, '=');
+   if (p == NULL)
+      return EDG_WLPR_ERROR_PROTO_PARSE_ERROR;
+
+   len = strcspn(p+1, separators);
+   if (len == 0)
+      return EDG_WLPR_ERROR_PROTO_PARSE_ERROR;
+
+   *value = malloc(len + 1);
+   if (*value == NULL)
+      return ENOMEM;
+
+   memcpy(*value, p+1, len);
+   (*value)[len] = '\0';
+
+   return 0;
+}
+
+int
+edg_wlpr_StoreToken(char **buf, size_t *buf_len, char *command,
+                    char *value, const char *separator)
+{
+   char line[2048];
+   char *tmp;
+
+   assert(buf != NULL);
+   assert(separator != NULL);
+
+   if (strlen(command) + 1 + strlen(value) + 2 > sizeof(line))
+      return ERANGE; /* XXX */
+
+   snprintf(line, sizeof(line), "%s%s%s", command, value, separator);
+
+   while (strlen(*buf) + strlen(line) + 1 > *buf_len) {
+      tmp = realloc(*buf, *buf_len + EDG_WLPR_BUF_SIZE);
+      if (tmp == NULL)
+         return ENOMEM;
+      *buf = tmp;
+      *buf_len += EDG_WLPR_BUF_SIZE;
+   }
+   strcat(*buf, line);
+
+   return 0;
+}
+
+void
+edg_wlpr_CleanRequest(edg_wlpr_Request *request)
+{
+   assert(request != NULL);
+   if (request->version)
+      free(request->version);
+   if (request->proxy_filename)
+      free(request->proxy_filename);
+   if (request->myproxy_server)
+      free(request->myproxy_server);
+   if (request->jobid)
+      free(request->jobid);
+   if (request->entries) {
+      char **p = request->entries;
+      char **next;
+      while (*p) {
+        next = p+1;
+        free(*p);
+        p = next;
+      }
+      free(request->entries);
+   }
+
+   memset(request, 0, sizeof(request));
+}
+
+void
+edg_wlpr_CleanResponse(edg_wlpr_Response *response)
+{
+   assert(response != NULL);
+   if (response->version)
+      free(response->version);
+   if (response->myproxy_server)
+      free(response->myproxy_server);
+   if (response->filenames) {
+      char **p = response->filenames;
+      char **next;
+
+      while (*p) {
+        next = p+1;
+        free(*p);
+        p = next;
+      }
+      free(response->filenames);
+   }
+   memset(response, 0, sizeof(*response));
+}
+
+const char *
+edg_wlpr_GetErrorString(int code)
+{
+   return (code == 0) ? "OK" : "Error";
+}
+
+char *
+edg_wlpr_EncodeInt(int num) /* long? time */
+{
+   static char ret[64];
+
+   snprintf(ret, sizeof(ret), "%d", num);
+   return ret;
+}
+
+int
+edg_wlpr_DecodeInt(char *str, int *num)
+{
+   *num = atol(str); /* XXX */
+   return 0;
+}
+
+int
+edg_wlpr_DecrementTimeout(struct timeval *timeout, struct timeval before, struct timeval after)
+{
+   (*timeout).tv_sec = (*timeout).tv_sec - (after.tv_sec - before.tv_sec);
+   (*timeout).tv_usec = (*timeout).tv_usec - (after.tv_usec - before.tv_usec);
+   while ( (*timeout).tv_usec < 0) {
+      (*timeout).tv_sec--;
+      (*timeout).tv_usec += 1000000;
+   }
+
+   if ( ((*timeout).tv_sec < 0) || (((*timeout).tv_sec == 0) && ((*timeout).tv_usec == 0)) ) return(1);
+   else return(0);
+}
diff --git a/org.glite.px.proxyrenewal/src/renew.c b/org.glite.px.proxyrenewal/src/renew.c
new file mode 100644 (file)
index 0000000..29105d2
--- /dev/null
@@ -0,0 +1,256 @@
+#include "renewal_locl.h"
+#include "renewd_locl.h"
+
+#include "glite/security/voms/voms_apic.h"
+
+#ident "$Header$"
+
+#define RENEWAL_COUNTS_MAX     1000    /* the slave daemon exits after that many attemtps */
+
+extern char *repository;
+extern char *cadir;
+extern char *vomsdir;
+extern int voms_enabled;
+static int received_signal = -1, die = 0;
+
+static void
+check_renewal(glite_renewal_core_context ctx, char *datafile, int force_renew, int *num_renewed);
+
+static int
+renew_proxy(glite_renewal_core_context ctx, proxy_record *record, char *basename, char **new_proxy);
+
+static void
+register_signal(int signal);
+
+static void
+register_signal(int signal)
+{
+      received_signal = signal;
+      switch ((received_signal = signal)) {
+        case SIGINT:
+        case SIGTERM:
+        case SIGQUIT:
+           die = signal;
+           break;
+        default:
+           break;
+      }
+}
+
+static int
+renew_proxy(glite_renewal_core_context ctx, proxy_record *record, char *basename, char **new_proxy)
+{
+   char repository_file[FILENAME_MAX];
+   int ret = -1;
+   char *p = NULL;
+   char *server = NULL;
+   unsigned int port = 0;
+
+   snprintf(repository_file, sizeof(repository_file),"%s.%d",
+           basename, record->suffix);
+
+   if (record->myproxy_server)
+      server = strdup(record->myproxy_server);
+
+   if (server && (p = strchr(server, ':'))) {
+      *p++ = '\0';
+      ret = edg_wlpr_DecodeInt(p, &port);
+   }
+
+   ret = glite_renewal_core_renew(ctx, server, port, repository_file, new_proxy);
+   if (ret)
+      goto end;
+
+   ret = 0;
+
+end:
+   if (server)
+      free(server);
+
+   return ret;
+}
+
+static void
+check_renewal(glite_renewal_core_context ctx, char *datafile, int force_renew, int *num_renewed)
+{
+   char line[1024];
+   proxy_record record;
+   char *p;
+   int ret, i;
+   time_t current_time;
+   FILE *meta_fd = NULL;
+   char basename[FILENAME_MAX];
+   edg_wlpr_Request request;
+   edg_wlpr_Response response;
+   char *new_proxy = NULL;
+   char *entry = NULL;
+   char **tmp;
+   int num = 0;
+
+   assert(datafile != NULL);
+
+   *num_renewed = 0;
+
+   memset(&record, 0, sizeof(record));
+   memset(basename, 0, sizeof(basename));
+   memset(&request, 0, sizeof(request));
+   memset(&response, 0, sizeof(response));
+   
+   strncpy(basename, datafile, sizeof(basename) - 1);
+   p = basename + strlen(basename) - strlen(".data");
+   if (strcmp(p, ".data") != 0) {
+      glite_renewal_log(ctx, LOG_ERR, "Meta filename doesn't end with '.data'");
+      return;
+   }
+   *p = '\0';
+
+   request.command = EDG_WLPR_COMMAND_UPDATE_DB;
+   request.proxy_filename = strdup(basename);
+
+   meta_fd = fopen(datafile, "r");
+   if (meta_fd == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot open meta file %s (%s)",
+                  datafile, strerror(errno));
+      return;
+   }
+
+   current_time = time(NULL);
+   glite_renewal_log(ctx, LOG_DEBUG, "Reading metafile %s", datafile);
+
+   while (fgets(line, sizeof(line), meta_fd) != NULL) {
+      free_record(ctx, &record);
+      p = strchr(line, '\n');
+      if (p)
+        *p = '\0';
+      ret = decode_record(ctx, line, &record);
+      if (ret)
+        continue; /* XXX exit? */
+      if (record.jobids.len == 0) /* no jobid registered for this proxy */
+        continue;
+      if (current_time + RENEWAL_CLOCK_SKEW >= record.end_time ||
+         record.next_renewal <= current_time ||
+         force_renew) {
+        ret = EDG_WLPR_PROXY_EXPIRED;
+        if ( record.end_time + RENEWAL_CLOCK_SKEW >= current_time) {
+           /* only try renewal if the proxy hasn't already expired */
+           ret = renew_proxy(ctx, &record, basename, &new_proxy);
+         }
+
+        /* if the proxy wasn't renewed have the daemon planned another renewal */
+        asprintf(&entry, "%d:%s", record.suffix, (ret == 0) ? new_proxy : "");
+        if (new_proxy) {
+           free(new_proxy); new_proxy = NULL;
+        }
+
+        tmp = realloc(request.entries, (num + 2) * sizeof(*tmp));
+        if (tmp == NULL) {
+           free_record(ctx, &record);
+           return;
+        }
+        request.entries = tmp;
+        request.entries[num] = entry;
+        request.entries[num+1] = NULL;
+        num++;
+      }
+   }
+   free_record(ctx, &record);
+
+   if (num > 0) {
+      ret = edg_wlpr_RequestSend(&request, &response);
+      if (ret != 0)
+        glite_renewal_log(ctx, LOG_ERR,
+                     "Failed to send update request to master (%d)", ret);
+      else if (response.response_code != 0)
+        glite_renewal_log(ctx, LOG_ERR,
+                     "Master failed to update database (%d)", response.response_code);
+
+      /* delete all tmp proxy files which may survive */
+      for (i = 0; i < num; i++) {
+        p = strchr(request.entries[i], ':');
+        if (p+1)
+           unlink(p+1);
+      }
+   }
+   fclose(meta_fd);
+
+   edg_wlpr_CleanResponse(&response);
+   edg_wlpr_CleanRequest(&request);
+
+   *num_renewed = num;
+
+   return;
+}
+
+int renewal(glite_renewal_core_context ctx, int force_renew, int *num_renewed)
+{
+   DIR *dir = NULL;
+   struct dirent *file;
+   FILE *fd;
+   int num = 0;
+
+   glite_renewal_log(ctx, LOG_DEBUG, "Starting renewal process");
+
+   *num_renewed = 0;
+
+   if (chdir(repository)) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot access repository directory %s (%s)",
+                  repository, strerror(errno));
+      return errno;
+   }
+
+   dir = opendir(repository);
+   if (dir == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot open repository directory %s (%s)",
+                  repository, strerror(errno));
+      return errno;
+   }
+
+   while ((file = readdir(dir))) {
+      /* read files of format `md5sum`.data, where md5sum() is of fixed length
+        32 chars */
+      if (file->d_name == NULL || strlen(file->d_name) != 37 ||
+         strcmp(file->d_name + 32, ".data") != 0)
+        continue;
+      fd = fopen(file->d_name, "r");
+      if (fd == NULL) {
+        glite_renewal_log(ctx, LOG_ERR, "Cannot open meta file %s (%s)",
+                     file->d_name, strerror(errno));
+        continue;
+      }
+      check_renewal(ctx, file->d_name, force_renew, &num);
+      *num_renewed += num;
+      fclose(fd);
+   }
+   closedir(dir);
+   glite_renewal_log(ctx, LOG_DEBUG, "Finishing renewal process");
+   return 0;
+}
+
+void
+watchdog_start(glite_renewal_core_context ctx)
+{
+   struct sigaction sa;
+   int force_renewal;
+   int count = 0, num;
+   
+   memset(&sa,0,sizeof(sa));
+   sa.sa_handler = register_signal;
+   sigaction(SIGUSR1, &sa, NULL);
+   sigaction(SIGINT,&sa,NULL);
+   sigaction(SIGQUIT,&sa,NULL);
+   sigaction(SIGTERM,&sa,NULL);
+   sigaction(SIGPIPE,&sa,NULL);
+
+   while (count < RENEWAL_COUNTS_MAX && !die) {
+       received_signal = -1;
+       sleep(60 * 5);
+       force_renewal = (received_signal == SIGUSR1) ? 1 : 0;
+       if (die)
+         break;
+       /* XXX uninstall signal handler ? */
+       renewal(ctx, force_renewal, &num);
+       count += num;
+   }
+   glite_renewal_log(ctx, LOG_DEBUG, "Terminating after %d renewal attempts", count);
+   exit(0);
+}
diff --git a/org.glite.px.proxyrenewal/src/renewal_core.c b/org.glite.px.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.px.proxyrenewal/src/renewal_locl.h b/org.glite.px.proxyrenewal/src/renewal_locl.h
new file mode 100644 (file)
index 0000000..256eb26
--- /dev/null
@@ -0,0 +1,148 @@
+#ifndef RENEWAL_LOCL_H
+#define RENEWAL_LOCL_H
+
+#ident "$Header$"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <syslog.h>
+#include <linux/limits.h>
+#include <signal.h>
+#include <assert.h>
+#include <getopt.h>
+#include <dirent.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <poll.h>
+#ifndef INFTIM
+#define INFTIM (-1)
+#endif
+
+#include <openssl/md5.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+#include "renewal.h"
+
+#define JDL_MYPROXY "Myproxy_server="
+
+typedef enum {
+  EDG_WLPR_COMMAND_NONE = 0,
+  EDG_WLPR_COMMAND_REG = 1,
+  EDG_WLPR_COMMAND_UNREG,
+  EDG_WLPR_COMMAND_GET,
+  EDG_WLPR_COMMAND_LIST,
+  EDG_WLPR_COMMAND_STATUS,
+  EDG_WLPR_COMMAND_UPDATE_DB,
+} edg_wlpr_Command;
+
+/* prefix neni nutny */
+#define EDG_WLPR_PROTO_VERSION          "Version="
+#define EDG_WLPR_PROTO_COMMAND          "Command="
+#define EDG_WLPR_PROTO_MYPROXY_SERVER   "Myproxy_server="
+#define EDG_WLPR_PROTO_PROXY            "Proxy_name="
+#define EDG_WLPR_PROTO_UNIQUE_PROXY     "Unique=" /* XXX */
+#define EDG_WLPR_PROTO_JOBID            "Jobid="
+#define EDG_WLPR_PROTO_ENTRY            "Entry="
+
+#define EDG_WLPR_PROTO_RESPONSE         "Response=" /* XXX result ?? */
+#define EDG_WLPR_PROTO_START_TIME       "Start_time="
+#define EDG_WLPR_PROTO_END_TIME         "End_time="
+#define EDG_WLPR_PROTO_RENEWAL_TIME     "Renewal_time=" /* XXX Next renewal ?? */
+
+#define EDG_WLPR_MYPROXY_PORT 7512
+
+#define EDG_WLPR_REPOSITORY_ROOT "/var/spool/edg-wl-renewd"
+
+#define EDG_WLPR_BUF_SIZE 4096
+
+#define EDG_WLPR_VERSION "EDG Proxy Renewal 1.0"
+
+#define MAX_PROXIES 4 /* max. number of jobids sharing one proxy */
+
+#define RENEWAL_CLOCK_SKEW (5 * 60)
+
+#define DGPR_RETRIEVE_DEFAULT_HOURS 10
+
+#define GLITE_PR_TIMEOUT_DEFAULT       120
+
+typedef struct {
+  char *version;
+  edg_wlpr_Command command;
+  char *myproxy_server;
+  char *proxy_filename;
+  int unique; 
+  char *jobid;
+  char **entries; /* for updates from the renewal part (renew.c) */
+} edg_wlpr_Request;
+
+typedef struct {
+  char *version;
+  int response_code;
+  time_t start_time;
+  time_t end_time;
+  time_t next_renewal_time;
+  int counter;
+  char *myproxy_server;
+  char **filenames;
+} edg_wlpr_Response;
+
+#define DGPR_REG_SOCKET_NAME_ROOT "/tmp/dgpr_renew_"
+
+#if 0
+/* Errors: */
+/* XXX enum */
+#define EDG_WLPR_ERROR_EOF 1
+#define EDG_WLPR_ERROR_PARSE_NOT_FOUND 2
+#define EDG_WLPR_ERROR_PARSE_ERROR 3
+#define EDG_WLPR_ERROR_UNKNOWN_COMMAND 4
+#define EDG_WLPR_ERROR_NOTFOUND 5
+#endif
+
+int
+edg_wlpr_GetToken(const char *msg, const size_t msg_len,
+                  const char *key, const char *separators,
+                  int req_index, char **value);
+
+int
+edg_wlpr_StoreToken(char **buf, size_t *buf_len, char *command,
+                    char *value, const char *separator);
+
+int
+edg_wlpr_Read(int sock, struct timeval *timeout, char **buf, size_t *buf_len);
+
+int
+edg_wlpr_Write(int sock, struct timeval *timeout, char *buf, size_t buf_len);
+
+void
+edg_wlpr_CleanRequest(edg_wlpr_Request *request);
+
+void
+edg_wlpr_CleanResponse(edg_wlpr_Response *response);
+
+const char *
+edg_wlpr_GetErrorString(int err);
+
+char *
+edg_wlpr_EncodeInt(int num); /* long? time */
+
+int
+edg_wlpr_DecodeInt(char *str, int *num);
+
+int
+edg_wlpr_RequestSend(edg_wlpr_Request *request, edg_wlpr_Response *response);
+
+int
+edg_wlpr_DecrementTimeout(struct timeval *timeout, struct timeval before, struct timeval after);
+
+#endif /* RENEWAL_LOCL_H */
diff --git a/org.glite.px.proxyrenewal/src/renewd.c b/org.glite.px.proxyrenewal/src/renewd.c
new file mode 100644 (file)
index 0000000..69a2ea0
--- /dev/null
@@ -0,0 +1,606 @@
+#include "renewal_locl.h"
+#include "renewd_locl.h"
+
+static const char rcsid[] = "$Header$";
+
+#define SEPARATORS "\n"
+/* GRIDMANAGER_CHECKPROXY_INTERVAL + GRIDMANAGER_MINIMUM_PROXY_TIME */
+#define CONDOR_MINIMUM_PROXY_TIME (1800)
+
+int debug = 0;
+char *repository = NULL;
+time_t condor_limit = CONDOR_MINIMUM_PROXY_TIME;
+char *cadir = NULL;
+char *vomsdir = NULL;
+int voms_enabled = 0;
+char *cert = NULL;
+char *key = NULL;
+char *vomsconf = NULL;
+
+static volatile int die = 0, child_died = 0;
+double default_timeout = 0;
+
+static struct option opts[] = {
+   { "help",       no_argument,       NULL,  'h' },
+   { "version",    no_argument,       NULL,  'v' },
+   { "debug",      no_argument,       NULL,  'd' },
+   { "repository", required_argument, NULL,  'r' },
+   { "condor-limit", required_argument, NULL, 'c' }, 
+   { "CAdir",      required_argument, NULL,  'C' },
+   { "VOMSdir",    required_argument, NULL,  'V' },
+   { "enable-voms", no_argument,     NULL,  'A' },
+   { "voms-config", required_argument, NULL, 'G' },
+   { "cert",        required_argument, NULL, 't' },
+   { "key",         required_argument, NULL, 'k' },
+   { NULL, 0, NULL, 0 }
+};
+
+typedef struct {
+   edg_wlpr_Command code;
+   void (*handler) (glite_renewal_core_context ctx, edg_wlpr_Request *request, edg_wlpr_Response *response);
+} command_table;
+
+static command_table commands[] = {
+   { EDG_WLPR_COMMAND_REG,     register_proxy,     },
+   { EDG_WLPR_COMMAND_UNREG,   unregister_proxy,   },
+   { EDG_WLPR_COMMAND_GET,     get_proxy,          },
+#if 0
+   { EDG_WLPR_COMMAND_LIST,    list_proxies,       },
+   { EDG_WLPR_COMMAND_STATUS,  status_proxy,       },
+#endif
+   { EDG_WLPR_COMMAND_UPDATE_DB, update_db,        },
+   { 0, NULL },
+};
+
+/* static prototypes */
+static void
+usage(glite_renewal_core_context ctx, char *progname);
+
+static int
+do_listen(glite_renewal_core_context ctx, char *socket_name, int *sock);
+
+static int
+encode_response(glite_renewal_core_context ctx, edg_wlpr_Response *response, char **msg);
+
+static command_table *
+find_command(glite_renewal_core_context ctx, edg_wlpr_Command code);
+
+static int
+proto(glite_renewal_core_context ctx, int sock);
+
+static int
+doit(glite_renewal_core_context ctx, int sock);
+
+static int
+decode_request(glite_renewal_core_context ctx, const char *msg, const size_t msg_len, edg_wlpr_Request *request);
+
+int
+start_watchdog(glite_renewal_core_context ctx, pid_t *pid);
+
+static void
+catchsig(int sig)
+{
+   switch (sig) {
+      case SIGINT:
+      case SIGTERM:
+      case SIGQUIT:
+        die = sig;
+        break;
+      case SIGCHLD:
+        child_died = 1;
+        break;
+      default:
+        break;
+   }
+}
+
+static command_table *
+find_command(glite_renewal_core_context ctx, edg_wlpr_Command code)
+{
+   command_table *c;
+
+   for (c = commands; c->code; c++) {
+      if (c->code == code)
+          return c;
+   }
+   return NULL;
+}
+
+static int
+proto(glite_renewal_core_context ctx, int sock)
+{
+   char  *buf = NULL;
+   size_t  buf_len;
+   int  ret;
+   edg_wlpr_Response  response;
+   edg_wlpr_Request  request;
+   command_table  *command;
+   struct timeval timeout;
+
+   memset(&request, 0, sizeof(request));
+   memset(&response, 0, sizeof(response));
+
+   timeout.tv_sec = (long) default_timeout;
+   timeout.tv_usec = (long) ((default_timeout - timeout.tv_sec) * 1e6);
+
+   ret = edg_wlpr_Read(sock, &timeout, &buf, &buf_len);
+   if (ret) {
+      glite_renewal_log(ctx, LOG_ERR, "Error reading from client: %s",
+                   edg_wlpr_GetErrorString(ret));
+      return ret;
+   }
+
+   ret = decode_request(ctx, buf, buf_len, &request);
+   free(buf);
+   if (ret)
+      goto end;
+
+   /* XXX check request (protocol version, ...) */
+
+   command = find_command(ctx, request.command);
+   if (command == NULL) {
+      ret = EDG_WLPR_ERROR_UNKNOWN_COMMAND;
+      glite_renewal_log(ctx, LOG_ERR, "Received unknown command (%d)", request.command);
+      goto end;
+   }
+
+   glite_renewal_log(ctx, LOG_INFO, "Received command code %d for proxy %s and jobid %s",
+                request.command,
+               request.proxy_filename ? request.proxy_filename : "(unspecified)",
+               request.jobid ? request.jobid : "(unspecified)");
+
+   command->handler(ctx, &request, &response);
+
+   ret = encode_response(ctx, &response, &buf);
+   if (ret)
+      goto end;
+
+   ret = edg_wlpr_Write(sock, &timeout, buf, strlen(buf) + 1);
+   free(buf);
+   if (ret) {
+      glite_renewal_log(ctx, LOG_ERR, "Error sending response to client: %s",
+                   edg_wlpr_GetErrorString(ret));
+      goto end;
+   }
+
+end:
+   edg_wlpr_CleanRequest(&request);
+   edg_wlpr_CleanResponse(&response);
+
+   return ret;
+}
+
+static int
+doit(glite_renewal_core_context ctx, int sock)
+{
+   int newsock;
+   struct sockaddr_un client_addr;
+   int client_addr_len = sizeof(client_addr);
+   int flags;
+
+   while (!die) {
+
+      if (child_died) {
+        int pid, newpid, ret;
+
+        while ((pid=waitpid(-1,NULL,WNOHANG))>0)
+           ;
+        ret = start_watchdog(ctx, &newpid);
+        if (ret)
+           return ret;
+        glite_renewal_log(ctx, LOG_DEBUG, "Renewal slave process re-started");
+        child_died = 0;
+        continue;
+      }
+
+      newsock = accept(sock, (struct sockaddr *) &client_addr, &client_addr_len);
+      if (newsock == -1) {
+        if (errno != EINTR)
+           glite_renewal_log(ctx, LOG_ERR, "accept() failed");
+         continue;
+      }
+      glite_renewal_log(ctx, LOG_DEBUG, "Got connection");
+
+      flags = fcntl(newsock, F_GETFL, 0);
+      if (fcntl(newsock, F_SETFL, flags | O_NONBLOCK) < 0) {
+        glite_renewal_log(ctx, LOG_ERR, "Can't set O_NONBLOCK mode (%s), closing.\n",
+                     strerror(errno));
+        close(newsock);
+        continue;
+      }
+        
+      proto(ctx, newsock);
+
+      glite_renewal_log(ctx, LOG_DEBUG, "Connection closed");
+      close(newsock);
+   }
+   glite_renewal_log(ctx, LOG_DEBUG, "Terminating on signal %d\n",die);
+   return 0;
+}
+
+static int
+decode_request(glite_renewal_core_context ctx, const char *msg, const size_t msg_len, edg_wlpr_Request *request)
+{
+   char *value = NULL;
+#if 0
+   char *p;
+   int port;
+#endif
+   int ret;
+   int index;
+   
+   /* XXX add an ending zero '\0' */
+
+   assert(msg != NULL);
+   assert(request != NULL);
+   
+   memset(request, 0, sizeof(*request));
+
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_VERSION, SEPARATORS,
+                          0, &request->version);
+   if (ret) {
+      glite_renewal_log(ctx, LOG_ERR, "Protocol error reading protocol specification: %s",
+                   edg_wlpr_GetErrorString(ret));
+      return ret;
+   }
+   
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_COMMAND, SEPARATORS,
+                          0, &value);
+   if (ret) {
+      glite_renewal_log(ctx, LOG_ERR, "Protocol error reading command specification: %s",
+                   edg_wlpr_GetErrorString(ret));
+      goto err;
+   }
+
+   ret = edg_wlpr_DecodeInt(value, (int *)(&request->command));
+   if (ret) {
+      glite_renewal_log(ctx, LOG_ERR, "Received non-numeric command specification (%s)",
+                   value);
+      free(value);
+      goto err;
+   }
+   free(value);
+
+   if (find_command(ctx, request->command) == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "Received unknown command (%d)", request->command);
+      ret = EDG_WLPR_ERROR_UNKNOWN_COMMAND;
+      goto err;
+   }
+
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_MYPROXY_SERVER,
+                          SEPARATORS, 0, &request->myproxy_server);
+   if (ret && ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND) {
+      glite_renewal_log(ctx, LOG_ERR, "Protocol error reading myproxy server specification: %s",
+                   edg_wlpr_GetErrorString(ret));
+      goto err;
+   }
+
+#if 0
+   request->myproxy_port = EDG_WLPR_MYPROXY_PORT; /* ??? */
+   if (request->myproxy_server && (p = strchr(request->myproxy_server, ':'))) {
+      *p = '\0';
+      port = atol(p+1); /* XXX see myproxy for err check */
+      request->myproxy_port = port;
+   }
+#endif
+
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_PROXY, SEPARATORS, 
+                          0, &request->proxy_filename);
+   if (ret && ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND) {
+      glite_renewal_log(ctx, LOG_ERR, "Protocol error reading proxy specification: %s",
+                   edg_wlpr_GetErrorString(ret));
+      goto err;
+   }
+
+#if 0
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_UNIQUE_PROXY, 
+                          SEPARATORS, 0, &value);
+   if (ret && ret != EDG_WLPR_ERROR_PARSE_NOT_FOUND)
+      goto err;
+   if (ret == 0 && strcasecmp(value, "yes") == 0)
+      request->unique = 1;
+   free(value);
+#endif
+
+   ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_JOBID, SEPARATORS,
+                          0, &request->jobid);
+   if (ret && ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND) {
+      glite_renewal_log(ctx, LOG_ERR, "Protocol error reading JobId : %s",
+                  edg_wlpr_GetErrorString(ret));
+      goto err;
+   }
+
+   index = 0;
+   while ((ret = edg_wlpr_GetToken(msg, msg_len, EDG_WLPR_PROTO_ENTRY,
+                                  SEPARATORS, index, &value)) == 0) {
+      char **tmp;
+
+      tmp = realloc(request->entries, (index + 2) * sizeof(*tmp));
+      if (tmp == NULL) {
+        ret = ENOMEM;
+        goto err;
+      }
+      request->entries = tmp;
+      request->entries[index] = value;
+      index++;
+   }
+   if (ret != EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND)
+      goto err;
+   if (request->entries)
+      request->entries[index] = NULL;
+
+   return 0;
+
+err:
+   edg_wlpr_CleanRequest(request);
+   return ret;
+}
+
+static int
+encode_response(glite_renewal_core_context ctx, edg_wlpr_Response *response, char **msg)
+{
+   char *buf;
+   size_t buf_len;
+   int ret;
+
+   buf_len = EDG_WLPR_BUF_SIZE;
+   buf = malloc(buf_len);
+   if (buf == NULL)
+      return ENOMEM;
+   buf[0] = '\0';
+
+   ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_VERSION,
+                            EDG_WLPR_VERSION, SEPARATORS);
+   if (ret)
+      goto err;
+
+   ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_RESPONSE,
+                             edg_wlpr_EncodeInt(response->response_code),
+                            SEPARATORS);
+   if (ret)
+      goto err;
+
+   if (response->myproxy_server) {
+      char host[1024];
+
+#if 0
+      snprintf(host, sizeof(host), "%s:%d", response->myproxy_server,
+               (response->myproxy_port) ? response->myproxy_port : EDG_WLPR_MYPROXY_PORT);
+#endif
+      ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_MYPROXY_SERVER,
+                                host, SEPARATORS);
+      if (ret)
+         goto err;
+   }
+
+   if (response->start_time) {
+      ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_START_TIME,
+                                edg_wlpr_EncodeInt(response->start_time),
+                               SEPARATORS);
+      if (ret)
+         goto err;
+   }
+
+   if (response->end_time) {
+      ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_END_TIME,
+                                edg_wlpr_EncodeInt(response->end_time),
+                               SEPARATORS);
+      if (ret)
+         goto err;
+   }
+
+   if (response->next_renewal_time) {
+      ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_RENEWAL_TIME,
+                                edg_wlpr_EncodeInt(response->next_renewal_time),
+                               SEPARATORS);
+      if (ret)
+         goto err;
+   }
+
+   if (response->filenames) {
+      char **p = response->filenames;
+      while (*p) {
+         ret = edg_wlpr_StoreToken(&buf, &buf_len, EDG_WLPR_PROTO_PROXY, *p,
+                                  SEPARATORS);
+         if (ret)
+            goto err;
+         p++;
+      }
+   }
+
+   buf[strlen(buf)] = '\0';
+   *msg = buf;
+   return 0;
+
+err:
+   free(buf);
+   *msg = NULL;
+   return ret;
+}
+
+
+static void
+usage(glite_renewal_core_context ctx, char *progname)
+{
+   fprintf(stderr,"usage: %s [option]\n"
+          "\t-h, --help           display this help and exit\n"
+          "\t-v, --version        output version information and exit\n"
+          "\t-d, --debug          don't fork, print out debugging information\n"
+          "\t-r, --repository     repository directory\n"
+          "\t-c, --condor-limit   how long before expiration the proxy must be renewed\n"
+          "\t-C, --CAdir          trusted certificates directory\n"
+          "\t-V, --VOMSdir        trusted VOMS servers certificates directory\n"
+          "\t-A, --enable-voms    renew also VOMS certificates in proxies\n"
+          "\t-G, --voms-config    location of the vomses configuration file\n",
+          progname);
+}
+
+static int
+do_listen(glite_renewal_core_context ctx, char *socket_name, int *sock)
+{
+   struct sockaddr_un my_addr;
+   int s;
+   int ret;
+
+   assert(sock != NULL);
+
+   memset(&my_addr, 0, sizeof(my_addr));
+   my_addr.sun_family = AF_UNIX;
+   strncpy(my_addr.sun_path, socket_name, sizeof(my_addr.sun_path));
+   unlink(socket_name);
+   umask(0177);
+
+   s = socket(AF_UNIX, SOCK_STREAM, 0);
+   if (s == -1) {
+      glite_renewal_log(ctx, LOG_ERR, "socket(): %s", strerror(errno));
+      return errno;
+   }
+
+   ret = bind(s, (struct sockaddr *)&my_addr, sizeof(my_addr));
+   if (ret == -1) {
+      glite_renewal_log(ctx, LOG_ERR, "bind(): %s", strerror(errno));
+      close(s);
+      return errno;
+   }
+
+   ret = listen(s, 50);
+   if (ret == -1) {
+      glite_renewal_log(ctx, LOG_ERR, "listen(): %s", strerror(errno));
+      close(s);
+      return errno;
+   }
+
+   *sock = s;
+   return 0;
+}
+
+int
+start_watchdog(glite_renewal_core_context ctx, pid_t *pid)
+{
+   pid_t p;
+
+   switch ((p = fork())) {
+      case -1:
+        glite_renewal_log(ctx, LOG_ERR, "fork() failed: %s",
+                     strerror(errno));
+        return errno;
+      case 0:
+        watchdog_start(ctx);
+        exit(0); 
+        break;
+      default:
+        *pid = p;
+        return 0;
+   }
+   /* not reachable */
+   exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+   int   sock;
+   char  *progname;
+   int   opt;
+   int   fd;
+   char  sockname[PATH_MAX];
+   int   ret;
+   pid_t pid;
+   struct sigaction    sa;
+   const char *s = NULL;
+   glite_renewal_core_context ctx = NULL;
+
+   progname = strrchr(argv[0],'/');
+   if (progname) progname++; 
+   else progname = argv[0];
+
+   repository = EDG_WLPR_REPOSITORY_ROOT;
+   debug = 0;
+
+   while ((opt = getopt_long(argc, argv, "hvdr:c:C:V:AG:t:k:", opts, NULL)) != EOF)
+      switch (opt) {
+        case 'h': usage(ctx, progname); exit(0);
+        case 'v': fprintf(stdout, "%s:\t%s\n", progname, rcsid); exit(0);
+        case 'd': debug = 1; break;
+         case 'r': repository = optarg; break;
+        case 'c': condor_limit = atoi(optarg); break;
+        case 'C': cadir = optarg; break;
+        case 'V': vomsdir = optarg; break;
+        case 'A': voms_enabled = 1; break;
+        case 'G': vomsconf = optarg; break;
+        case 't': cert = optarg; break;
+        case 'k': key = optarg; break;
+        case '?': usage(ctx, progname); return 1;
+      }
+
+   if (optind < argc) {
+      usage(ctx, progname);
+      exit(1);
+   }
+
+   ret = glite_renewal_core_init_ctx(&ctx);
+   if (ret) {
+      fprintf(stderr, "Cannot initialize context\n");
+      exit(1);
+   }
+   if (debug) {
+      ctx->log_level = LOG_DEBUG;
+      ctx->log_dst = GLITE_RENEWAL_LOG_STDOUT;
+   }
+   ctx->voms_conf = vomsconf;
+
+   if (chdir(repository)) {
+      glite_renewal_log(ctx, LOG_ERR, "Cannot access repository directory %s (%s)",
+                  repository, strerror(errno));
+      exit(1);
+   }
+
+   globus_module_activate(GLOBUS_GSI_CERT_UTILS_MODULE);
+   globus_module_activate(GLOBUS_GSI_PROXY_MODULE);
+
+   if (!debug) {
+      /* chdir ? */
+      if (daemon(1,0) == -1) {
+        perror("deamon()");
+        exit(1);
+      }
+      openlog(progname, LOG_PID, LOG_DAEMON);
+   }
+
+   if (cert)
+      setenv("X509_USER_CERT", cert, 1);
+
+   if (key)
+      setenv("X509_USER_KEY", key, 1);
+
+   if (cadir)
+      setenv("X509_CERT_DIR", cadir, 1);
+
+   s = getenv("GLITE_PR_TIMEOUT");
+   default_timeout = s ? atof(s) : GLITE_PR_TIMEOUT_DEFAULT;
+
+   memset(&sa,0,sizeof(sa));
+   sa.sa_handler = catchsig;
+   sigaction(SIGINT,&sa,NULL);
+   sigaction(SIGQUIT,&sa,NULL);
+   sigaction(SIGTERM,&sa,NULL);
+   sigaction(SIGCHLD,&sa,NULL);
+   sigaction(SIGPIPE,&sa,NULL);
+
+   ret = start_watchdog(ctx, &pid);
+   if (ret)
+      return 1;
+  
+   umask(0177);
+   snprintf(sockname, sizeof(sockname), "%s%d",
+           DGPR_REG_SOCKET_NAME_ROOT, getuid());
+   /* XXX check that the socket is not already active */
+   ret = do_listen(ctx, sockname, &sock);
+   if (ret)
+      return 1;
+   glite_renewal_log(ctx, LOG_DEBUG, "Listening at %s", sockname);
+
+   ret = doit(ctx, sock);
+
+   close(sock);
+   return ret;
+}
diff --git a/org.glite.px.proxyrenewal/src/renewd_locl.h b/org.glite.px.proxyrenewal/src/renewd_locl.h
new file mode 100644 (file)
index 0000000..489e909
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef RENEWALD_LOCL_H
+#define RENEWALD_LOCL_H
+
+#ident "$Header$"
+
+#include <globus_gsi_credential.h>
+#include <globus_gsi_proxy.h>
+#include <globus_gsi_cert_utils_constants.h>
+
+#include "renewal.h"
+#include "renewal_core.h"
+
+#ifdef HAVE_DMALLOC_H
+#include <dmalloc.h>
+#endif
+
+/* XXX */
+#if 0
+#define EDG_WLPR_ERROR_PARSE_NOT_FOUND EDG_WLPR_ERROR_PROTO_PARSE_ERROR
+#define EDG_WLPR_ERROR_NOTFOUND        EDG_WLPR_PROXY_NOT_REGISTERED
+#endif
+
+typedef struct {
+   unsigned int len;
+   char **val;
+} prd_list;
+
+typedef struct {
+   int suffix;
+   prd_list jobids;
+   int unique;
+   int voms_exts;
+   char *myproxy_server;
+   time_t end_time;
+   time_t next_renewal;
+} proxy_record;
+
+/* commands */
+void
+register_proxy(glite_renewal_core_context ctx, edg_wlpr_Request *request, edg_wlpr_Response *response);
+
+void
+unregister_proxy(glite_renewal_core_context ctx, edg_wlpr_Request *request, edg_wlpr_Response *response);
+
+void
+get_proxy(glite_renewal_core_context ctx, edg_wlpr_Request *request, edg_wlpr_Response *response);
+
+void
+update_db(glite_renewal_core_context ctx, edg_wlpr_Request *request, edg_wlpr_Response *response);
+
+int
+get_times(glite_renewal_core_context ctx, char *proxy_file, proxy_record *record);
+
+void
+watchdog_start(glite_renewal_core_context ctx);
+
+void
+glite_renewal_log(glite_renewal_core_context ctx, int dbg_level, const char *format, ...);
+
+int
+decode_record(glite_renewal_core_context ctx, char *line, proxy_record *record);
+
+int
+encode_record(glite_renewal_core_context ctx, proxy_record *record, char **line);
+
+void
+free_record(glite_renewal_core_context ctx, proxy_record *record);
+
+int
+glite_renewal_load_proxy(glite_renewal_core_context ctx, const char *filename, X509 **cert, EVP_PKEY **privkey,
+           STACK_OF(X509) **chain, globus_gsi_cred_handle_t *proxy);
+
+int
+glite_renewal_get_proxy_base_name(glite_renewal_core_context ctx, const char *file, char **subject);
+
+int
+glite_renewal_renew_voms_creds(glite_renewal_core_context ctx, const char *cur_file, const char *renewed_file, const char *new_file);
+
+int
+glite_renewal_check_voms_attrs(glite_renewal_core_context ctx, const char *proxy);
+
+#endif /* RENEWALD_LOCL_H */
diff --git a/org.glite.px.proxyrenewal/src/voms.c b/org.glite.px.proxyrenewal/src/voms.c
new file mode 100644 (file)
index 0000000..687d93b
--- /dev/null
@@ -0,0 +1,356 @@
+#include "renewal_locl.h"
+#include "renewd_locl.h"
+
+#include <string.h>
+#include <openssl/x509.h>
+
+#include "glite/security/voms/voms_apic.h"
+
+#include "glite/security/voms/newformat.h"
+
+char * Decode(const char *, int, int *);
+char **listadd(char **, char *, int);
+
+static int
+generate_proxy(glite_renewal_core_context ctx, 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) {
+      glite_renewal_log(ctx, LOG_ERR, "globus_gsi_proxy_handle_init() failed\n");
+      goto end;
+   }
+
+   result = globus_gsi_cred_get_key(cur_proxy, &cur_proxy_priv_key);
+   if (result) {
+      glite_renewal_log(ctx, LOG_ERR, "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) {
+      glite_renewal_log(ctx, LOG_ERR, "globus_gsi_cred_get_cert_type() failed\n");
+      goto end;
+   }
+
+   result = globus_gsi_proxy_handle_set_type(proxy_handle, proxy_type);
+   if (result) {
+      glite_renewal_log(ctx, LOG_ERR, "globus_gsi_proxy_handle_set_type() failed\n");
+      goto end;
+   }
+
+   result = globus_gsi_proxy_create_signed(proxy_handle, cur_proxy, &proxy);
+   if (result) {
+      glite_renewal_log(ctx, LOG_ERR, "globus_gsi_proxy_handle_init() failed\n");
+      goto end;
+   }
+
+   /* Get the new proxy */
+   result = globus_gsi_cred_get_cert(proxy, &new_cert);
+   if (result) {
+      glite_renewal_log(ctx, LOG_ERR, "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) {
+      glite_renewal_log(ctx, LOG_ERR, "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(glite_renewal_core_context ctx, 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) {
+      glite_renewal_log(ctx, LOG_ERR, "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(glite_renewal_core_context ctx, 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) {
+        glite_renewal_log(ctx, LOG_ERR, "VOMS_Ordering() failed\n"); 
+        return 1;
+      }
+   }
+#endif
+
+   if (voms_cert == NULL || *voms_cert == NULL || (*voms_cert)->std == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "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(glite_renewal_core_context ctx, 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, ctx->voms_conf, NULL, &voms_error);
+
+   if (voms_contacts == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "VOMS_FindByVO() failed\n");
+      return 1;
+   }
+
+   ret = create_voms_command(ctx, vd, voms_cert, &command);
+
+   /* XXX the lifetime should be taken from the older proxy */
+   ret = VOMS_SetLifetime(60*60*12, vd, &voms_error);
+
+   /* 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) {
+      glite_renewal_log(ctx, LOG_ERR, "VOMS_Contact() failed\n");
+      return 1;
+   }
+
+   VOMS_DeleteContacts(voms_contacts);
+
+   if (command)
+      free(command);
+
+   return 0;
+}
+
+static int
+renew_voms_certs(glite_renewal_core_context ctx, const char *cur_file, const char *renewed_file, const char *new_file)
+{
+   globus_gsi_cred_handle_t cur_proxy = NULL;
+   globus_gsi_cred_handle_t new_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 = 0;
+   X509_EXTENSION *extension = NULL;
+   char *old_env_proxy = getenv("X509_USER_PROXY");
+   char *old_env_cert = getenv("X509_USER_CERT");
+   char *old_env_key = getenv("X509_USER_KEY");
+
+   setenv("X509_USER_PROXY", cur_file, 1);
+   setenv("X509_USER_CERT", renewed_file, 1);
+   setenv("X509_USER_KEY", renewed_file, 1);
+
+   ret = glite_renewal_load_proxy(ctx, cur_file, &cert, NULL, &chain, &cur_proxy);
+   if (ret)
+      goto end;
+
+   vd = VOMS_Init(NULL, NULL);
+   if (vd == NULL) {
+      glite_renewal_log(ctx, LOG_ERR, "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 */
+        /* XXX this part shouldn't be reachable, this call is only called
+         * if the proxy does contain VOMS attributes */
+        glite_renewal_log(ctx, LOG_ERR, "No VOMS attributes found in proxy %s\n", cur_file);
+        ret = 0;
+        goto end;
+      } else {
+        glite_renewal_log(ctx, LOG_ERR, "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(ctx, 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(ctx, buf, buf_len, &extension);
+   if (ret)
+      goto end;
+
+   ret = glite_renewal_load_proxy(ctx, renewed_file, NULL, NULL, NULL, &new_proxy);
+   if (ret)
+      goto end;
+
+   ret = generate_proxy(ctx, new_proxy, extension, new_file);
+
+end:
+   (old_env_proxy) ? setenv("X509_USER_PROXY", old_env_proxy, 1) :
+                    unsetenv("X509_USER_PROXY");
+   (old_env_cert) ? setenv("X509_USER_CERT", old_env_cert, 1) :
+                    unsetenv("X509_USER_CERT");
+   (old_env_key) ? setenv("X509_USER_KEY", old_env_key, 1) :
+                   unsetenv("X509_USER_KEY");
+
+   if (cert)
+      X509_free(cert);
+   if (chain)
+      sk_X509_pop_free(chain, X509_free);
+   if (vd)
+      VOMS_Destroy(vd);
+   if (cur_proxy)
+      globus_gsi_cred_handle_destroy(cur_proxy);
+   if (new_proxy)
+      globus_gsi_cred_handle_destroy(new_proxy);
+   if (buf)
+      free(buf);
+
+   return ret;
+}
+
+int
+glite_renewal_renew_voms_creds(glite_renewal_core_context ctx, const char *cur_file, const char *renewed_file, const char *new_file)
+{
+   return renew_voms_certs(ctx, cur_file, renewed_file, new_file);
+}
+
+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;
+}
+
+#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) {
+       glite_renewal_log(ctx, LOG_ERR, "[%d]: Unable to initialize Globus modules\n", getpid());
+       return 1;
+   }
+
+   ret = renew_voms_certs(current_proxy, renewed_proxy);
+
+   return 0;
+}
+#endif