From cf087fa24c8e5b398cde03e1fc69b1bc5f747757 Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Fri, 18 Feb 2011 11:52:01 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'branch_2_1'. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Cherrypick from master 2011-01-21 16:14:33 UTC Zdeněk Šustr 'The most recent version copied. Do not modify this instance (RW in ./org.glite.lb).': org.glite.lbjp-common.gsoap-plugin/Makefile org.glite.lbjp-common.gsoap-plugin/configure org.glite.lbjp-common.gsoap-plugin/project/ChangeLog org.glite.lbjp-common.gsoap-plugin/project/version.properties org.glite.lbjp-common.gss/Makefile org.glite.lbjp-common.gss/configure org.glite.lbjp-common.gss/interface/glite_gss.h org.glite.lbjp-common.gss/project/ChangeLog org.glite.lbjp-common.gss/project/version.properties Cherrypick from master 2011-02-18 11:52:00 UTC Daniel Kouřil 'make sure credentials are loaded': org.glite.lbjp-common.gss/src/glite_gss.c --- org.glite.lbjp-common.gsoap-plugin/Makefile | 338 +++++ org.glite.lbjp-common.gsoap-plugin/configure | 1069 ++++++++++++++ .../project/ChangeLog | 52 + .../project/version.properties | 3 + org.glite.lbjp-common.gss/Makefile | 170 +++ org.glite.lbjp-common.gss/configure | 1069 ++++++++++++++ org.glite.lbjp-common.gss/interface/glite_gss.h | 188 +++ org.glite.lbjp-common.gss/project/ChangeLog | 47 + .../project/version.properties | 3 + org.glite.lbjp-common.gss/src/glite_gss.c | 1553 ++++++++++++++++++++ 10 files changed, 4492 insertions(+) create mode 100644 org.glite.lbjp-common.gsoap-plugin/Makefile create mode 100755 org.glite.lbjp-common.gsoap-plugin/configure create mode 100644 org.glite.lbjp-common.gsoap-plugin/project/ChangeLog create mode 100644 org.glite.lbjp-common.gsoap-plugin/project/version.properties create mode 100644 org.glite.lbjp-common.gss/Makefile create mode 100755 org.glite.lbjp-common.gss/configure create mode 100644 org.glite.lbjp-common.gss/interface/glite_gss.h create mode 100644 org.glite.lbjp-common.gss/project/ChangeLog create mode 100644 org.glite.lbjp-common.gss/project/version.properties create mode 100644 org.glite.lbjp-common.gss/src/glite_gss.c diff --git a/org.glite.lbjp-common.gsoap-plugin/Makefile b/org.glite.lbjp-common.gsoap-plugin/Makefile new file mode 100644 index 0000000..49dd394 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/Makefile @@ -0,0 +1,338 @@ +# defaults +top_srcdir=.. +builddir=build +top_builddir=${top_srcdir}/${builddir} +stagedir=. +globalprefix=glite +package=gsoap-plugin +version=1.0.0 +PREFIX=/opt/glite + +glite_location=/opt/glite +gsoap_prefix=/opt/gsoap + +CC=gcc + +gsoap_versions_noflavours?=2.6.2 2.7.0f 2.7.6b 2.7.6d 2.7.9d 2.7.9b +gsoap_versions_flavours?=2.7.10 + +-include Makefile.inc +-include ../Makefile.inc +-include ../project/version.properties +-include ../../project/version.properties + +version=${module.version} +gsoap_versions_flavours:=${shell if ! echo ${gsoap_versions_flavours} | grep '\<${gsoap_default_version}\>' >/dev/null; then echo "${gsoap_default_version} "; else echo ''; fi} ${gsoap_versions_flavours} + +GSPLUGIN_DEBUG?=no +GSPLUGIN_VERSION_CHECKING?=yes +CC=gcc + +# In order to use libtool versioning correcty, we must have: +# +# current = major + minor + offset +# revision = patch +# age = minor +# +# where offset is a sum of maximal released minor's of all previous major's +# + +# counted minors: 1.5 +# TODO: bump offset to 5 on next major change +offset=-1 +version_info:=-version-info ${shell \ + perl -e '$$,=":"; @F=split "\\.","${version}"; print $$F[0]+$$F[1]+${offset},$$F[2],$$F[1]' } + +ext_repository:=${shell if [ -d "${repository}/externals" ]; then \ + echo "${repository}/externals"; \ + else echo "${repository}"; \ + fi} + +gsoap_version=${gsoap_default_version} +gsoap_prefix?=${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform} +ifdef lang +langflavour:=_${lang} +langsuffix:=.${lang} +endif + +VPATH=${top_srcdir}/src:${top_srcdir}/test:${top_srcdir}/examples + +default: all + +DEBUG:=-g -O0 -W -Wall -Wno-unused-parameter +# not for globus and gsoap: -Werror +ifeq ($(GSPLUGIN_DEBUG),yes) + DEBUG:=${DEBUG} -DGSPLUGIN_DEBUG=1 +endif +# gsoap logs: -DDEBUG +ifeq ($(GSOAP_DEBUG),yes) + DEBUG:=${DEBUG} -DDEBUG=1 +endif + +#ifeq ($(GSPLUGIN_VERSION_CHECKING),yes) +# DEBUG:=${DEBUG} -DCHECK_GSOAP_VERSION +#endif + +CFLAGS:= ${CFLAGS} ${DEBUG} \ + -DVERSION=\"${version}\" \ + -DWITH_NONAMESPACES \ + -I. -I${top_srcdir}/interface \ + -I${stagedir}/include \ + ${COVERAGE_FLAGS} -D_GNU_SOURCE -DDATAGRID_EXTENSION -DWITH_IPV6 + +LDFLAGS:=${LDFLAGS} ${COVERAGE_FLAGS} + +COMPILE:=libtool --mode=compile ${CC} ${CFLAGS} +COMPILEXX:=libtool --mode=compile ${CXX} ${CFLAGS} +LINK:=libtool --mode=link ${CC} -rpath ${stagedir}/${libdir} ${LDFLAGS} +LINKXX:=libtool --mode=link ${CXX} -rpath ${stagedir}/${libdir} ${LDFLAGS} +INSTALL:=libtool --mode=install install +LINK_lang:=PATH=${top_srcdir}/project/libtoolhack:${PATH} libtool --mode=link ${CXX} -rpath ${stagedir}/${libdir} ${LDFLAGS} +ifeq (${lang},c) +LINK_lang:=${LINK} +endif +ifeq (${lang},cxx) +LINK_lang:=${LINKXX} +endif + +gsoaplibdir=$(shell if test -d "${gsoap_prefix}/${libdir}"; then echo "${gsoap_prefix}/${libdir}"; else echo "${gsoap_prefix}/lib"; fi) +GSOAP_LIBS?=-L${gsoaplibdir} -lgsoap + +EX_NOTHRLIBS:=-L${stagedir}/${libdir} -lglite_security_gss_${nothrflavour} +EX_THRLIBS:=-L${stagedir}/${libdir} -lglite_security_gss_${thrflavour} +EX_LIBS:=-L${stagedir}/${libdir} -lglite_security_gss +HDRS:=glite_gsplugin.h glite_gscompat.h glite_gsplugin-int.h +EXAMPLES:=wscalc_clt_ex wscalc_srv_ex wscalc_srv_ex2 +TESTS:=test_cxx + +NOTHRSTATICLIB:=libglite_security_gsoap_plugin_${nothrflavour}${langflavour}.a +THRSTATICLIB:=libglite_security_gsoap_plugin_${thrflavour}${langflavour}.a +STATICLIB:=libglite_security_gsoap_plugin${langflavour}.a +NOTHRLTLIB:=libglite_security_gsoap_plugin_${nothrflavour}${langflavour}.la +THRLTLIB:=libglite_security_gsoap_plugin_${thrflavour}${langflavour}.la +LTLIB:=libglite_security_gsoap_plugin${langflavour}.la + +OBJS:=${GSS_OBJS} glite_gsplugin${langsuffix}.o +LOBJS:=${OBJS:.o=.lo} +THROBJS:=${OBJS:.o=.thr.o} +THRLOBJS:=${OBJS:.o=.thr.lo} + +dotless_ver:=${shell echo ${gsoap_version} | tr -d '.'} +NOTHRSTATICLIB_S:=libglite_security_gsoap_plugin_${dotless_ver}_${nothrflavour}${langflavour}.a +THRSTATICLIB_S:=libglite_security_gsoap_plugin_${dotless_ver}_${thrflavour}${langflavour}.a +STATICLIB_S:=libglite_security_gsoap_plugin_${dotless_ver}${langflavour}.a +NOTHRLTLIB_S:=libglite_security_gsoap_plugin_${dotless_ver}_${nothrflavour}${langflavour}.la +THRLTLIB_S:=libglite_security_gsoap_plugin_${dotless_ver}_${thrflavour}${langflavour}.la +LTLIB_S:=libglite_security_gsoap_plugin_${dotless_ver}${langflavour}.la + +ifeq (${thrflavour},) +lib_LTLIBRARIES:=${STATICLIB} ${LTLIB} +lib_LTLIBRARIES_S:=${LTLIB_S} +LTLIB_TEST_S:=libglite_security_gsoap_plugin_${dotless_ver}_cxx.la +default_ltlib_s:=${LTLIB_S} +else +lib_LTLIBRARIES:=${NOTHRSTATICLIB} ${NOTHRLTLIB} ${THRSTATICLIB} ${THRLTLIB} +lib_LTLIBRARIES_S:=${NOTHRLTLIB_S} ${THRLTLIB_S} +LTLIB_TEST_S:=libglite_security_gsoap_plugin_${dotless_ver}_${nothrflavour}_cxx.la +default_ltlib_s:=${NOTHRLTLIB_S} +endif + +ifeq (${gsoap_version},${gsoap_default_version}) +OBJS_S:=glite_gsplugin${langsuffix}.o +GSOAP_DEFAULT_LIBS:=${GSOAP_LIBS} +else +OBJS_S:=glite_gsplugin${langsuffix}.o stdsoap2${langsuffix}.o +GSOAP_DEFAULT_LIBS:= +endif +LOBJS_S:=${OBJS_S:.o=.lo} +THROBJS_S:=${OBJS_S:.o=.thr.o} +THRLOBJS_S:=${OBJS_S:.o=.thr.lo} + +ifeq (${thrflavour},) +${STATICLIB}: ${OBJS} + ar crv $@ ${OBJS} + ranlib $@ + +${LTLIB}: ${OBJS} + ${LINK_lang} ${version_info} -o $@ ${LOBJS} ${EX_LIBS} + +${STATICLIB_S}: ${OBJS_S} + ar crv $@ ${OBJS_S} + ranlib $@ + +${LTLIB_S}: ${OBJS_S} + ${LINK_lang} ${version_info} -o $@ ${LOBJS_S} ${EX_LIBS} ${GSOAP_DEFAULT_LIBS} +else +${NOTHRSTATICLIB}: ${OBJS} + ar crv $@ ${OBJS} + ranlib $@ + +${THRSTATICLIB}: ${THROBJS} + ar crv $@ ${THROBJS} + ranlib $@ + +${NOTHRLTLIB}: ${OBJS} + ${LINK_lang} ${version_info} -o $@ ${LOBJS} ${EX_NOTHRLIBS} + +${THRLTLIB}: ${THROBJS} + ${LINK_lang} ${version_info} -o $@ ${THRLOBJS} ${EX_THRLIBS} + +${NOTHRSTATICLIB_S}: ${OBJS_S} + ar crv $@ ${OBJS_S} + ranlib $@ + +${THRSTATICLIB_S}: ${THROBJS_S} + ar crv $@ ${THROBJS_S} + ranlib $@ + +${NOTHRLTLIB_S}: ${OBJS_S} + ${LINK_lang} ${version_info} -o $@ ${LOBJS_S} ${EX_NOTHRLIBS} ${GSOAP_DEFAULT_LIBS} + +${THRLTLIB_S}: ${THROBJS_S} + ${LINK_lang} ${version_info} -o $@ ${THRLOBJS_S} ${EX_THRLIBS} +endif + +all compile: \ + ${lib_LTLIBRARIES} \ + all-libs-with-soap examples + +check: check.cxx + +# C/C++ compatibility test +# (C flavour, gsoap 2.7.10 ==> C++ test fails) +check.cxx: + ${MAKE} lang=cxx -f ${top_srcdir}/Makefile ${LTLIB_TEST_S} test_cxx + LD_LIBRARY_PATH=${cares_prefix}/${libdir}:${LD_LIBRARY_PATH} ./test_cxx + +examples: ${EXAMPLES} + +all-libs-with-soap: + for v in ${gsoap_versions_noflavours}; do \ + dir=`echo $$v | tr -d .`; \ + mkdir $$dir; \ + ${MAKE} -C $$dir -f ../Makefile gsoap_version=$$v top_srcdir=../.. lang= libs-with-soap || exit $?; \ + done + for v in ${gsoap_versions_flavours}; do \ + dir=`echo $$v | tr -d .`; \ + mkdir $$dir; \ + ${MAKE} -C $$dir -f ../Makefile gsoap_version=$$v top_srcdir=../.. lang=c libs-with-soap || exit $?; \ + ${MAKE} -C $$dir -f ../Makefile gsoap_version=$$v top_srcdir=../.. lang=cxx libs-with-soap || exit $?; \ + done + +libs-with-soap: ${lib_LTLIBRARIES_S} + +gsoap_srcname=gsoap-`echo ${gsoap_version} | cut -d. -f1,2` + +link-gsoap: + if [ ${gsoap_version} = ${gsoap_default_version} ]; then \ + ln -sf ${gsoap_prefix}/include/stdsoap2.h stdsoap2.h; \ + elif [ -f ${top_srcdir}/src/stdsoap2_${gsoap_version}.c ]; then \ + ln -sf ${top_srcdir}/src/stdsoap2_${gsoap_version}.c stdsoap2.c; \ + ln -sf ${top_srcdir}/src/stdsoap2_${gsoap_version}.h stdsoap2.h; \ + elif [ -f ${ext_repository}/${gsoap_name}/${gsoap_version}/src/stdsoap2.c ]; then \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/src/stdsoap2.[ch] .; \ + elif [ -f ${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform}/stdsoap2.c ]; then \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform}/stdsoap2.[ch] .; \ + elif [ -f ${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform}/src/stdsoap2.c ]; then \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform}/src/stdsoap2.c .; \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform}/include/stdsoap2.h .; \ + elif [ -f ${ext_repository}/${gsoap_name}/${gsoap_version}/src/stdsoap2.c ]; then \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/src/stdsoap2.[ch] .; \ + elif [ -f ${ext_repository}/${gsoap_name}/${gsoap_version}/src/${gsoap_srcname}/soapcpp2/stdsoap2.c ]; then \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/src/${gsoap_srcname}/soapcpp2/stdsoap2.[ch] .; \ + else false ; \ + fi + +stdsoap2.c stdsoap2.h: link-gsoap + +GSOAP_FPREFIX:= GSOAP_ + +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 +WSCALC_SRV2_OBJS = wscalc_srv_ex2.o ${GSOAP_FPREFIX}C.o ${GSOAP_FPREFIX}Server.o + +wscalc_clt_ex.o wscalc_srv_ex.o wscalc_srv_ex2.o: ${GSOAP_FPREFIX}H.h + +wscalc_clt_ex: ${WSCALC_CLT_OBJS} ${default_ltlib_s} + ${LINK_lang} -o $@ ${WSCALC_CLT_OBJS} ${default_ltlib_s} ${GSOAP_DEFAULT_LIBS} + +wscalc_srv_ex: ${WSCALC_SRV_OBJS} ${default_ltlib_s} + ${LINK_lang} -o $@ ${WSCALC_SRV_OBJS} ${default_ltlib_s} ${GSOAP_DEFAULT_LIBS} + +wscalc_srv_ex2: ${WSCALC_SRV2_OBJS} ${default_ltlib_s} + ${LINK_lang} -o $@ ${WSCALC_SRV2_OBJS} ${default_ltlib_s} ${GSOAP_DEFAULT_LIBS} + +test_cxx: test_gsplugin_cxx.o ${GSOAP_FPREFIX}C.cxx.o + ${LINKXX} -o $@ $+ ${LTLIB_TEST_S} + +soapcpp:=${shell if [ -x ${gsoap_prefix}/bin/soapcpp2 ]; then \ + echo ${gsoap_prefix}/bin/soapcpp2; \ + else echo ${gsoap_prefix}/soapcpp2; \ + fi} + +${GSOAP_FPREFIX}H.h ${GSOAP_FPREFIX}C.c ${GSOAP_FPREFIX}Server.c ${GSOAP_FPREFIX}Client.c ${GSOAP_FPREFIX}ServerLib.c ${GSOAP_FPREFIX}ClientLib.c: calc.h.S + ${soapcpp} -c -p ${GSOAP_FPREFIX} ${top_srcdir}/examples/calc.h.S + +wscalc_clt_ex.o: wscalc_clt_ex.c + ${CC} -c ${CFLAGS} -o $@ $< + +doc: + +stage: + $(MAKE) install PREFIX=${stagedir} DOSTAGE=yes + +install: + -mkdir -p ${PREFIX}/${libdir} + -mkdir -p ${PREFIX}/include/glite/security + -mkdir -p ${PREFIX}/share/doc/${package}-${version} + -mkdir -p ${PREFIX}/include/glite/security/ + ${INSTALL} -m 644 ${top_srcdir}/LICENSE ${PREFIX}/share/doc/${package}-${version} + cd ${top_srcdir}/interface && ${INSTALL} -m 644 ${HDRS} ${PREFIX}/include/glite/security/ + for v in ${gsoap_versions_noflavours}; do \ + ${MAKE} -C `echo $$v | tr -d .` -f ../Makefile install-soaplib gsoap_version=$$v lang= PREFIX=${PREFIX} top_srcdir=${top_srcdir}/.. || exit $?; \ + done + for v in ${gsoap_versions_flavours}; do \ + ${MAKE} -C `echo $$v | tr -d .` -f ../Makefile install-soaplib gsoap_version=$$v lang=c PREFIX=${PREFIX} top_srcdir=${top_srcdir}/.. || exit $?; \ + ${MAKE} -C `echo $$v | tr -d .` -f ../Makefile install-soaplib gsoap_version=$$v lang=cxx PREFIX=${PREFIX} top_srcdir=${top_srcdir}/.. || exit $?; \ + done + +install-soaplib: + ${INSTALL} -m 755 ${lib_LTLIBRARIES_S} ${PREFIX}/${libdir} + +clean: + rm -rvf ${lib_LTLIBRARIES} + rm -rvf ${lib_LTLIBRARIES_S} + rm -rvf ${LTLIB_TEST_S} + rm -rvf *.c *.h *.xml *.nsmap *.o *.lo .libs ${EXAMPLES} ${TESTS} + rm -rvf CalcService.wsdl wscalc.xsd + rm -rvf log.xml project/ rpmbuild/ RPMS/ tgz/ debian/ + for v in ${gsoap_versions_noflavours} ${gsoap_versions_flavours}; do \ + rm -rvf `echo $$v | tr -d .`; \ + done + +%.c.o: %.c + ${COMPILE} -o $@ -c $< + +%.cxx.o: %.c + ${COMPILEXX} -o $@ -c $< + +%.o: %.c + ${COMPILE} -o $@ -c $< + +%.c.thr.o: %.c + ${COMPILE} -o $@ -c $< + +%.cxx.thr.o: %.c + ${COMPILEXX} -o $@ -c $< + +%.thr.o: %.c + ${COMPILE} -o $@ -c $< + +test_gsplugin_cxx.o: %.o: %.cpp stdsoap2.h + ${COMPILEXX} -c ${GLOBUS_INC} $< + +glite_gsplugin${langsuffix}.o glite_gsplugin${langsuffix}.thr.o: soap_version.h + +soap_version.h: stdsoap2.h + head stdsoap2.h | \ + perl -ne '/^\s*stdsoap2.h\s+([0-9])\.([0-9])\.(\S+)\s.*/ && printf "#define GSOAP_VERSION %d%02d%02d\n#define GSOAP_MIN_VERSION \"$$3\"\n#ident \"soap_version.h $$1.$$2.$$3\"\n",$$1,$$2,$$3' >$@ diff --git a/org.glite.lbjp-common.gsoap-plugin/configure b/org.glite.lbjp-common.gsoap-plugin/configure new file mode 100755 index 0000000..598d569 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/configure @@ -0,0 +1,1069 @@ +#!/usr/bin/perl + +# WARNING: Don't edit this file unless it is the master copy in org.glite.lb +# +# For the purpose of standalone builds of lb/jobid/lbjp-common components +# it is copied on tagging + +# $Header$ +# +# Copyright (c) Members of the EGEE Collaboration. 2004-2010. +# See http://www.eu-egee.org/partners/ for details on the copyright holders. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +use Getopt::Long; + +my $pwd = `pwd`; chomp $pwd; +my $prefix = $pwd.'/stage'; +my $stagedir; +my $staged; +my $module; +my $thrflavour = 'gcc64dbgpthr'; +my $nothrflavour = 'gcc64dbg'; +my $mode = 'build'; +my $help = 0; +my $listmodules; +my $version; +my $branch; +my $output; +my $lb_tag = ''; +my $lbjp_tag = ''; +my $jp_tag = ''; +my $sec_tag = ''; +my $jobid_tag = ''; +my $libdir = getlibdir(); + +my @nodes = qw/client server logger utils client-java doc ws-test db jpprimary jpindex jpclient harvester/; +my %enable_nodes; +my %disable_nodes; + +my %externs = ( + cares => { + prefix => '/opt/c-ares', + pkg => 'libcares' + }, + classads => { + prefix=> '/opt/classads', + pkg => 'classads' + }, + cppunit => { + prefix=> '/usr', + pkg => 'cppunit' + }, + expat => { + prefix=> '/usr', + pkg => 'expat' + }, + globus => { + prefix=> '/opt/globus', + pkg => 'globus-gssapi-gsi' + }, + myproxy => { + prefix=> '/opt/myproxy', + pkg => 'myproxy' + }, + gsoap => { + prefix=> '/usr', + pkg => 'gsoap' + }, + mysql => { + prefix=> '/usr' + }, + 'mysql-devel' => { + prefix=> '' + }, + 'mysql-server' => { + prefix => '' + }, + voms => { + prefix => '/opt/glite', + pkg => 'voms-1.0' + }, + gridsite => { + prefix => '/opt/glite' + }, + lcas => { + prefix => '/opt/glite' + }, + trustmanager => { + prefix => '/opt/glite' + }, + utiljava => { + prefix=> '/opt/glite' + }, + ant => { + prefix=> '/usr' + }, + jdk => { + prefix=> '/usr' + }, + libtar => { + prefix=> '/usr' + }, + axis => { + prefix=> '/usr' + }, + log4c => { + prefix=> '/usr' + }, + postgresql => { + prefix=> '/usr' + } +); + +my %jar = ( + 'jakarta-commons-codec' => '/usr/share/java/commons-codec.jar', + 'jakarta-commons-lang' => '/usr/share/java/commons-lang.jar', +); + + +my %glite_prefix; +my %need_externs; +my %need_externs_type; +my %need_jars; +my %extrafull; +my %extranodmod; +my %deps; +my %deps_type; +my %buildroot; + +my %lbmodules = ( + 'lb' => [ qw/client client-java common doc logger server state-machine types utils ws-interface ws-test harvester yaim glite-LB/], + 'security' => [qw/gss gsoap-plugin/], + 'lbjp-common' => [qw/db log maildir server-bones trio jp-interface gss gsoap-plugin/], + 'jobid' => [qw/api-c api-cpp api-java/], + 'jp' => [ qw/client doc index primary server-common ws-interface/ ], + 'gridsite' => [ qw/apache shared commands core/ ], + 'px' => [ qw/proxyrenewal glite-PX myproxy-yaim myproxy-config/ ], + ); + + +my @opts = ( + 'prefix=s' => \$prefix, + 'staged=s' => \$staged, + 'module=s' => \$module, + 'thrflavour:s' => \$thrflavour, + 'nothrflavour:s' => \$nothrflavour, + 'mode=s' => \$mode, + 'listmodules=s' => \$listmodules, + 'version=s' => \$version, + 'branch=s' => \$branch, + 'output=s' => \$output, + 'stage=s' => \$stagedir, + 'lb-tag=s' => \$lb_tag, + 'lbjp-common-tag=s' => \$lbjp_tag, + 'jp-tag=s' => \$jp_tag, + 'security-tag=s' => \$sec_tag, + 'jobid-tag=s' => \$jobid_tag, + 'help' => \$help, + 'libdir=s' => \$libdir, + 'emi' => \$emi, +); + +for (@nodes) { + $enable_nodes{$_} = 0; + $disable_nodes{$_} = 0; + + push @opts,"disable-$_",\$disable_nodes{$_}; + push @opts,"enable-$_",\$enable_nodes{$_}; +} + +push @opts,"with-$_=s",\$externs{$_}{withprefix} for keys %externs; +push @opts,"with-$_=s",\$jar{$_} for keys %jar; + +my @keeparg = @ARGV; + +GetOptions @opts or die "Errors parsing command line\n"; + +$externs{'mysql-devel'}{prefix}=$externs{mysql}{prefix} if $externs{'mysql-devel'}{prefix} eq ''; +$externs{'mysql-server'}{prefix}=$externs{mysql}{prefix} if $externs{'mysql-server'}{prefix} eq ''; + +if ($help) { usage(); exit 0; } + +if ($listmodules) { + my @m = map "org.glite.$listmodules.$_",@{$lbmodules{$listmodules}}; + print "@m\n"; + exit 0; +} + +warn "$0: --version, --branch and --output make sense only in --mode=etics\n" + if ($version || $output || $branch) && $mode ne 'etics'; + +my $en; +for (keys %enable_nodes) { $en = 1 if $enable_nodes{$_}; } + +my $dis; +for (keys %disable_nodes) { $dis = 1 if $disable_nodes{$_}; } + +die "--enable-* and --disable-* are mutually exclusive\n" + if $en && $dis; + +die "--module cannot be used with --enable-* or --disable-*\n" + if $module && ($en || $dis); + +die "$module: unknown module\n" if $module && ! grep $module,@{$lbmodules{lb}},@{$lbmodules{security}},{$lbmodules{jp}}; + +if ($mode eq 'build') { for my $ext (keys %externs) { + if (defined $externs{$ext}{withprefix}) { $externs{$ext}{prefix} = $externs{$ext}{withprefix}; } + elsif (defined $externs{$ext}{pkg}) { + my ($prefix, $flag); + my $pkg = $externs{$ext}{pkg}; + my $flagname = uc $externs{$ext}{pkg}; + $flagname =~ s/-[0-9\.]*$//; + $flagname =~ s/-/_/g; + + print "Checking $pkg ... "; + `pkg-config "$pkg" --exists >/dev/null`; + if ($? == 0) { + $externs{$ext}{prefix}=`pkg-config $pkg --variable=prefix`; + chomp $externs{$ext}{prefix}; + print "$externs{$ext}{prefix}\n"; + + $flag=`pkg-config $pkg --cflags`; + $externs{$ext}{flags} .= "${flagname}_CFLAGS=$flag" if ($flag); + $flag=`pkg-config $pkg --libs`; + $externs{$ext}{flags} .= "${flagname}_LIBS=$flag" if ($flag); + } else { + print "(using default)\n"; + } + } +} } + +if ($dis) { + for (@nodes) { + $enable_nodes{$_} = 1 unless $disable_nodes{$_}; + } +} + +if (!$en && !$dis) { $enable_nodes{$_} = 1 for (@nodes) } ; + +for (keys %enable_nodes) { delete $enable_nodes{$_} unless $enable_nodes{$_}; } + +$stagedir = $prefix unless $stagedir; + +if ($mode eq 'build') { + print "Writing config.status\n"; + open CONF,">config.status" or die "config.status: $!\n"; + print CONF "PKG_CONFIG_PATH=$ENV{PKG_CONFIG_PATH} $0 @keeparg\n"; + close CONF; +} + + +my @modules; +my %aux; + +if ($module) { +# push @modules,split(/[,.]+/,$module); + push @modules,$module; +} +else { + @modules = map(($extranodmod{$_} ? $extranodmod{$_} : 'lb.'.$_),(keys %enable_nodes)); + + my $n; + + do { + local $"="\n"; + $n = $#modules; + push @modules,(map @{$deps{$_}},@modules); + + undef %aux; @aux{@modules} = (1) x ($#modules+1); + @modules = keys %aux; + } while ($#modules > $n); +} + +@aux{@modules} = (1) x ($#modules+1); +delete $aux{$_} for (split /,/,$staged); +@modules = keys %aux; + +mode_build() if $mode eq 'build'; +mode_checkout() if $mode eq 'checkout'; +mode_etics($module) if $mode eq 'etics'; + +sub mode_build { + print "\nBuilding modules: @modules\n"; + + my @ext = map @{$need_externs{$_}},@modules; + my @myjars = map @{$need_jars{$_}},@modules; + undef %aux; @aux{@ext} = 1; + @ext = keys %aux; + undef %aux; @aux{@myjars} = (1) x ($#myjars+1); + @myjars = keys %aux; + + print "\nRequired externals:\n"; + print "\t$_: $externs{$_}{prefix}\n" for @ext; + print "\t$_: $jar{$_}\n" for @myjars; + for (@ext) { if (defined($externs{$_}{flags})) { print "$externs{$_}{flags}"; } }; + print "\nThis is a poor-man configure, it's up to you to have sources and externals there\n\n"; + + mkinc($_) for @modules; + + print "Creating Makefile\n"; + + open MAK,">Makefile" or die "Makefile: $!\n"; + + print MAK "all: @modules\n\nclean:\n"; + + for (@modules) { + my $full = full($_); + print MAK "\tcd $full/$buildroot{$_} && \${MAKE} clean\n" + } + + print MAK "\ndistclean:\n"; + + for (@modules) { + my $full = full($_); + print MAK $buildroot{$_} eq '' ? + "\tcd $full && \${MAKE} distclean\n" : + "\trm -rf $full/$buildroot{$_}\n" + } + + print MAK "\n"; + + for (@modules) { + my %ldeps; undef %ldeps; + @ldeps{@{$deps{$_}}} = 1; + for my $x (split /,/,$staged) { delete $ldeps{$x}; } + my @dnames = $module ? () : keys %ldeps; + + my $full = full($_); + my $build = $buildroot{$_}; + + print MAK "$_: @dnames\n\tcd $full/$build && \${MAKE} && \${MAKE} install\n\n"; + } + + close MAK; +} + +sub mode_checkout() { + for (@modules) { + my $module = $_; + my $tag = ""; + if ($lb_tag){ + for (@{$lbmodules{lb}}){ + if ("lb.".$_ eq $module){ + $tag = '-r '.$lb_tag; + } + } + } + if ($lbjp_tag){ + for (@{$lbmodules{'lbjp-common'}}){ + if ("lbjp-common.".$_ eq $module){ + $tag = '-r '.$lbjp_tag; + } + } + } + if ($jp_tag){ + for (@{$lbmodules{'jp'}}){ + if ("jp.".$_ eq $module){ + $tag = '-r '.$jp_tag; + } + } + } + if ($sec_tag){ + for (@{$lbmodules{security}}){ + if ("security.".$_ eq $module){ + $tag = '-r '.$sec_tag; + } + } + } + if ($jobid_tag){ + for (@{$lbmodules{jobid}}){ + if ("jobid.".$_ eq $module){ + $tag = '-r '.$jobid_tag; + } + } + } + #if (grep {"lb.".$_ eq $module} @{$lbmodules{lb}}){ + # print "found"; + #} + $_ = full($_); + print "\n*** Checking out $_\n"; + system("cvs checkout $tag $_") == 0 or die "cvs checkout $tag $_: $?\n"; + } +} + +BEGIN{ +%need_externs_aux = ( + 'lb.client' => [ qw/cppunit:B classads/ ], + 'lb.client-java' => [ qw/ant:B jdk:B axis:B trustmanager utiljava/ ], + 'lb.common' => [ qw/expat cares:B cppunit:B classads/ ], + 'lb.doc' => [], + 'lb.logger' => [ qw/cppunit:B/ ], + 'lb.server' => [ qw/globus_essentials:R globus:B expat cares mysql:R mysql-server:R mysql-devel:B cppunit:B gsoap:B classads voms lcas gridsite/ ], + 'lb.state-machine' => [ qw/classads/ ], + 'lb.utils' => [ qw/cppunit:B/ ], + 'lb.ws-interface' => [], + 'lb.ws-test' => [ qw/gsoap:B/ ], + 'lb.types' => [ qw// ], + 'lb.harvester' => [ qw// ], + 'lb.yaim' => [ qw/yaim_core:R/ ], + 'lb.glite-LB' => [ qw/fetchcrl:R gpt:R gip_release:R gip_service:R bdii:R glite_version:R glite_info_templates:R glue_schema:R/ ], + 'lbjp-common.db' => [ qw/mysql:B mysql-devel:B postgresql:B cppunit:B log4c:B/ ], + 'lbjp-common.log' => [ qw/log4c/ ], + 'lbjp-common.maildir' => [ qw// ], + 'lbjp-common.server-bones' => [ qw// ], + 'lbjp-common.trio' => [ qw/cppunit:B/ ], + 'lbjp-common.jp-interface' => [ qw/cppunit:B log4c:B/ ], + 'lbjp-common.gss' => [ qw/globus_essentials:R globus:B cares cppunit:B/ ], + 'lbjp-common.gsoap-plugin' => [ qw/cppunit:B globus_essentials:R globus:B cares:B gsoap:B/ ], + 'security.gss' => [ qw/globus_essentials:R globus:B cares cppunit:B/ ], + 'security.gsoap-plugin' => [ qw/cppunit:B globus_essentials:R globus:B cares:B gsoap:B/ ], + 'jobid.api-c' => [ qw/cppunit:B/ ], + 'jobid.api-cpp' => [ qw/cppunit:B/ ], + 'jobid.api-java' => [ qw/ant:B jdk:B/ ], + 'jp.client' => [ qw/gsoap libtar globus_essentials:R globus:B/ ], + 'jp.doc' => [], + 'jp.index' => [ qw/gsoap globus_essentials:R globus:B/ ], + 'jp.primary' => [ qw/classads gsoap libtar globus_essentials:R globus:B/ ], + 'jp.server-common' => [], + 'jp.ws-interface' => [], + 'gridsite.core' => [qw/httpd-devel:B gsoap:B globus:B/ ], + 'px.proxyrenewal' => [ qw/globus:B myproxy voms/ ], + 'px.glite-PX' => [qw/myproxy:R fetchcrl:R gip_service:R bdii:R glite_version:R/], + 'px.myproxy-yaim' => [ qw/yaim_core:R/ ], + 'px.myproxy-config' => [], +); + +for my $ext (keys %need_externs_aux) { + for (@{$need_externs_aux{$ext}}) { + /([^:]*)(?::(.*))?/; + push @{$need_externs{$ext}},$1; + my $type = $2 ? $2 : 'BR'; + $need_externs_type{$ext}->{$1} = $type; + } +} + +%need_jars = ( + 'jobid.api-java' => [ qw/jakarta-commons-codec/ ], + 'lb.client-java' => [ qw/jakarta-commons-lang/ ], +); + +for my $jar (keys %need_jars) { + for (@{$need_jars{$jar}}) { + $need_externs_type{$jar}->{$_} = 'BR'; # XXX + } +} + +%deps_aux = ( + 'lb.client' => [ qw/ + lb.types:B lb.common + lbjp-common.trio + jobid.api-cpp:B jobid.api-c + lbjp-common.gss + / ], + 'lb.client-java' => [ qw/ + lb.types:B + lb.ws-interface:B + jobid.api-java + / ], + 'lb.common' => [ qw/ + jobid.api-cpp:B jobid.api-c + lb.types:B lbjp-common.trio lbjp-common.gss + / ], + 'lb.doc' => [ qw/lb.types:B/ ], + 'lb.logger' => [ qw/ + lbjp-common.trio + lbjp-common.log + jobid.api-c + lb.common + lbjp-common.gss + / ], + 'lb.server' => [ qw/ + lb.ws-interface lb.types:B lb.common lb.state-machine + lbjp-common.db lbjp-common.server-bones lbjp-common.trio lbjp-common.maildir lbjp-common.log + jobid.api-c + lbjp-common.gsoap-plugin lbjp-common.gss + / ], + 'lb.state-machine' => [ qw/lb.types:B lb.common lbjp-common.jp-interface lbjp-common.gss/ ], + 'lb.utils' => [ qw/ + lbjp-common.jp-interface + jobid.api-c + lbjp-common.trio lbjp-common.maildir + lb.client lb.state-machine + / ], + 'lb.ws-test' => [ qw/lbjp-common.gsoap-plugin lb.ws-interface/ ], + 'lb.ws-interface' => [ qw/lb.types:B/ ], + 'lb.types' => [ qw// ], + 'lb.harvester' => [ qw/ + jobid.api-c lbjp-common.trio lbjp-common.db lb.common lb.client + lbjp-common.gss lbjp-common.log + / ], + 'lb.yaim' => [ qw// ], + 'lb.glite-LB' => [ qw/ + lb.logger:R lb.server:R lb.utils:R lb.doc:R + lb.ws-test:R lb.harvester:R lb.yaim:R lb.client-java:R + / ], + 'lbjp-common.db' => [ qw/lbjp-common.trio lbjp-common.log/ ], + 'lbjp-common.maildir' => [ qw// ], + 'lbjp-common.log' => [ qw// ], + 'lbjp-common.server-bones' => [ qw/lbjp-common.log/ ], + 'lbjp-common.trio' => [ qw// ], + 'lbjp-common.gss' => [ qw// ], + 'lbjp-common.gsoap-plugin' => [ qw/lbjp-common.gss/ ], + 'security.gss' => [ qw// ], + 'security.gsoap-plugin' => [ qw/security.gss/ ], + 'jobid.api-c' => [ qw// ], + 'jobid.api-cpp' => [ qw/jobid.api-c/ ], + 'jobid.api-java' => [ qw// ], + + 'lbjp-common.jp-interface' => [ qw/lbjp-common.db jobid.api-c/ ], + + 'jp.client' => [ qw/ + jp.ws-interface + lbjp-common.jp-interface lbjp-common.maildir + jobid.api-c + lbjp-common.gsoap-plugin + / ], + 'jp.doc' => [ qw// ], + 'jp.index' => [ qw/ + jp.server-common jp.ws-interface + lbjp-common.jp-interface lbjp-common.trio lbjp-common.db lbjp-common.server-bones + lbjp-common.gsoap-plugin + / ], + 'jp.primary' => [ qw/ + jobid.api-c + jp.server-common jp.ws-interface + lb.state-machine + lbjp-common.jp-interface lbjp-common.trio lbjp-common.db lbjp-common.server-bones + lbjp-common.gsoap-plugin + / ], + 'jp.server-common' => [ qw/ + lbjp-common.jp-interface lbjp-common.db + / ], + 'jp.ws-interface' => [ qw// ], + + 'gridsite.core' => [ qw/build.common-cpp:B/ ], + + 'px.proxyrenewal' => [ qw// ], + 'px.glite-PX' => [qw/px.myproxy-yaim:R/], + 'px.myproxy-yaim' => [], + 'px.myproxy-config' => [], +); + +for my $ext (keys %deps_aux) { + for (@{$deps_aux{$ext}}) { + /([^:]*)(?::(.*))?/; + push @{$deps{$ext}},$1; + my $type = $2 ? $2 : 'BR'; + $deps_type{$ext}->{$1} = $type; + } +} + + +%extrafull = ( gridsite=>'org.gridsite.core'); + +#( java => 'client-java' ); +%extranodmod = ( + db => 'lbjp-common.db', + jpprimary => 'jp.primary', + jpindex => 'jp.index', + jpclient => 'jp.client', +); + +%obsoletes = ( + 'lb.yaim' => [ qq/glite-yaim-lb/ ], + 'px.proxyrenewal' => [ qq/glite-security-proxyrenewal/ ], + 'px.myproxy-yaim' => [ qq/glite-yaim-myproxy/ ], + 'px.myproxy-config' => [ qq/myproxy-config/ ], + 'lbjp-common.gss' => [ qq/glite-security-gss/ ], + 'lbjp-common.gsoap-plugin' => [ qq/glite-security-gsoap-plugin/ ], +); + +%cvs_prefix = ( + 'lb' => 'org.glite', + 'jp' => 'org.glite', + 'jobid' => 'org.glite', + 'lbjp-common' => 'org.glite', + 'gridsite' => 'org', + 'security' => 'org.glite', + 'px' => 'org.glite', +); + +%conf_prefix = ( + 'lb' => 'glite-', + 'jp' => 'glite-', + 'jobid' => 'glite-', + 'lbjp-common' => 'glite-', + 'gridsite' => '', + 'security' => 'glite-', + 'px' => 'glite-', +); + +%emi_conf_prefix = ( + 'lb' => 'emi-', + 'jp' => 'emi-', + 'jobid' => 'emi-', + 'lbjp-common' => 'emi-', + 'gridsite' => '', + 'security' => 'emi-', + 'px' => 'emi-', +); + +my @k = keys %deps_aux; +@buildroot{@k} = ('build') x ($#k+1); + +my @t = qw/lb.client-java jobid.api-java lb.types/; +@buildroot{@t} = ('') x ($#t+1); + +$buildroot{'gridsite.core'} = 'src'; +} + +sub full +{ + my $short = shift; + return $extrafull{$short} ? $extrafull{$short} : 'org.glite.'.$short; +} + +sub mkinc +{ + my %aux; + undef %aux; + my @m=qw/ +lb.client lb.doc lb.state-machine lb.ws-interface lb.logger lb.types lb.common lb.server lb.utils lb.ws-test lb.client-java lb.harvester lb.yaim lb.glite-LB +security.gss security.gsoap-plugin +jobid.api-c jobid.api-cpp jobid.api-java +lbjp-common.db lbjp-common.log lbjp-common.maildir lbjp-common.server-bones lbjp-common.trio lbjp-common.jp-interface lbjp-common.gss lbjp-common.gsoap-plugin +jp.client jp.doc jp.index jp.primary jp.server-common jp.ws-interface +px.proxyrenewal px.myproxy-yaim px.glite-PX px.myproxy-config +/; + @aux{@m} = (1) x ($#m+1); + + my $short = shift; + my $full = full $short; + + unless ($aux{$short}) { + print "Makefile.inc not needed in $full\n"; + return; + } + + my $build = ''; + + unless ($buildroot{$_} eq '') { + $build = "/$buildroot{$_}"; + unless (-d "$full/$buildroot{$_}") { + mkdir "$full/$buildroot{$_}" or die "mkdir $full/$buildroot{$_}: $!\n"; + } + unlink "$full/$buildroot{$_}/Makefile"; + symlink "../Makefile","$full/$buildroot{$_}/Makefile" or die "symlink ../Makefile $full/$buildroot{$_}/Makefile: $!\n"; + } + + open MKINC,">$full/$buildroot{$_}/Makefile.inc" + or die "$full/$buildroot{$_}/Makefile.inc: $!\n"; + + print "Creating $full/$buildroot{$_}/Makefile.inc\n"; + + print MKINC qq{ +PREFIX = $prefix +stagedir = $stagedir +thrflavour = $thrflavour +nothrflavour = $nothrflavour +libdir = $libdir +}; + + for (@{$need_externs{$short}}) { + print MKINC "${_}_prefix = $externs{$_}{prefix}\n"; + print MKINC "$externs{$_}{flags}" if defined $externs{$_}{flags}; + } + + for (@{$need_jars{$short}}) { + print MKINC "${_}_jar = $jar{$_}\n" + } + + my $need_gsoap = 0; + for (@{$need_externs{$short}}) { $need_gsoap = 1 if $_ eq 'gsoap'; } + + print MKINC "gsoap_default_version=".gsoap_version()."\n" if $need_gsoap; + + close MKINC; +} + +my %etics_externs; +my %etics_projects; +BEGIN{ + %etics_externs = ( + globus_essentials=>'vdt_globus_essentials', + globus=>'globus', + myproxy=>'myproxy', + cares=>'c-ares', + voms=>'org.glite.security.voms-api-cpp', + gridsite=>'org.gridsite.shared', + lcas=>'org.glite.security.lcas', + trustmanager=>'org.glite.security.trustmanager', + utiljava=>'org.glite.security.util-java', + gpt=>'gpt', + fetchcrl=>'fetch-crl', + gip_release=>'glite-info-provider-release', + gip_service=>'glite-info-provider-service', + bdii=>'bdii', + glite_version=>'glite-version', + glite_info_templates=>'glite-info-templates', + glue_schema=>'glue-schema', + yaim_core=>'org.glite.yaim.core', + ); + %etics_projects = ( + vdt=>[qw/globus globus_essentials myproxy/], + 'org.glite'=>[qw/voms gridsite lcas gpt gip_release gip_service bdii glite_version glite_info_templates glue_schema yaim_core/], + ); + + %platform_properties = ( + 'gridsite.core' => { + sl5_x86_64_gcc412 => { aprSuffix => '1' }, + sl5_ia32_gcc412 => { aprSuffix => '1' }, + deb5_x86_64_gcc432 => { aprSuffix => '1.0' }, + deb5_ia32_gcc432 => { aprSuffix => '1.0' }, + slc4_x86_64_gcc346 => { aprSuffix => '0' }, + slc4_ia32_gcc346 => { aprSuffix => '0' }, + default => { + } + }, + ); +}; + +sub mode_etics { + $fmod = shift; + + die "$0: --module required with --etics\n" unless $fmod; + + my ($subsys,$module) = split /\./,$fmod; + + my ($major,$minor,$rev,$age); + + if ($version) { + $version =~ /([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)-(.+)/; + ($major,$minor,$rev,$age) = ($1,$2,$3,$4); + } + else { + open V,"$cvs_prefix{$subsys}.$subsys.$module/project/version.properties" + or die "$cvs_prefix{$subsys}.$subsys.$module/project/version.properties: $!\n"; + + while ($_ = ) { + chomp; + ($major,$minor,$rev) = ($1,$2,$3) if /module\.version\s*=\s*([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/; + $age = $1 if /module\.age\s*=\s*([[:digit:]]+)/; + } + close V; + } + + my @copts = (); + my %ge; + @ge{@{$etics_projects{'org.glite'}}} = (1) x ($#{$etics_projects{'org.glite'}}+1); + + for (@{$need_externs{"$subsys.$module"}}) { + if ($need_externs_type{"$subsys.$module"}->{$_}=~/B/) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + if ($emi) { + if ($ge{$_} and not defined $externs{$_}{pkg}) { + push @copts, "--with-$_=\${stageDir}"; + } + } else { + push @copts,$ge{$_} ? "--with-$_=\${stageDir}" : "--with-$_=\${$eext.location}"; + } + } + } + + for (@{$need_jars{"$subsys.$module"}}) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + + push @copts,"--with-$_ \${$eext.location}$jar{$_}" if (not $emi); + } + + my $conf; + my $conftag; + my $confprefix; + + $dwpath = "path = \${projectName}/\${moduleName}/\${version}/\${platformName}/\${packageName}-\${version}-\${age}.tar.gz\n"; + + if ($emi) { $confprefix = $emi_conf_prefix{$subsys} } + else { $confprefix = $conf_prefix{$subsys} } + + if ($branch) { + $conf = "$confprefix${subsys}-${module}_$branch"; + $conftag = $branch; + # forced low age number + $age = $branch eq 'HEAD' ? '0head' : '0dev'; } + else { + $conf = "$confprefix$subsys-${module}_R_${major}_${minor}_${rev}_${age}"; + +# XXX: gridsite hack + $conftag = $subsys eq 'gridsite' ? "$conf_prefix{$subsys}$subsys-${module}_R_${major}_${minor}_${rev}" : + "$conf_prefix{$subsys}$subsys-${module}_R_${major}_${minor}_${rev}_${age}"; } + if ($emi) { + $age = "${age}emi"; + } + + my $file = $output ? $output : "$conf.ini"; + open C,">$file" or die "$file: $!\n"; + + my $buildroot = $buildroot{"$subsys.$module"} eq '' ? '#no build.root' : "build.root = " . $buildroot{"$subsys.$module"}; + + my $confdir = $buildroot{"$subsys.$module"} eq '' ? '..' : '../..'; + + my $package_description = ""; + my $package_summary = ""; + + if (-e "$cvs_prefix{$subsys}.$subsys.$module/project/package.description") { + open V, "$cvs_prefix{$subsys}.$subsys.$module/project/package.description"; + $package_description = join ("", ); + close V; + chomp $package_description; + $package_description =~ s/\n/\\n/g; + $package_description = "package.description = $package_description\n"; + } + else { + print STDERR "package.description not found for $subsys.$module!\n"; } + + if (-e "$cvs_prefix{$subsys}.$subsys.$module/project/package.summary") { + open V, "$cvs_prefix{$subsys}.$subsys.$module/project/package.summary"; + $package_summary = join ("", ); + close V; + chomp $package_summary; + $package_summary =~ s/\n/\\n/g; + $package_summary = "package.summary = $package_summary\n"; + } + else { + print STDERR "package.summary not found for $subsys.$module!\n"; } + + my %cmd; + @cmd{qw/configure compile test install packaging clean/} = ('None') x 6; + $cmd{clean} = 'make clean'; + + if ($subsys eq 'gridsite') { + if ($module eq 'core') { + my $flags = 'RELEASE_VERSION=${age}.${platformFamily} prefix=${prefix} libdir=${libdir} GSOAPDIR=${gsoap.location} OPENSSL_GLOBUS_FLAGS=-I${globus.location}/include/${globus.dbg.nothr.flavor} OPENSSL_GLOBUS_LIBS=-L${globus.location}/${libdir}/ FLAVOR_GLOBUS_EXT=_${globus.dbg.nothr.flavor} HTTPD_FLAGS="-I${httpd-devel.location}/include/httpd -I${httpd-devel.location}/include/apache2 -I${httpd-devel.location}/include/apr-${aprSuffix} -I${httpd-devel.location}/include/pcre"'; + + $cmd{compile} = "make $flags build"; + $cmd{install} = "make $flags install"; + $cmd{packaging} = "make $flags rpm"; + } + else { + $cmd{packaging} = "echo building nothing, org.gridsite.core make rpm step will create this"; + } + } + else { + my $flavours = $emi ? "--thrflavour= --nothrflavour=" : "--thrflavour=\${globus.thr.flavor} --nothrflavour=\${globus.nothr.flavor}"; + $cmd{configure} = "cd $confdir && /usr/bin/perl \${moduleName}/configure $flavours --prefix=\${prefix} --stage=\${stageDir} --libdir=\${libdir} --module $subsys.$module @copts"; + $cmd{compile} = 'make'; + $cmd{test} = 'make check'; + $cmd{install} = 'make install'; + } + + my $defprops = ''; + + for my $p (keys %{$platform_properties{"$subsys.$module"}->{default}}) { + $defprops .= $p . ' = ' . $platform_properties{"$subsys.$module"}->{default}->{$p} . "\n"; + } + + my $checkoutcmd; + if ($conftag eq 'HEAD') { + $checkoutcmd = "cvs -d \${vcsroot} co -A \${moduleName}"; + } else { + $checkoutcmd = "cvs -d \${vcsroot} co -r \${tag} \${moduleName}"; + } + + print STDERR "Writing $file\n"; + print C qq{ +[Configuration-$conf] +profile = None +moduleName = $cvs_prefix{$subsys}.$subsys.$module +displayName = $conf +description = $cvs_prefix{$subsys}.$subsys.$module +projectName = org.glite +age = $age +deploymentType = None +tag = $conftag +version = $major.$minor.$rev +$dwpath +[Platform-default:VcsCommand] +displayName = None +description = None +tag = cvs -d \${vcsroot} tag -R \${tag} \${moduleName} +branch = None +commit = None +checkout = $checkoutcmd + +[Platform-default:BuildCommand] +postpublish = None +packaging = $cmd{packaging} +displayName = None +description = None +doc = None +prepublish = None +publish = None +compile = $cmd{compile} +init = None +install = $cmd{install} +clean = $cmd{clean} +test = $cmd{test} +configure = $cmd{configure} +checkstyle = None + +[Platform-default:Property] +$buildroot +aprSuffix = 0 +package.RPMSLocation = \${moduleDir}/RPMTMP/RPMS +package.SRPMSLocation = \${moduleDir}/RPMTMP/SRPMS +package.preserve.libtool = false +$package_description$package_summary$defprops}; + + for (@{$obsoletes{"$subsys.$module"}}) { + print C "package.obsoletes = $_\n"; + print C "package.replaces = $_\n"; + } + + for my $pp (keys %{$platform_properties{"$subsys.$module"}}) { + next if $pp eq 'default'; + print C "[Platform-$pp:Property]\n$buildroot\n"; + + for my $p (keys %{$platform_properties{"$subsys.$module"}->{$pp}}) { + print C $p . ' = ' . $platform_properties{"$subsys.$module"}->{$pp}->{$p} . "\n"; + } + print C q{package.RPMSLocation = ${moduleDir}/RPMTMP/RPMS +package.SRPMSLocation = ${moduleDir}/RPMTMP/SRPMS +}; + print C "$package_description$package_summary\n"; + } + + print C qq{ +[Platform-default:DynamicDependency] +}; + for (@{$need_externs{"$subsys.$module"}},@{$need_jars{"$subsys.$module"}}) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + + my $proj = 'externals'; + for my $p (keys %etics_projects) { + for $m (@{$etics_projects{$p}}) { + $proj = $p if $m eq $_; + } + } + + my $type = $need_externs_type{"$subsys.$module"}->{$_}; + print C "$proj|$eext = $type\n"; + } + + for (@{$deps{"$subsys.$module"}}) { + my $type = $deps_type{"$subsys.$module"}->{$_}; + print C "org.glite|org.glite.$_ = $type\n"; + } + + close C; +} + +sub gsoap_version { + local $_; + my $gsoap_version; + open S,"$externs{gsoap}{prefix}/bin/soapcpp2 -v 2>&1 |" or die "$externs{gsoap}{prefix}/bin/soapcpp2: $!\n"; + + while ($_ = ) { + chomp; + + $gsoap_version = $1 if /The gSOAP Stub and Skeleton Compiler for C and C\+\+ ([.[:digit:][:alpha:]]+)$/; + } + close S; + return $gsoap_version; +} + +sub getlibdir { + if ( -e "/etc/debian_version") { # We are on Debian + $lib64="lib"; + $lib32="lib32"; } + else { # Another distribution + $lib64="lib64"; + $lib32="lib"; } + $libdir=$lib32; + + open INP, "uname -s | "; # Check kernel name + $kname= ; + chomp($kname); + close INP; + + if ( $kname == "Linux") { + $arch = ("x86_64\npowerpc\nppc64\n"); + + open INP, "uname -p | "; # Check processor type + $procname= ; + chomp($procname); + close INP; + + if ($arch =~/^$procname\n/) { + return ($lib64); } + + open INP, "uname -m | "; # Check machine hardware + $machname= ; + chomp($machname); + close INP; + + if ($arch =~/^$machname\n/) { + return ($lib64); } + + # special cases (hyperlink lib64, Debian) + if (-l "/usr/lib64") { + $libdir=$lib32; } + + # if /usr/lib64 doesn't exist at all (AIX) + unless ( -e "/usr/lib64" ) { + $libdir=$lib32; } + } + + if ( $kname == "SunOS") { + if (-e "/usr/lib/64") { + $libdir="lib/64"; } + } + + return $libdir; +} + +sub usage { + my @ext = keys %externs; + my @myjars, keys %jar; + + print STDERR qq{ +usage: $0 options + +General options (defaults in []): + --prefix=PREFIX destination directory [./stage] + --staged=module,module,... what is already in PREFIX (specify without org.glite.) + --thrflavour=flavour + --nothrflavour=flavour threaded and non-treaded flavours [gcc64dbgpthr,gcc64dbg] + --listmodules=subsys list modules of a subsystem + --version=maj.min.rev-age specify version here instead of reading version.properties + --branch=branch CVS branch/etics name suffix (HEAD, branch_2_1, ...) + --libdir=libdir typically [lib,lib64] postfix + --emi generate configurations with emi flavor in mode 'etics' + +Mode of operation: + --mode={checkout|build|etics} what to do [build] + +What to build: + --module=module build this module only (mostly in-Etics operation) + --enable-NODE build this "node" (set of modules) only. Available nodes are + @{$lbmodules{lb}},@{$lbmodules{security}} + --disable-NODE don't build this node + --lb-tag=tag checkout LB modules with specific tag + --jp-tag=tag checkout JP modules with specific tag + --lbjp-common-tag=tag checkout lbjp-common modules with specific tag + --security-tag=tag checkout security modules with specific tag + --jobid-tag=tag checkout jobid modules with specific tag + +Dependencies: + --with-EXTERNAL=PATH where to look for an external. Required externals + (not all for all modules) are: + @ext + --with-JAR=JAR where to look for jars. Required jars are: + @myjars + Summary of what will be used is always printed + +}; + +} diff --git a/org.glite.lbjp-common.gsoap-plugin/project/ChangeLog b/org.glite.lbjp-common.gsoap-plugin/project/ChangeLog new file mode 100644 index 0000000..9d39895 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/ChangeLog @@ -0,0 +1,52 @@ +1.5.3-1 +- avoid memleak in gsoap +- fix #32059 +- support gsoap 2.7.10 + +1.5.4-1 +- handle client connection errors in gsoap (generate faults) +- don't define gsoap.platformName in configuration confusingly + +1.5.4-2 +- disctinct c and c++ builds (concerns gsoap 2.7.10 only) + +2.0.0-1 +- LB 2.0 release + +2.0.0-2 +- configure script update (globus flavors added to configure call) + +2.0.1-1 +- API reverted towards backward compatibility + +2.0.1-2 +- Module repacked + +2.0.1-3 +- install libraries into $libdir + +2.0.2-1 +- Updated Makefile & Configure script + +2.1.0-1 +- IPv6 fixes +- Fixed error reporting +- Attempt to fix compatibility with gsoap 2.7.10 +- Improved portability + +2.1.1-1 +- libtool version numbering reintroduced + +2.1.2-1 +- Fixed target 'clean' in the Makefile to handle debian builds + +2.1.2-2 +- Module rebuilt + +2.1.3-1 +- Module renamed +- Makefile a configuration updated to work across org.glite & EMI + +2.1.3-2 +- Module rebuilt + diff --git a/org.glite.lbjp-common.gsoap-plugin/project/version.properties b/org.glite.lbjp-common.gsoap-plugin/project/version.properties new file mode 100644 index 0000000..1cb0126 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/version.properties @@ -0,0 +1,3 @@ +# $Header$ +module.version=2.1.3 +module.age=2 diff --git a/org.glite.lbjp-common.gss/Makefile b/org.glite.lbjp-common.gss/Makefile new file mode 100644 index 0000000..612b573 --- /dev/null +++ b/org.glite.lbjp-common.gss/Makefile @@ -0,0 +1,170 @@ +# defaults +top_srcdir=.. +builddir=build +top_builddir=${top_srcdir}/${builddir} +stagedir=. +globalprefix=glite +package=gss +version=1.0.0 +PREFIX=/opt/glite + +glite_location=/opt/glite +globus_prefix=/opt/globus +cppunit_prefix=/opt/cppunit + +CC=gcc + +-include Makefile.inc +-include ../project/version.properties + +version=${module.version} + +# In order to use libtool versioning correcty, we must have: +# +# current = major + minor + offset +# revision = patch +# age = minor +# +# where offset is a sum of maximal released minor's of all previous major's +# + +# counted minors: gsoap-plugin 1.5 +# TODO: bump offset to 5 on next major change +offset=-1 +version_info:=-version-info ${shell \ + perl -e '$$,=":"; @F=split "\\.","${version}"; print $$F[0]+$$F[1]+${offset},$$F[2],$$F[1]' } + +VPATH=${top_srcdir}/src:${top_srcdir}/test + +default: all + +DEBUG:=-g -O0 -W -Wall -Wno-unused-parameter +# not for globus, gsoap: -Werror + +CFLAGS:= ${CFLAGS} ${DEBUG} \ + -DVERSION=\"${version}\" \ + -I. -I${top_srcdir}/interface \ + -I${stagedir}/include \ + ${COVERAGE_FLAGS} -D_GNU_SOURCE -DDATAGRID_EXTENSION + +LDFLAGS:=${LDFLAGS} ${COVERAGE_FLAGS} + +COMPILE:=libtool --mode=compile ${CC} ${CFLAGS} +LINK:=libtool --mode=link ${CC} -rpath ${stagedir}/${libdir} ${LDFLAGS} +LINKXX:=libtool --mode=link ${CXX} -rpath ${stagedir}/${libdir} ${LDFLAGS} +INSTALL:=libtool --mode=install install + +CPPUNIT_LIBS?=-L${cppunit_prefix}/${libdir} -lcppunit +CPPUNIT_CFLAGS?=-I${cppunit_prefix}/include + +GLOBUS_NOTHR_INC:= -I${globus_prefix}/include/${nothrflavour} +GLOBUS_THR_INC:= -I${globus_prefix}/include/${thrflavour} + +GLOBUS_NOTHR_LIBS:= -L${globus_prefix}/lib \ + -lglobus_common_${nothrflavour} \ + -lglobus_gssapi_gsi_${nothrflavour} +GLOBUS_THR_LIBS:= -L${globus_prefix}/lib \ + -lglobus_common_${thrflavour} \ + -lglobus_gssapi_gsi_${thrflavour} + +GLOBUS_GSSAPI_GSI_LIBS?=${GLOBUS_NOTHR_LIBS} +GLOBUS_GSSAPI_GSI_CFLAGS?=${GLOBUS_NOTHR_INC} + +LIBCARES_CFLAGS?=-I${cares_prefix}/include +LIBCARES_LIBS?=-L${cares_prefix}/${libdir} -L${cares_prefix}/lib -lcares + +HDRS:=glite_gss.h + +GSS_OBJS:=glite_gss.o +GSS_LOBJS:=${GSS_OBJS:.o=.lo} +GSS_THROBJS:=${GSS_OBJS:.o=.thr.o} +GSS_THRLOBJS:=${GSS_OBJS:.o=.thr.lo} + +GSS_NOTHRSTATICLIB:=libglite_security_gss_${nothrflavour}.a +GSS_THRSTATICLIB:=libglite_security_gss_${thrflavour}.a +GSS_STATICLIB:=libglite_security_gss.a +GSS_NOTHRLTLIB:=libglite_security_gss_${nothrflavour}.la +GSS_THRLTLIB:=libglite_security_gss_${thrflavour}.la +GSS_LTLIB:=libglite_security_gss.la + +ifeq ($(thrflavour),) +lib_LTLIBRARIES=${GSS_LTLIB} +lib_LIBRARIES=${GSS_STATICLIB} +default_gss=${GSS_LTLIB} +else +lib_LTLIBRARIES=${GSS_NOTHRLTLIB} ${GSS_THRLTLIB} +lib_LIBRARIES=${GSS_NOTHRSTATICLIB} ${GSS_THRSTATICLIB} +default_gss=${GSS_NOTHRLTLIB} +endif + + +ifeq ($(thrflavour),) +${GSS_STATICLIB}: ${GSS_OBJS} + ar crv $@ ${GSS_OBJS} + ranlib $@ + +${GSS_LTLIB}: ${GSS_OBJS} + ${LINK} ${version_info} -o $@ ${GSS_LOBJS} ${GLOBUS_GSSAPI_GSI_LIBS} ${LIBCARES_LIBS} +else +${GSS_NOTHRSTATICLIB}: ${GSS_OBJS} + ar crv $@ ${GSS_OBJS} + ranlib $@ + +${GSS_THRSTATICLIB}: ${GSS_THROBJS} + ar crv $@ ${GSS_THROBJS} + ranlib $@ + +${GSS_NOTHRLTLIB}: ${GSS_OBJS} + ${LINK} ${version_info} -o $@ ${GSS_LOBJS} ${GLOBUS_NOTHR_LIBS} ${LIBCARES_LIBS} + +${GSS_THRLTLIB}: ${GSS_THROBJS} + ${LINK} ${version_info} -o $@ ${GSS_THRLOBJS} ${GLOBUS_THR_LIBS} ${LIBCARES_LIBS} +endif + + +all compile: $(lib_LTLIBRARIES) ${lib_LIBRARIES} examples + +check: compile check.gss + +check.gss: test_gss + # ./test_gss out.xml + echo test_gss not run automatically util we have got some credentials in X509_USER_PROXY + +test_gss: test_gss.o + ${LINKXX} -o $@ test_gss.o ${default_gss} ${CPPUNIT_LIBS} ${GLOBUS_GSSAPI_GSI_LIBS} ${LIBCARES_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: + +doc: + +stage: + $(MAKE) install PREFIX=${stagedir} DOSTAGE=yes + +install: + -mkdir -p ${PREFIX}/${libdir} + -mkdir -p ${PREFIX}/share/doc/${package}-${version} + -mkdir -p ${PREFIX}/include/glite/security + ${INSTALL} -m 755 ${lib_LTLIBRARIES} ${PREFIX}/${libdir} + ${INSTALL} -m 644 ${top_srcdir}/LICENSE ${PREFIX}/share/doc/${package}-${version} + cd ${top_srcdir}/interface && ${INSTALL} -m 644 ${HDRS} ${PREFIX}/include/glite/security/ + if [ x${DOSTAGE} = xyes ]; then \ + install -m 644 ${lib_LIBRARIES} ${PREFIX}/${libdir}; \ + fi + +clean: + rm -rf *.o *.lo *.a *.la .libs test_gss + rm -rvf log.xml project/ rpmbuild/ RPMS/ tgz/ debian/ + +%.o: %.c + ${COMPILE} ${GLOBUS_GSSAPI_GSI_CFLAGS} ${LIBCARES_CFLAGS} -o $@ -c $< + +%.thr.o: %.c + ${COMPILE} ${GLOBUS_THR_INC} ${LIBCARES_CFLAGS} -o $@ -c $< + +test_gss.o: %.o: %.cpp + ${CXX} -c ${CFLAGS} ${GLOBUS_GSSAPI_GSI_CFLAGS} ${CPPUNIT_CFLAGS} -Wno-error $< diff --git a/org.glite.lbjp-common.gss/configure b/org.glite.lbjp-common.gss/configure new file mode 100755 index 0000000..598d569 --- /dev/null +++ b/org.glite.lbjp-common.gss/configure @@ -0,0 +1,1069 @@ +#!/usr/bin/perl + +# WARNING: Don't edit this file unless it is the master copy in org.glite.lb +# +# For the purpose of standalone builds of lb/jobid/lbjp-common components +# it is copied on tagging + +# $Header$ +# +# Copyright (c) Members of the EGEE Collaboration. 2004-2010. +# See http://www.eu-egee.org/partners/ for details on the copyright holders. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +use Getopt::Long; + +my $pwd = `pwd`; chomp $pwd; +my $prefix = $pwd.'/stage'; +my $stagedir; +my $staged; +my $module; +my $thrflavour = 'gcc64dbgpthr'; +my $nothrflavour = 'gcc64dbg'; +my $mode = 'build'; +my $help = 0; +my $listmodules; +my $version; +my $branch; +my $output; +my $lb_tag = ''; +my $lbjp_tag = ''; +my $jp_tag = ''; +my $sec_tag = ''; +my $jobid_tag = ''; +my $libdir = getlibdir(); + +my @nodes = qw/client server logger utils client-java doc ws-test db jpprimary jpindex jpclient harvester/; +my %enable_nodes; +my %disable_nodes; + +my %externs = ( + cares => { + prefix => '/opt/c-ares', + pkg => 'libcares' + }, + classads => { + prefix=> '/opt/classads', + pkg => 'classads' + }, + cppunit => { + prefix=> '/usr', + pkg => 'cppunit' + }, + expat => { + prefix=> '/usr', + pkg => 'expat' + }, + globus => { + prefix=> '/opt/globus', + pkg => 'globus-gssapi-gsi' + }, + myproxy => { + prefix=> '/opt/myproxy', + pkg => 'myproxy' + }, + gsoap => { + prefix=> '/usr', + pkg => 'gsoap' + }, + mysql => { + prefix=> '/usr' + }, + 'mysql-devel' => { + prefix=> '' + }, + 'mysql-server' => { + prefix => '' + }, + voms => { + prefix => '/opt/glite', + pkg => 'voms-1.0' + }, + gridsite => { + prefix => '/opt/glite' + }, + lcas => { + prefix => '/opt/glite' + }, + trustmanager => { + prefix => '/opt/glite' + }, + utiljava => { + prefix=> '/opt/glite' + }, + ant => { + prefix=> '/usr' + }, + jdk => { + prefix=> '/usr' + }, + libtar => { + prefix=> '/usr' + }, + axis => { + prefix=> '/usr' + }, + log4c => { + prefix=> '/usr' + }, + postgresql => { + prefix=> '/usr' + } +); + +my %jar = ( + 'jakarta-commons-codec' => '/usr/share/java/commons-codec.jar', + 'jakarta-commons-lang' => '/usr/share/java/commons-lang.jar', +); + + +my %glite_prefix; +my %need_externs; +my %need_externs_type; +my %need_jars; +my %extrafull; +my %extranodmod; +my %deps; +my %deps_type; +my %buildroot; + +my %lbmodules = ( + 'lb' => [ qw/client client-java common doc logger server state-machine types utils ws-interface ws-test harvester yaim glite-LB/], + 'security' => [qw/gss gsoap-plugin/], + 'lbjp-common' => [qw/db log maildir server-bones trio jp-interface gss gsoap-plugin/], + 'jobid' => [qw/api-c api-cpp api-java/], + 'jp' => [ qw/client doc index primary server-common ws-interface/ ], + 'gridsite' => [ qw/apache shared commands core/ ], + 'px' => [ qw/proxyrenewal glite-PX myproxy-yaim myproxy-config/ ], + ); + + +my @opts = ( + 'prefix=s' => \$prefix, + 'staged=s' => \$staged, + 'module=s' => \$module, + 'thrflavour:s' => \$thrflavour, + 'nothrflavour:s' => \$nothrflavour, + 'mode=s' => \$mode, + 'listmodules=s' => \$listmodules, + 'version=s' => \$version, + 'branch=s' => \$branch, + 'output=s' => \$output, + 'stage=s' => \$stagedir, + 'lb-tag=s' => \$lb_tag, + 'lbjp-common-tag=s' => \$lbjp_tag, + 'jp-tag=s' => \$jp_tag, + 'security-tag=s' => \$sec_tag, + 'jobid-tag=s' => \$jobid_tag, + 'help' => \$help, + 'libdir=s' => \$libdir, + 'emi' => \$emi, +); + +for (@nodes) { + $enable_nodes{$_} = 0; + $disable_nodes{$_} = 0; + + push @opts,"disable-$_",\$disable_nodes{$_}; + push @opts,"enable-$_",\$enable_nodes{$_}; +} + +push @opts,"with-$_=s",\$externs{$_}{withprefix} for keys %externs; +push @opts,"with-$_=s",\$jar{$_} for keys %jar; + +my @keeparg = @ARGV; + +GetOptions @opts or die "Errors parsing command line\n"; + +$externs{'mysql-devel'}{prefix}=$externs{mysql}{prefix} if $externs{'mysql-devel'}{prefix} eq ''; +$externs{'mysql-server'}{prefix}=$externs{mysql}{prefix} if $externs{'mysql-server'}{prefix} eq ''; + +if ($help) { usage(); exit 0; } + +if ($listmodules) { + my @m = map "org.glite.$listmodules.$_",@{$lbmodules{$listmodules}}; + print "@m\n"; + exit 0; +} + +warn "$0: --version, --branch and --output make sense only in --mode=etics\n" + if ($version || $output || $branch) && $mode ne 'etics'; + +my $en; +for (keys %enable_nodes) { $en = 1 if $enable_nodes{$_}; } + +my $dis; +for (keys %disable_nodes) { $dis = 1 if $disable_nodes{$_}; } + +die "--enable-* and --disable-* are mutually exclusive\n" + if $en && $dis; + +die "--module cannot be used with --enable-* or --disable-*\n" + if $module && ($en || $dis); + +die "$module: unknown module\n" if $module && ! grep $module,@{$lbmodules{lb}},@{$lbmodules{security}},{$lbmodules{jp}}; + +if ($mode eq 'build') { for my $ext (keys %externs) { + if (defined $externs{$ext}{withprefix}) { $externs{$ext}{prefix} = $externs{$ext}{withprefix}; } + elsif (defined $externs{$ext}{pkg}) { + my ($prefix, $flag); + my $pkg = $externs{$ext}{pkg}; + my $flagname = uc $externs{$ext}{pkg}; + $flagname =~ s/-[0-9\.]*$//; + $flagname =~ s/-/_/g; + + print "Checking $pkg ... "; + `pkg-config "$pkg" --exists >/dev/null`; + if ($? == 0) { + $externs{$ext}{prefix}=`pkg-config $pkg --variable=prefix`; + chomp $externs{$ext}{prefix}; + print "$externs{$ext}{prefix}\n"; + + $flag=`pkg-config $pkg --cflags`; + $externs{$ext}{flags} .= "${flagname}_CFLAGS=$flag" if ($flag); + $flag=`pkg-config $pkg --libs`; + $externs{$ext}{flags} .= "${flagname}_LIBS=$flag" if ($flag); + } else { + print "(using default)\n"; + } + } +} } + +if ($dis) { + for (@nodes) { + $enable_nodes{$_} = 1 unless $disable_nodes{$_}; + } +} + +if (!$en && !$dis) { $enable_nodes{$_} = 1 for (@nodes) } ; + +for (keys %enable_nodes) { delete $enable_nodes{$_} unless $enable_nodes{$_}; } + +$stagedir = $prefix unless $stagedir; + +if ($mode eq 'build') { + print "Writing config.status\n"; + open CONF,">config.status" or die "config.status: $!\n"; + print CONF "PKG_CONFIG_PATH=$ENV{PKG_CONFIG_PATH} $0 @keeparg\n"; + close CONF; +} + + +my @modules; +my %aux; + +if ($module) { +# push @modules,split(/[,.]+/,$module); + push @modules,$module; +} +else { + @modules = map(($extranodmod{$_} ? $extranodmod{$_} : 'lb.'.$_),(keys %enable_nodes)); + + my $n; + + do { + local $"="\n"; + $n = $#modules; + push @modules,(map @{$deps{$_}},@modules); + + undef %aux; @aux{@modules} = (1) x ($#modules+1); + @modules = keys %aux; + } while ($#modules > $n); +} + +@aux{@modules} = (1) x ($#modules+1); +delete $aux{$_} for (split /,/,$staged); +@modules = keys %aux; + +mode_build() if $mode eq 'build'; +mode_checkout() if $mode eq 'checkout'; +mode_etics($module) if $mode eq 'etics'; + +sub mode_build { + print "\nBuilding modules: @modules\n"; + + my @ext = map @{$need_externs{$_}},@modules; + my @myjars = map @{$need_jars{$_}},@modules; + undef %aux; @aux{@ext} = 1; + @ext = keys %aux; + undef %aux; @aux{@myjars} = (1) x ($#myjars+1); + @myjars = keys %aux; + + print "\nRequired externals:\n"; + print "\t$_: $externs{$_}{prefix}\n" for @ext; + print "\t$_: $jar{$_}\n" for @myjars; + for (@ext) { if (defined($externs{$_}{flags})) { print "$externs{$_}{flags}"; } }; + print "\nThis is a poor-man configure, it's up to you to have sources and externals there\n\n"; + + mkinc($_) for @modules; + + print "Creating Makefile\n"; + + open MAK,">Makefile" or die "Makefile: $!\n"; + + print MAK "all: @modules\n\nclean:\n"; + + for (@modules) { + my $full = full($_); + print MAK "\tcd $full/$buildroot{$_} && \${MAKE} clean\n" + } + + print MAK "\ndistclean:\n"; + + for (@modules) { + my $full = full($_); + print MAK $buildroot{$_} eq '' ? + "\tcd $full && \${MAKE} distclean\n" : + "\trm -rf $full/$buildroot{$_}\n" + } + + print MAK "\n"; + + for (@modules) { + my %ldeps; undef %ldeps; + @ldeps{@{$deps{$_}}} = 1; + for my $x (split /,/,$staged) { delete $ldeps{$x}; } + my @dnames = $module ? () : keys %ldeps; + + my $full = full($_); + my $build = $buildroot{$_}; + + print MAK "$_: @dnames\n\tcd $full/$build && \${MAKE} && \${MAKE} install\n\n"; + } + + close MAK; +} + +sub mode_checkout() { + for (@modules) { + my $module = $_; + my $tag = ""; + if ($lb_tag){ + for (@{$lbmodules{lb}}){ + if ("lb.".$_ eq $module){ + $tag = '-r '.$lb_tag; + } + } + } + if ($lbjp_tag){ + for (@{$lbmodules{'lbjp-common'}}){ + if ("lbjp-common.".$_ eq $module){ + $tag = '-r '.$lbjp_tag; + } + } + } + if ($jp_tag){ + for (@{$lbmodules{'jp'}}){ + if ("jp.".$_ eq $module){ + $tag = '-r '.$jp_tag; + } + } + } + if ($sec_tag){ + for (@{$lbmodules{security}}){ + if ("security.".$_ eq $module){ + $tag = '-r '.$sec_tag; + } + } + } + if ($jobid_tag){ + for (@{$lbmodules{jobid}}){ + if ("jobid.".$_ eq $module){ + $tag = '-r '.$jobid_tag; + } + } + } + #if (grep {"lb.".$_ eq $module} @{$lbmodules{lb}}){ + # print "found"; + #} + $_ = full($_); + print "\n*** Checking out $_\n"; + system("cvs checkout $tag $_") == 0 or die "cvs checkout $tag $_: $?\n"; + } +} + +BEGIN{ +%need_externs_aux = ( + 'lb.client' => [ qw/cppunit:B classads/ ], + 'lb.client-java' => [ qw/ant:B jdk:B axis:B trustmanager utiljava/ ], + 'lb.common' => [ qw/expat cares:B cppunit:B classads/ ], + 'lb.doc' => [], + 'lb.logger' => [ qw/cppunit:B/ ], + 'lb.server' => [ qw/globus_essentials:R globus:B expat cares mysql:R mysql-server:R mysql-devel:B cppunit:B gsoap:B classads voms lcas gridsite/ ], + 'lb.state-machine' => [ qw/classads/ ], + 'lb.utils' => [ qw/cppunit:B/ ], + 'lb.ws-interface' => [], + 'lb.ws-test' => [ qw/gsoap:B/ ], + 'lb.types' => [ qw// ], + 'lb.harvester' => [ qw// ], + 'lb.yaim' => [ qw/yaim_core:R/ ], + 'lb.glite-LB' => [ qw/fetchcrl:R gpt:R gip_release:R gip_service:R bdii:R glite_version:R glite_info_templates:R glue_schema:R/ ], + 'lbjp-common.db' => [ qw/mysql:B mysql-devel:B postgresql:B cppunit:B log4c:B/ ], + 'lbjp-common.log' => [ qw/log4c/ ], + 'lbjp-common.maildir' => [ qw// ], + 'lbjp-common.server-bones' => [ qw// ], + 'lbjp-common.trio' => [ qw/cppunit:B/ ], + 'lbjp-common.jp-interface' => [ qw/cppunit:B log4c:B/ ], + 'lbjp-common.gss' => [ qw/globus_essentials:R globus:B cares cppunit:B/ ], + 'lbjp-common.gsoap-plugin' => [ qw/cppunit:B globus_essentials:R globus:B cares:B gsoap:B/ ], + 'security.gss' => [ qw/globus_essentials:R globus:B cares cppunit:B/ ], + 'security.gsoap-plugin' => [ qw/cppunit:B globus_essentials:R globus:B cares:B gsoap:B/ ], + 'jobid.api-c' => [ qw/cppunit:B/ ], + 'jobid.api-cpp' => [ qw/cppunit:B/ ], + 'jobid.api-java' => [ qw/ant:B jdk:B/ ], + 'jp.client' => [ qw/gsoap libtar globus_essentials:R globus:B/ ], + 'jp.doc' => [], + 'jp.index' => [ qw/gsoap globus_essentials:R globus:B/ ], + 'jp.primary' => [ qw/classads gsoap libtar globus_essentials:R globus:B/ ], + 'jp.server-common' => [], + 'jp.ws-interface' => [], + 'gridsite.core' => [qw/httpd-devel:B gsoap:B globus:B/ ], + 'px.proxyrenewal' => [ qw/globus:B myproxy voms/ ], + 'px.glite-PX' => [qw/myproxy:R fetchcrl:R gip_service:R bdii:R glite_version:R/], + 'px.myproxy-yaim' => [ qw/yaim_core:R/ ], + 'px.myproxy-config' => [], +); + +for my $ext (keys %need_externs_aux) { + for (@{$need_externs_aux{$ext}}) { + /([^:]*)(?::(.*))?/; + push @{$need_externs{$ext}},$1; + my $type = $2 ? $2 : 'BR'; + $need_externs_type{$ext}->{$1} = $type; + } +} + +%need_jars = ( + 'jobid.api-java' => [ qw/jakarta-commons-codec/ ], + 'lb.client-java' => [ qw/jakarta-commons-lang/ ], +); + +for my $jar (keys %need_jars) { + for (@{$need_jars{$jar}}) { + $need_externs_type{$jar}->{$_} = 'BR'; # XXX + } +} + +%deps_aux = ( + 'lb.client' => [ qw/ + lb.types:B lb.common + lbjp-common.trio + jobid.api-cpp:B jobid.api-c + lbjp-common.gss + / ], + 'lb.client-java' => [ qw/ + lb.types:B + lb.ws-interface:B + jobid.api-java + / ], + 'lb.common' => [ qw/ + jobid.api-cpp:B jobid.api-c + lb.types:B lbjp-common.trio lbjp-common.gss + / ], + 'lb.doc' => [ qw/lb.types:B/ ], + 'lb.logger' => [ qw/ + lbjp-common.trio + lbjp-common.log + jobid.api-c + lb.common + lbjp-common.gss + / ], + 'lb.server' => [ qw/ + lb.ws-interface lb.types:B lb.common lb.state-machine + lbjp-common.db lbjp-common.server-bones lbjp-common.trio lbjp-common.maildir lbjp-common.log + jobid.api-c + lbjp-common.gsoap-plugin lbjp-common.gss + / ], + 'lb.state-machine' => [ qw/lb.types:B lb.common lbjp-common.jp-interface lbjp-common.gss/ ], + 'lb.utils' => [ qw/ + lbjp-common.jp-interface + jobid.api-c + lbjp-common.trio lbjp-common.maildir + lb.client lb.state-machine + / ], + 'lb.ws-test' => [ qw/lbjp-common.gsoap-plugin lb.ws-interface/ ], + 'lb.ws-interface' => [ qw/lb.types:B/ ], + 'lb.types' => [ qw// ], + 'lb.harvester' => [ qw/ + jobid.api-c lbjp-common.trio lbjp-common.db lb.common lb.client + lbjp-common.gss lbjp-common.log + / ], + 'lb.yaim' => [ qw// ], + 'lb.glite-LB' => [ qw/ + lb.logger:R lb.server:R lb.utils:R lb.doc:R + lb.ws-test:R lb.harvester:R lb.yaim:R lb.client-java:R + / ], + 'lbjp-common.db' => [ qw/lbjp-common.trio lbjp-common.log/ ], + 'lbjp-common.maildir' => [ qw// ], + 'lbjp-common.log' => [ qw// ], + 'lbjp-common.server-bones' => [ qw/lbjp-common.log/ ], + 'lbjp-common.trio' => [ qw// ], + 'lbjp-common.gss' => [ qw// ], + 'lbjp-common.gsoap-plugin' => [ qw/lbjp-common.gss/ ], + 'security.gss' => [ qw// ], + 'security.gsoap-plugin' => [ qw/security.gss/ ], + 'jobid.api-c' => [ qw// ], + 'jobid.api-cpp' => [ qw/jobid.api-c/ ], + 'jobid.api-java' => [ qw// ], + + 'lbjp-common.jp-interface' => [ qw/lbjp-common.db jobid.api-c/ ], + + 'jp.client' => [ qw/ + jp.ws-interface + lbjp-common.jp-interface lbjp-common.maildir + jobid.api-c + lbjp-common.gsoap-plugin + / ], + 'jp.doc' => [ qw// ], + 'jp.index' => [ qw/ + jp.server-common jp.ws-interface + lbjp-common.jp-interface lbjp-common.trio lbjp-common.db lbjp-common.server-bones + lbjp-common.gsoap-plugin + / ], + 'jp.primary' => [ qw/ + jobid.api-c + jp.server-common jp.ws-interface + lb.state-machine + lbjp-common.jp-interface lbjp-common.trio lbjp-common.db lbjp-common.server-bones + lbjp-common.gsoap-plugin + / ], + 'jp.server-common' => [ qw/ + lbjp-common.jp-interface lbjp-common.db + / ], + 'jp.ws-interface' => [ qw// ], + + 'gridsite.core' => [ qw/build.common-cpp:B/ ], + + 'px.proxyrenewal' => [ qw// ], + 'px.glite-PX' => [qw/px.myproxy-yaim:R/], + 'px.myproxy-yaim' => [], + 'px.myproxy-config' => [], +); + +for my $ext (keys %deps_aux) { + for (@{$deps_aux{$ext}}) { + /([^:]*)(?::(.*))?/; + push @{$deps{$ext}},$1; + my $type = $2 ? $2 : 'BR'; + $deps_type{$ext}->{$1} = $type; + } +} + + +%extrafull = ( gridsite=>'org.gridsite.core'); + +#( java => 'client-java' ); +%extranodmod = ( + db => 'lbjp-common.db', + jpprimary => 'jp.primary', + jpindex => 'jp.index', + jpclient => 'jp.client', +); + +%obsoletes = ( + 'lb.yaim' => [ qq/glite-yaim-lb/ ], + 'px.proxyrenewal' => [ qq/glite-security-proxyrenewal/ ], + 'px.myproxy-yaim' => [ qq/glite-yaim-myproxy/ ], + 'px.myproxy-config' => [ qq/myproxy-config/ ], + 'lbjp-common.gss' => [ qq/glite-security-gss/ ], + 'lbjp-common.gsoap-plugin' => [ qq/glite-security-gsoap-plugin/ ], +); + +%cvs_prefix = ( + 'lb' => 'org.glite', + 'jp' => 'org.glite', + 'jobid' => 'org.glite', + 'lbjp-common' => 'org.glite', + 'gridsite' => 'org', + 'security' => 'org.glite', + 'px' => 'org.glite', +); + +%conf_prefix = ( + 'lb' => 'glite-', + 'jp' => 'glite-', + 'jobid' => 'glite-', + 'lbjp-common' => 'glite-', + 'gridsite' => '', + 'security' => 'glite-', + 'px' => 'glite-', +); + +%emi_conf_prefix = ( + 'lb' => 'emi-', + 'jp' => 'emi-', + 'jobid' => 'emi-', + 'lbjp-common' => 'emi-', + 'gridsite' => '', + 'security' => 'emi-', + 'px' => 'emi-', +); + +my @k = keys %deps_aux; +@buildroot{@k} = ('build') x ($#k+1); + +my @t = qw/lb.client-java jobid.api-java lb.types/; +@buildroot{@t} = ('') x ($#t+1); + +$buildroot{'gridsite.core'} = 'src'; +} + +sub full +{ + my $short = shift; + return $extrafull{$short} ? $extrafull{$short} : 'org.glite.'.$short; +} + +sub mkinc +{ + my %aux; + undef %aux; + my @m=qw/ +lb.client lb.doc lb.state-machine lb.ws-interface lb.logger lb.types lb.common lb.server lb.utils lb.ws-test lb.client-java lb.harvester lb.yaim lb.glite-LB +security.gss security.gsoap-plugin +jobid.api-c jobid.api-cpp jobid.api-java +lbjp-common.db lbjp-common.log lbjp-common.maildir lbjp-common.server-bones lbjp-common.trio lbjp-common.jp-interface lbjp-common.gss lbjp-common.gsoap-plugin +jp.client jp.doc jp.index jp.primary jp.server-common jp.ws-interface +px.proxyrenewal px.myproxy-yaim px.glite-PX px.myproxy-config +/; + @aux{@m} = (1) x ($#m+1); + + my $short = shift; + my $full = full $short; + + unless ($aux{$short}) { + print "Makefile.inc not needed in $full\n"; + return; + } + + my $build = ''; + + unless ($buildroot{$_} eq '') { + $build = "/$buildroot{$_}"; + unless (-d "$full/$buildroot{$_}") { + mkdir "$full/$buildroot{$_}" or die "mkdir $full/$buildroot{$_}: $!\n"; + } + unlink "$full/$buildroot{$_}/Makefile"; + symlink "../Makefile","$full/$buildroot{$_}/Makefile" or die "symlink ../Makefile $full/$buildroot{$_}/Makefile: $!\n"; + } + + open MKINC,">$full/$buildroot{$_}/Makefile.inc" + or die "$full/$buildroot{$_}/Makefile.inc: $!\n"; + + print "Creating $full/$buildroot{$_}/Makefile.inc\n"; + + print MKINC qq{ +PREFIX = $prefix +stagedir = $stagedir +thrflavour = $thrflavour +nothrflavour = $nothrflavour +libdir = $libdir +}; + + for (@{$need_externs{$short}}) { + print MKINC "${_}_prefix = $externs{$_}{prefix}\n"; + print MKINC "$externs{$_}{flags}" if defined $externs{$_}{flags}; + } + + for (@{$need_jars{$short}}) { + print MKINC "${_}_jar = $jar{$_}\n" + } + + my $need_gsoap = 0; + for (@{$need_externs{$short}}) { $need_gsoap = 1 if $_ eq 'gsoap'; } + + print MKINC "gsoap_default_version=".gsoap_version()."\n" if $need_gsoap; + + close MKINC; +} + +my %etics_externs; +my %etics_projects; +BEGIN{ + %etics_externs = ( + globus_essentials=>'vdt_globus_essentials', + globus=>'globus', + myproxy=>'myproxy', + cares=>'c-ares', + voms=>'org.glite.security.voms-api-cpp', + gridsite=>'org.gridsite.shared', + lcas=>'org.glite.security.lcas', + trustmanager=>'org.glite.security.trustmanager', + utiljava=>'org.glite.security.util-java', + gpt=>'gpt', + fetchcrl=>'fetch-crl', + gip_release=>'glite-info-provider-release', + gip_service=>'glite-info-provider-service', + bdii=>'bdii', + glite_version=>'glite-version', + glite_info_templates=>'glite-info-templates', + glue_schema=>'glue-schema', + yaim_core=>'org.glite.yaim.core', + ); + %etics_projects = ( + vdt=>[qw/globus globus_essentials myproxy/], + 'org.glite'=>[qw/voms gridsite lcas gpt gip_release gip_service bdii glite_version glite_info_templates glue_schema yaim_core/], + ); + + %platform_properties = ( + 'gridsite.core' => { + sl5_x86_64_gcc412 => { aprSuffix => '1' }, + sl5_ia32_gcc412 => { aprSuffix => '1' }, + deb5_x86_64_gcc432 => { aprSuffix => '1.0' }, + deb5_ia32_gcc432 => { aprSuffix => '1.0' }, + slc4_x86_64_gcc346 => { aprSuffix => '0' }, + slc4_ia32_gcc346 => { aprSuffix => '0' }, + default => { + } + }, + ); +}; + +sub mode_etics { + $fmod = shift; + + die "$0: --module required with --etics\n" unless $fmod; + + my ($subsys,$module) = split /\./,$fmod; + + my ($major,$minor,$rev,$age); + + if ($version) { + $version =~ /([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)-(.+)/; + ($major,$minor,$rev,$age) = ($1,$2,$3,$4); + } + else { + open V,"$cvs_prefix{$subsys}.$subsys.$module/project/version.properties" + or die "$cvs_prefix{$subsys}.$subsys.$module/project/version.properties: $!\n"; + + while ($_ = ) { + chomp; + ($major,$minor,$rev) = ($1,$2,$3) if /module\.version\s*=\s*([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/; + $age = $1 if /module\.age\s*=\s*([[:digit:]]+)/; + } + close V; + } + + my @copts = (); + my %ge; + @ge{@{$etics_projects{'org.glite'}}} = (1) x ($#{$etics_projects{'org.glite'}}+1); + + for (@{$need_externs{"$subsys.$module"}}) { + if ($need_externs_type{"$subsys.$module"}->{$_}=~/B/) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + if ($emi) { + if ($ge{$_} and not defined $externs{$_}{pkg}) { + push @copts, "--with-$_=\${stageDir}"; + } + } else { + push @copts,$ge{$_} ? "--with-$_=\${stageDir}" : "--with-$_=\${$eext.location}"; + } + } + } + + for (@{$need_jars{"$subsys.$module"}}) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + + push @copts,"--with-$_ \${$eext.location}$jar{$_}" if (not $emi); + } + + my $conf; + my $conftag; + my $confprefix; + + $dwpath = "path = \${projectName}/\${moduleName}/\${version}/\${platformName}/\${packageName}-\${version}-\${age}.tar.gz\n"; + + if ($emi) { $confprefix = $emi_conf_prefix{$subsys} } + else { $confprefix = $conf_prefix{$subsys} } + + if ($branch) { + $conf = "$confprefix${subsys}-${module}_$branch"; + $conftag = $branch; + # forced low age number + $age = $branch eq 'HEAD' ? '0head' : '0dev'; } + else { + $conf = "$confprefix$subsys-${module}_R_${major}_${minor}_${rev}_${age}"; + +# XXX: gridsite hack + $conftag = $subsys eq 'gridsite' ? "$conf_prefix{$subsys}$subsys-${module}_R_${major}_${minor}_${rev}" : + "$conf_prefix{$subsys}$subsys-${module}_R_${major}_${minor}_${rev}_${age}"; } + if ($emi) { + $age = "${age}emi"; + } + + my $file = $output ? $output : "$conf.ini"; + open C,">$file" or die "$file: $!\n"; + + my $buildroot = $buildroot{"$subsys.$module"} eq '' ? '#no build.root' : "build.root = " . $buildroot{"$subsys.$module"}; + + my $confdir = $buildroot{"$subsys.$module"} eq '' ? '..' : '../..'; + + my $package_description = ""; + my $package_summary = ""; + + if (-e "$cvs_prefix{$subsys}.$subsys.$module/project/package.description") { + open V, "$cvs_prefix{$subsys}.$subsys.$module/project/package.description"; + $package_description = join ("", ); + close V; + chomp $package_description; + $package_description =~ s/\n/\\n/g; + $package_description = "package.description = $package_description\n"; + } + else { + print STDERR "package.description not found for $subsys.$module!\n"; } + + if (-e "$cvs_prefix{$subsys}.$subsys.$module/project/package.summary") { + open V, "$cvs_prefix{$subsys}.$subsys.$module/project/package.summary"; + $package_summary = join ("", ); + close V; + chomp $package_summary; + $package_summary =~ s/\n/\\n/g; + $package_summary = "package.summary = $package_summary\n"; + } + else { + print STDERR "package.summary not found for $subsys.$module!\n"; } + + my %cmd; + @cmd{qw/configure compile test install packaging clean/} = ('None') x 6; + $cmd{clean} = 'make clean'; + + if ($subsys eq 'gridsite') { + if ($module eq 'core') { + my $flags = 'RELEASE_VERSION=${age}.${platformFamily} prefix=${prefix} libdir=${libdir} GSOAPDIR=${gsoap.location} OPENSSL_GLOBUS_FLAGS=-I${globus.location}/include/${globus.dbg.nothr.flavor} OPENSSL_GLOBUS_LIBS=-L${globus.location}/${libdir}/ FLAVOR_GLOBUS_EXT=_${globus.dbg.nothr.flavor} HTTPD_FLAGS="-I${httpd-devel.location}/include/httpd -I${httpd-devel.location}/include/apache2 -I${httpd-devel.location}/include/apr-${aprSuffix} -I${httpd-devel.location}/include/pcre"'; + + $cmd{compile} = "make $flags build"; + $cmd{install} = "make $flags install"; + $cmd{packaging} = "make $flags rpm"; + } + else { + $cmd{packaging} = "echo building nothing, org.gridsite.core make rpm step will create this"; + } + } + else { + my $flavours = $emi ? "--thrflavour= --nothrflavour=" : "--thrflavour=\${globus.thr.flavor} --nothrflavour=\${globus.nothr.flavor}"; + $cmd{configure} = "cd $confdir && /usr/bin/perl \${moduleName}/configure $flavours --prefix=\${prefix} --stage=\${stageDir} --libdir=\${libdir} --module $subsys.$module @copts"; + $cmd{compile} = 'make'; + $cmd{test} = 'make check'; + $cmd{install} = 'make install'; + } + + my $defprops = ''; + + for my $p (keys %{$platform_properties{"$subsys.$module"}->{default}}) { + $defprops .= $p . ' = ' . $platform_properties{"$subsys.$module"}->{default}->{$p} . "\n"; + } + + my $checkoutcmd; + if ($conftag eq 'HEAD') { + $checkoutcmd = "cvs -d \${vcsroot} co -A \${moduleName}"; + } else { + $checkoutcmd = "cvs -d \${vcsroot} co -r \${tag} \${moduleName}"; + } + + print STDERR "Writing $file\n"; + print C qq{ +[Configuration-$conf] +profile = None +moduleName = $cvs_prefix{$subsys}.$subsys.$module +displayName = $conf +description = $cvs_prefix{$subsys}.$subsys.$module +projectName = org.glite +age = $age +deploymentType = None +tag = $conftag +version = $major.$minor.$rev +$dwpath +[Platform-default:VcsCommand] +displayName = None +description = None +tag = cvs -d \${vcsroot} tag -R \${tag} \${moduleName} +branch = None +commit = None +checkout = $checkoutcmd + +[Platform-default:BuildCommand] +postpublish = None +packaging = $cmd{packaging} +displayName = None +description = None +doc = None +prepublish = None +publish = None +compile = $cmd{compile} +init = None +install = $cmd{install} +clean = $cmd{clean} +test = $cmd{test} +configure = $cmd{configure} +checkstyle = None + +[Platform-default:Property] +$buildroot +aprSuffix = 0 +package.RPMSLocation = \${moduleDir}/RPMTMP/RPMS +package.SRPMSLocation = \${moduleDir}/RPMTMP/SRPMS +package.preserve.libtool = false +$package_description$package_summary$defprops}; + + for (@{$obsoletes{"$subsys.$module"}}) { + print C "package.obsoletes = $_\n"; + print C "package.replaces = $_\n"; + } + + for my $pp (keys %{$platform_properties{"$subsys.$module"}}) { + next if $pp eq 'default'; + print C "[Platform-$pp:Property]\n$buildroot\n"; + + for my $p (keys %{$platform_properties{"$subsys.$module"}->{$pp}}) { + print C $p . ' = ' . $platform_properties{"$subsys.$module"}->{$pp}->{$p} . "\n"; + } + print C q{package.RPMSLocation = ${moduleDir}/RPMTMP/RPMS +package.SRPMSLocation = ${moduleDir}/RPMTMP/SRPMS +}; + print C "$package_description$package_summary\n"; + } + + print C qq{ +[Platform-default:DynamicDependency] +}; + for (@{$need_externs{"$subsys.$module"}},@{$need_jars{"$subsys.$module"}}) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + + my $proj = 'externals'; + for my $p (keys %etics_projects) { + for $m (@{$etics_projects{$p}}) { + $proj = $p if $m eq $_; + } + } + + my $type = $need_externs_type{"$subsys.$module"}->{$_}; + print C "$proj|$eext = $type\n"; + } + + for (@{$deps{"$subsys.$module"}}) { + my $type = $deps_type{"$subsys.$module"}->{$_}; + print C "org.glite|org.glite.$_ = $type\n"; + } + + close C; +} + +sub gsoap_version { + local $_; + my $gsoap_version; + open S,"$externs{gsoap}{prefix}/bin/soapcpp2 -v 2>&1 |" or die "$externs{gsoap}{prefix}/bin/soapcpp2: $!\n"; + + while ($_ = ) { + chomp; + + $gsoap_version = $1 if /The gSOAP Stub and Skeleton Compiler for C and C\+\+ ([.[:digit:][:alpha:]]+)$/; + } + close S; + return $gsoap_version; +} + +sub getlibdir { + if ( -e "/etc/debian_version") { # We are on Debian + $lib64="lib"; + $lib32="lib32"; } + else { # Another distribution + $lib64="lib64"; + $lib32="lib"; } + $libdir=$lib32; + + open INP, "uname -s | "; # Check kernel name + $kname= ; + chomp($kname); + close INP; + + if ( $kname == "Linux") { + $arch = ("x86_64\npowerpc\nppc64\n"); + + open INP, "uname -p | "; # Check processor type + $procname= ; + chomp($procname); + close INP; + + if ($arch =~/^$procname\n/) { + return ($lib64); } + + open INP, "uname -m | "; # Check machine hardware + $machname= ; + chomp($machname); + close INP; + + if ($arch =~/^$machname\n/) { + return ($lib64); } + + # special cases (hyperlink lib64, Debian) + if (-l "/usr/lib64") { + $libdir=$lib32; } + + # if /usr/lib64 doesn't exist at all (AIX) + unless ( -e "/usr/lib64" ) { + $libdir=$lib32; } + } + + if ( $kname == "SunOS") { + if (-e "/usr/lib/64") { + $libdir="lib/64"; } + } + + return $libdir; +} + +sub usage { + my @ext = keys %externs; + my @myjars, keys %jar; + + print STDERR qq{ +usage: $0 options + +General options (defaults in []): + --prefix=PREFIX destination directory [./stage] + --staged=module,module,... what is already in PREFIX (specify without org.glite.) + --thrflavour=flavour + --nothrflavour=flavour threaded and non-treaded flavours [gcc64dbgpthr,gcc64dbg] + --listmodules=subsys list modules of a subsystem + --version=maj.min.rev-age specify version here instead of reading version.properties + --branch=branch CVS branch/etics name suffix (HEAD, branch_2_1, ...) + --libdir=libdir typically [lib,lib64] postfix + --emi generate configurations with emi flavor in mode 'etics' + +Mode of operation: + --mode={checkout|build|etics} what to do [build] + +What to build: + --module=module build this module only (mostly in-Etics operation) + --enable-NODE build this "node" (set of modules) only. Available nodes are + @{$lbmodules{lb}},@{$lbmodules{security}} + --disable-NODE don't build this node + --lb-tag=tag checkout LB modules with specific tag + --jp-tag=tag checkout JP modules with specific tag + --lbjp-common-tag=tag checkout lbjp-common modules with specific tag + --security-tag=tag checkout security modules with specific tag + --jobid-tag=tag checkout jobid modules with specific tag + +Dependencies: + --with-EXTERNAL=PATH where to look for an external. Required externals + (not all for all modules) are: + @ext + --with-JAR=JAR where to look for jars. Required jars are: + @myjars + Summary of what will be used is always printed + +}; + +} diff --git a/org.glite.lbjp-common.gss/interface/glite_gss.h b/org.glite.lbjp-common.gss/interface/glite_gss.h new file mode 100644 index 0000000..37f719f --- /dev/null +++ b/org.glite.lbjp-common.gss/interface/glite_gss.h @@ -0,0 +1,188 @@ +#ifndef __EDG_WORKLOAD_LOGGING_COMMON_LB_GSS_H__ +#define __EDG_WORKLOAD_LOGGING_COMMON_LB_GSS_H__ + +#ident "$Header$" +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +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 */ +}; + +enum { + EDG_WLL_GSS_FLAG_DELEG = 1, + EDG_WLL_GSS_FLAG_CONF = 16, + EDG_WLL_GSS_FLAG_INTEG = 32, + EDG_WLL_GSS_FLAG_ANON = 64, +}; + +typedef void * edg_wll_GssCtx; + +typedef struct _edg_wll_GssConnection { + edg_wll_GssCtx context; + int sock; + char *buffer; + size_t bufsize; +} edg_wll_GssConnection; + +typedef struct _edg_wll_GssStatus { + unsigned int major_status; + unsigned int minor_status; +} edg_wll_GssStatus; + +typedef struct _edg_wll_GssPrincipal_data { + char *name; + unsigned int flags; + char **fqans; +#if 0 + char **voms_groups; /* needed for legacy LB server authZ mechanism */ + edg_wll_GssOid authn_mech; +#endif +} edg_wll_GssPrincipal_data; +typedef struct _edg_wll_GssPrincipal_data *edg_wll_GssPrincipal; + +typedef struct _edg_wll_GssCred_data { + void *gss_cred; + time_t lifetime; + char *name; +} _edg_wll_GssCred_data; +typedef struct _edg_wll_GssCred_data *edg_wll_GssCred; + +int +edg_wll_gss_initialize(void); + +void +edg_wll_gss_finalize(void); + +int +edg_wll_gss_acquire_cred_gsi(const char *cert_file, + const char *key_file, + edg_wll_GssCred *cred, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_release_cred(edg_wll_GssCred *cred, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_connect(edg_wll_GssCred cred, + char const *hostname, + int port, + struct timeval *timeout, + edg_wll_GssConnection *connection, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_accept(edg_wll_GssCred 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_get_client_conn(edg_wll_GssConnection *connection, + edg_wll_GssPrincipal *principal, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_get_client_pem(edg_wll_GssConnection *connection, + const char *my_cert_file, const char *my_key_file, + char **pem_string); + +void +edg_wll_gss_free_princ(edg_wll_GssPrincipal principal); + +int +edg_wll_gss_gethostname(char *name, int len); + +char * +edg_wll_gss_normalize_subj(char *in, + int replace_in); + +int +edg_wll_gss_equal_subj(const char *a, + const char *b); + +int +edg_wll_gss_unread(edg_wll_GssConnection *connection, + void *data, + size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* __EDG_WORKLOAD_LOGGING_COMMON_LB_GSS_H__ */ diff --git a/org.glite.lbjp-common.gss/project/ChangeLog b/org.glite.lbjp-common.gss/project/ChangeLog new file mode 100644 index 0000000..3a73c6b --- /dev/null +++ b/org.glite.lbjp-common.gss/project/ChangeLog @@ -0,0 +1,47 @@ +2.0.0-1 +- LB 2.0 release + +2.0.0-2 +- proper reference to cppunit + +2.0.0-3 +- globus flavors added to configure + +2.0.0-4 +- Module repacked. + +2.0.0-5 +- New age to fix an erroneous lock + +2.0.0-6 +- install libraries into $libdir + +2.0.1-1 +- Memleak fixes +- Working with c-ares >= 1.5.0 +- Added edg_wll_gss_unread() +- Consider arch libdir when linking c-ares + +2.1.0-1 +- IPv6 fixes + +2.1.1-1 +- Fixed making target 'check' + +2.1.2-1 +- Fixed target 'clean' in the Makefile to handle debian builds + +2.1.3-1 +- c-ares function call adjusted to new/old c-ares version + +2.1.4-1 +- Support IPv6 literal adresses. + +2.1.5-1 +- EMI build (flavor-less globus, pkg-config, ...) +- fix using globus in thread environment +- new finalize function + +2.1.5-2 +- Module rebuilt + diff --git a/org.glite.lbjp-common.gss/project/version.properties b/org.glite.lbjp-common.gss/project/version.properties new file mode 100644 index 0000000..2cf185d --- /dev/null +++ b/org.glite.lbjp-common.gss/project/version.properties @@ -0,0 +1,3 @@ +# $Header$ +module.version=2.1.5 +module.age=2 diff --git a/org.glite.lbjp-common.gss/src/glite_gss.c b/org.glite.lbjp-common.gss/src/glite_gss.c new file mode 100644 index 0000000..f77c3c3 --- /dev/null +++ b/org.glite.lbjp-common.gss/src/glite_gss.c @@ -0,0 +1,1553 @@ +#ident "$Header$" +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "glite_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 globus_common_activated = 0; + +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() */ +#if ARES_VERSION >= 0x010500 +static void callback_ares_gethostbyname(void *arg, int status, int timeouts, struct hostent *h) +#else +static void callback_ares_gethostbyname(void *arg, int status, struct hostent *h) +#endif +{ + 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(h->h_length); + 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], + h->h_length); + arp->ent->h_addr_list[1] = NULL; + arp->ent->h_addrtype = h->h_addrtype; + 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_getservbyname2(int af, struct sockaddr_storage *addrOut, socklen_t *a_len,char const *name, int port, 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; + int err = NETDB_INTERNAL; + char *name2, *p; + size_t namelen; + + name2 = name; + namelen = strlen(name); + if (name[0]=='[' && name[namelen-1]==']') { + /* IPv6 literal, strip brackets */ + name2 = strdup(name); + if (!name2) return NETDB_INTERNAL; + name2[namelen-1] = '\0'; + name2++; + /* Ignore scope identifier, not supported by c-ares */ + p = strchr(name2, '%'); + if (p) *p = '\0'; + } + +/* 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, name2, af, callback_ares_gethostbyname, + (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 (timeout && 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); + } + } + + if (ar.err == NETDB_SUCCESS) { + struct sockaddr_in *p4 = (struct sockaddr_in *)addrOut; + struct sockaddr_in6 *p6 = (struct sockaddr_in6 *)addrOut; + + memset(addrOut, 0, sizeof *addrOut); + addrOut->ss_family = ar.ent->h_addrtype; + switch (ar.ent->h_addrtype) { + case AF_INET: + memcpy(&p4->sin_addr,ar.ent->h_addr_list[0], sizeof(struct in_addr)); + p4->sin_port = htons(port); + *a_len = sizeof (struct sockaddr_in); + break; + case AF_INET6: + memcpy(&p6->sin6_addr,ar.ent->h_addr_list[0], sizeof(struct in6_addr)); + p6->sin6_port = htons(port); + *a_len = sizeof (struct sockaddr_in6); + break; + default: + return NETDB_INTERNAL; + break; + } + } + free_hostent(ar.ent); ar.ent = NULL; + err = ar.err; + + /* literal conversion should always succeed */ + if (name2 != name) free(name2-1); + + ares_destroy(channel); + + return err; +} + +static int asyn_getservbyname(struct sockaddr_storage *addrOut, socklen_t *a_len,char const *name, int port, struct timeval *timeout) { + int res; + + res = asyn_getservbyname2(AF_INET6, addrOut, a_len, name, port, timeout); + if (res != HOST_NOT_FOUND) return res; + res = asyn_getservbyname2(AF_INET, addrOut, a_len, name, port, timeout); + return res; +} + +static int +do_connect(int *s, char const *hostname, int port, struct timeval *timeout) +{ + int sock; + struct timeval before,after,to; + struct sockaddr_storage a; + socklen_t a_len; + int sock_err; + socklen_t err_len; + int h_errno; + int opt; + + /* XXX todo: try multiple addresses */ + switch (h_errno = asyn_getservbyname(&a, &a_len, hostname, port, timeout)) { + case NETDB_SUCCESS: + 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; + } + + sock = socket(a.ss_family, SOCK_STREAM, 0); + if (sock < 0) return EDG_WLL_GSS_ERROR_ERRNO; + + opt = 1; + setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,&opt,sizeof opt); + + 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 (connect(sock,(struct sockaddr *) &a, a_len) < 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) { + if (tl==0) { + free(t); + return EDG_WLL_GSS_ERROR_EOF; + } else goto end; + } + tmp=realloc(t, tl + count); + if (tmp == NULL) { + errno = ENOMEM; + free(t); + return EDG_WLL_GSS_ERROR_ERRNO; + } + t = tmp; + memcpy(t + tl, buf, count); + tl += count; + + } while (count < 0); /* restart on EINTR */ + +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(const char *cert_file, const 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; + } + + len = write(out, "\n", 1); + if (len != 1) { + 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(const char *cert_file, const char *key_file, edg_wll_GssCred *cred, + 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; + char *name = 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 = (char *)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; + } + + 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 = calloc(1, sizeof(**cred)); + if (*cred == NULL) { + ret = EDG_WLL_GSS_ERROR_ERRNO; + free(name); + goto end; + } + + (*cred)->gss_cred = gss_cred; + gss_cred = GSS_C_NO_CREDENTIAL; + (*cred)->lifetime = lifetime; + (*cred)->name = name; + + 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; +} + +/* XXX XXX This is black magic. "Sometimes" server refuses the client with SSL + * * alert "certificate expired" even if it is not true. In this case the server + * * slave terminates (which helps, usually), and we can reconnect transparently. + * */ + +/* This string appears in the error message in this case */ +#define _EXPIRED_ALERT_MESSAGE "function SSL3_READ_BYTES: sslv3 alert certificate expired" +#define _EXPIRED_ALERT_RETRY_COUNT 10 /* default number of slaves, hope that not all + are in the bad state */ +#define _EXPIRED_ALERT_RETRY_DELAY 10 /* ms */ + +/* XXX XXX This is black magic. "Sometimes" server refuses the client with SSL + * * alert "certificate expired" even if it is not true. In this case the server + * * slave terminates (which helps, usually), and we can reconnect transparently. + * */ + +/* This string appears in the error message in this case */ +#define _EXPIRED_ALERT_MESSAGE "function SSL3_READ_BYTES: sslv3 alert certificate expired" +#define _EXPIRED_ALERT_RETRY_COUNT 10 /* default number of slaves, hope that not all + are in the bad state */ +#define _EXPIRED_ALERT_RETRY_DELAY 10 /* ms */ + +int +edg_wll_gss_connect(edg_wll_GssCred 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; + int retry = _EXPIRED_ALERT_RETRY_COUNT; + + maj_stat = min_stat = min_stat2 = req_flags = 0; + memset(connection, 0, sizeof(*connection)); + + /* 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 */ + + do { /* XXX: the black magic above */ + + /* 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->gss_cred, &context, + GSS_C_NO_NAME, GSS_C_NO_OID, + req_flags | GSS_C_MUTUAL_FLAG | GSS_C_CONF_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) { + gss_delete_sec_context(&min_stat2, &context, &output_token); + context = GSS_C_NO_CONTEXT; + if (output_token.length) { + send_token(sock, output_token.value, output_token.length, timeout); + gss_release_buffer(&min_stat2, &output_token); + } + } + 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 */ + + /* retry on false "certificate expired" */ + if (ret == EDG_WLL_GSS_ERROR_GSS) { + edg_wll_GssStatus gss_stat; + char *msg = NULL; + + gss_stat.major_status = maj_stat; + gss_stat.minor_status = min_stat; + edg_wll_gss_get_error(&gss_stat,"",&msg); + + if (strstr(msg,_EXPIRED_ALERT_MESSAGE)) { + usleep(_EXPIRED_ALERT_RETRY_DELAY); + retry--; + } + else retry = 0; + + free(msg); + } + else retry = 0; + + } while (retry); + + 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(edg_wll_GssCred 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; + memset(connection, 0, sizeof(*connection)); + + if (cred == NULL) + return EINVAL; + + /* 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; + + if (client_name != GSS_C_NO_NAME) + gss_release_name(&min_stat2, &client_name); + + maj_stat = gss_accept_sec_context(&min_stat, &context, + cred->gss_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) { + gss_delete_sec_context(&min_stat2, &context, &output_token); + context = GSS_C_NO_CONTEXT; + if (output_token.length) { + send_token(sock, output_token.value, output_token.length, timeout); + gss_release_buffer(&min_stat2, &output_token); + } + } + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + +#if 0 + maj_stat = gss_display_name(&min_stat, client_name, &output_token, NULL); + gss_release_buffer(&min_stat2, &output_token); + if (GSS_ERROR(maj_stat)) { + /* XXX close context ??? */ + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } +#endif + + connection->sock = sock; + connection->context = context; + 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, 1, 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, min_stat2; + gss_buffer_desc input_token; + gss_buffer_desc output_token; + size_t i, len; + int ret; + + if (connection->bufsize > 0) { + len = (connection->bufsize < bufsize) ? connection->bufsize : bufsize; + memcpy(buf, connection->buffer, len); + if (connection->bufsize - len == 0) { + free(connection->buffer); + connection->buffer = NULL; + } else { + for (i = 0; i < connection->bufsize - len; i++) + connection->buffer[i] = connection->buffer[i+len]; + } + connection->bufsize -= len; + + return len; + } + + do { + ret = recv_token(connection->sock, &input_token.value, &input_token.length, + timeout); + if (ret) + return ret; + + ERR_clear_error(); + maj_stat = gss_unwrap(&min_stat, connection->context, &input_token, + &output_token, NULL, NULL); + gss_release_buffer(&min_stat2, &input_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; + } + } while (maj_stat == 0 && output_token.length == 0 && output_token.value == NULL); + + if (output_token.length > bufsize) { + connection->bufsize = output_token.length - bufsize; + connection->buffer = malloc(connection->bufsize); + if (connection->buffer == NULL) { + connection->bufsize = 0; + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + memcpy(connection->buffer, output_token.value + bufsize, connection->bufsize); + output_token.length = bufsize; + } + + memcpy(buf, output_token.value, output_token.length); + ret = output_token.length; + +end: + gss_release_buffer(&min_stat, &output_token); + + return ret; +} + +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) +{ + size_t len, i; + *total = 0; + + if (connection->bufsize > 0) { + len = (connection->bufsize < bufsize) ? connection->bufsize : bufsize; + memcpy(buf, connection->buffer, len); + if (connection->bufsize - len == 0) { + free(connection->buffer); + connection->buffer = NULL; + } else { + for (i = 0; i < connection->bufsize - len; i++) + connection->buffer[i] = connection->buffer[i+len]; + } + connection->bufsize -= len; + *total = len; + } + + while (*total < bufsize) { + int len; + + 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); +} + +/* Request credential reload each 60 seconds in order to work around + * Globus bug (not reloading expired CRLs) + */ +#define GSS_CRED_WATCH_LIMIT 60 +int +edg_wll_gss_watch_creds(const char *proxy_file, time_t *last_time) +{ + struct stat pstat; + time_t now; + + now = time(NULL); + + if ( now >= (*last_time+GSS_CRED_WATCH_LIMIT) ) { + *last_time = now; + return 1; + } + + if (!proxy_file) return 0; + if (stat(proxy_file,&pstat)) return -1; + + if ( pstat.st_mtime >= *last_time ) { + *last_time = now + 1; + return 1; + } + + return 0; +} + +int +edg_wll_gss_close(edg_wll_GssConnection *con, struct timeval *timeout) +{ + OM_uint32 min_stat; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + struct timeval def_timeout = { 0, 100000}; + + if (con->context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&min_stat, (gss_ctx_id_t *)&con->context, &output_token); + +#if 0 + /* XXX: commented out till timeout handling in caller is fixed */ + + /* send the buffer (if any) to the peer. GSSAPI specs doesn't + * recommend sending it, but we want SSL compatibility */ + if (output_token.length && con->sock>=0) { + send_token(con->sock, output_token.value, output_token.length, + timeout ? timeout : &def_timeout); + } +#endif + gss_release_buffer(&min_stat, &output_token); + + /* 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); + } + if (con->buffer) + free(con->buffer); + 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; +} + + +int +edg_wll_gss_initialize(void) +{ + int ret = 0; + + if (globus_module_activate(GLOBUS_GSI_GSSAPI_MODULE) != GLOBUS_SUCCESS) { + errno = EINVAL; + ret = EDG_WLL_GSS_ERROR_ERRNO; + } + + if (globus_module_activate(GLOBUS_COMMON_MODULE) == GLOBUS_SUCCESS) + globus_common_activated = 1; + + return ret; +} + + +void +edg_wll_gss_finalize(void) +{ + globus_module_deactivate(GLOBUS_GSI_GSSAPI_MODULE); + if (globus_common_activated) { + globus_module_deactivate(GLOBUS_COMMON_MODULE); + globus_common_activated = 0; + } +} + + +int +edg_wll_gss_release_cred(edg_wll_GssCred *cred, edg_wll_GssStatus* gss_code) +{ + OM_uint32 maj_stat, min_stat; + int ret = 0; + + if (gss_code) + gss_code->major_status = gss_code->minor_status = 0; + + if (cred == NULL || *cred == NULL) + return ret; + + if ((*cred)->gss_cred) { + maj_stat = gss_release_cred(&min_stat, (gss_cred_id_t*)&(*cred)->gss_cred); + if (GSS_ERROR(maj_stat)) { + ret = EDG_WLL_GSS_ERROR_GSS; + if (gss_code) { + gss_code->major_status = maj_stat; + gss_code->minor_status = min_stat; + } + } + } + + if ((*cred)->name) + free((*cred)->name); + + free(*cred); + *cred = NULL; + + return ret; +} + +int +edg_wll_gss_get_client_conn(edg_wll_GssConnection *connection, + edg_wll_GssPrincipal *principal, + edg_wll_GssStatus* gss_code) +{ + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + OM_uint32 maj_stat, min_stat, ctx_flags; + gss_name_t client_name = GSS_C_NO_NAME; + edg_wll_GssPrincipal p; + int ret; + + maj_stat = gss_inquire_context(&min_stat, connection->context, &client_name, + NULL, NULL, NULL, &ctx_flags, NULL, NULL); + if (GSS_ERROR(maj_stat)) + goto end; + + maj_stat = gss_display_name(&min_stat, client_name, &token, NULL); + if (GSS_ERROR(maj_stat)) + goto end; + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + errno = ENOMEM; + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + + p->name = strdup(token.value); + p->flags = ctx_flags; + + *principal = p; + ret = 0; + +end: + if (GSS_ERROR(maj_stat)) { + ret = EDG_WLL_GSS_ERROR_GSS; + if (gss_code) { + gss_code->major_status = maj_stat; + gss_code->minor_status = min_stat; + } + } + + if (token.length) + gss_release_buffer(&min_stat, &token); + if (client_name != GSS_C_NO_NAME) + gss_release_name(&min_stat, &client_name); + + return ret; +} + +/* Beware, this call manipulates with environment variables and is not + thread-safe */ +static int +get_peer_cred(edg_wll_GssConnection *gss, const char *my_cert_file, + const char *my_key_file, STACK_OF(X509) **chain, + edg_wll_GssStatus* gss_code) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER; + BIO *bio = NULL; + SSL_SESSION *session = NULL; + unsigned char int_buffer[4]; + long length; + int ret, index; + STACK_OF(X509) *cert_chain = NULL; + X509 *p_cert; + char *orig_cert = NULL, *orig_key = NULL; + + maj_stat = gss_export_sec_context(&min_stat, (gss_ctx_id_t *) &gss->context, + &buffer); + if (GSS_ERROR(maj_stat)) { + if (gss_code) { + gss_code->major_status = maj_stat; + gss_code->minor_status = min_stat; + } + return EDG_WLL_GSS_ERROR_GSS; + } + + /* The GSSAPI specs requires gss_export_sec_context() to destroy the + * context after exporting. So we have to resurrect the context here by + * importing from just generated buffer. gss_import_sec_context() must be + * able to read valid credential before it loads the exported context + * so we set the environment temporarily to point to the ones used by + * the server. + * */ + + orig_cert = getenv("X509_USER_CERT"); + orig_key = getenv("X509_USER_KEY"); + + if (my_cert_file) + setenv("X509_USER_CERT", my_cert_file, 1); + if (my_key_file) + setenv("X509_USER_KEY", my_key_file, 1); + + maj_stat = gss_import_sec_context(&min_stat, &buffer, + (gss_ctx_id_t *)&gss->context); + + if (orig_cert) + setenv("X509_USER_CERT", orig_cert, 1); + else + unsetenv("X509_USER_CERT"); + + if (orig_key) + setenv("X509_USER_KEY", orig_key, 1); + else + unsetenv("X509_USER_KEY"); + + if (GSS_ERROR(maj_stat)) { + if (gss_code) { + gss_code->major_status = maj_stat; + gss_code->minor_status = min_stat; + } + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + ret = ENOMEM; + goto end; + } + + /* Store exported context to memory, skipping the version number and and cred_usage fields */ + BIO_write(bio, buffer.value + 8 , buffer.length - 8); + + /* decode the session data in order to skip at the start of the cert chain */ + session = d2i_SSL_SESSION_bio(bio, NULL); + if (session == NULL) { + ret = EINVAL; + goto end; + } + SSL_SESSION_free(session); + + cert_chain = sk_X509_new_null(); + + BIO_read(bio, (char *) int_buffer, 4); + length = (((size_t) int_buffer[0]) << 24) & 0xffff; + length |= (((size_t) int_buffer[1]) << 16) & 0xffff; + length |= (((size_t) int_buffer[2]) << 8) & 0xffff; + length |= (((size_t) int_buffer[3]) ) & 0xffff; + + if (length == 0) { + ret = EINVAL; + goto end; + } + + for(index = 0; index < length; index++) { + p_cert = d2i_X509_bio(bio, NULL); + if (p_cert == NULL) { + ret = EINVAL; + sk_X509_pop_free(cert_chain, X509_free); + goto end; + } + + sk_X509_push(cert_chain, p_cert); + } + + *chain = cert_chain; + ret = 0; + +end: + gss_release_buffer(&min_stat, &buffer); + + return ret; +} + +int +edg_wll_gss_get_client_pem(edg_wll_GssConnection *connection, + const char *my_cert_file, const char *my_key_file, + char **pem_string) +{ + char *tmp = NULL; + STACK_OF(X509) *chain = NULL; + BIO *bio = NULL; + int ret, i; + size_t total_len, l; + + ret = get_peer_cred(connection, my_cert_file, my_key_file, &chain, NULL); + if (ret) + return ret; + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + ret = ENOMEM; + goto end; + } + + for (i = 0; i < sk_X509_num(chain); i++) { + ret = PEM_write_bio_X509(bio, sk_X509_value(chain, i)); + if (ret <= 0) { + ret = EINVAL; + goto end; + } + } + + total_len = BIO_pending(bio); + if (total_len <= 0) { + ret = EINVAL; + goto end; + } + + tmp = malloc(total_len + 1); + if (tmp == NULL) { + ret = ENOMEM; + goto end; + } + + l = 0; + while (l < total_len) { + ret = BIO_read(bio, tmp+l, total_len-l); + if (ret <= 0) { + ret = EINVAL; + goto end; + } + l += ret; + } + + tmp[total_len] = '\0'; + *pem_string = tmp; + tmp = NULL; + + ret = 0; + +end: + sk_X509_pop_free(chain, X509_free); + if (bio) + BIO_free(bio); + if (tmp) + free(tmp); + + return ret; +} + +void +edg_wll_gss_free_princ(edg_wll_GssPrincipal principal) +{ + if (principal == NULL) + return; + + if (principal->name) + free(principal->name); + + free(principal); +} + +int +edg_wll_gss_gethostname(char *name, int len) +{ + int ret; + + if (globus_common_activated) + ret = globus_libc_gethostname(name, len); + else + ret = gethostname(name, len); + + return ret; +} + +char * +edg_wll_gss_normalize_subj(char *in, int replace_in) +{ + char *new, *ptr; + size_t len; + + if (in == NULL) return NULL; + if (replace_in) + new = in; + else + new = strdup(in); + + while ((ptr = strstr(new, "/emailAddress="))) { + memcpy(ptr, "/Email=",7); + memmove(ptr+7, ptr+14, strlen(ptr+14)+1); + } + + len = strlen(new); + while (len > 9 && !strcmp(new+len-9, "/CN=proxy")) { + *(new+len-9) = '\0'; + len -= 9; + } + + return new; +} + +int +edg_wll_gss_equal_subj(const char *a, const char *b) +{ + char *an,*bn; + int res; + + an = edg_wll_gss_normalize_subj((char*)a, 0); + bn = edg_wll_gss_normalize_subj((char*)b, 0); + + if (!an || !bn) + res = 0; + else + res = !strcmp(an,bn); + + free(an); free(bn); + return res; +} + +int +edg_wll_gss_unread(edg_wll_GssConnection *con, void *data, size_t len) +{ + char *tmp; + + if (len == 0) + return 0; + + tmp = malloc(len + con->bufsize); + if (tmp == NULL) + return ENOMEM; + + memcpy(tmp, data, len); + if (con->bufsize > 0) + memcpy(tmp + len, con->buffer, con->bufsize); + + free(con->buffer); + con->buffer = tmp; + con->bufsize += len; + + return 0; +} -- 1.8.2.3