--- /dev/null
+# 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=/opt/glite
+globus_prefix=/opt/globus
+nothrflavour=gcc32
+thrflavour=gcc32pthr
+myproxy_prefix=/software/myproxy-0.4
+
+-include Makefile.inc
+
+VPATH:=${top_srcdir}/src
+
+GLOBUSINC:= -I${globus_prefix}/include/${nothrflavour} \
+ -I${globus_prefix}/include/${nothrflavour}/openssl
+
+GLOBUSTHRINC:= -I${globus_prefix}/include/${thrflavour} \
+ -I${globus_prefix}/include/${thrflavour}/openssl
+
+
+DEBUG:=-g -O0
+
+# XXX: until VOMS is ready in SCM
+CFLAGS:= -DNOVOMS \
+ ${DEBUG} \
+ -DVOMS_INSTALL_PATH=\"${voms_prefix}\"\
+ -I${myproxy_prefix}/include \
+ -I${top_srcdir}/src -I${top_srcdir}/interface \
+ -I${stagedir}/include
+
+GLOBUS_LIBS:=-L${globus_prefix}/lib \
+ -lglobus_common_${nothrflavour} \
+ -lssl_${nothrflavour}
+
+SSL_UTILS_LIB:=-L${stagedir}/lib -lglobus_ssl_utils
+MYPROXY_LIB:=-L${myproxy_prefix}/lib -lmyproxy
+
+JOBIDLIB:=-L${stagedir}/lib -lglite_wms_cjobid
+
+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
+LIBOBJ:=api.o common.o
+CLIENTOBJ:=client.o
+
+THRLIBOBJ:=${LIBOBJ:.o=.thr.o}
+LIBLOBJ:=${LIBOBJ:.o=.lo}
+THRLIBLOBJ:=${LIBOBJ:.o=.thr.lo}
+
+LIB:=libglite_security_proxyrenewal_${nothrflavour}.la
+THRLIB:=libglite_security_proxyrenewal_${thrflavour}.la
+
+DAEMON:=glite-proxy-renewd
+CLIENT:=glite-proxy-renew
+
+default: all
+compile all: ${LIB} ${THRLIB} ${DAEMON} ${CLIENT}
+
+${LIB}: ${LIBOBJ}
+ ${LINK} -o $@ ${LIBLOBJ} -rpath ${glite_location}/lib ${JOBIDLIB} ${SSL_UTILS_LIB}
+
+
+${THRLIB}: ${THRLIBOBJ}
+ ${LINK} -o $@ ${THRLIBLOBJ} -rpath ${glite_location}/lib ${SSL_UTILS_LIB}
+
+${DAEMON}: ${DAEMONOBJ}
+ ${LINK} -o $@ ${DAEMONOBJ} ${JOBIDLIB} ${SSL_UTILS_LIB} ${MYPROXY_LIB} -lglobus_gss_assist_${nothrflavour} ${GLOBUS_LIBS}
+
+${CLIENT}: ${CLIENTOBJ} ${LIB}
+ ${LINK} -o $@ ${CLIENTOBJ} ${LIB} ${GLOBUS_LIBS}
+
+${THRLIBOBJ}: %.thr.o: %.c
+ ${COMPILE} ${GLOBUSTHRINC} -o $@ -c $<
+
+%.o: %.c
+ ${COMPILE} ${GLOBUSINC} -c $<
+
+install:
+ -mkdir -p ${PREFIX}/bin ${PREFIX}/lib ${PREFIX}/include/glite/security
+ ${INSTALL} -m 644 ${LIB} ${THRLIB} ${PREFIX}/lib
+ ${INSTALL} -m 755 ${DAEMON} ${CLIENT} ${PREFIX}/bin
+ cd ${top_srcdir}/interface && ${INSTALL} -m 644 renewal.h ${PREFIX}/include/glite/security
+
+
+stage: compile
+ $(MAKE) install PREFIX=${stagedir}
+
+
+check:
+ echo No unit tests
--- /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.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="compile">
+
+ <!-- =========================================
+ 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}"/>
+
+ <!-- ==============================================
+ Local private targets
+ ============================================== -->
+
+ <target name="localinit"
+ description="Module specific initialization tasks">
+ <antcall target="lbmakefiles" />
+ </target>
+
+ <target name="localcompile"
+ description="Module specific compile tasks">
+ </target>
+
+ <target name="localclean"
+ description="Module specific cleaning tasks">
+ </target>
+
+</project>
--- /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$"
+
+#include "glite/wms/jobid/cjobid.h"
+
+#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_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.
+ */
+int
+edg_wlpr_RegisterProxyExt(
+ const char * filename,
+ const char * server,
+ unsigned int port,
+ edg_wlc_JobId 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().
+ */
+int
+edg_wlpr_UnregisterProxy(
+ edg_wlc_JobId 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().
+ */
+int
+edg_wlpr_GetProxy(edg_wlc_JobId jobid, char **repository_filename);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RENEWAL_H */
--- /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 LB Client module
+
+ Authors: Ales Krenek <ljocha@ics.muni.cz>
+-->
+
+ <!-- ======================================================
+ Define extra properties here ...
+ ====================================================== -->
+
+ <project name="LB Client configuration options">
+ <target name="lbmakefiles">
+ <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}
+ </echo>
+ </target>
+ </project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project name="Proxy renewal">
+
+ <property file="build.properties" />
+ <property name="subsystem.name" value="${security.subsystem.name}"/>
+ <property name="subsystem.prefix" value="${security.subsystem.prefix}"/>
+ <property name="component.prefix" value="proxyrenewal" />
+
+ <import file="${component.general.properties.file}" />
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project name="tasks and types definitions">
+</project>
--- /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, int *sock);
+
+static int
+send_request(int sock, 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, int *sock)
+{
+ struct sockaddr_un my_addr;
+ int s;
+ int ret;
+
+ assert(sock != NULL);
+ memset(&my_addr, 0, sizeof(my_addr));
+
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (s == -1) {
+ 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) {
+ close(s);
+ return errno;
+ }
+
+ *sock = s;
+ return 0;
+}
+
+static int
+send_request(int sock, 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, buf, strlen(buf) + 1);
+ free(buf);
+ if (ret)
+ return ret;
+
+ ret = edg_wlpr_Read(sock, &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;
+
+ snprintf(sockname, sizeof(sockname), "%s%d",
+ DGPR_REG_SOCKET_NAME_ROOT, getuid());
+ ret = do_connect(sockname, &sock);
+ if (ret)
+ return ret;
+
+ ret = send_request(sock, request, response);
+
+ close(sock);
+ return ret;
+}
+
+int
+edg_wlpr_RegisterProxyExt(const char *filename, const char * server,
+ unsigned int port,
+ edg_wlc_JobId 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));
+
+ request.command = EDG_WLPR_COMMAND_REG;
+ request.myproxy_server = server;
+ request.proxy_filename = filename;
+ request.jobid = edg_wlc_JobIdUnparse(jobid);
+ if (request.jobid == NULL)
+ return EINVAL; /* XXX */
+
+ 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;
+}
+
+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));
+}
+
+int
+edg_wlpr_UnregisterProxy(edg_wlc_JobId 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));
+
+ request.command = EDG_WLPR_COMMAND_UNREG;
+ request.proxy_filename = repository_filename;
+ request.jobid = edg_wlc_JobIdUnparse(jobid);
+ if (request.jobid == NULL)
+ return EINVAL;
+
+ ret = edg_wlpr_RequestSend(&request, &response);
+ free(request.jobid);
+
+ if (ret == 0)
+ ret = response.response_code;
+ edg_wlpr_CleanResponse(&response);
+
+ return ret;
+}
+
+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",
+};
+
+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
+edg_wlpr_GetProxy(edg_wlc_JobId jobid, char **repository_filename)
+{
+ edg_wlpr_Request request;
+ edg_wlpr_Response response;
+ int ret;
+
+ memset(&request, 0, sizeof(request));
+ memset(&response, 0, sizeof(response));
+
+ request.command = EDG_WLPR_COMMAND_GET;
+ request.jobid = edg_wlc_JobIdUnparse(jobid);
+ if (request.jobid == NULL)
+ return EINVAL;
+
+ 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;
+}
--- /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;
+ edg_wlc_JobId jobid = 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 (jobid_str && edg_wlc_JobIdParse(jobid_str, &jobid)) {
+ fprintf(stderr, "Cannot parse jobid\n");
+ exit(1);
+ }
+
+ if (strcmp(argv[optind], "start") == 0) {
+ if (proxyfile == NULL || server == NULL || jobid == NULL)
+ usage(1);
+ ret = edg_wlpr_RegisterProxyExt(proxyfile, server, port, jobid, 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 == NULL)
+ usage(1);
+ ret = edg_wlpr_UnregisterProxy(jobid, 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 == NULL)
+ usage(1);
+ ret = edg_wlpr_GetProxy(jobid, &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"
+
+#ifndef NOVOMS
+#include <voms_apic.h>
+#endif
+
+#ident "$Header$"
+
+#define SEPARATORS ",\n"
+#define RENEWAL_START_FRACTION 0.75 /* XXX */
+#define RENEWAL_CLOCK_SKEW (5 * 60)
+#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(const char *s, unsigned char *digest);
+
+static int
+get_record_ext(FILE *fd, proxy_record *record, int *last_used_suffix);
+
+static int
+get_record(FILE *fd, proxy_record *record);
+
+static int
+store_record(char *basename, proxy_record *record);
+
+static int
+copy_file_content(FILE *in, FILE *out);
+
+static int
+copy_file(char *src, char *dst);
+
+static int
+get_base_filename(char *proxy_file, char **basefilename);
+
+int
+decode_record(char *line, proxy_record *record);
+
+int
+encode_record(proxy_record *record, char **line);
+
+static int
+open_metafile(char *proxy_file, FILE **fd);
+
+void
+free_record(proxy_record *record);
+
+static int
+realloc_prd_list(prd_list *list);
+
+/* make public: */
+static int
+edg_wlpr_GetTokenInt(const char *msg, const size_t msg_len,
+ const char *key, const char *separators,
+ int req_index, int *value);
+
+static void
+record_to_response(int status_code, proxy_record *record,
+ edg_wlpr_Response *response);
+
+static int
+filename_to_response(char *filename, edg_wlpr_Response *response);
+
+
+
+
+static char *
+strmd5(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(char *proxy_file, char **basefilename)
+{
+ FILE *cert_file = NULL;
+ X509 *cert = NULL;
+ X509_NAME *s = NULL;
+ char *subject = NULL;
+ char file[FILENAME_MAX];
+ int ret;
+
+ assert(basefilename != NULL);
+
+ cert_file = fopen(proxy_file, "r");
+ if (cert_file == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot open file %s (%s)",
+ proxy_file, strerror(errno));
+ return errno;
+ }
+
+ cert = PEM_read_X509(cert_file, NULL, NULL, NULL);
+ if (cert == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot read certificate from %s", proxy_file);
+ ret = EDG_WLPR_ERROR_SSL; /* XXX */
+ goto end;
+ }
+
+ s = X509_NAME_dup(X509_get_subject_name(cert));
+ proxy_get_base_name(s);
+ subject = X509_NAME_oneline(s, NULL, 0);
+ X509_NAME_free(s);
+ X509_free(cert);
+ if (subject == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot read subject name from %s", proxy_file);
+ ret = EDG_WLPR_ERROR_SSL; /* XXX */
+ goto end;
+ }
+
+ snprintf(file, sizeof(file), "%s/%s", repository, strmd5(subject, NULL));
+ *basefilename = strdup(file); /* XXX test ENOMEM */
+ ret = 0;
+
+end:
+ if (subject)
+ free(subject);
+ fclose(cert_file);
+ return ret;
+}
+
+static int
+copy_file_content(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))) {
+ edg_wlpr_Log(LOG_ERR, "Reading failed: %s", strerror(errno));
+ return ret;
+ }
+ num = fwrite(buf, sizeof(*buf), num, out);
+ if ((ret = ferror(in))) {
+ edg_wlpr_Log(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(time_t current_time, time_t start_time, time_t end_time)
+{
+ time_t length, lifetime;
+ time_t delta;
+ int condor_tested = 0;
+
+ lifetime = end_time - start_time;
+ delta = 0;
+ while (1) {
+ if (end_time - current_time <= RENEWAL_MIN_LIFETIME)
+ /* if the proxy is too short, renew it as soon as possible */
+ return RENEWAL_CLOCK_SKEW;
+
+ /* renewal starts at 3/4 of lifetime */
+ length = end_time - (start_time + delta);
+ delta += length * RENEWAL_START_FRACTION;
+
+ if (!condor_tested && delta > lifetime - condor_limit) {
+ /* Condor requires the proxies to be renewed a specified time interval
+ before the proxies have expired (see the
+ GRIDMANAGER_MINIMUM_PROXY_TIME variable). We must ensure that
+ renewal takes place before Condor does this check */
+ if (current_time > end_time - condor_limit) {
+ edg_wlpr_Log(LOG_ERR, "Proxy lifetime exceeded value of the Condor limit!");
+ }
+ else
+ delta = lifetime - condor_limit - RENEWAL_CLOCK_SKEW;
+ condor_tested = 1;
+ }
+
+ if (abs(current_time - (start_time + delta)) < RENEWAL_CLOCK_SKEW)
+ continue;
+
+ return (start_time + delta) - current_time;
+ };
+
+ /* not reachable */
+ return 0;
+}
+
+int
+get_times(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) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(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);
+ end_time = ASN1_UTCTIME_mktime(X509_get_notAfter(cert));
+ start_time = ASN1_UTCTIME_mktime(X509_get_notBefore(cert));
+ 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) {
+ edg_wlpr_Log(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;
+ }
+ edg_wlpr_Log(LOG_ERR, "Cannot read additional certificates from %s",
+ proxy_file);
+ ret = -1; /* XXX SSL_ERROR */
+ goto end;
+ }
+ tmp_end = ASN1_UTCTIME_mktime(X509_get_notAfter(cert));
+ if (tmp_end + RENEWAL_CLOCK_SKEW < current_time) {
+ edg_wlpr_Log(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(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(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) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(LOG_ERR, "Cannot create temporary file (%s)",
+ strerror(errno));
+ ret = errno;
+ goto end;
+ }
+
+
+ tmp_to = fdopen(tmp_fd, "w");
+ if (tmp_to == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot associate stream with temporary file (%s)",
+ strerror(errno));
+ unlink(tmpfile);
+ ret = errno;
+ goto end;
+ }
+
+ ret = copy_file_content(from, tmp_to);
+ fclose(tmp_to);
+ if (ret) {
+ goto end;
+ }
+
+ ret = rename(tmpfile, dst);
+ if (ret) {
+ edg_wlpr_Log(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(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(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(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(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(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(line, len, "suffix=", SEPARATORS, 0,
+ &record->suffix);
+ if (ret)
+ return ret;
+
+#if 0
+ ret = edg_wlpr_GetTokenInt(line, len, "counter=", SEPARATORS, 0,
+ &record->counter);
+ if (ret)
+ goto end;
+#endif
+
+ ret = edg_wlpr_GetTokenInt(line, len, "unique=", SEPARATORS, 0,
+ &record->unique);
+ if (ret)
+ goto end;
+
+ ret = edg_wlpr_GetTokenInt(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(line, len, "next_renewal=", SEPARATORS, 0,
+ (int *)&record->next_renewal);
+ if (ret)
+ goto end;
+
+ ret = edg_wlpr_GetTokenInt(line, len, "end_time=", SEPARATORS, 0,
+ (int *)&record->end_time);
+ if (ret)
+ goto end;
+
+ ret = get_jobids(line, len, record);
+ if (ret)
+ goto end;
+
+end:
+ if (ret)
+ free_record(record);
+
+ return ret;
+}
+
+int
+encode_record(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(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;
+
+ assert(record != NULL);
+ memset(&tmp_record, 0, sizeof(tmp_record));
+
+ current_time = time(NULL);
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ free_record(&tmp_record);
+ p = strchr(line, '\n');
+ if (p)
+ *p = '\0';
+ ret = decode_record(line, &tmp_record);
+ if (ret)
+ return ret; /* XXX 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 */
+ char *server = record->myproxy_server;
+
+ memset(record, sizeof(*record), 0);
+ record->suffix = tmp_record.suffix;
+ if (record->myproxy_server)
+ free(record->myproxy_server);
+ record->myproxy_server = server;
+ free_record(&tmp_record);
+ return 0;
+ }
+
+ 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 &&
+ tmp_record.end_time - current_time < condor_limit) {
+ /* skip expired proxy (and that 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) {
+ edg_wlpr_Log(LOG_DEBUG, "Requested suffix %d not found in meta file",
+ record->suffix);
+ }
+
+ free_record(&tmp_record);
+
+ return EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND;
+}
+
+static int
+get_record(FILE *fd, proxy_record *record)
+{
+ return get_record_ext(fd, record, NULL);
+}
+
+static int
+store_record(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];
+
+ 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) {
+ free_record(&tmp_record);
+ p = strchr(line, '\n');
+ if (p)
+ *p = '\0';
+ ret = decode_record(line, &tmp_record);
+ if (ret)
+ goto end;
+ 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(&tmp_record.jobids);
+ tmp_record.jobids.val[tmp_record.jobids.len - 1] =
+ strdup(record->jobids.val[i]);
+ }
+ stored = 1;
+ }
+ ret = encode_record(&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(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(&tmp_record);
+ if (fd)
+ fclose(fd);
+ close(temp);
+ return ret;
+}
+
+static int
+open_metafile(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) {
+ edg_wlpr_Log(LOG_ERR, "Opening meta file %s failed (%s)",
+ meta_filename, strerror(errno));
+ return errno;
+ }
+ rewind(meta_fd);
+ *fd = meta_fd;
+ edg_wlpr_Log(LOG_DEBUG, "Using meta file %s", meta_filename);
+ return 0;
+}
+
+static int
+filename_to_response(char *filename, edg_wlpr_Response *response)
+{
+ response->filenames = malloc(2 * sizeof(*response->filenames));
+ if (response->filenames == NULL) {
+ edg_wlpr_Log(LOG_DEBUG, "Not enough memory");
+ return errno;
+ }
+ response->filenames[0] = strdup(filename);
+ if (response->filenames[0] == NULL) {
+ edg_wlpr_Log(LOG_DEBUG, "Not enough memory");
+ free(response->filenames);
+ return errno;
+ }
+ response->filenames[1] = NULL;
+ return 0;
+}
+
+static void
+record_to_response(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(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) {
+ edg_wlpr_Log(LOG_ERR, "Cannot open meta file %s (%s)",
+ datafile, strerror(errno));
+ return errno;
+ }
+
+ while (fgets(line, sizeof(line), meta_fd) != NULL) {
+ free_record(&record);
+ p = strchr(line, '\n');
+ if (p)
+ *p = '\0';
+ ret = decode_record(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(&record);
+ fclose(meta_fd);
+ return 0;
+ }
+ }
+ }
+ free_record(&record);
+ fclose(meta_fd);
+ return EDG_WLPR_ERROR_PROTO_PARSE_NOT_FOUND;
+}
+
+int
+find_proxyname(char *jobid, char **filename)
+{
+ DIR *dir = NULL;
+ struct dirent *file;
+ int ret;
+
+ chdir(repository);
+
+ dir = opendir(repository);
+ if (dir == NULL) {
+ edg_wlpr_Log(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(file->d_name, jobid, filename);
+ if (ret == 0) {
+ closedir(dir);
+ return 0;
+ }
+ }
+ closedir(dir);
+ edg_wlpr_Log(LOG_ERR, "Requested proxy is not registered");
+ return EDG_WLPR_PROXY_NOT_REGISTERED;
+}
+
+#ifdef NOVOMS
+int
+find_voms_cert(char *file, int *present)
+{
+ *present = 0;
+ return 0;
+}
+
+#else
+int
+find_voms_cert(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) {
+ edg_wlpr_Log(LOG_ERR, "check_voms_cert(): Cannot initialize VOMS context (VOMS_Init() failed, probably voms dir was not specified)");
+ return EDG_WLPR_ERROR_VOMS;
+ }
+
+ ret = load_proxy(file, &cert, &privkey, &chain);
+ 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(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));
+ edg_wlpr_Log(LOG_DEBUG, "Registration request for %s", request->proxy_filename);
+
+ if (request->proxy_filename == NULL || request->jobid == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Registration request doesn't contain registration information");
+ return; /* EINVAL; */
+ }
+ umask(0177);
+
+ ret = get_base_filename(request->proxy_filename, &basename);
+ if (ret)
+ goto end;
+
+ ret = open_metafile(basename, &meta_fd);
+ if (ret)
+ goto end;
+
+ if (voms_enabled)
+ ret = find_voms_cert(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(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(request->proxy_filename, filename);
+ if (ret)
+ goto end;
+ ret = get_times(filename, &record);
+ if (ret)
+ goto end;
+ record.suffix = suffix;
+ ret = realloc_prd_list(&record.jobids);
+ if (ret)
+ goto end;
+ record.jobids.val[record.jobids.len - 1] = strdup(request->jobid);
+ record.unique = request->unique;
+ edg_wlpr_Log(LOG_DEBUG, "Created a new proxy file in repository (%s)",
+ filename);
+ } else {
+ ret = realloc_prd_list(&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);
+ edg_wlpr_Log(LOG_DEBUG, "Inremented counter on %s", filename);
+ }
+
+ ret = store_record(basename, &record);
+
+end:
+ if (meta_fd) {
+ fclose(meta_fd);
+ }
+
+ if (basename)
+ free(basename);
+
+ if (ret == 0)
+ ret = filename_to_response(filename, response);
+ record_to_response(ret, &record, response);
+ free_record(&record);
+}
+
+void
+unregister_proxy(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));
+ edg_wlpr_Log(LOG_DEBUG, "Unregistration request for %s", request->jobid);
+
+ if (request->jobid == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Unregistration request doesn't contain needed information");
+ ret = EINVAL;
+ goto end;
+ }
+
+ if (request->proxy_filename == NULL) {
+ ret = find_proxyname(request->jobid, &request->proxy_filename);
+ if (ret)
+ goto end;
+ }
+
+ ret = get_base_filename(request->proxy_filename, &basename);
+ if (ret) {
+ goto end;
+ }
+
+ if (strncmp(request->proxy_filename, basename, strlen(basename) != 0)) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(LOG_DEBUG, "Requested proxy %s is not from repository",
+ request->proxy_filename);
+ ret = EDG_WLPR_PROXY_NOT_REGISTERED;
+ goto end;
+ }
+
+ ret = open_metafile(basename, &meta_fd);
+ if (ret) {
+ /* fill in error response */
+ return;
+ }
+
+ ret = get_record(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) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(LOG_DEBUG, "Cannot stat file %s: (%s)",
+ request->proxy_filename, strerror(errno));
+ ret = errno;
+ goto end;
+ }
+
+ ret = store_record(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(request->proxy_filename, response);
+ record_to_response(ret, &record, response);
+ free_record(&record);
+}
+
+void
+get_proxy(edg_wlpr_Request *request, edg_wlpr_Response *response)
+{
+ char *filename = NULL;
+ int ret;
+
+ memset(response, 0, sizeof(*response));
+
+ edg_wlpr_Log(LOG_DEBUG, "GET request for %s", request->jobid);
+
+ if (request->jobid == NULL) {
+ edg_wlpr_Log(LOG_ERR, "GET request doesn't contain jobid specification");
+ ret = EINVAL;
+ goto end;
+ }
+
+ ret = find_proxyname(request->jobid, &filename);
+
+end:
+ if (ret == 0)
+ ret = filename_to_response(filename, response);
+ if (filename)
+ free(filename);
+ response->response_code = ret;
+}
+
+void
+update_db(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));
+
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(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(&record);
+ p = strchr(line, '\n');
+ if (p)
+ *p = '\0';
+ ret = decode_record(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(&record);
+ record.suffix = suffix;
+ record.myproxy_server = server;
+ edg_wlpr_Log(LOG_WARNING, "Removed expired proxy (suffix %d)",
+ suffix);
+ } else
+ get_times(cur_proxy, &record);
+ } else {
+ ret = get_times(proxy, &record);
+ (ret == 0) ? rename(proxy, cur_proxy) : unlink(proxy);
+ }
+ }
+
+ ret = encode_record(&record, &new_line);
+ if (ret)
+ goto end;
+
+ dprintf(tmp_fd, "%s\n", new_line);
+ free(new_line);
+ new_line = NULL;
+ }
+ free_record(&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(&record);
+
+ return;
+}
--- /dev/null
+#include "renewal_locl.h"
+
+#ident "$Header$"
+
+/* nread() and nwrite() never return partial data */
+static size_t
+nread(int sock, char *buf, size_t buf_len)
+{
+ size_t count;
+ size_t remain = buf_len;
+ char *cbuf = buf;
+
+ while (remain > 0) {
+ count = read(sock, cbuf, remain);
+ if (count < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ return count;
+ } else
+ if (count == 0) {
+ return count;
+ }
+ cbuf += count;
+ remain -= count;
+ }
+ return buf_len;
+}
+
+static size_t
+nwrite(int sock, const char *buf, size_t buf_len)
+{
+ const char *cbuf = buf;
+ size_t count;
+ size_t remain = buf_len;
+
+ while (remain > 0) {
+ count = write(sock, cbuf, remain);
+ if (count < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ return count;
+ }
+ cbuf += count;
+ remain -= count;
+ }
+ return buf_len;
+}
+
+int
+edg_wlpr_Read(int sock, char **buf, size_t *buf_len)
+{
+ int ret;
+ unsigned char length[4];
+
+ ret = nread(sock, length, 4);
+ if (ret == -1) {
+ *buf_len = 0;
+ return errno;
+ }
+ if (ret < 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, *buf, *buf_len);
+ if (ret != *buf_len) {
+ free(*buf);
+ *buf_len = 0;
+ return errno;
+ }
+
+ return 0;
+}
+
+int
+edg_wlpr_Write(int sock, char *buf, size_t buf_len)
+{
+ unsigned char length[4];
+
+ 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 (nwrite(sock, length, 4) != 4 ||
+ nwrite(sock, buf, buf_len) != buf_len)
+ return errno;
+
+ 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;
+}
--- /dev/null
+#include "renewal_locl.h"
+#include "renewd_locl.h"
+
+#ifndef NOVOMS
+#include <voms_apic.h>
+#endif
+
+#ident "$Header$"
+
+extern char *repository;
+extern char *cadir;
+extern char *vomsdir;
+extern int voms_enabled;
+extern char *vomsconf;
+extern struct vomses_records vomses;
+
+static int received_signal = -1;
+
+static void
+check_renewal(char *datafile, int force_renew);
+
+static int
+renew_proxy(proxy_record *record, char *basename, char **new_proxy);
+
+static void
+register_signal(int signal);
+
+
+#define DGPR_RETRIEVE_DEFAULT_HOURS 10
+#define RENEWAL_CLOCK_SKEW 5 * 60
+
+static const char *
+get_ssl_err()
+{
+ return "SSL failed";
+}
+
+int
+load_proxy(const char *filename, X509 **cert, EVP_PKEY **privkey,
+ STACK_OF(X509) **chain)
+{
+ X509 *my_cert = NULL;
+ EVP_PKEY *my_key = NULL;
+ STACK_OF(X509) *my_chain = NULL;
+ FILE *fd = NULL;
+ int ret;
+
+ fd = fopen(filename, "r");
+ if (fd == NULL) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot read VOMS certificate (fopen() failed on %s: %s)",
+ filename, strerror(errno));
+ return errno;
+ }
+
+ my_cert = PEM_read_X509(fd, NULL, NULL, NULL);
+ if (my_cert == NULL) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot read VOMS certificate (PEM_read_X509() failed: %s)",
+ get_ssl_err());
+ ret = EDG_WLPR_ERROR_SSL;
+ goto end;
+ }
+
+ my_key = PEM_read_PrivateKey(fd, NULL, NULL, NULL);
+ if (my_key == NULL) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot read VOMS certificate (PEM_read_PrivateKey() failed: %s)",
+ get_ssl_err());
+ ret = EDG_WLPR_ERROR_SSL;
+ goto end;
+ }
+
+ my_chain = sk_X509_new_null();
+ if (my_chain == NULL) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot read VOMS certificate (sk_X509_new_null() failed: %s)",
+ get_ssl_err());
+ ret = EDG_WLPR_ERROR_SSL;
+ goto end;
+ }
+
+ while (1) {
+ X509 *c;
+
+ c = PEM_read_X509(fd, NULL, NULL, NULL);
+ if (c == NULL) {
+ if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) {
+ /* End of file reached. no error */
+ ERR_clear_error();
+ break;
+ }
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot read VOMS certificate (PEM_read_X509() failed: %s)",
+ get_ssl_err());
+ ret = EDG_WLPR_ERROR_SSL;
+ goto end;
+ }
+ sk_X509_push(my_chain, c);
+ }
+
+ *cert = my_cert;
+ *privkey = my_key;
+ *chain = my_chain;
+ my_cert = NULL; my_key = NULL; my_chain = NULL;
+ ret = 0;
+
+end:
+ fclose(fd);
+
+ if (my_cert)
+ X509_free(my_cert);
+ if (my_key)
+ EVP_PKEY_free(my_key);
+ if (my_chain)
+ sk_X509_pop_free(my_chain, X509_free);
+
+ return ret;
+}
+
+static int
+save_proxy(const char *filename, X509 *new_cert, EVP_PKEY *new_privkey,
+ STACK_OF(X509) *chain)
+{
+ FILE *fd = NULL;
+ int ret, i;
+ int retval = EDG_WLPR_ERROR_SSL;
+
+ fd = fopen(filename, "w");
+ if (fd == NULL) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot store proxy (fopen() failed on %s: %s)",
+ filename, strerror(errno));
+ return errno;
+ }
+
+ ret = PEM_write_X509(fd, new_cert);
+ if (ret == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot store proxy (PEM_write_X509() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+
+ ret = PEM_write_PrivateKey(fd, new_privkey, NULL, NULL, 0, NULL, NULL);
+ if (ret == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot store proxy (PEM_write_PrivateKey() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+
+ for (i = 0; i < sk_X509_num(chain); i++) {
+ X509 *cert = sk_X509_value(chain, i);
+ ret = PEM_write_X509(fd, cert);
+ if (ret == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot store proxy (PEM_write_X509() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+ }
+
+ retval = 0;
+
+end:
+ fclose(fd);
+
+ return retval;
+}
+
+static int
+gen_keypair(EVP_PKEY **keypair, int requested_bits)
+{
+ RSA *rsa = NULL;
+ EVP_PKEY *key;
+
+ *keypair = NULL;
+ rsa = RSA_generate_key(requested_bits,
+ RSA_F4 /* public exponent */,
+ NULL, NULL);
+ if (rsa == NULL) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (RSA_generate_key() failed: %s)",
+ get_ssl_err());
+ return EDG_WLPR_ERROR_SSL;
+ }
+
+ key = EVP_PKEY_new();
+ if (key == NULL) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (EVP_PKEY_new() failed: %s)",
+ get_ssl_err());
+ RSA_free(rsa);
+ return EDG_WLPR_ERROR_SSL;
+ }
+
+ if (EVP_PKEY_assign_RSA(key, rsa) == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (EVP_PKEY_assign_RSA() failed: %s)",
+ get_ssl_err());
+ RSA_free(rsa);
+ EVP_PKEY_free(key);
+ return EDG_WLPR_ERROR_SSL;
+ }
+
+ *keypair = key;
+
+ return 0;
+}
+
+static int
+gen_subject_name(X509 *old_cert, X509 *new_cert)
+{
+ X509_NAME *name = NULL;
+ X509_NAME_ENTRY *name_entry = NULL;
+ int ret = EDG_WLPR_ERROR_SSL;
+
+ name = X509_NAME_dup(X509_get_subject_name(old_cert));
+ if (name == NULL) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (X509_NAME_dup() failed: %s",
+ get_ssl_err());
+ goto end;
+ }
+
+ name_entry = X509_NAME_ENTRY_create_by_NID(NULL /* make new entry */,
+ NID_commonName,
+ V_ASN1_APP_CHOOSE,
+ "proxy", -1);
+ if (name_entry == NULL) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (X509_NAME_ENTRY_create_by_NID() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+
+ if (X509_NAME_add_entry(name, name_entry, X509_NAME_entry_count(name), 0) == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (X509_NAME_add_entry() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+
+
+ if (X509_set_subject_name(new_cert, name) == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (X509_set_subject_name() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+ if (name)
+ X509_NAME_free(name);
+ if (name_entry != NULL)
+ X509_NAME_ENTRY_free(name_entry);
+
+ return ret;
+}
+
+static int
+create_proxy(X509 *old_cert, EVP_PKEY *old_privkey, X509_EXTENSION *extension,
+ X509 **new_cert, EVP_PKEY **new_privkey)
+{
+ /* Inspired by code from Myproxy */
+ EVP_PKEY *key_pair = NULL;
+ X509 *cert = NULL;
+ int ret;
+ int retval = EDG_WLPR_ERROR_SSL;
+
+ ret = gen_keypair(&key_pair, 512);
+ if (ret)
+ return ret;
+
+ cert = X509_new();
+ if (cert == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot generate new proxy (X509_new() failed: Not enough memory)");
+ goto end;
+ }
+
+ ret = gen_subject_name(old_cert, cert);
+ if (ret) {
+ retval = ret;
+ goto end;
+ }
+
+ if (X509_set_issuer_name(cert, X509_get_subject_name(old_cert)) == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (X509_set_issuer_name() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+
+ if (X509_set_serialNumber(cert, X509_get_serialNumber(old_cert)) == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (X509_set_serialNumber() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+
+ X509_gmtime_adj(X509_get_notBefore(cert), -(60 * 5));
+ X509_set_notAfter(cert, X509_get_notAfter(old_cert));
+
+ if (X509_set_pubkey(cert, key_pair) == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (X509_set_pubkey() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+
+ /* set v3 */
+ if (X509_set_version(cert, 2L) == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (X509_set_version() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+
+ if (cert->cert_info->extensions != NULL)
+ sk_X509_EXTENSION_pop_free(cert->cert_info->extensions,
+ X509_EXTENSION_free);
+ cert->cert_info->extensions = sk_X509_EXTENSION_new_null();
+ sk_X509_EXTENSION_push(cert->cert_info->extensions, extension);
+
+ if (X509_sign(cert, old_privkey, EVP_md5()) == 0) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (X509_sign() failed: %s)",
+ get_ssl_err());
+ goto end;
+ }
+
+ *new_privkey = key_pair;
+ *new_cert = cert;
+ key_pair = NULL;
+ cert = NULL;
+
+ retval = 0;
+
+end:
+ if (key_pair)
+ EVP_PKEY_free(key_pair);
+ if (cert)
+ X509_free(cert);
+
+ return retval;
+}
+
+static int
+create_voms_extension(char *buf, size_t buf_len, X509_EXTENSION **extensions)
+{
+ ASN1_OBJECT *voms_obj = NULL;
+ ASN1_OCTET_STRING *voms_oct = NULL;
+
+ *extensions = NULL;
+
+ voms_oct = ASN1_OCTET_STRING_new();
+ if (voms_oct == NULL) {
+ edg_wlpr_Log(LOG_ERR,
+ "Cannot generate new proxy (ASN1_OCTET_STRING_new() failed: %s)",
+ get_ssl_err());
+ return EDG_WLPR_ERROR_SSL;
+ }
+
+ voms_oct->data = buf;
+ voms_oct->length = buf_len;
+
+ voms_obj = OBJ_nid2obj(OBJ_txt2nid("VOMS"));
+ if (voms_obj == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot generate new proxy (OBJ_nid2obj() failed");
+ goto end;
+ }
+
+ *extensions = X509_EXTENSION_create_by_OBJ(NULL, voms_obj, 0, voms_oct);
+ if (*extensions == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot generate new proxy (X509_EXTENSION_create_by_OBJ() failed");
+ goto end;
+ }
+
+ return 0;
+
+end:
+ if (voms_oct)
+ ASN1_OCTET_STRING_free(voms_oct);
+ if (voms_obj)
+ ASN1_OBJECT_free(voms_obj);
+ return EDG_WLPR_ERROR_SSL;
+}
+
+#ifndef NOVOMS
+static int
+export_std_data(struct data *voms_data, char **buf)
+{
+ asprintf(buf, "GROUP: %s\n"
+ "ROLE:%s\n" /* the space is missing intentionaly */
+ "CAP: %s\n",
+ (voms_data->group) ? voms_data->group : "NULL",
+ (voms_data->role) ? voms_data->role : "NULL",
+ (voms_data->cap) ? voms_data->cap : "NULL");
+ return 0;
+}
+
+static int
+export_user_data(struct voms *voms_cert, char **buf, size_t *len)
+{
+ struct data **voms_data;
+ char *str = NULL;
+ char *ptr;
+
+ *buf = NULL;
+
+ switch (voms_cert->type) {
+ case TYPE_NODATA:
+ *buf = strdup("NO DATA");
+ break;
+ case TYPE_CUSTOM:
+ *buf = strdup(voms_cert->custom);
+ break;
+ case TYPE_STD:
+ for (voms_data = voms_cert->std; voms_data && *voms_data; voms_data++) {
+ export_std_data(*voms_data, &str);
+ if (*buf == NULL)
+ ptr = calloc(strlen(str) + 1, 1);
+ else
+ ptr = realloc(*buf, strlen(*buf) + strlen(str) + 1);
+ if (ptr == NULL) {
+ return ENOMEM;
+ }
+ *buf = ptr;
+ strcat(*buf, str);
+ free(str);
+ }
+
+ break;
+ default:
+ return -1;
+ }
+
+ *len = strlen(*buf);
+ return 0;
+}
+
+#endif
+
+static int
+encode_voms_buf(const char *label, char *data, size_t data_len,
+ char **buf, size_t *buf_len)
+{
+ char *tmp;
+
+ tmp = realloc(*buf, *buf_len + strlen(label) + data_len + 1);
+ if (tmp == NULL)
+ return ENOMEM;
+
+ memcpy(tmp + *buf_len, label, strlen(label));
+
+ memcpy(tmp + *buf_len + strlen(label), data, data_len);
+ tmp[*buf_len + strlen(label) + data_len] = '\n';
+ *buf = tmp;
+ *buf_len = *buf_len + strlen(label) + data_len + 1;
+
+ return 0;
+}
+
+static int
+encode_voms_int(const char *label, int value, char **buf, size_t *buf_len)
+{
+ char tmp[16];
+
+ snprintf(tmp, sizeof(tmp), "%d", value);
+ return encode_voms_buf(label, tmp, strlen(tmp), buf, buf_len);
+}
+
+static int
+encode_voms_str(const char *label, char *value, char **buf, size_t *buf_len)
+{
+ return encode_voms_buf(label, value, strlen(value), buf, buf_len);
+}
+
+#if 0
+static int
+VOMS_Export(struct vomsdata *voms_info, char **buf, size_t *len)
+{
+ struct voms *vc;
+ char *enc_voms = NULL;
+ size_t enc_voms_len = 0;
+ char *data_buf;
+ size_t data_len;
+ int ret;
+
+ if (voms_info == NULL || voms_info->data == NULL || *voms_info->data == NULL)
+ return EINVAL;
+ vc = *voms_info->data;
+
+ ret = export_user_data(vc, &data_buf, &data_len);
+ if (ret)
+ return ret;
+
+ encode_voms_int("SIGLEN:", vc->siglen, &enc_voms, &enc_voms_len);
+ encode_voms_buf("SIGNATURE:",vc->signature, vc->siglen,
+ &enc_voms, &enc_voms_len);
+ enc_voms_len--; /* Signature is not followed by '\n' */
+ encode_voms_str("USER:", vc->user, &enc_voms, &enc_voms_len);
+ encode_voms_str("UCA:", vc->userca, &enc_voms, &enc_voms_len);
+ encode_voms_str("SERVER:", vc->server, &enc_voms, &enc_voms_len);
+ encode_voms_str("SCA:", vc->serverca, &enc_voms, &enc_voms_len);
+ encode_voms_str("VO:", vc->voname, &enc_voms, &enc_voms_len);
+ encode_voms_str("URI:", vc->uri, &enc_voms, &enc_voms_len);
+ encode_voms_str("TIME1:", vc->date1, &enc_voms, &enc_voms_len);
+ encode_voms_str("TIME2:", vc->date2, &enc_voms, &enc_voms_len);
+ encode_voms_int("DATALEN:", data_len, &enc_voms, &enc_voms_len);
+ encode_voms_buf("", data_buf, data_len, &enc_voms, &enc_voms_len);
+ enc_voms_len--; /* the data already contains endind '\n' */
+
+ free(data_buf);
+ if (enc_voms == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot renew VOMS certificate (Not enough memory)");
+ return ENOMEM;
+ }
+ *buf = enc_voms;
+ *len = enc_voms_len;
+ return 0;
+}
+
+static int
+voms_cert_renew(char *hostname, int port, char *voms_subject,
+ char *proxy,
+ struct voms **cur_voms_cert, struct vomsdata *voms_info)
+{
+ int ret = 0;
+ char *command = "A";
+ int err = 0;
+ char *old_env_proxy = getenv("X509_USER_PROXY");
+
+ setenv("X509_USER_PROXY", proxy, 1);
+
+ /* hack (suggested by Vincenzo Ciaschini) to work around problem with
+ * unitialized VOMS struct */
+ ret = VOMS_Ordering("zzz:zzz", voms_info, &err);
+ if (ret == 0) {
+ edg_wlpr_Log(LOG_ERR, "Cannot renew VOMS certificate (VOMS_Ordering() failed");
+ ret = EDG_WLPR_ERROR_VOMS;
+ goto end;
+ }
+
+ /* XXX only attributes which are in current certificate should be requested*/
+ ret = VOMS_Contact(hostname, port, (*cur_voms_cert)->server, command,
+ voms_info, &err);
+ if (ret == 0) {
+#if 0
+ if (err == 1) { /* XXX cannot connect voms server */
+ ret = 0;
+ goto end;
+ }
+#endif
+ edg_wlpr_Log(LOG_ERR, "Cannot renew VOMS certificate (VOMS_Contact() failed: %d)", err);
+ ret = EDG_WLPR_ERROR_VOMS;
+ } else
+ ret = 0;
+
+end:
+ (old_env_proxy) ? setenv("X509_USER_PROXY", old_env_proxy, 1) :
+ unsetenv("X509_USER_PROXY");
+
+ return ret;
+}
+
+static int
+renew_voms_cert(struct voms **cur_voms_cert, char *proxy, char **buf, size_t *buf_len)
+{
+ struct vomsdata *voms_info = NULL;
+ char *hostname = NULL;
+ char *p;
+ int port, ret;
+
+ hostname = strdup((*cur_voms_cert)->uri);
+ p = strchr(hostname, ':');
+ if (p)
+ *p = '\0';
+ port = (p) ? atoi(p+1) : 15000;
+
+ voms_info = VOMS_Init(vomsdir, cadir);
+ if (voms_info == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot renew VOMS certificate (VOMS_Init() failed)");
+ ret = EDG_WLPR_ERROR_VOMS;
+ goto end;
+ }
+
+ ret = voms_cert_renew(hostname, port, (*cur_voms_cert)->server, proxy, cur_voms_cert,
+ voms_info);
+ if (ret)
+ goto end;
+
+ ret = VOMS_Export(voms_info, buf, buf_len);
+ if (ret) {
+ edg_wlpr_Log(LOG_ERR, "Cannot renew VOMS certificate (VOMS_Export() failed)");
+ ret = EDG_WLPR_ERROR_VOMS;
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+ if (hostname)
+ free(hostname);
+#if 0
+ if (voms_info)
+ VOMS_Destroy(voms_info);
+#endif
+
+ return ret;
+}
+#endif
+
+#ifndef NOVOMS
+static vomses_record *
+find_vomses_record(char *hostname, int port)
+{
+ int i;
+
+ for (i = 0; i < vomses.len; i++) {
+ if (strcmp(vomses.val[i]->hostname, hostname) == 0 &&
+ vomses.val[i]->port == port)
+ return vomses.val[i];
+ }
+
+ return NULL;
+}
+
+static int
+set_vo_params(struct voms **voms_cert, char **arg)
+{
+ vomses_record *r;
+ char *tmp;
+ int port;
+ char *hostname;
+ char *p;
+
+ hostname = strdup((*voms_cert)->uri);
+ p = strchr(hostname, ':');
+ if (p)
+ *p = '\0';
+ port = (p) ? atoi(p+1) : 15000;
+
+ r = find_vomses_record(hostname, port);
+ if (r == NULL)
+ return EINVAL;
+
+ if (*arg == NULL) {
+ asprintf(arg, " -voms %s", r->nick);
+ } else {
+ tmp = realloc(*arg,
+ strlen(*arg) + strlen(" -voms ") + strlen(r->nick) + 1);
+ if (tmp == NULL)
+ return ENOMEM;
+ *arg = tmp;
+ *arg = strcat(*arg, " -voms ");
+ *arg = strcat(*arg, r->nick);
+ }
+ return 0;
+}
+#endif
+
+static int
+exec_voms_proxy_init(char *arg, char *old_proxy, char *new_proxy)
+{
+ char command[256];
+ int ret;
+ char *old_env_proxy = getenv("X509_USER_PROXY");
+
+ setenv("X509_USER_PROXY", old_proxy, 1);
+
+ snprintf(command, sizeof(command),
+ "edg-voms-proxy-init -out %s -key %s -cert %s -confile %s -q %s",
+ new_proxy, old_proxy, old_proxy, vomsconf, arg);
+ ret = system(command);
+
+ (old_env_proxy) ? setenv("X509_USER_PROXY", old_env_proxy, 1) :
+ unsetenv("X509_USER_PROXY");
+
+ return ret;
+}
+
+#if 0
+static int
+renew_voms_certs(const char *old_proxy, const char *new_proxy)
+{
+ struct vomsdata *voms_info = NULL;
+ struct voms **voms_cert = NULL;
+ STACK_OF(X509) *chain = NULL;
+ EVP_PKEY *privkey = NULL;
+ X509 *cert = NULL;
+ int ret, err;
+ char *buf = NULL;
+ size_t buf_len = 0;
+ X509_EXTENSION *extension = NULL;
+ X509 *new_cert = NULL;
+ EVP_PKEY *new_privkey = NULL;
+
+ voms_info = VOMS_Init(vomsdir, cadir);
+ if (voms_info == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot initialize VOMS context (VOMS_Init() failed)");
+ return EDG_WLPR_ERROR_VOMS;
+ }
+
+ ret = load_proxy(old_proxy, &cert, &privkey, &chain);
+ if (ret)
+ goto end;
+
+ ret = VOMS_Retrieve(cert, chain, RECURSE_CHAIN, voms_info, &err);
+ if (ret == 0) {
+ if (err == VERR_NOEXT) {
+ /* no VOMS cred, no problem; continue */
+ ret = 0;
+ } else {
+ edg_wlpr_Log(LOG_ERR, "Cannot get VOMS certificate(s) from proxy");
+ ret = EDG_WLPR_ERROR_VOMS;
+ }
+ goto end;
+ }
+
+ for (voms_cert = voms_info->data; voms_cert && *voms_cert; voms_cert++) {
+ char *tmp, *ptr;
+ size_t tmp_len;
+
+ ret = renew_voms_cert(voms_cert, old_proxy, &tmp, &tmp_len);
+ if (ret)
+ continue;
+ 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 = create_voms_extension(buf, buf_len, &extension);
+ if (ret)
+ goto end;
+
+ X509_free(cert);
+ EVP_PKEY_free(privkey);
+ sk_X509_pop_free(chain, X509_free);
+
+ ret = load_proxy(new_proxy, &cert, &privkey, &chain);
+ if (ret)
+ goto end;
+
+ ret = create_proxy(cert, privkey, extension, &new_cert, &new_privkey);
+ if (ret)
+ goto end;
+
+ sk_X509_insert(chain, cert, 0);
+
+ ret = save_proxy(new_proxy, new_cert, new_privkey, chain);
+ if (ret)
+ goto end;
+
+ ret = 0;
+
+end:
+ VOMS_Destroy(voms_info);
+
+ return ret;
+}
+#else /* 0 */
+
+#ifdef NOVOMS
+static int
+renew_voms_certs(const char *old_proxy, char *myproxy_proxy, const char *new_proxy)
+{
+ return 0;
+}
+
+#else
+static int
+renew_voms_certs(const char *old_proxy, char *myproxy_proxy, const char *new_proxy)
+{
+ struct vomsdata *voms_info = NULL;
+ struct voms **voms_cert = NULL;
+ STACK_OF(X509) *chain = NULL;
+ EVP_PKEY *privkey = NULL;
+ X509 *cert = NULL;
+ int ret, err;
+ char *arg = NULL;
+
+ voms_info = VOMS_Init(vomsdir, cadir);
+ if (voms_info == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot initialize VOMS context (VOMS_Init() failed)");
+ return EDG_WLPR_ERROR_VOMS;
+ }
+
+ ret = load_proxy(old_proxy, &cert, &privkey, &chain);
+ if (ret)
+ goto end;
+
+ ret = VOMS_Retrieve(cert, chain, RECURSE_CHAIN, voms_info, &err);
+ if (ret == 0) {
+ if (err == VERR_NOEXT) {
+ /* no VOMS cred, no problem; continue */
+ ret = 0;
+ } else {
+ edg_wlpr_Log(LOG_ERR, "Cannot get VOMS certificate(s) from proxy");
+ ret = EDG_WLPR_ERROR_VOMS;
+ }
+ goto end;
+ }
+
+ for (voms_cert = voms_info->data; voms_cert && *voms_cert; voms_cert++) {
+ ret = set_vo_params(voms_cert, &arg);
+ if (ret)
+ goto end;
+ }
+ ret = exec_voms_proxy_init(arg, myproxy_proxy, new_proxy);
+
+end:
+ VOMS_Destroy(voms_info);
+ return ret;
+}
+#endif /* NOVOMS */
+
+#endif /* 0 */
+
+static void
+register_signal(int signal)
+{
+ received_signal = signal;
+}
+
+static int
+renew_proxy(proxy_record *record, char *basename, char **new_proxy)
+{
+ char tmp_proxy[FILENAME_MAX];
+ int tmp_fd;
+ char repository_file[FILENAME_MAX];
+ FILE *fd = NULL;
+ int ret = -1;
+ char *p;
+ X509 *cert = NULL;
+ X509_NAME *subject = NULL;
+ char *server = NULL;
+ myproxy_socket_attrs_t *socket_attrs;
+ myproxy_request_t *client_request;
+ myproxy_response_t *server_response;
+ char *renewed_proxy;
+
+ 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));
+
+ edg_wlpr_Log(LOG_DEBUG, "Trying to renew proxy in %s.%d",
+ basename, record->suffix);
+
+ snprintf(tmp_proxy, sizeof(tmp_proxy), "%s.%d.renew.XXXXXX",
+ basename, record->suffix);
+ tmp_fd = mkstemp(tmp_proxy);
+ if (tmp_fd == -1) {
+ edg_wlpr_Log(LOG_ERR, "Cannot create temporary file (%s)",
+ strerror(errno));
+ return errno;
+ }
+
+ myproxy_set_delegation_defaults(socket_attrs, client_request);
+
+ snprintf(repository_file, sizeof(repository_file),"%s.%d",
+ basename, record->suffix);
+ fd = fopen(repository_file, "r");
+ if (fd == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot open proxy %s for renewal (%s)",
+ repository_file, strerror(errno));
+ ret = errno;
+ goto end; /* XXX */
+ }
+
+ cert = PEM_read_X509(fd, NULL, NULL, NULL);
+ fclose(fd);
+ if (cert == NULL) {
+ edg_wlpr_Log(LOG_ERR, "SSL routines failed to read proxy %s for renewal",
+ repository_file);
+ ret = EDG_WLPR_ERROR_SSL;
+ goto end;
+ }
+
+ subject = X509_NAME_dup(X509_get_subject_name(cert));
+ proxy_get_base_name(subject);
+ client_request->username = X509_NAME_oneline(subject, NULL, 0);
+ X509_NAME_free(subject);
+ X509_free(cert);
+ if (client_request->username == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot read subject name from %s", repository_file);
+ ret = EINVAL;
+ goto end;
+ }
+
+ /* XXX support VERY_SHORT_LIFETIME ? */
+ client_request->proxy_lifetime = 60 * 60 * DGPR_RETRIEVE_DEFAULT_HOURS;
+
+ server = (record->myproxy_server) ? record->myproxy_server :
+ socket_attrs->pshost;
+ if (server == NULL) {
+ edg_wlpr_Log(LOG_ERR, "No myproxy server specified");
+ ret = EINVAL;
+ goto end;
+ }
+ socket_attrs->pshost = strdup(server);
+
+ p = strchr(socket_attrs->pshost, ':');
+ if (p) {
+ *p++ = '\0';
+ ret = edg_wlpr_DecodeInt(p, &socket_attrs->psport);
+ if (ret)
+ goto end;
+ } else
+ socket_attrs->psport = MYPROXY_SERVER_PORT;
+
+ ret = myproxy_get_delegation(socket_attrs, client_request, repository_file,
+ server_response, tmp_proxy);
+ if (ret == 1) {
+ ret = EDG_WLPR_ERROR_MYPROXY;
+ edg_wlpr_Log(LOG_ERR, "Cannot get renewed proxy from Myproxy server");
+ goto end;
+ }
+
+ renewed_proxy = tmp_proxy;
+
+ if (voms_enabled) {
+ char tmp_voms_proxy[FILENAME_MAX];
+ int tmp_voms_fd;
+
+ snprintf(tmp_voms_proxy, sizeof(tmp_voms_proxy), "%s.%d.renew.XXXXXX",
+ basename, record->suffix);
+ tmp_voms_fd = mkstemp(tmp_voms_proxy);
+ if (tmp_voms_fd == -1) {
+ edg_wlpr_Log(LOG_ERR, "Cannot create temporary file (%s)",
+ strerror(errno));
+ ret = errno;
+ goto end;
+ }
+
+ ret = renew_voms_certs(repository_file, tmp_proxy, tmp_voms_proxy);
+ if (ret)
+ goto end;
+
+ renewed_proxy = tmp_voms_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;
+}
+
+static void
+check_renewal(char *datafile, int force_renew)
+{
+ 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);
+
+ 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) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(LOG_ERR, "Cannot open meta file %s (%s)",
+ datafile, strerror(errno));
+ return;
+ }
+
+ current_time = time(NULL);
+ edg_wlpr_Log(LOG_DEBUG, "Reading metafile %s", datafile);
+
+ while (fgets(line, sizeof(line), meta_fd) != NULL) {
+ free_record(&record);
+ p = strchr(line, '\n');
+ if (p)
+ *p = '\0';
+ ret = decode_record(line, &record);
+ if (ret)
+ continue; /* XXX exit? */
+ if (record.jobids.len == 0) /* no jobid registered for this proxy */
+ continue;
+ if (record.end_time - current_time < RENEWAL_CLOCK_SKEW ||
+ abs(record.next_renewal - current_time) < RENEWAL_CLOCK_SKEW ||
+ record.next_renewal < current_time ||
+ record.end_time < current_time ||
+ force_renew) {
+ ret = EDG_WLPR_PROXY_EXPIRED;
+ if (record.end_time >= current_time)
+ /* only try renewal if the proxy hasn't already expired */
+ ret = renew_proxy(&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(&record);
+ return;
+ }
+ request.entries = tmp;
+ request.entries[num] = entry;
+ request.entries[num+1] = NULL;
+ num++;
+ }
+ }
+ free_record(&record);
+
+ if (num > 0) {
+ ret = edg_wlpr_RequestSend(&request, &response);
+ if (ret != 0)
+ edg_wlpr_Log(LOG_ERR,
+ "Failed to send update request to master (%d)", ret);
+ else if (response.response_code != 0)
+ edg_wlpr_Log(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);
+
+ return;
+}
+
+int renewal(int force_renew)
+{
+ DIR *dir = NULL;
+ struct dirent *file;
+ FILE *fd;
+
+ edg_wlpr_Log(LOG_DEBUG, "Starting renewal process");
+
+ if (chdir(repository)) {
+ edg_wlpr_Log(LOG_ERR, "Cannot access repository directory %s (%s)",
+ repository, strerror(errno));
+ return errno;
+ }
+
+ dir = opendir(repository);
+ if (dir == NULL) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(LOG_ERR, "Cannot open meta file %s (%s)",
+ file->d_name, strerror(errno));
+ continue;
+ }
+ check_renewal(file->d_name, force_renew);
+ fclose(fd);
+ }
+ closedir(dir);
+ edg_wlpr_Log(LOG_DEBUG, "Finishing renewal process");
+ return 0;
+}
+
+void
+watchdog_start(void)
+{
+ struct sigaction sa;
+ int force_renewal;
+
+ memset(&sa,0,sizeof(sa));
+ sa.sa_handler = register_signal;
+ sigaction(SIGUSR1, &sa, NULL);
+
+ /* load_vomses(); */
+
+ while (1) {
+ received_signal = -1;
+ sleep(60 * 5);
+ force_renewal = (received_signal == SIGUSR1) ? 1 : 0;
+ /* XXX uninstall signal handler ? */
+ renewal(force_renewal);
+ }
+}
--- /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 <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 */
+
+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, char **buf, size_t *buf_len);
+
+int
+edg_wlpr_Write(int sock, 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);
+
+#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 *vomsconf = "/opt/edg/etc/vomses";
+#ifndef NOVOMS
+struct vomses_records vomses;
+#endif
+
+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' },
+ { NULL, 0, NULL, 0 }
+};
+
+typedef struct {
+ edg_wlpr_Command code;
+ void (*handler) (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(char *progname);
+
+static int
+do_listen(char *socket_name, int *sock);
+
+static int
+encode_response(edg_wlpr_Response *response, char **msg);
+
+static command_table *
+find_command(edg_wlpr_Command code);
+
+static int
+proto(int sock);
+
+static int
+doit(int sock);
+
+static int
+decode_request(const char *msg, const size_t msg_len, edg_wlpr_Request *request);
+
+static command_table *
+find_command(edg_wlpr_Command code)
+{
+ command_table *c;
+
+ for (c = commands; c->code; c++) {
+ if (c->code == code)
+ return c;
+ }
+ return NULL;
+}
+
+static int
+proto(int sock)
+{
+ char *buf = NULL;
+ size_t buf_len;
+ int ret;
+ edg_wlpr_Response response;
+ edg_wlpr_Request request;
+ command_table *command;
+
+ memset(&request, 0, sizeof(request));
+ memset(&response, 0, sizeof(response));
+
+ ret = edg_wlpr_Read(sock, &buf, &buf_len);
+ if (ret) {
+ edg_wlpr_Log(LOG_ERR, "Error reading from client: %s",
+ edg_wlpr_GetErrorString(ret));
+ return ret;
+ }
+
+ ret = decode_request(buf, buf_len, &request);
+ free(buf);
+ if (ret)
+ goto end;
+
+ /* XXX check request (protocol version, ...) */
+
+ command = find_command(request.command);
+ if (command == NULL) {
+ ret = EDG_WLPR_ERROR_UNKNOWN_COMMAND;
+ edg_wlpr_Log(LOG_ERR, "Received unknown command (%d)", request.command);
+ goto end;
+ }
+
+ edg_wlpr_Log(LOG_INFO, "Received command code %d for proxy %s",
+ request.command,
+ request.proxy_filename ? request.proxy_filename : "(unspecified)");
+
+ command->handler(&request, &response);
+
+ ret = encode_response(&response, &buf);
+ if (ret)
+ goto end;
+
+ ret = edg_wlpr_Write(sock, buf, strlen(buf) + 1);
+ free(buf);
+ if (ret) {
+ edg_wlpr_Log(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(int sock)
+{
+ int newsock;
+ struct sockaddr_un client_addr;
+ int client_addr_len = sizeof(client_addr);
+#if 0
+ next_renewal = LONG_MAX;
+ size_of_proxies = PROXIES_ALLOC_SIZE;
+ proxies = malloc((size_of_proxies) * sizeof(struct guarded_proxy *));
+ if (proxies == NULL) {
+ return ENOMEM;
+ }
+ proxies[0] = NULL;
+#endif
+
+#if 0
+ sigemptyset(&sset);
+ sigaddset(&sset,SIGTERM);
+ sigaddset(&sset,SIGINT);
+ sigaddset(&sset, SIGKILL);
+ sigaddset(&sset, SIGUSR1);
+ sigaddset(&sset, SIGALRM);
+ sigprocmask(SIG_BLOCK,&sset,NULL);
+#endif
+
+ while (1) {
+#if 0
+ sigprocmask(SIG_UNBLOCK,&sset,NULL);
+ newsock = accept(sock, (struct sockaddr *) &client_addr, &client_addr_len);
+ sigprocmask(SIG_BLOCK,&sset,NULL);
+
+ if (newsock == -1) {
+ if (errno == EINTR) /* ERESTARTSYS */
+ proxy_renewal(received_signal);
+ else
+ log();
+ continue;
+ }
+#else
+ newsock = accept(sock, (struct sockaddr *) &client_addr, &client_addr_len);
+ if (newsock == -1) {
+ edg_wlpr_Log(LOG_ERR, "accept() failed");
+ continue;
+ }
+ edg_wlpr_Log(LOG_DEBUG, "Got connection");
+
+#endif
+
+ proto(newsock);
+
+ edg_wlpr_Log(LOG_DEBUG, "Connection closed");
+ close(newsock);
+ }
+}
+
+static int
+decode_request(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) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(LOG_ERR, "Protocol error reading command specification: %s",
+ edg_wlpr_GetErrorString(ret));
+ goto err;
+ }
+
+ ret = edg_wlpr_DecodeInt(value, (int *)(&request->command));
+ if (ret) {
+ edg_wlpr_Log(LOG_ERR, "Received non-numeric command specification (%s)",
+ value);
+ free(value);
+ goto err;
+ }
+ free(value);
+
+ if (find_command(request->command) == NULL) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(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) {
+ edg_wlpr_Log(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(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(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(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) {
+ edg_wlpr_Log(LOG_ERR, "socket(): %s", strerror(errno));
+ return errno;
+ }
+
+ ret = bind(s, (struct sockaddr *)&my_addr, sizeof(my_addr));
+ if (ret == -1) {
+ edg_wlpr_Log(LOG_ERR, "bind(): %s", strerror(errno));
+ close(s);
+ return errno;
+ }
+
+ ret = listen(s, 5); /* XXX enough ? */
+ if (ret == -1) {
+ edg_wlpr_Log(LOG_ERR, "listen(): %s", strerror(errno));
+ close(s);
+ return errno;
+ }
+
+ *sock = s;
+ return 0;
+}
+
+void
+edg_wlpr_Log(int dbg_level, const char *format, ...)
+{
+ va_list ap;
+ char log_mess[1024];
+
+ /* cannot handle the %m format argument specific for syslog() */
+ va_start(ap, format);
+ vsnprintf(log_mess, sizeof(log_mess), format, ap);
+ va_end(ap);
+
+ if (debug)
+ printf("[%d] %s\n", getpid(), log_mess);
+ else
+ if (dbg_level < LOG_DEBUG) /* XXX make configurable */
+ syslog(dbg_level, "%s", log_mess);
+}
+
+int
+start_watchdog(pid_t *pid)
+{
+ pid_t p;
+
+ switch ((p = fork())) {
+ case -1:
+ edg_wlpr_Log(LOG_ERR, "fork() failed: %s",
+ strerror(errno));
+ return errno;
+ case 0:
+ watchdog_start();
+ exit(0);
+ break;
+ default:
+ *pid = p;
+ return 0;
+ }
+ /* not reachable */
+ exit(0);
+}
+
+#ifdef NOVOMS
+static int
+load_vomses()
+{
+ return ENOSYS;
+}
+
+#else
+static int
+load_vomses()
+{
+ FILE *fd = NULL;
+ char line[1024];
+ char *nick, *hostname;
+ int port;
+ vomses_record *rec;
+ vomses_record **tmp;
+ char *p;
+
+ fd = fopen(vomsconf, "r");
+ if (fd == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Cannot open vomses configuration file (%s)",
+ strerror(errno));
+ return errno;
+ }
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ p = line;
+ if (*p != '"') {
+ edg_wlpr_Log(LOG_ERR, "Parsing error when reading vomses configuration file");
+ return EINVAL;
+ }
+ nick = strdup(strtok(p+1, "\""));
+
+ p = strtok(NULL, "\"");
+ hostname = strdup(strtok(NULL, "\""));
+
+ p = strtok(NULL, "\"");
+ port = atoi(strdup(strtok(NULL, "\"")));
+
+ if (nick == NULL || hostname == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Parsing error when reading vomses configuration file");
+ return EINVAL;
+ }
+
+ rec = calloc(1, sizeof(*rec));
+ if (rec == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Not enough memory");
+ return ENOMEM;
+ }
+ rec->nick = nick;
+ rec->hostname = hostname;
+ rec->port = port;
+
+ tmp = realloc(vomses.val, vomses.len + 1);
+ if (tmp == NULL) {
+ edg_wlpr_Log(LOG_ERR, "Not enough memory");
+ return ENOMEM;
+ }
+ vomses.val = tmp;
+ vomses.len++;
+
+ vomses.val[vomses.len-1] = rec;
+ }
+ fclose(fd);
+ return 0;
+}
+#endif
+
+int main(int argc, char *argv[])
+{
+ int sock;
+ char *progname;
+ int opt;
+ int fd;
+ char sockname[PATH_MAX];
+ int ret;
+ pid_t pid;
+
+ 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:", opts, NULL)) != EOF)
+ switch (opt) {
+ case 'h': usage(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 '?': usage(progname); return 1;
+ }
+
+ if (optind < argc) {
+ usage(progname);
+ exit(1);
+ }
+
+ if (chdir(repository)) {
+ edg_wlpr_Log(LOG_ERR, "Cannot access repository directory %s (%s)",
+ repository, strerror(errno));
+ exit(1);
+ }
+
+ if (!debug)
+ for (fd = 3; fd < OPEN_MAX; fd++) close(fd);
+
+ if (!debug) {
+ /* chdir ? */
+ if (daemon(1,0) == -1) {
+ perror("deamon()");
+ exit(1);
+ }
+ openlog(progname, LOG_PID, LOG_DAEMON);
+ }
+
+ if (voms_enabled) {
+ char *path;
+ char *new_path;
+ ret = load_vomses();
+ if (ret)
+ return 1;
+ setenv("GLOBUS_VERSION", "22", 0);
+ if (VOMS_INSTALL_PATH != NULL && *VOMS_INSTALL_PATH != '\0') {
+ path = getenv("PATH");
+ asprintf(&new_path, "%s:%s/bin", path, VOMS_INSTALL_PATH);
+ setenv("PATH", new_path, 1);
+ }
+ }
+
+ ret = start_watchdog(&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(sockname, &sock);
+ if (ret)
+ return 1;
+ edg_wlpr_Log(LOG_DEBUG, "Listening at %s", sockname);
+
+#if 0
+ /* XXX ??? */
+ install_handlers();
+#endif
+
+
+#if 0
+ /* XXX this overrides setings done by install_handlers()? */
+ signal(SIGTERM, cleanup);
+ signal(SIGINT, cleanup);
+ signal(SIGKILL, cleanup);
+ signal(SIGPIPE, SIG_IGN);
+
+ atexit(cleanup);
+#endif
+
+ ret = doit(sock);
+
+ close(sock);
+ return ret;
+}
--- /dev/null
+#ifndef RENEWALD_LOCL_H
+#define RENEWALD_LOCL_H
+
+#ident "$Header$"
+
+#include <myproxy.h>
+#include <myproxy_delegation.h>
+
+#include "glite/wms/thirdparty/globus_ssl_utils/sslutils.h"
+#include "renewal.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;
+
+typedef struct vomses_record {
+ char *nick;
+ char *hostname;
+ int port;
+} vomses_record;
+
+typedef struct vomses_records {
+ unsigned int len;
+ struct vomses_record **val;
+} vomses_records;
+
+/* commands */
+void
+register_proxy(edg_wlpr_Request *request, edg_wlpr_Response *response);
+
+void
+unregister_proxy(edg_wlpr_Request *request, edg_wlpr_Response *response);
+
+void
+get_proxy(edg_wlpr_Request *request, edg_wlpr_Response *response);
+
+void
+update_db(edg_wlpr_Request *request, edg_wlpr_Response *response);
+
+int
+get_times(char *proxy_file, proxy_record *record);
+
+void
+watchdog_start(void);
+
+void
+edg_wlpr_Log(int dbg_level, const char *format, ...);
+
+int
+decode_record(char *line, proxy_record *record);
+
+int
+encode_record(proxy_record *record, char **line);
+
+void
+free_record(proxy_record *record);
+
+int
+load_proxy(const char *filename, X509 **cert, EVP_PKEY **privkey,
+ STACK_OF(X509) **chain);
+
+#endif /* RENEWALD_LOCL_H */