--- /dev/null
+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/
+
+
--- /dev/null
+#
+# 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
--- /dev/null
+<?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
of users' proxy certificates. Its primary goal is to support long-time jobs
running on the grid. This package also contains a library and header file
that allow to develop C/C++ applications accessing the daemon." />
+
+</project>
--- /dev/null
+#!/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
--- /dev/null
+#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;
+}
--- /dev/null
+/**
+ * \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 */
--- /dev/null
+#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 */
--- /dev/null
+module.build=137
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+tar_exclude
+CVS
+build.xml
+build
+build.properties
+properties.xml
+configure.properties.xml
+.cvsignore
+.project
+.cdtproject
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project name="tasks and types definitions">
+</project>
--- /dev/null
+module.version=1.3.0
+module.age=1
--- /dev/null
+#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 */
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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);
+}
--- /dev/null
+#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);
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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 */
--- /dev/null
+#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;
+}
--- /dev/null
+#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 */
--- /dev/null
+#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