--- /dev/null
+LICENSE file for EGEE Middleware\r
+================================\r
+\r
+Copyright (c) 2004 on behalf of the EU EGEE Project: \r
+The European Organization for Nuclear Research (CERN), \r
+Istituto Nazionale di Fisica Nucleare (INFN), Italy\r
+Datamat Spa, Italy\r
+Centre National de la Recherche Scientifique (CNRS), France\r
+CS Systeme d'Information (CSSI), France\r
+Royal Institute of Technology, Center for Parallel Computers (KTH-PDC), Sweden\r
+Universiteit van Amsterdam (UvA), Netherlands\r
+University of Helsinki (UH.HIP), Finlan\r
+University of Bergen (UiB), Norway\r
+Council for the Central Laboratory of the Research Councils (CCLRC), United Kingdom\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions are\r
+met: \r
+\r
+1. Redistributions of source code must retain the above copyright\r
+notice, this list of conditions and the following disclaimer.\r
+\r
+2. Redistributions in binary form must reproduce the above copyright\r
+notice, this list of conditions and the following disclaimer in the\r
+documentation and/or other materials provided with the distribution.\r
+\r
+3. The end-user documentation included with the redistribution, if\r
+any, must include the following acknowledgment: "This product includes\r
+software developed by The EU EGEE Project (http://cern.ch/eu-egee/)."\r
+Alternatively, this acknowledgment may appear in the software itself, if\r
+and wherever such third-party acknowledgments normally appear.\r
+\r
+4. The names EGEE and the EU EGEE Project must not be\r
+used to endorse or promote products derived from this software without\r
+prior written permission. For written permission, please contact\r
+<email address>.\r
+\r
+5. You are under no obligation whatsoever to provide anyone with any\r
+bug fixes, patches, or upgrades to the features, functionality or\r
+performance of the Software ("Enhancements") that you may develop over\r
+time; however, if you choose to provide your Enhancements to The EU\r
+EGEE Project, or if you choose to otherwise publish or distribute your\r
+Enhancements, in source code form without contemporaneously requiring\r
+end users of The EU EGEE Proejct to enter into a separate written license\r
+agreement for such Enhancements, then you hereby grant The EU EGEE Project\r
+a non-exclusive, royalty-free perpetual license to install, use, copy,\r
+modify, prepare derivative works, incorporate into the EGEE Middleware\r
+or any other computer software, distribute, and sublicense your\r
+Enhancements or derivative works thereof, in binary and source code\r
+form (if any), whether developed by The EU EGEE Project or third parties.\r
+\r
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED\r
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+DISCLAIMED. IN NO EVENT SHALL PROJECT OR ITS CONTRIBUTORS BE LIABLE\r
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\r
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\r
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+This software consists of voluntary contributions made by many\r
+individuals on behalf of the EU EGEE Prject. For more information on The\r
+EU EGEE Project, please see http://cern.ch/eu-egee/. For more information on\r
+EGEE Middleware, please see http://egee-jra1.web.cern.ch/egee-jra1/\r
+\r
+\r
--- /dev/null
+# defaults
+top_srcdir=.
+builddir=build
+top_builddir=${top_srcdir}/${builddir}
+stagedir=.
+distdir=.
+globalprefix=glite
+lbprefix=lb
+package=glite-security-gsoap-plugin
+version=1.0.0
+PREFIX=/opt/glite
+
+glite_location=/opt/glite
+globus_prefix=/opt/globus
+nothrflavour=gcc32
+thrflavour=gcc32pthr
+gsoap_prefix=/opt/gsoap
+
+-include Makefile.inc
+-include ../Makefile.inc
+
+GSPLUGIN_DEBUG:= yes
+
+version_info=-version-info `echo ${version} | cut -d. -f1,2 | tr . :`
+
+VPATH=${top_srcdir}/src:${top_srcdir}/test:${top_srcdir}/examples
+
+TEST_LIBS:=-L${cppunit}/lib -lcppunit
+TEST_INC:=-I${cppunit}/include
+
+ifeq ($(GSPLUGIN_DEBUG),yes)
+ DEBUG:=-g -O0 -Wall -DGSPLUGIN_DEBUG
+else
+ DEBUG:=-g -O0 -Wall
+endif
+
+CFLAGS:= ${DEBUG} \
+ -DVERSION=\"${version}\" \
+ -I${top_srcdir}/src -I${top_srcdir}/interface -I. \
+ -I${stagedir}/include \
+ -I${gsoap_prefix}/include \
+ -I${globus_prefix}/include/${nothrflavour} \
+ -I${globus_prefix}/include/${nothrflavour}/openssl \
+ ${COVERAGE_FLAGS} -D_GNU_SOURCE -DDATAGRID_EXTENSION
+
+LDFLAGS:=${COVERAGE_FLAGS}
+
+COMPILE:=libtool --mode=compile ${CC} ${CFLAGS}
+LINK:=libtool --mode=link ${CC} ${LDFLAGS}
+LINKXX:=libtool --mode=link ${CXX} ${LDFLAGS}
+INSTALL:=libtool --mode=install install
+LINKXX:=libtool --mode=link ${CXX} -rpath ${stagedir}/lib ${LDFLAGS}
+
+GLOBUS_INC:= -I${globus_prefix}/include/${nothrflavour}
+GLOBUS_LIBS:= -L${globus_prefix}/lib \
+ -lglobus_common_${nothrflavour} \
+ -lglobus_gssapi_gsi_${nothrflavour} \
+
+GSOAP_LIBS:= -L${gsoap_prefix}/lib -lgsoap
+
+EX_LIBS:= ${GLOBUS_LIBS} -L${ares_prefix}/lib -lares
+
+GSS_OBJS:=lb_gss.o
+GSS_LOBJS:=${GSS_OBJS:.o=.lo}
+GSS_THROBJS:=${GSS_OBJS:.o=.thr.o}
+GSS_THRLOBJS:=${GSS_OBJS:.o=.thr.lo}
+
+GSS_STATICLIB:=libglite_security_gss_${nothrflavour}.a
+GSS_THRSTATICLIB:=libglite_security_gss_${thrflavour}.a
+GSS_LTLIB:=libglite_security_gss_${nothrflavour}.la
+GSS_THRLTLIB:=libglite_security_gss_${thrflavour}.la
+
+OBJS:=${GSS_OBJS} glite_gsplugin.o
+LOBJS:=${GSS_OBJS:.o=.lo}
+THROBJS:=${GSS_OBJS:.o=.thr.o}
+THRLOBJS:=${GSS_OBJS:.o=.thr.lo}
+
+STATICLIB:=libglite_security_gsoap_plugin_${nothrflavour}.a
+THRSTATICLIB:=libglite_security_gsoap_plugin_${thrflavour}.a
+LTLIB:=libglite_security_gsoap_plugin_${nothrflavour}.la
+THRLTLIB:=libglite_security_gsoap_plugin_${thrflavour}.la
+
+HDRS:=lb_gss.h
+
+${GSS_STATICLIB}: ${GSS_OBJS}
+ ar crv $@ ${GSS_OBJS}
+ ranlib $@
+
+${GSS_THRSTATICLIB}: ${GSS_THROBJS}
+ ar crv $@ ${GSS_THROBJS}
+ ranlib $@
+
+${GSS_LTLIB}: ${GSS_OBJS}
+ ${LINK} ${version_info} -o $@ ${GSS_LOBJS}
+
+${GSS_THRLTLIB}: ${GSS_THROBJS}
+ ${LINK} ${version_info} -o $@ ${GSS_THRLOBJS}
+
+${STATICLIB}: ${OBJS}
+ ar crv $@ ${OBJS}
+ ranlib $@
+
+${THRSTATICLIB}: ${THROBJS}
+ ar crv $@ ${THROBJS}
+ ranlib $@
+
+${LTLIB}: ${OBJS}
+ ${LINK} ${version_info} -o $@ ${LOBJS}
+
+${THRLTLIB}: ${THROBJS}
+ ${LINK} ${version_info} -o $@ ${THRLOBJS}
+
+default: all
+
+all compile: ${GSS_STATICLIB} ${GSS_LTLIB} ${GSS_THRSTATICLIB} ${GSS_THRLTLIB} ${STATICLIB} ${LTLIB} ${THRSTATICLIB} ${THRLTLIB} examples
+
+check: compile check.gss
+
+check.gss: test_gss
+ # ./test_gss
+ echo test_gss not run automatically util we have got some credentials
+
+test_gss: test_gss.o
+ ${LINKXX} -o $@ test_gss.o ${GSS_LTLIB} ${TEST_LIBS} ${GLOBUS_LIBS} ${EX_LIBS}
+
+test_coverage:
+ -mkdir coverage
+ cd coverage && $(MAKE) -f ../Makefile top_srcdir=../../ COVERAGE_FLAGS="-fprofile-arcs -ftest-coverage" check
+ cd coverage && for i in ${OBJS}; do gcov -o .libs/ $$i ; done
+
+
+examples: soap_gen wscalc_clt_ex wscalc_srv_ex
+
+GSOAP_FPREFIX:= GSOAP_
+
+ifeq ($(GSPLUGIN_DEBUG),yes)
+ WSCALC_CLT_OBJS = wscalc_clt_ex.o ${GSOAP_FPREFIX}C.o ${GSOAP_FPREFIX}Client.o \
+ stdsoap2.o
+ WSCALC_SRV_OBJS = wscalc_srv_ex.o ${GSOAP_FPREFIX}C.o ${GSOAP_FPREFIX}Server.o \
+ stdsoap2.o
+else
+ WSCALC_CLT_OBJS = wscalc_clt_ex.o ${GSOAP_FPREFIX}C.o ${GSOAP_FPREFIX}Client.o
+ WSCALC_SRV_OBJS = wscalc_srv_ex.o ${GSOAP_FPREFIX}C.o ${GSOAP_FPREFIX}Server.o
+endif
+
+
+wscalc_clt_ex: ${WSCALC_CLT_OBJS} ${STATICLIB}
+ ${LINK} -o $@ ${STATICLIB} ${GSOAP_LIBS} ${EX_LIBS} ${WSCALC_CLT_OBJS}
+
+wscalc_srv_ex: ${WSCALC_SRV_OBJS} ${STATICLIB}
+ ${LINK} -o $@ ${STATICLIB} ${GSOAP_LIBS} ${EX_LIBS} ${WSCALC_SRV_OBJS}
+
+${GSOAP_FPREFIX}H.h ${GSOAP_FPREFIX}C.c ${GSOAP_FPREFIX}Server.c ${GSOAP_FPREFIX}Client.c ${GSOAP_FPREFIX}ServerLib.c ${GSOAP_FPREFIX}ClientLib.c soap_gen: calc.h.S
+ ${gsoap_prefix}/bin/soapcpp2 -c -p ${GSOAP_FPREFIX} ${top_srcdir}/examples/calc.h.S
+
+wscalc_clt_ex.o: wscalc_clt_ex.c
+ ${CC} -c ${CFLAGS} ${GLOBUS_INC} -o $@ $<
+
+stdsoap2.o: ${gsoap_prefix}/devel/stdsoap2.c
+ ${CC} -c ${CFLAGS} -o $@ $<
+
+doc:
+
+stage: compile
+ $(MAKE) install PREFIX=${stagedir} DOSTAGE=yes
+
+dist: distsrc distbin
+
+distsrc:
+ mkdir -p ${top_srcdir}/${package}-${version}
+ cd ${top_srcdir} && GLOBIGNORE="${package}-${version}" && cp -Rf * ${package}-${version}
+ cd ${top_srcdir} && tar -czf ${distdir}/${package}-${version}_src.tar.gz --exclude-from=project/tar_exclude ${package}-${version}
+ rm -rf ${top_srcdir}/${package}-${version}
+
+distbin:
+ $(MAKE) install PREFIX=`pwd`/tmpbuilddir${stagedir}
+ save_dir=`pwd`; cd tmpbuilddir${stagedir} && tar -czf $$save_dir/${top_srcdir}/${distdir}/${package}-${version}_bin.tar.gz *; cd $$save_dir
+ rm -rf tmpbuilddir
+
+install:
+ -mkdir -p ${PREFIX}/lib
+ -mkdir -p ${PREFIX}/share/doc/${package}-${version}
+ -mkdir -p ${PREFIX}/include/glite/security/${package}
+# ${INSTALL} -m 644 ${LTLIB} ${THRLTLIB} ${PREFIX}/lib
+# ${INSTALL} -m 644 ${GSS_LTLIB} ${GSS_THRLTLIB} ${PREFIX}/lib
+# ${INSTALL} -m 644 ${top_srcdir}/LICENSE ${PREFIX}/share/doc/${package}-${version}
+# cd ${top_srcdir}/interface && ${INSTALL} -m 644 lb_gss.h glite_gsplugin.h ${PREFIX}/include/glite/security/${package}
+# if [ x${DOSTAGE} = xyes ]; then \
+# install -m 644 ${GSS_STATICLIB} ${GSS_THRSTATICLIB} ${STATICLIB} ${THRSTATICLIB} ${PREFIX}/lib; \
+# fi
+
+clean:
+
+%.o: %.c
+ ${COMPILE} ${GLOBUS_INC} -o $@ -c $<
+
+%.thr.o: %.c
+ ${COMPILE} ${GLOBUS_THR_INC} -o $@ -c $<
+
+test_gss.o: %.o: %.cpp
+ ${CXX} -c ${CFLAGS} ${GLOBUSINC} ${TEST_INC} $<
--- /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 gSOAP plugin and gss libraries
+
+ Release: $Name$
+
+ Revision history:
+
+-->
+
+<project name="gsoap-plugin" default="dist">
+
+ <!-- =========================================
+ Builds the GLite gSOAP plugin and gss libraries
+ ========================================= -->
+
+ <!-- =========================================
+ 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="secmakefiles" />
+ </target>
+
+ <target name="localcompile"
+ description="Module specific compile tasks">
+ </target>
+
+ <target name="localclean"
+ description="Module specific cleaning tasks">
+ </target>
+
+ <!-- =========================================
+ RPM settings
+ ========================================= -->
+
+ <property name="build.package.summary" value="gSOAP plugin and gss libraries" />
+ <property name="build.package.description" value=" The gSOAP gss plugin" />
+
+</project>
--- /dev/null
+//gsoap egeesec schema namespace: urn:calc
+//
+//gsoap egeesec service name: calc
+//gsoap egeesec service port: http://localhost:9999/
+//gsoap egeesec service namespace: urn:calc:wscalc
+
+//gsoap egeesec service method-style: add rpc
+//gsoap egeesec service method-action: add ""
+int wscalc__add(double a, double b, double *result);
+
+//gsoap egeesec service method-style: sub rpc
+//gsoap egeesec service method-action: sub ""
+int wscalc__sub(double a, double b, double *result);
--- /dev/null
+#include <glite_gsplugin.h>
+
+#include "GSOAP_H.h"
+#include "wscalc.nsmap"
+
+static const char *server = "http://localhost:9999/";
+
+int
+main(int argc, char **argv)
+{
+ struct soap soap;
+ double a, b, result;
+ int ret;
+
+
+ if (argc < 4) {
+ fprintf(stderr, "Usage: [add|sub] num num\n");
+ exit(1);
+ }
+
+ soap_init(&soap);
+ soap_register_plugin(&soap, glite_gsplugin);
+
+ a = strtod(argv[2], NULL);
+ b = strtod(argv[3], NULL);
+ switch ( *argv[1] ) {
+ case 'a':
+ ret = soap_call_wscalc__add(&soap, server, "", a, b, &result);
+ break;
+ case 's':
+ ret = soap_call_wscalc__sub(&soap, server, "", a, b, &result);
+ break;
+ default:
+ fprintf(stderr, "Unknown command\n");
+ exit(2);
+ }
+
+ if ( ret ) {
+ fprintf(stderr, "NECO JE V ****\n\n");
+ fprintf(stderr, "plugin err: %s", glite_gsplugin_errdesc(&soap));
+ soap_print_fault(&soap, stderr);
+ }
+ else printf("result = %g\n", result);
+
+
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <getopt.h>
+#include <stdsoap2.h>
+#include <glite_gsplugin.h>
+
+#include "GSOAP_H.h"
+#include "wscalc.nsmap"
+
+
+static struct option long_options[] = {
+ { "cert", required_argument, NULL, 'c' },
+ { "key", required_argument, NULL, 'k' },
+ { "CAdir", required_argument, NULL, 'd' },
+ { NULL, 0, NULL, 0 }
+};
+
+void
+usage(const char *me)
+{
+ fprintf(stderr,
+ "usage: %s [option]\n"
+ "\t-c, --cred\t certificate file\n"
+ "\t-k, --key\t private key file\n"
+ "\t-d, --CAdir\t trusted certificates directory\n", me);
+}
+
+
+int
+main(int argc, char **argv)
+{
+ struct soap soap;
+ edg_wll_GssStatus gss_code;
+ gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
+ char *name, *msg;
+ char *cert, *key, *cadir;
+ int m, s; /* master and slave sockets */
+ int opt;
+
+
+ cert = key = cadir = NULL;
+ name = strrchr(argv[0],'/');
+ if ( name ) name++; else name = argv[0];
+
+ while ((opt = getopt_long(argc, argv, "c:k:d:", long_options, NULL)) != EOF) {
+ switch (opt) {
+ case 'c': cert = optarg; break;
+ case 'k': key = optarg; break;
+ case 'd': cadir = optarg; break;
+ case '?':
+ default : usage(name); exit(1);
+ }
+ }
+
+ if ( cert || key ) {
+ char *subject = NULL;
+
+ if ( edg_wll_gss_acquire_cred_gsi(cert, key,
+ &cred, &subject, &gss_code) ) {
+ edg_wll_gss_get_error(&gss_code, "Failed to read credential", &msg);
+ fprintf(stderr, "%s\n", msg);
+ free(msg);
+ exit(1);
+ }
+ if (subject) {
+ printf("server running with certificate: %s\n", subject);
+ free(subject);
+ }
+ }
+
+ soap_init(&soap);
+
+ if ( soap_register_plugin(&soap, glite_gsplugin) ) {
+ fprintf(stderr, "Can't register plugin\n");
+ exit(1);
+ }
+
+ if ( (m = soap_bind(&soap, NULL, 9999, 100)) < 0 ) {
+ soap_print_fault(&soap, stderr);
+ exit(1);
+ }
+
+ while ( 1 ) {
+ printf("accepting connection\n");
+ s = soap_accept(&soap);
+ if ( s < 0 ) {
+ fprintf(stderr, "soap_accept() failed!!!\n");
+ soap_print_fault(&soap, stderr);
+ fprintf(stderr, "plugin err: %s", glite_gsplugin_errdesc(&soap));
+ break;
+ }
+
+ printf("serving connection\n");
+ if ( soap_serve(&soap) ) {
+ soap_print_fault(&soap, stderr);
+ fprintf(stderr, "plugin err: %s", glite_gsplugin_errdesc(&soap));
+ }
+
+ /* clean up class instances
+ */
+ soap_destroy(&soap);
+ /* clean up everything and close socket
+ */
+ soap_end(&soap);
+ }
+ soap_done(&soap); // close master socket
+
+ return 0;
+}
+
+int wscalc__add(struct soap *soap, double a, double b, double *result)
+{
+ *result = a + b;
+ return SOAP_OK;
+}
+
+int wscalc__sub(struct soap *soap, double a, double b, double *result)
+{
+ *result = a - b;
+ return SOAP_OK;
+}
--- /dev/null
+#ifndef __GLITE_GSOAP_PLUGIN_H__
+#define __GLITE_GSOAP_PLUGIN_H__
+
+#include <stdsoap2.h>
+
+#include "lb_gss.h"
+
+#define PLUGIN_ID "GLITE_GSOAP_PLUGIN"
+
+struct _glite_gsplugin_ctx {
+ struct timeval timeout; /**< timeout for all netcalls
+ * if tv_sec ==0 and tv_usec == 0 then
+ * no timeout is used - every call will
+ * be considered as a nonblocking */
+
+ char *error_msg;
+
+ char *key_filename;
+ char *cert_filename;
+
+ edg_wll_GssConnection *connection;
+ gss_cred_id_t cred;
+};
+
+typedef struct _glite_gsplugin_ctx *glite_gsplugin_Context;
+
+extern int glite_gsplugin_init_context(glite_gsplugin_Context *);
+
+extern int glite_gsplugin(struct soap *, struct soap_plugin *, void *);
+extern char *glite_gsplugin_errdesc(struct soap *);
+
+#endif
--- /dev/null
+#ifndef __EDG_WORKLOAD_LOGGING_COMMON_LB_GSS_H__
+#define __EDG_WORKLOAD_LOGGING_COMMON_LB_GSS_H__
+
+#include <gssapi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ EDG_WLL_GSS_OK = 0, /* no GSS errors */
+ EDG_WLL_GSS_ERROR_GSS = -1, /* GSS specific error, call edg_wll_get_gss_error() for details */
+ EDG_WLL_GSS_ERROR_TIMEOUT = -2, /* Timeout */
+ EDG_WLL_GSS_ERROR_EOF = -3, /* EOF occured */
+ EDG_WLL_GSS_ERROR_ERRNO = -4, /* System error. See errno */
+ EDG_WLL_GSS_ERROR_HERRNO = -5 /* Resolver error. See h_errno */
+};
+
+typedef struct _edg_wll_GssConnection {
+ gss_ctx_id_t context;
+ int sock;
+ char buffer[BUFSIZ];
+ size_t bufsize;
+} edg_wll_GssConnection;
+
+typedef struct _edg_wll_GssStatus {
+ OM_uint32 major_status;
+ OM_uint32 minor_status;
+} edg_wll_GssStatus;
+
+
+int
+edg_wll_gss_acquire_cred_gsi(char *cert_file,
+ char *key_file,
+ gss_cred_id_t *cred,
+ char **name,
+ edg_wll_GssStatus* gss_code);
+
+int
+edg_wll_gss_connect(gss_cred_id_t cred,
+ char const *hostname,
+ int port,
+ struct timeval *timeout,
+ edg_wll_GssConnection *connection,
+ edg_wll_GssStatus* gss_code);
+
+int
+edg_wll_gss_accept(gss_cred_id_t cred,
+ int sock,
+ struct timeval *timeout,
+ edg_wll_GssConnection *connection,
+ edg_wll_GssStatus* gss_code);
+
+int
+edg_wll_gss_read(edg_wll_GssConnection *connection,
+ void *buf,
+ size_t bufsize,
+ struct timeval *timeout,
+ edg_wll_GssStatus* gss_code);
+
+int
+edg_wll_gss_write(edg_wll_GssConnection *connection,
+ const void *buf,
+ size_t bufsize,
+ struct timeval *timeout,
+ edg_wll_GssStatus* gss_code);
+
+int
+edg_wll_gss_read_full(edg_wll_GssConnection *connection,
+ void *buf,
+ size_t bufsize,
+ struct timeval *timeout,
+ size_t *total,
+ edg_wll_GssStatus* gss_code);
+
+int
+edg_wll_gss_write_full(edg_wll_GssConnection *connection,
+ const void *buf,
+ size_t bufsize,
+ struct timeval *timeout,
+ size_t *total,
+ edg_wll_GssStatus* gss_code);
+
+int
+edg_wll_gss_watch_creds(const char * proxy_file,
+ time_t * proxy_mtime);
+
+int
+edg_wll_gss_get_error(edg_wll_GssStatus* gss_code,
+ const char *prefix,
+ char **errmsg);
+
+int
+edg_wll_gss_close(edg_wll_GssConnection *connection,
+ struct timeval *timeout);
+
+int
+edg_wll_gss_reject(int sock);
+
+int
+edg_wll_gss_oid_equal(const gss_OID a,
+ const gss_OID b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /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 gSOAP plugin and gss libraries
+
+ Revision history:
+
+
+-->
+
+ <!-- ======================================================
+ Define extra properties here ...
+ ====================================================== -->
+
+ <project name="gSOAP plugin configuration options">
+ <target name="secmakefiles">
+ <exec executable="ln" failonerror="true">
+ <arg line="-fs ${component.dir}/Makefile ${module.build.dir}/Makefile"/>
+ </exec>
+ <echo file="${module.build.dir}/Makefile.inc">
+top_srcdir=..
+builddir=build
+stagedir=${stage.abs.dir}
+distdir=${dist.dir}
+globalprefix=${global.prefix}
+lbprefix=${subsystem.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}
+cppunit=${with.cppunit.prefix}
+gsoap_prefix=${with.gsoap.prefix}
+ </echo>
+ </target>
+ </project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2004 on behalf of the EU EGEE Project:
+ The European Organization for Nuclear Research (CERN),
+ Istituto Nazionale di Fisica Nucleare (INFN), Italy
+ Datamat Spa, Italy
+ Centre National de la Recherche Scientifique (CNRS), France
+ CS Systeme d'Information (CSSI), France
+ Royal Institute of Technology, Center for Parallel Computers (KTH-PDC), Sweden
+ Universiteit van Amsterdam (UvA), Netherlands
+ University of Helsinki (UH.HIP), Finland
+ University of Bergen (UiB), Norway
+ Council for the Central Laboratory of the Research Councils (CCLRC), United Kingdom
+
+ Common build properties file for the GLite gSOAP plugin and gss libraries
+
+ Revision history:
+
+-->
+
+<project name="GLite gSOAP plugin component common properties">
+
+ <!-- Include build properties to allow overwriting
+ of properties for subsystem -->
+ <property file="build.properties" />
+
+ <!-- ======================================================
+ Define corresponding subsystem properties
+ ====================================================== -->
+
+ <!-- Subsystem name -->
+ <property name="subsystem.name" value="${security.subsystem.name}"/>
+
+ <!-- Subsystem prefix -->
+ <property name="subsystem.prefix" value="${security.subsystem.prefix}"/>
+
+ <!-- ======================================================
+ Define component properties
+ ====================================================== -->
+
+ <!-- Component name prefix -->
+ <property name="component.prefix" value="gsoap-plugin" />
+
+ <!-- ======================================================
+ Define general component properties
+ ====================================================== -->
+
+ <import file="${component.general.properties.file}" />
+
+ <!-- ======================================================
+ Define extra properties here ...
+ ====================================================== -->
+
+
+</project>
--- /dev/null
+tar_exclude
+CVS
+build.xml
+build
+build.properties
+properties.xml
+configure-options.xml
+.cvsignore
+.project
+.cdtproject
--- /dev/null
+module.version=1.0.0
+module.build=0
+module.age=0
--- /dev/null
+#include <stdio.h>
+#include <assert.h>
+#include <signal.h>
+#include <stdsoap2.h>
+
+#include "glite_gsplugin.h"
+
+#ifdef GSPLUGIN_DEBUG
+# define pdprintf(s) printf s
+#else
+# define pdprintf(s)
+#endif
+
+typedef struct _int_plugin_data_t {
+ glite_gsplugin_Context ctx; /**< data used for connection etc. */
+ int def; /**< is the context created by plugin? */
+} int_plugin_data_t;
+
+static const char plugin_id[] = PLUGIN_ID;
+
+static void glite_gsplugin_delete(struct soap *, struct soap_plugin *);
+static int glite_gsplugin_copy(struct soap *, struct soap_plugin *, struct soap_plugin *);
+
+static size_t glite_gsplugin_recv(struct soap *, char *, size_t);
+static int glite_gsplugin_send(struct soap *, const char *, size_t);
+static int glite_gsplugin_connect(struct soap *, const char *, const char *, int);
+static int glite_gsplugin_close(struct soap *);
+static int glite_gsplugin_accept(struct soap *, int, struct sockaddr *, int *);
+
+
+int
+glite_gsplugin_init_context(glite_gsplugin_Context *ctx)
+{
+ glite_gsplugin_Context out = (glite_gsplugin_Context) malloc(sizeof(*out));
+ if (!out) return ENOMEM;
+
+ memset(out, 0, sizeof(*out));
+ out->cred = GSS_C_NO_CREDENTIAL;
+
+ /* XXX: some troubles with lb_gss and blocking calls!
+ */
+ out->timeout.tv_sec = 10000;
+ *ctx = out;
+
+ return 0;
+}
+
+int
+glite_gsplugin_free_context(glite_gsplugin_Context ctx)
+{
+ OM_uint32 ms;
+
+ if ( ctx->cred != GSS_C_NO_CREDENTIAL ) gss_release_cred(&ms, &ctx->cred);
+ if ( ctx->connection ) {
+ if ( ctx->connection->context != GSS_C_NO_CONTEXT )
+ edg_wll_gss_close(ctx->connection, NULL);
+ free(ctx->connection);
+ }
+ free(ctx->error_msg);
+ free(ctx->key_filename);
+ free(ctx->cert_filename);
+ free(ctx);
+
+ return 0;
+}
+
+int
+glite_gsplugin(struct soap *soap, struct soap_plugin *p, void *arg)
+{
+ int_plugin_data_t *pdata = malloc(sizeof(int_plugin_data_t));
+
+ pdprintf(("GSLITE_GSPLUGIN: initializing gSOAP plugin\n"));
+ if ( !pdata ) return ENOMEM;
+ if ( arg ) {
+ pdprintf(("GSLITE_GSPLUGIN: Context is given\n"));
+ pdata->ctx = arg;
+ pdata->def = 0;
+ }
+ else {
+ edg_wll_GssStatus gss_code;
+ char *subject = NULL;
+
+ pdprintf(("GSLITE_GSPLUGIN: Creating default context\n"));
+ if ( glite_gsplugin_init_context((glite_gsplugin_Context*)&(pdata->ctx)) ) {
+ free(pdata);
+ return ENOMEM;
+ }
+ if ( edg_wll_gss_acquire_cred_gsi(NULL, NULL, &pdata->ctx->cred, &subject, &gss_code) ) {
+ /* XXX: Let user know, that cred. load failed. Somehow...
+ */
+ glite_gsplugin_free_context(pdata->ctx);
+ return EINVAL;
+ }
+ pdprintf(("GSLITE_GSPLUGIN: server running with certificate: %s\n", subject));
+ free(subject);
+ }
+
+ p->id = plugin_id;
+ p->data = pdata;
+ p->fdelete = glite_gsplugin_delete;
+ p->fcopy = glite_gsplugin_copy;
+
+ soap->fconnect = glite_gsplugin_connect;
+ soap->fclose = glite_gsplugin_close;
+ soap->faccept = glite_gsplugin_accept;
+ soap->fsend = glite_gsplugin_send;
+ soap->frecv = glite_gsplugin_recv;
+
+
+ return SOAP_OK;
+}
+
+
+char *glite_gsplugin_errdesc(struct soap *soap)
+{
+ glite_gsplugin_Context ctx;
+
+ ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx;
+ if ( ctx ) return ctx->error_msg;
+
+ return NULL;
+}
+
+
+
+static int
+glite_gsplugin_copy(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src)
+{
+ pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_copy()\n"));
+ /* Should be the copy code here?
+ */
+ return SOAP_OK;
+}
+
+static void
+glite_gsplugin_delete(struct soap *soap, struct soap_plugin *p)
+{
+ int_plugin_data_t *d = (int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id);
+
+ pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_delete()\n"));
+ if ( d->def ) {
+ OM_uint32 ms;
+
+ glite_gsplugin_close(soap);
+ if (d->ctx->cred != GSS_C_NO_CREDENTIAL) gss_release_cred(&ms, &d->ctx->cred);
+ free(d->ctx->error_msg);
+ }
+ free(d);
+}
+
+
+static int
+glite_gsplugin_connect(
+ struct soap *soap,
+ const char *endpoint,
+ const char *host,
+ int port)
+{
+ glite_gsplugin_Context ctx;
+ edg_wll_GssStatus gss_stat;
+ int ret;
+
+
+ pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_connect()\n"));
+ ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx;
+
+ if ( ctx->cred == GSS_C_NO_CREDENTIAL ) {
+ pdprintf(("GSLITE_GSPLUGIN: loading credentials\n"));
+ ret = edg_wll_gss_acquire_cred_gsi(ctx->cert_filename, ctx->key_filename,
+ &ctx->cred, NULL, &gss_stat);
+ if ( ret ) {
+ edg_wll_gss_get_error(&gss_stat, "failed to load GSI credentials",
+ &ctx->error_msg);
+ goto err;
+ }
+ }
+
+ if ( !(ctx->connection = malloc(sizeof(*ctx->connection))) ) return errno;
+ ret = edg_wll_gss_connect(ctx->cred,
+ host, port,
+ (ctx->timeout.tv_usec || ctx->timeout.tv_sec)? &ctx->timeout: NULL,
+ ctx->connection, &gss_stat);
+ if ( ret ) {
+ edg_wll_gss_get_error(&gss_stat, "edg_wll_gss_connect()", &ctx->error_msg);
+ goto err;
+ }
+
+ /* XXX: co s tim???
+ *
+ soap->socket = 2;
+ */
+
+ return SOAP_OK;
+
+err:
+ pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_connect() error!\n"));
+ switch ( ret ) {
+ case EDG_WLL_GSS_ERROR_HERRNO:
+ case EDG_WLL_GSS_ERROR_ERRNO: return errno;
+ case EDG_WLL_GSS_ERROR_EOF: return ECONNREFUSED;
+ case EDG_WLL_GSS_ERROR_TIMEOUT: return ETIMEDOUT;
+ }
+
+ return ret;
+}
+
+/** It is called in soap_closesocket()
+ *
+ * return like errno value
+ */
+static int
+glite_gsplugin_close(struct soap *soap)
+{
+ glite_gsplugin_Context ctx;
+ int ret = SOAP_OK;
+
+
+ pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_close()\n"));
+ ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx;
+ if ( ctx->connection ) {
+ if ( ctx->connection->context != GSS_C_NO_CONTEXT) {
+ pdprintf(("GSLITE_GSPLUGIN: closing gss connection\n"));
+ ret = edg_wll_gss_close(ctx->connection,
+ (ctx->timeout.tv_usec || ctx->timeout.tv_sec)? &ctx->timeout: NULL);
+ }
+ free(ctx->connection);
+ ctx->connection = NULL;
+ }
+
+ return ret;
+}
+
+
+static int
+glite_gsplugin_accept(struct soap *soap, int s, struct sockaddr *a, int *n)
+{
+ glite_gsplugin_Context ctx;
+ edg_wll_GssStatus gss_code;
+ int conn;
+
+
+ pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_accept()\n"));
+ ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx;
+ if ( (conn = accept(s, (struct sockaddr *)&a, n)) < 0 ) return conn;
+ if ( !ctx->connection
+ && !(ctx->connection = malloc(sizeof(*ctx->connection))) ) return -1;
+ if ( edg_wll_gss_accept(ctx->cred, conn, &ctx->timeout, ctx->connection, &gss_code)) {
+ pdprintf(("GSLITE_GSPLUGIN: Client authentication failed, closing.\n"));
+ edg_wll_gss_get_error(&gss_code, "Client authentication failed", &ctx->error_msg);
+ return -1;
+ }
+
+ return conn;
+}
+
+static size_t
+glite_gsplugin_recv(struct soap *soap, char *buf, size_t bufsz)
+{
+ glite_gsplugin_Context ctx;
+ edg_wll_GssStatus gss_code;
+ int len;
+
+
+ ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx;
+ if ( ctx->error_msg ) { free(ctx->error_msg); ctx->error_msg = NULL; }
+
+ if ( ctx->connection->context == GSS_C_NO_CONTEXT ) {
+ soap->errnum = ENOTCONN;
+ /* XXX glite_gsplugin_send() returns SOAP_EOF on errors */
+ return 0;
+ }
+
+ len = edg_wll_gss_read(ctx->connection, buf, bufsz,
+ (ctx->timeout.tv_usec || ctx->timeout.tv_sec)? &ctx->timeout: NULL,
+ &gss_code);
+
+ switch ( len ) {
+ case EDG_WLL_GSS_OK:
+ break;
+
+ case EDG_WLL_GSS_ERROR_GSS:
+ edg_wll_gss_get_error(&gss_code, "receving WS request",
+ &ctx->error_msg);
+ soap->errnum = ENOTCONN;
+ return 0;
+
+ case EDG_WLL_GSS_ERROR_ERRNO:
+ ctx->error_msg = strdup("edg_wll_gss_read()");
+ soap->errnum = errno;
+ return 0;
+
+ case EDG_WLL_GSS_ERROR_TIMEOUT:
+ soap->errnum = ETIMEDOUT;
+ return 0;
+
+ case EDG_WLL_GSS_ERROR_EOF:
+ soap->errnum = ENOTCONN;
+ return 0;
+
+ /* default: fallthrough */
+ }
+
+ pdprintf(("\nWS received:\n%s\n\n", buf));
+ return len;
+}
+
+static int
+glite_gsplugin_send(struct soap *soap, const char *buf, size_t bufsz)
+{
+ glite_gsplugin_Context ctx;
+ edg_wll_GssStatus gss_code;
+ struct sigaction sa, osa;
+ size_t total = 0;
+ int ret;
+
+
+ pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_send():\n%s\n\n", buf));
+ ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx;
+ /* XXX: check whether ctx is initialized
+ * i.e. ctx->connection != NULL
+ */
+ if ( ctx->error_msg ) { free(ctx->error_msg); ctx->error_msg = NULL; }
+ if ( ctx->connection->context == GSS_C_NO_CONTEXT ) {
+ soap->errnum = ENOTCONN;
+ return SOAP_EOF;
+ }
+
+ memset(&sa, 0, sizeof(sa));
+ assert(sa.sa_handler == NULL);
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &sa, &osa);
+
+ ret = edg_wll_gss_write_full(ctx->connection,
+ (void*)buf, bufsz, &ctx->timeout, &total, &gss_code);
+
+ sigaction(SIGPIPE, &osa, NULL);
+
+ switch ( ret ) {
+ case EDG_WLL_GSS_OK:
+ pdprintf(("\nWS sent:\n%s\n\n", buf));
+ break;
+
+ case EDG_WLL_GSS_ERROR_TIMEOUT:
+ ctx->error_msg = strdup("glite_gsplugin_send()");
+ soap->errnum = ETIMEDOUT;
+ return SOAP_EOF;
+
+ case EDG_WLL_GSS_ERROR_ERRNO:
+ if ( errno == EPIPE ) {
+ ctx->error_msg = strdup("glite_gsplugin_send()");
+ soap->errnum = ENOTCONN;
+ }
+ else {
+ ctx->error_msg = strdup("glite_gsplugin_send()");
+ soap->errnum = errno;
+ }
+ return SOAP_EOF;
+
+ case EDG_WLL_GSS_ERROR_GSS:
+ case EDG_WLL_GSS_ERROR_EOF:
+ default:
+ ctx->error_msg = strdup("glite_gsplugin_send()");
+ soap->errnum = ENOTCONN;
+ return SOAP_EOF;
+ }
+
+ return SOAP_OK;
+}
--- /dev/null
+/* /cvs/jra1mw/org.glite.lb.common/src/lb_gss.c,v 1.3 2004/10/21 10:20:12 dkouril*/
+#ident "$Header$"
+
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <ares.h>
+#include <errno.h>
+
+#include "lb_gss.h"
+
+#define tv_sub(a,b) {\
+ (a).tv_usec -= (b).tv_usec;\
+ (a).tv_sec -= (b).tv_sec;\
+ if ((a).tv_usec < 0) {\
+ (a).tv_sec--;\
+ (a).tv_usec += 1000000;\
+ }\
+}
+
+struct asyn_result {
+ struct hostent *ent;
+ int err;
+};
+
+static int decrement_timeout(struct timeval *timeout, struct timeval before, struct timeval after)
+{
+ (*timeout).tv_sec = (*timeout).tv_sec - (after.tv_sec - before.tv_sec);
+ (*timeout).tv_usec = (*timeout).tv_usec - (after.tv_usec - before.tv_usec);
+ while ( (*timeout).tv_usec < 0) {
+ (*timeout).tv_sec--;
+ (*timeout).tv_usec += 1000000;
+ }
+ if ( ((*timeout).tv_sec < 0) || (((*timeout).tv_sec == 0) && ((*timeout).tv_usec == 0)) ) return(1);
+ else return(0);
+}
+
+/* ares callback handler for ares_gethostbyname() */
+static void callback_handler(void *arg, int status, struct hostent *h) {
+ struct asyn_result *arp = (struct asyn_result *) arg;
+
+ switch (status) {
+ case ARES_SUCCESS:
+ if (h && h->h_addr_list[0]) {
+ arp->ent->h_addr_list =
+ (char **) malloc(2 * sizeof(char *));
+ if (arp->ent->h_addr_list == NULL) {
+ arp->err = NETDB_INTERNAL;
+ break;
+ }
+ arp->ent->h_addr_list[0] =
+ malloc(sizeof(struct in_addr));
+ if (arp->ent->h_addr_list[0] == NULL) {
+ free(arp->ent->h_addr_list);
+ arp->err = NETDB_INTERNAL;
+ break;
+ }
+ memcpy(arp->ent->h_addr_list[0], h->h_addr_list[0],
+ sizeof(struct in_addr));
+ arp->ent->h_addr_list[1] = NULL;
+ arp->err = NETDB_SUCCESS;
+ } else {
+ arp->err = NO_DATA;
+ }
+ break;
+ case ARES_EBADNAME:
+ case ARES_ENOTFOUND:
+ arp->err = HOST_NOT_FOUND;
+ break;
+ case ARES_ENOTIMP:
+ arp->err = NO_RECOVERY;
+ break;
+ case ARES_ENOMEM:
+ case ARES_EDESTRUCTION:
+ default:
+ arp->err = NETDB_INTERNAL;
+ break;
+ }
+}
+
+static void free_hostent(struct hostent *h){
+ int i;
+
+ if (h) {
+ if (h->h_name) free(h->h_name);
+ if (h->h_aliases) {
+ for (i=0; h->h_aliases[i]; i++) free(h->h_aliases[i]);
+ free(h->h_aliases);
+ }
+ if (h->h_addr_list) {
+ for (i=0; h->h_addr_list[i]; i++) free(h->h_addr_list[i]);
+ free(h->h_addr_list);
+ }
+ free(h);
+ }
+}
+
+static int asyn_gethostbyname(char **addrOut, char const *name, struct timeval *timeout) {
+ struct asyn_result ar;
+ ares_channel channel;
+ int nfds;
+ fd_set readers, writers;
+ struct timeval tv, *tvp;
+ struct timeval start_time,check_time;
+
+/* start timer */
+ gettimeofday(&start_time,0);
+
+/* ares init */
+ if ( ares_init(&channel) != ARES_SUCCESS ) return(NETDB_INTERNAL);
+ ar.ent = (struct hostent *) calloc (sizeof(*ar.ent),1);
+
+/* query DNS server asynchronously */
+ ares_gethostbyname(channel, name, AF_INET, callback_handler,
+ (void *) &ar);
+
+/* wait for result */
+ while (1) {
+ FD_ZERO(&readers);
+ FD_ZERO(&writers);
+ nfds = ares_fds(channel, &readers, &writers);
+ if (nfds == 0)
+ break;
+
+ gettimeofday(&check_time,0);
+ if (decrement_timeout(timeout, start_time, check_time)) {
+ ares_destroy(channel);
+ free_hostent(ar.ent);
+ return(TRY_AGAIN);
+ }
+ start_time = check_time;
+
+ tvp = ares_timeout(channel, timeout, &tv);
+
+ switch ( select(nfds, &readers, &writers, NULL, tvp) ) {
+ case -1: if (errno != EINTR) {
+ ares_destroy(channel);
+ free_hostent(ar.ent);
+ return NETDB_INTERNAL;
+ } else
+ continue;
+ case 0:
+ FD_ZERO(&readers);
+ FD_ZERO(&writers);
+ /* fallthrough */
+ default: ares_process(channel, &readers, &writers);
+ }
+ }
+
+ ares_destroy(channel);
+
+ if (ar.err == NETDB_SUCCESS) {
+ *addrOut = malloc(sizeof(struct in_addr));
+ memcpy(*addrOut,ar.ent->h_addr_list[0], sizeof(struct in_addr));
+ free_hostent(ar.ent);
+ }
+ return(ar.err);
+}
+
+static int
+do_connect(int *s, char const *hostname, int port, struct timeval *timeout)
+{
+ int sock;
+ struct timeval before,after,to;
+ struct sockaddr_in a;
+ int sock_err;
+ socklen_t err_len;
+ char *addr;
+ int h_errno;
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0) return EDG_WLL_GSS_ERROR_ERRNO;
+
+ if (timeout) {
+ int flags = fcntl(sock, F_GETFL, 0);
+ if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0)
+ return EDG_WLL_GSS_ERROR_ERRNO;
+ gettimeofday(&before,NULL);
+ }
+
+ if (timeout) {
+ switch (h_errno = asyn_gethostbyname(&addr, hostname, timeout)) {
+ case NETDB_SUCCESS:
+ memset(&a,0,sizeof a);
+ a.sin_family = AF_INET;
+ memcpy(&a.sin_addr.s_addr,addr,sizeof a.sin_addr.s_addr);
+ a.sin_port = htons(port);
+ free(addr);
+ break;
+ case TRY_AGAIN:
+ close(sock);
+ return EDG_WLL_GSS_ERROR_TIMEOUT;
+ case NETDB_INTERNAL:
+ /* fall through */
+ default:
+ close(sock);
+ /* h_errno may be thread safe with Linux pthread libs,
+ * but such an assumption is not portable
+ */
+ errno = h_errno;
+ return EDG_WLL_GSS_ERROR_HERRNO;
+ }
+ } else {
+ struct hostent *hp;
+
+ hp = gethostbyname(hostname);
+ if (hp == NULL) {
+ close(sock);
+ errno = h_errno;
+ return EDG_WLL_GSS_ERROR_HERRNO;
+ }
+
+ memset(&a,0,sizeof a);
+ a.sin_family = AF_INET;
+ memcpy(&a.sin_addr.s_addr, hp->h_addr_list[0], sizeof(a.sin_addr.s_addr));
+ a.sin_port = htons(port);
+ }
+
+ if (connect(sock,(struct sockaddr *) &a,sizeof a) < 0) {
+ if (timeout && errno == EINPROGRESS) {
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(sock,&fds);
+ memcpy(&to,timeout,sizeof to);
+ gettimeofday(&before,NULL);
+ switch (select(sock+1,NULL,&fds,NULL,&to)) {
+ case -1: close(sock);
+ return EDG_WLL_GSS_ERROR_ERRNO;
+ case 0: close(sock);
+ return EDG_WLL_GSS_ERROR_TIMEOUT;
+ }
+ gettimeofday(&after,NULL);
+ tv_sub(after,before);
+ tv_sub(*timeout,after);
+
+ err_len = sizeof sock_err;
+ if (getsockopt(sock,SOL_SOCKET,SO_ERROR,&sock_err,&err_len)) {
+ close(sock);
+ return EDG_WLL_GSS_ERROR_ERRNO;
+ }
+ if (sock_err) {
+ close(sock);
+ errno = sock_err;
+ return EDG_WLL_GSS_ERROR_ERRNO;
+ }
+ }
+ else {
+ close(sock);
+ return EDG_WLL_GSS_ERROR_ERRNO;
+ }
+ }
+
+ *s = sock;
+ return 0;
+}
+
+static int
+send_token(int sock, void *token, size_t token_length, struct timeval *to)
+{
+ size_t num_written = 0;
+ ssize_t count;
+ fd_set fds;
+ struct timeval timeout,before,after;
+ int ret;
+
+ if (to) {
+ memcpy(&timeout,to,sizeof(timeout));
+ gettimeofday(&before,NULL);
+ }
+
+
+ ret = 0;
+ while(num_written < token_length) {
+ FD_ZERO(&fds);
+ FD_SET(sock,&fds);
+ switch (select(sock+1, NULL, &fds, NULL, to ? &timeout : NULL)) {
+ case 0: ret = EDG_WLL_GSS_ERROR_TIMEOUT;
+ goto end;
+ break;
+ case -1: ret = EDG_WLL_GSS_ERROR_ERRNO;
+ goto end;
+ break;
+ }
+
+ count = write(sock, ((char *)token) + num_written,
+ token_length - num_written);
+ if(count < 0) {
+ if(errno == EINTR)
+ continue;
+ else {
+ ret = EDG_WLL_GSS_ERROR_ERRNO;
+ goto end;
+ }
+ }
+ num_written += count;
+ }
+
+end:
+ if (to) {
+ gettimeofday(&after,NULL);
+ tv_sub(after,before);
+ tv_sub(*to,after);
+ if (to->tv_sec < 0) {
+ to->tv_sec = 0;
+ to->tv_usec = 0;
+ }
+ }
+
+ return ret;
+}
+
+static int
+recv_token(int sock, void **token, size_t *token_length, struct timeval *to)
+{
+ ssize_t count;
+ char buf[4098];
+ char *t = NULL;
+ char *tmp;
+ size_t tl = 0;
+ fd_set fds;
+ struct timeval timeout,before,after;
+ int ret;
+
+ if (to) {
+ memcpy(&timeout,to,sizeof(timeout));
+ gettimeofday(&before,NULL);
+ }
+
+ ret = 0;
+ do {
+ FD_ZERO(&fds);
+ FD_SET(sock,&fds);
+ switch (select(sock+1, &fds, NULL, NULL, to ? &timeout : NULL)) {
+ case 0:
+ ret = EDG_WLL_GSS_ERROR_TIMEOUT;
+ goto end;
+ break;
+ case -1:
+ ret = EDG_WLL_GSS_ERROR_ERRNO;
+ goto end;
+ break;
+ }
+
+ count = read(sock, buf, sizeof(buf));
+ if (count < 0) {
+ if (errno == EINTR)
+ continue;
+ else {
+ ret = EDG_WLL_GSS_ERROR_ERRNO;
+ goto end;
+ }
+ }
+ if (count == 0 && tl == 0 && errno == 0)
+ return EDG_WLL_GSS_ERROR_EOF;
+ tmp=realloc(t, tl + count);
+ if (tmp == NULL) {
+ errno = ENOMEM;
+ return EDG_WLL_GSS_ERROR_ERRNO;
+ }
+ t = tmp;
+ memcpy(t + tl, buf, count);
+ tl += count;
+ } while (count == sizeof(buf));
+
+end:
+ if (to) {
+ gettimeofday(&after,NULL);
+ tv_sub(after,before);
+ tv_sub(*to,after);
+ if (to->tv_sec < 0) {
+ to->tv_sec = 0;
+ to->tv_usec = 0;
+ }
+ }
+
+ if (ret == 0) {
+ *token = t;
+ *token_length = tl;
+ } else
+ free(t);
+
+ return ret;
+}
+
+static int
+create_proxy(char *cert_file, char *key_file, char **proxy_file)
+{
+ char buf[4096];
+ int in, out;
+ char *name = NULL;
+ int ret, len;
+
+ *proxy_file = NULL;
+
+ asprintf(&name, "%s/%d.lb.XXXXXX", P_tmpdir, getpid());
+
+ out = mkstemp(name);
+ if (out < 0)
+ return EDG_WLL_GSS_ERROR_ERRNO;
+
+ in = open(cert_file, O_RDONLY);
+ if (in < 0) {
+ ret = EDG_WLL_GSS_ERROR_ERRNO;
+ goto end;
+ }
+ while ((ret = read(in, buf, sizeof(buf))) > 0) {
+ len = write(out, buf, ret);
+ if (len != ret) {
+ ret = -1;
+ break;
+ }
+ }
+ close(in);
+ if (ret < 0) {
+ ret = EDG_WLL_GSS_ERROR_ERRNO;
+ goto end;
+ }
+
+ in = open(key_file, O_RDONLY);
+ if (in < 0) {
+ ret = EDG_WLL_GSS_ERROR_ERRNO;
+ goto end;
+ }
+ while ((ret = read(in, buf, sizeof(buf))) > 0) {
+ len = write(out, buf, ret);
+ if (len != ret) {
+ ret = -1;
+ break;
+ }
+ }
+ close(in);
+ if (ret < 0) {
+ ret = EDG_WLL_GSS_ERROR_ERRNO;
+ goto end;
+ }
+
+ ret = 0;
+ *proxy_file = name;
+
+end:
+ close(out);
+ if (ret) {
+ unlink(name);
+ free(name);
+ }
+
+ return ret;
+}
+
+static int
+destroy_proxy(char *proxy_file)
+{
+ /* XXX we should erase the contents safely (i.e. overwrite with 0's) */
+ unlink(proxy_file);
+ return 0;
+}
+
+int
+edg_wll_gss_acquire_cred_gsi(char *cert_file, char *key_file, gss_cred_id_t *cred,
+ char **name, edg_wll_GssStatus* gss_code)
+{
+ OM_uint32 major_status = 0, minor_status, minor_status2;
+ gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL;
+ gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
+ gss_name_t gss_name = GSS_C_NO_NAME;
+ OM_uint32 lifetime;
+ char *proxy_file = NULL;
+ int ret;
+
+ if ((cert_file == NULL && key_file != NULL) ||
+ (cert_file != NULL && key_file == NULL))
+ return EINVAL;
+
+ if (cert_file == NULL) {
+ major_status = gss_acquire_cred(&minor_status, GSS_C_NO_NAME, 0,
+ GSS_C_NO_OID_SET, GSS_C_BOTH,
+ &gss_cred, NULL, NULL);
+ if (GSS_ERROR(major_status)) {
+ ret = EDG_WLL_GSS_ERROR_GSS;
+ goto end;
+ }
+ } else {
+ proxy_file = cert_file;
+ if (strcmp(cert_file, key_file) != 0 &&
+ (ret = create_proxy(cert_file, key_file, &proxy_file))) {
+ proxy_file = NULL;
+ goto end;
+ }
+
+ asprintf((char**)&buffer.value, "X509_USER_PROXY=%s", proxy_file);
+ if (buffer.value == NULL) {
+ errno = ENOMEM;
+ ret = EDG_WLL_GSS_ERROR_ERRNO;
+ goto end;
+ }
+ buffer.length = strlen(proxy_file);
+
+ major_status = gss_import_cred(&minor_status, &gss_cred, GSS_C_NO_OID, 1,
+ &buffer, 0, NULL);
+ free(buffer.value);
+ if (GSS_ERROR(major_status)) {
+ ret = EDG_WLL_GSS_ERROR_GSS;
+ goto end;
+ }
+ }
+
+ /* gss_import_cred() doesn't check validity of credential loaded, so let's
+ * verify it now */
+ major_status = gss_inquire_cred(&minor_status, gss_cred, &gss_name,
+ &lifetime, NULL, NULL);
+ if (GSS_ERROR(major_status)) {
+ ret = EDG_WLL_GSS_ERROR_GSS;
+ goto end;
+ }
+
+ /* Must cast to time_t since OM_uint32 is unsinged and hence we couldn't
+ * detect negative values. */
+ if ((time_t) lifetime <= 0) {
+ major_status = GSS_S_CREDENTIALS_EXPIRED;
+ minor_status = 0; /* XXX */
+ ret = EDG_WLL_GSS_ERROR_GSS;
+ goto end;
+ }
+
+ if (name) {
+ major_status = gss_display_name(&minor_status, gss_name, &buffer, NULL);
+ if (GSS_ERROR(major_status)) {
+ ret = EDG_WLL_GSS_ERROR_GSS;
+ goto end;
+ }
+ *name = buffer.value;
+ memset(&buffer, 0, sizeof(buffer));
+ }
+
+ *cred = gss_cred;
+ gss_cred = GSS_C_NO_CREDENTIAL;
+ ret = 0;
+
+end:
+ if (cert_file && key_file && proxy_file && strcmp(cert_file, key_file) != 0) {
+ destroy_proxy(proxy_file);
+ free(proxy_file);
+ }
+
+ if (gss_name != GSS_C_NO_NAME)
+ gss_release_name(&minor_status2, &gss_name);
+
+ if (gss_cred != GSS_C_NO_CREDENTIAL)
+ gss_release_cred(&minor_status2, &gss_cred);
+
+ if (GSS_ERROR(major_status)) {
+ if (gss_code) {
+ gss_code->major_status = major_status;
+ gss_code->minor_status = minor_status;
+ }
+ ret = EDG_WLL_GSS_ERROR_GSS;
+ }
+
+ return ret;
+}
+
+int
+edg_wll_gss_connect(gss_cred_id_t cred, char const *hostname, int port,
+ struct timeval *timeout, edg_wll_GssConnection *connection,
+ edg_wll_GssStatus* gss_code)
+{
+ int sock, ret;
+ OM_uint32 maj_stat, min_stat, min_stat2, req_flags;
+ int context_established = 0;
+ gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+ gss_name_t server = GSS_C_NO_NAME;
+ gss_ctx_id_t context = GSS_C_NO_CONTEXT;
+ char *servername = NULL;
+
+ maj_stat = min_stat = min_stat2 = req_flags = 0;
+
+ /* GSI specific */
+ req_flags = GSS_C_GLOBUS_SSL_COMPATIBLE;
+
+ ret = do_connect(&sock, hostname, port, timeout);
+ if (ret)
+ return ret;
+
+ /* XXX find appropriate fqdn */
+ asprintf (&servername, "host@%s", hostname);
+ if (servername == NULL) {
+ errno = ENOMEM;
+ ret = EDG_WLL_GSS_ERROR_ERRNO;
+ goto end;
+ }
+ input_token.value = servername;
+ input_token.length = strlen(servername) + 1;
+
+ maj_stat = gss_import_name(&min_stat, &input_token,
+ GSS_C_NT_HOSTBASED_SERVICE, &server);
+ if (GSS_ERROR(maj_stat)) {
+ ret = EDG_WLL_GSS_ERROR_GSS;
+ goto end;
+ }
+
+ free(servername);
+ memset(&input_token, 0, sizeof(input_token));
+
+ /* XXX if cred == GSS_C_NO_CREDENTIAL set the ANONYMOUS flag */
+
+ /* XXX prepsat na do {} while (maj_stat == CONT) a osetrit chyby*/
+ while (!context_established) {
+ /* XXX verify ret_flags match what was requested */
+ maj_stat = gss_init_sec_context(&min_stat, cred, &context,
+ GSS_C_NO_NAME, GSS_C_NO_OID,
+ req_flags | GSS_C_MUTUAL_FLAG,
+ 0, GSS_C_NO_CHANNEL_BINDINGS,
+ &input_token, NULL, &output_token,
+ NULL, NULL);
+ if (input_token.length > 0) {
+ free(input_token.value);
+ input_token.length = 0;
+ }
+
+ if (output_token.length != 0) {
+ ret = send_token(sock, output_token.value, output_token.length, timeout);
+ gss_release_buffer(&min_stat2, &output_token);
+ if (ret)
+ goto end;
+ }
+
+ if (GSS_ERROR(maj_stat)) {
+ if (context != GSS_C_NO_CONTEXT) {
+ /* XXX send closing token to the friend */
+ gss_delete_sec_context(&min_stat2, &context, GSS_C_NO_BUFFER);
+ context = GSS_C_NO_CONTEXT;
+ }
+ ret = EDG_WLL_GSS_ERROR_GSS;
+ goto end;
+ }
+
+ if(maj_stat & GSS_S_CONTINUE_NEEDED) {
+ ret = recv_token(sock, &input_token.value, &input_token.length, timeout);
+ if (ret)
+ goto end;
+ } else
+ context_established = 1;
+ }
+
+ /* XXX check ret_flags matches to what was requested */
+
+ memset(connection, 0, sizeof(*connection));
+ connection->sock = sock;
+ connection->context = context;
+ servername = NULL;
+ ret = 0;
+
+end:
+ if (ret == EDG_WLL_GSS_ERROR_GSS && gss_code) {
+ gss_code->major_status = maj_stat;
+ gss_code->minor_status = min_stat;
+ }
+ if (server != GSS_C_NO_NAME)
+ gss_release_name(&min_stat2, &server);
+ if (servername == NULL)
+ free(servername);
+ if (ret)
+ close(sock);
+
+ return ret;
+}
+
+int
+edg_wll_gss_accept(gss_cred_id_t cred, int sock, struct timeval *timeout,
+ edg_wll_GssConnection *connection, edg_wll_GssStatus* gss_code)
+{
+ OM_uint32 maj_stat, min_stat, min_stat2;
+ OM_uint32 ret_flags = 0;
+ gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+ gss_name_t client_name = GSS_C_NO_NAME;
+ gss_ctx_id_t context = GSS_C_NO_CONTEXT;
+ int ret;
+
+ maj_stat = min_stat = min_stat2 = 0;
+
+ /* GSI specific */
+ ret_flags = GSS_C_GLOBUS_SSL_COMPATIBLE;
+
+ do {
+ ret = recv_token(sock, &input_token.value, &input_token.length, timeout);
+ if (ret)
+ goto end;
+
+ maj_stat = gss_accept_sec_context(&min_stat, &context,
+ cred, &input_token,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &client_name, NULL, &output_token,
+ &ret_flags, NULL, NULL);
+ if (input_token.length > 0) {
+ free(input_token.value);
+ input_token.length = 0;
+ }
+
+ if (output_token.length) {
+ ret = send_token(sock, output_token.value, output_token.length, timeout);
+ gss_release_buffer(&min_stat2, &output_token);
+ if (ret)
+ goto end;
+ }
+ } while(maj_stat & GSS_S_CONTINUE_NEEDED);
+
+ if (GSS_ERROR(maj_stat)) {
+ if (context != GSS_C_NO_CONTEXT) {
+ /* XXX send closing token to the friend */
+ gss_delete_sec_context(&min_stat2, &context, GSS_C_NO_BUFFER);
+ context = GSS_C_NO_CONTEXT;
+ }
+ ret = EDG_WLL_GSS_ERROR_GSS;
+ goto end;
+ }
+
+ maj_stat = gss_display_name(&min_stat, client_name, &output_token, NULL);
+ if (GSS_ERROR(maj_stat)) {
+ /* XXX close context ??? */
+ ret = EDG_WLL_GSS_ERROR_GSS;
+ goto end;
+ }
+
+ memset(connection, 0, sizeof(*connection));
+ connection->sock = sock;
+ connection->context = context;
+ memset(&output_token, 0, sizeof(output_token.value));
+ ret = 0;
+
+end:
+ if (ret == EDG_WLL_GSS_ERROR_GSS && gss_code) {
+ gss_code->major_status = maj_stat;
+ gss_code->minor_status = min_stat;
+ }
+ if (client_name != GSS_C_NO_NAME)
+ gss_release_name(&min_stat2, &client_name);
+
+ return ret;
+}
+
+int
+edg_wll_gss_write(edg_wll_GssConnection *connection, const void *buf, size_t bufsize,
+ struct timeval *timeout, edg_wll_GssStatus* gss_code)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc input_token;
+ gss_buffer_desc output_token;
+ int ret;
+
+ input_token.value = (void*)buf;
+ input_token.length = bufsize;
+
+ maj_stat = gss_wrap (&min_stat, connection->context, 0, GSS_C_QOP_DEFAULT,
+ &input_token, NULL, &output_token);
+ if (GSS_ERROR(maj_stat)) {
+ if (gss_code) {
+ gss_code->minor_status = min_stat;
+ gss_code->major_status = maj_stat;
+ }
+
+ return EDG_WLL_GSS_ERROR_GSS;
+ }
+
+ ret = send_token(connection->sock, output_token.value, output_token.length,
+ timeout);
+ gss_release_buffer(&min_stat, &output_token);
+
+ return ret;
+}
+
+
+int
+edg_wll_gss_read(edg_wll_GssConnection *connection, void *buf, size_t bufsize,
+ struct timeval *timeout, edg_wll_GssStatus* gss_code)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc input_token;
+ gss_buffer_desc output_token;
+ int ret, i;
+
+ if (connection->bufsize > 0) {
+ size_t len;
+
+ len = (connection->bufsize < bufsize) ? connection->bufsize : bufsize;
+ memcpy(buf, connection->buffer, len);
+ connection->bufsize -= len;
+ if (connection->bufsize > 0) {
+ for (i = 0; i < sizeof(connection->buffer) - len; i++)
+ connection->buffer[i] = connection->buffer[i+len];
+ }
+
+ return len;
+ }
+
+ do {
+ ret = recv_token(connection->sock, &input_token.value, &input_token.length,
+ timeout);
+ if (ret)
+ /* XXX cleanup */
+ return ret;
+
+ maj_stat = gss_unwrap(&min_stat, connection->context, &input_token,
+ &output_token, NULL, NULL);
+ if (GSS_ERROR(maj_stat)) {
+ /* XXX cleanup */
+ return EDG_WLL_GSS_ERROR_GSS;
+ }
+ } while (maj_stat == 0 && output_token.length == 0 && output_token.value == NULL);
+
+ if (output_token.length > bufsize) {
+ if (output_token.length - bufsize > sizeof(connection->buffer))
+ return EINVAL;
+ connection->bufsize = output_token.length - bufsize;
+ memcpy(connection->buffer, output_token.value + bufsize, connection->bufsize);
+ output_token.length = bufsize;
+ }
+ memcpy(buf, output_token.value, output_token.length);
+
+ return output_token.length;
+}
+
+int
+edg_wll_gss_read_full(edg_wll_GssConnection *connection, void *buf,
+ size_t bufsize, struct timeval *timeout, size_t *total,
+ edg_wll_GssStatus* gss_code)
+{
+ int len,i;
+ *total = 0;
+
+ if (connection->bufsize > 0) {
+ size_t len;
+
+
+ len = (connection->bufsize < bufsize) ? connection->bufsize : bufsize;
+ memcpy(buf, connection->buffer, len);
+ connection->bufsize -= len;
+ if (connection->bufsize > 0) {
+ for (i = 0; i < sizeof(connection->buffer) - len; i++)
+ connection->buffer[i] = connection->buffer[i+len];
+ }
+ *total = len;
+ }
+
+ while (*total < bufsize) {
+ len = edg_wll_gss_read(connection, buf+*total, bufsize-*total,
+ timeout, gss_code);
+ if (len < 0) return len;
+ *total += len;
+ }
+
+ return 0;
+}
+
+int
+edg_wll_gss_write_full(edg_wll_GssConnection *connection, const void *buf,
+ size_t bufsize, struct timeval *timeout, size_t *total,
+ edg_wll_GssStatus* gss_code)
+{
+ return edg_wll_gss_write(connection, buf, bufsize, timeout, gss_code);
+}
+
+/* XXX: I'm afraid the contents of stuct stat is somewhat OS dependent */
+int
+edg_wll_gss_watch_creds(const char *proxy_file, time_t *proxy_mtime)
+{
+ struct stat pstat;
+ int reload = 0;
+
+ if (!proxy_file) return 0;
+ if (stat(proxy_file,&pstat)) return -1;
+
+ if (!*proxy_mtime) *proxy_mtime = pstat.st_mtime;
+
+ if (*proxy_mtime != pstat.st_mtime) {
+ *proxy_mtime = pstat.st_mtime;
+ reload = 1;
+ }
+
+ return reload;
+}
+
+int
+edg_wll_gss_close(edg_wll_GssConnection *con, struct timeval *timeout)
+{
+ OM_uint32 min_stat;
+
+ /* XXX if timeout is NULL use value of 120 secs */
+
+ if (con->context != GSS_C_NO_CONTEXT) {
+ gss_delete_sec_context(&min_stat, &con->context, GSS_C_NO_BUFFER);
+ /* XXX send the buffer (if any) to the peer. GSSAPI specs doesn't
+ * recommend sending it, though */
+
+ /* XXX can socket be open even if context == GSS_C_NO_CONTEXT) ? */
+ /* XXX ensure that edg_wll_GssConnection is created with sock set to -1 */
+ if (con->sock >= 0)
+ close(con->sock);
+ }
+ memset(con, 0, sizeof(*con));
+ con->context = GSS_C_NO_CONTEXT;
+ con->sock = -1;
+ return 0;
+}
+
+int
+edg_wll_gss_get_error(edg_wll_GssStatus *gss_err, const char *prefix, char **msg)
+{
+ OM_uint32 maj_stat, min_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc maj_status_string = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc min_status_string = GSS_C_EMPTY_BUFFER;
+ char *str = NULL;
+ char *line, *tmp;
+
+ str = strdup(prefix);
+ do {
+ maj_stat = gss_display_status(&min_stat, gss_err->major_status,
+ GSS_C_GSS_CODE, GSS_C_NO_OID,
+ &msg_ctx, &maj_status_string);
+ if (GSS_ERROR(maj_stat))
+ break;
+
+ maj_stat = gss_display_status(&min_stat, gss_err->minor_status,
+ GSS_C_MECH_CODE, GSS_C_NULL_OID,
+ &msg_ctx, &min_status_string);
+ if (GSS_ERROR(maj_stat)) {
+ gss_release_buffer(&min_stat, &maj_status_string);
+ break;
+ }
+
+ asprintf(&line, ": %s (%s)", (char *)maj_status_string.value,
+ (char *)min_status_string.value);
+ gss_release_buffer(&min_stat, &maj_status_string);
+ gss_release_buffer(&min_stat, &min_status_string);
+
+ tmp = realloc(str, strlen(str) + strlen(line) + 1);
+ if (tmp == NULL) {
+ /* abort() ? */
+ free(line);
+ free(str);
+ str = "WARNING: Not enough memory to produce error message";
+ break;
+ }
+ str = tmp;
+ strcat(str, line);
+ free(line);
+ } while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
+
+ *msg = str;
+ return 0;
+}
+
+int
+edg_wll_gss_oid_equal(const gss_OID a, const gss_OID b)
+{
+ if (a == b)
+ return 1;
+ else {
+ if (a == GSS_C_NO_OID || b == GSS_C_NO_OID || a->length != b->length)
+ return 0;
+ else
+ return (memcmp(a->elements, b->elements, a->length) == 0);
+ }
+}
+
+int
+edg_wll_gss_reject(int sock)
+{
+ /* XXX is it possible to cut & paste edg_wll_ssl_reject() ? */
+ return 0;
+}
--- /dev/null
+#include <iostream>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+
+#include "lb_gss.h"
+
+class GSSTest: public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(GSSTest);
+ CPPUNIT_TEST(echo);
+ CPPUNIT_TEST(errorTest);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void echo();
+ void errorTest();
+
+ void setUp();
+
+private:
+ gss_cred_id_t my_cred;
+ char * my_subject;
+ int sock, port;
+ struct timeval timeout;
+
+ void replier();
+
+};
+
+
+void GSSTest::replier() {
+ edg_wll_GssConnection conn;
+ edg_wll_GssStatus stat;
+ struct sockaddr_in a;
+ socklen_t alen = sizeof(a);
+ int s, len;
+ char buf[100];
+
+
+ if ( (s = accept(sock, (struct sockaddr *) &a, &alen)) < 0 ) exit(1);
+
+ if ( edg_wll_gss_accept(my_cred, s, &timeout, &conn, &stat) ) exit(1);
+
+ while ( (len = edg_wll_gss_read(&conn, buf, sizeof(buf), &timeout, &stat)) >= 0 ) {
+ if ( edg_wll_gss_write(&conn, buf, len, &timeout, &stat) ) exit(1);
+ }
+
+ exit(0);
+}
+
+
+void GSSTest::setUp(void) {
+ pid_t pid;
+ edg_wll_GssStatus stat;
+ struct sockaddr_in a;
+ socklen_t alen = sizeof(a);
+ char * cred_file = NULL;
+ char * key_file = NULL;
+
+ timeout.tv_sec = 10;
+ timeout.tv_usec = 0;
+
+ key_file = cred_file = getenv("X509_USER_PROXY");
+ CPPUNIT_ASSERT_MESSAGE("credential file", cred_file);
+
+ if (edg_wll_gss_acquire_cred_gsi(cred_file, key_file, &my_cred, &my_subject, &stat))
+ CPPUNIT_ASSERT_MESSAGE("gss_acquire_cred", 0);
+
+ sock = socket(PF_INET,SOCK_STREAM,0);
+ CPPUNIT_ASSERT_MESSAGE("socket()", sock >= 0);
+
+ a.sin_family = AF_INET;
+ a.sin_port = 0;
+ a.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind(sock,(struct sockaddr *) &a,sizeof(a))) {
+ CPPUNIT_ASSERT_MESSAGE("bind()", 0);
+ }
+
+ if (listen(sock,1)) {
+ CPPUNIT_ASSERT_MESSAGE("listen()", 0);
+ }
+
+ getsockname(sock,(struct sockaddr *) &a,&alen);
+ port = ntohs(a.sin_port);
+
+ if ( !(pid = fork()) ) replier();
+ else close(sock);
+}
+
+
+
+void GSSTest::echo()
+{
+ edg_wll_GssConnection conn;
+ edg_wll_GssStatus stat;
+ size_t total;
+ int err;
+ char buf[] = "f843fejwfanczn nc4*&686%$$&^(*)*#$@WSH";
+ char buf2[100];
+
+
+ err = edg_wll_gss_connect(my_cred, "localhost", port, &timeout, &conn, &stat);
+ CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_connect()", !err);
+
+ err = edg_wll_gss_write(&conn, buf, strlen(buf)+1, &timeout, &stat);
+ CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_write()", !err);
+
+ err = edg_wll_gss_read_full(&conn, buf2, strlen(buf)+1, &timeout, &total, &stat);
+ CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_read_full()", !err);
+
+ CPPUNIT_ASSERT(strlen(buf)+1 == total && !strcmp(buf,buf2) );
+
+ edg_wll_gss_close(&conn, &timeout);
+
+}
+
+
+void GSSTest::errorTest()
+{
+ edg_wll_GssConnection conn;
+ edg_wll_GssStatus stat;
+ int err;
+ char * msg = NULL;
+
+
+ err = edg_wll_gss_connect(my_cred, "xxx.porno.net", port, &timeout, &conn, &stat);
+ if (err) edg_wll_gss_get_error(&stat, "gss_connect()", &msg);
+ CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_get_error()", msg);
+}
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( GSSTest );
+
+int main (int ac,const char *av[])
+{
+ CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
+ CppUnit::TextUi::TestRunner runner;
+
+ runner.addTest(suite);
+ return runner.run() ? 0 : 1;
+}