From 105a6c1315c94784767506aacc3382673b3fb782 Mon Sep 17 00:00:00 2001
From: Alberto Di Meglio
Date: Tue, 26 Oct 2004 17:54:24 +0000
Subject: [PATCH] First version of this file
---
org.gridsite.core/CHANGES | 114 ++
org.gridsite.core/INSTALL | 39 +
org.gridsite.core/LICENSE | 47 +
org.gridsite.core/README | 3 +
org.gridsite.core/VERSION | 4 +
org.gridsite.core/build.xml | 195 ++
org.gridsite.core/doc/admin.html | 103 ++
org.gridsite.core/doc/build-apache2.sh | 79 +
org.gridsite.core/doc/config.html | 192 ++
org.gridsite.core/doc/gacl.html | 84 +
org.gridsite.core/doc/htcp.1 | 138 ++
org.gridsite.core/doc/htll.1 | 1 +
org.gridsite.core/doc/htls.1 | 1 +
org.gridsite.core/doc/htmkdir.1 | 1 +
org.gridsite.core/doc/htrm.1 | 1 +
org.gridsite.core/doc/httpd-fileserver.conf | 145 ++
org.gridsite.core/doc/httpd-webserver.conf | 217 +++
org.gridsite.core/doc/index.html | 92 +
org.gridsite.core/doc/install.html | 148 ++
org.gridsite.core/doc/library.html | 1 +
org.gridsite.core/doc/module.html | 271 +++
org.gridsite.core/doc/urlencode.1 | 46 +
org.gridsite.core/doc/user.html | 302 ++++
org.gridsite.core/interface/gridsite-gacl.h | 188 ++
org.gridsite.core/interface/gridsite.h | 269 +++
org.gridsite.core/project/build.properties | 0
org.gridsite.core/project/configure.properties.xml | 8 +
org.gridsite.core/project/dependencies.properties | 9 +
org.gridsite.core/project/gridsite.core.csf.xml | 255 +++
org.gridsite.core/project/properties.xml | 53 +
org.gridsite.core/project/taskdefs.xml | 31 +
org.gridsite.core/project/version.properties | 3 +
org.gridsite.core/src/Doxyfile | 993 +++++++++++
org.gridsite.core/src/Makefile | 204 +++
org.gridsite.core/src/doxygen.css | 49 +
org.gridsite.core/src/doxyheader.html | 1 +
org.gridsite.core/src/gaclexample.c | 147 ++
org.gridsite.core/src/gridsite.spec | 76 +
org.gridsite.core/src/grst_admin.h | 57 +
org.gridsite.core/src/grst_admin_file.c | 1571 +++++++++++++++++
org.gridsite.core/src/grst_admin_gacl.c | 968 ++++++++++
org.gridsite.core/src/grst_admin_main.c | 365 ++++
org.gridsite.core/src/grst_gacl.c | 1136 ++++++++++++
org.gridsite.core/src/grst_http.c | 407 +++++
org.gridsite.core/src/grst_x509.c | 846 +++++++++
org.gridsite.core/src/htcp | Bin 0 -> 20971 bytes
org.gridsite.core/src/htcp.c | 1127 ++++++++++++
org.gridsite.core/src/mod_gridsite.c | 1853 ++++++++++++++++++++
org.gridsite.core/src/mod_ssl-private.h | 106 ++
org.gridsite.core/src/real-gridsite-admin.cgi | Bin 0 -> 81444 bytes
org.gridsite.core/src/roffit | 370 ++++
org.gridsite.core/src/urlencode.c | 73 +
52 files changed, 13389 insertions(+)
create mode 100644 org.gridsite.core/CHANGES
create mode 100644 org.gridsite.core/INSTALL
create mode 100644 org.gridsite.core/LICENSE
create mode 100644 org.gridsite.core/README
create mode 100644 org.gridsite.core/VERSION
create mode 100644 org.gridsite.core/build.xml
create mode 100644 org.gridsite.core/doc/admin.html
create mode 100644 org.gridsite.core/doc/build-apache2.sh
create mode 100644 org.gridsite.core/doc/config.html
create mode 100644 org.gridsite.core/doc/gacl.html
create mode 100644 org.gridsite.core/doc/htcp.1
create mode 100644 org.gridsite.core/doc/htll.1
create mode 100644 org.gridsite.core/doc/htls.1
create mode 100644 org.gridsite.core/doc/htmkdir.1
create mode 100644 org.gridsite.core/doc/htrm.1
create mode 100644 org.gridsite.core/doc/httpd-fileserver.conf
create mode 100644 org.gridsite.core/doc/httpd-webserver.conf
create mode 100644 org.gridsite.core/doc/index.html
create mode 100644 org.gridsite.core/doc/install.html
create mode 100644 org.gridsite.core/doc/library.html
create mode 100644 org.gridsite.core/doc/module.html
create mode 100644 org.gridsite.core/doc/urlencode.1
create mode 100644 org.gridsite.core/doc/user.html
create mode 100644 org.gridsite.core/interface/gridsite-gacl.h
create mode 100644 org.gridsite.core/interface/gridsite.h
create mode 100644 org.gridsite.core/project/build.properties
create mode 100644 org.gridsite.core/project/configure.properties.xml
create mode 100644 org.gridsite.core/project/dependencies.properties
create mode 100644 org.gridsite.core/project/gridsite.core.csf.xml
create mode 100644 org.gridsite.core/project/properties.xml
create mode 100644 org.gridsite.core/project/taskdefs.xml
create mode 100644 org.gridsite.core/project/version.properties
create mode 100644 org.gridsite.core/src/Doxyfile
create mode 100644 org.gridsite.core/src/Makefile
create mode 100644 org.gridsite.core/src/doxygen.css
create mode 100644 org.gridsite.core/src/doxyheader.html
create mode 100644 org.gridsite.core/src/gaclexample.c
create mode 100644 org.gridsite.core/src/gridsite.spec
create mode 100644 org.gridsite.core/src/grst_admin.h
create mode 100644 org.gridsite.core/src/grst_admin_file.c
create mode 100644 org.gridsite.core/src/grst_admin_gacl.c
create mode 100644 org.gridsite.core/src/grst_admin_main.c
create mode 100644 org.gridsite.core/src/grst_gacl.c
create mode 100644 org.gridsite.core/src/grst_http.c
create mode 100644 org.gridsite.core/src/grst_x509.c
create mode 100644 org.gridsite.core/src/htcp
create mode 100644 org.gridsite.core/src/htcp.c
create mode 100644 org.gridsite.core/src/mod_gridsite.c
create mode 100644 org.gridsite.core/src/mod_ssl-private.h
create mode 100644 org.gridsite.core/src/real-gridsite-admin.cgi
create mode 100755 org.gridsite.core/src/roffit
create mode 100644 org.gridsite.core/src/urlencode.c
diff --git a/org.gridsite.core/CHANGES b/org.gridsite.core/CHANGES
new file mode 100644
index 0000000..c7c17d5
--- /dev/null
+++ b/org.gridsite.core/CHANGES
@@ -0,0 +1,114 @@
+* Thu Jul 22 2004 Andrew McNab
+- ==== GridSite version 1.0.4 ====
+* Mon Jul 19 2004 Andrew McNab
+- Changes in line with EGEE SCM - most importantly
+ the top level directory becomes org.gridsite.core
+* Mon Jul 19 2004 Andrew McNab
+- ==== GridSite version 1.0.3 ====
+* Mon Jun 28 2004 Andrew McNab
+- In GRSTx509CheckChain() and GRSTx509CompactCreds()
+ we now accept the first cert in a chain as a CA
+ even if it is X509v3 but without the CA bits set.
+ (On the basis that the first chain is from the
+ administrator-installed CA files store.)
+* Sun Jun 27 2004 Andrew McNab
+- ==== GridSite version 1.0.2 ====
+* Sun Jun 27 2004 Andrew McNab
+- Fix for Bug #2860 (so can now read DN Lists over
+ HTTPS when have no user certificate if relevant
+ .gacl gives permission but not )
+- Include gridsite-gacl.h mods from Daniel Kouril
+ to fix faulty definitions
+ of GACLnewEntry() and GACLnewAcl() and to make
+ a legacy non-static GACLparseEntry() wrapper.
+* Thu Jun 17 2004 Andrew McNab
+- Changes to mod_gridsite.h for Fedora Core 2 /
+ Apache 2.0.49+ mod_ssl changes (mod_ssl-private.h)
+* Wed Jun 9 2004 Andrew McNab
+- Incorporate EGEE CVS layout changes in production
+ branch.
+* Wed Jun 9 2004 Andrew McNab
+- ==== GridSite version 1.0.1 ====
+* Sun Dec 14 2003 Andrew McNab
+- 1.0.0 is first full production release
+ (development now in 1.1.x branch)
+* Sun Dec 14 2003 Andrew McNab
+- ==== GridSite version 1.0.0 ====
+* Sat Dec 13 2003 Andrew McNab
+- Remove need for modified mod_ssl-gridsite: now
+ mod_gridsite intercepts callbacks with wrappers.
+- Add GRSTx509NameCmp() which compares string reps of
+ DNs across OpenSSL version changes (ie Email=)
+* Fri Dec 12 2003 Andrew McNab
+- ==== GridSite version 0.9.11 ====
+* Thu Dec 11 2003 Andrew McNab
+- Simplify checking of cert/proxy chain in
+ mod_ssl-gridsite: rely on mod_ssl/OpenSSL more.
+* Wed Dec 2 2003 Andrew McNab
+- ==== GridSite version 0.9.10 ====
+* Tue Dec 1 2003 Andrew McNab
+- GACL ignores leading/trailing spaces in values.
+* Sat Nov 29 2003 Andrew McNab
+- Better directory listing in htcp.
+- htcp now built as separate binary RPM.
+- gridsite-admin.cgi upload now redirects to same
+ directory after upload (Bug #1939); allows
+ optional new name for file (Request / Bug #1940);
+ and has better checking of ../dir/file attacks.
+* Sat Nov 29 2003 Andrew McNab
+- ==== GridSite version 0.9.8 ====
+* Thu Nov 27 2003 Andrew McNab
+- Shiv's updated GACL editor, with redirects.
+* Wed Nov 26 2003 Andrew McNab
+- Include Daniel Stenberg's roffit script to make
+ HTML man pages for htcp and urlencode.
+- Various fixes found when installing GridPP WWW.
+* Wed Nov 26 2003 Andrew McNab
+- ==== GridSite version 0.9.7 ====
+* Thu Nov 20 2003 Andrew McNab
+- Major updates to htcp (htrm/htls/htll)
+- GACL now recurses subdirectories when examining
+ the DN List directories path.
+* Sat Nov 15 2003 Andrew McNab
+- ==== GridSite version 0.9.6 ====
+* Fri Nov 14 2003 Andrew McNab
+- Function call fixes in grst-admin.cgi
+* Thu Nov 13 2003 Andrew McNab
+- Add htcp (curl-url-get reborn)
+* Thu Nov 13 2003 Andrew McNab
+- ==== GridSite version 0.9.5 ====
+* Thu Nov 13 2003 Andrew McNab
+- More grst-admin.cgi GACL updates from Shiv.
+- .gacl security improvements to grst-admin.cgi from
+ Shiv Kaushal and Peter Moore.
+* Tue Nov 11 2003 Andrew McNab
+- One RPM instead of three, with version from VERSION
+- Textarea for HTML/Text editing now 80 columns
+* Mon Nov 10 2003 Andrew McNab
+- Add delegation level and GridSiteGSIProxyLimit
+ support.
+- Add GridSiteAdminList handling to mod_gridsite
+ and real-gridsite-admin.cgi
+* Sun Nov 9 2003 Andrew McNab
+- Add directory create/delete, and file/dir rename.
+- Add ZIP listing/unzipping via external unzip
+ utility from http://www.info-zip.org/pub/infozip/
+* Mon Nov 3 2003 Andrew McNab
+- Include next version of Shiv's GACL editor.
+- Add rpm-usr target to Makefile, to make RPMs
+ out-of-the-box compatible with RH9 and its Apache2
+- Use REMOTE_DOUBLE_REV for GACL hostname creds in
+ mod_gridsite.c/mod_gridsite_perm_handler()
+* Sun Oct 26 2003 Andrew McNab
+- Include GACL editor in real-gridsite-admin.cgi
+ from Shiv Kaushal
+* Sun Oct 26 2003 Andrew McNab
+- Reorganise into a single build tree, including
+ Apache 2.0 .h files to remove circular dependency.
+* Sun Oct 26 2003 Andrew McNab
+- ==== GridSite version 0.9.4 ====
+* Sun Oct 19 2003 Andrew McNab
+- Include many pieces of GridSite code from 0.3.x (CGI)
+ fileGridSite and mod_gridsite 0.9.0
+* Sun Oct 19 2003 Andrew McNab
+- ==== GridSite version 0.9.3 ====
diff --git a/org.gridsite.core/INSTALL b/org.gridsite.core/INSTALL
new file mode 100644
index 0000000..68e150a
--- /dev/null
+++ b/org.gridsite.core/INSTALL
@@ -0,0 +1,39 @@
+BUILDING/INSTALLING GRIDSITE
+============================
+
+For more detailed instructions, see the install.html file, either
+in the ./doc subdirectory in the sources, in the directory
+gridsite-VERSION/html of the docs directory when GridSite is
+installed, or http://www.gridpp.ac.uk/gridsite/1.0.x/install.html
+
+GridSite is currently only supported on Linux, but should be
+trivially portable to other Unix platforms where the GNU build
+tools are available.
+
+When building from source, two routes are available: building
+with Make or with RPM.
+
+BUILDING WITH MAKE
+==================
+
+make
+make install
+
+will build all components and install them all under the default
+locations of /usr/local/[lib|bin|include|sbin] The default prefix
+/usr/local is set by the prefix variable in the top level Makefile
+
+BUILDING WITH RPM
+=================
+
+For RedHat Linux and derivatives, building with RPM is recommended.
+The command
+
+make rpm
+
+will build the gridsite and htcp binary RPMs in the directory
+../RPMTMP/RPMS/i386 relative to the working directory. A SRPM is
+put into ../RPMTMP/SRPMS
+
+Building with RPM uses the default prefix /usr, although the
+resulting RPMs are relocatable to other hierarchies.
diff --git a/org.gridsite.core/LICENSE b/org.gridsite.core/LICENSE
new file mode 100644
index 0000000..ce67433
--- /dev/null
+++ b/org.gridsite.core/LICENSE
@@ -0,0 +1,47 @@
+Copyright (c) 2002-4, Andrew McNab and Shiv Kaushal,
+University of Manchester. All rights reserved.
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following
+conditions are met:
+
+ o Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ o Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+Clearly marked portions of the published GridSite source code
+are derived from Apache httpd or its modules, and are covered
+by the Apache Software License:
+
+Copyright 2001-2004 The Apache Software Foundation
+
+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.
diff --git a/org.gridsite.core/README b/org.gridsite.core/README
new file mode 100644
index 0000000..5fbb1db
--- /dev/null
+++ b/org.gridsite.core/README
@@ -0,0 +1,3 @@
+See INSTALL for build and installation instructions, and
+http://www.gridpp.ac.uk/gridsite/ for configuration and
+usage guides.
diff --git a/org.gridsite.core/VERSION b/org.gridsite.core/VERSION
new file mode 100644
index 0000000..10c4a0f
--- /dev/null
+++ b/org.gridsite.core/VERSION
@@ -0,0 +1,4 @@
+MAJOR_VERSION=1
+MINOR_VERSION=1.0
+PATCH_VERSION=1.0.4
+VERSION=$(PATCH_VERSION)
diff --git a/org.gridsite.core/build.xml b/org.gridsite.core/build.xml
new file mode 100644
index 0000000..3ade883
--- /dev/null
+++ b/org.gridsite.core/build.xml
@@ -0,0 +1,195 @@
+
+
+
+
+
+
+ Ant build file to build the Gridsite Core Component
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <project name="${subsystem.name}" type="post-subsystem" packageName="gridsite-${subsystem.prefix}"/>
+
+
+
+
diff --git a/org.gridsite.core/doc/admin.html b/org.gridsite.core/doc/admin.html
new file mode 100644
index 0000000..1f7f422
--- /dev/null
+++ b/org.gridsite.core/doc/admin.html
@@ -0,0 +1,103 @@
+GridSite Admin Guide
+
+
GridSite Admin Guide
+
+
+This Guide is intended for people administrating areas of GridSite
+websites or fileservers, or managing GridSite's DN List groups - that is,
+how to use GridSite to manage other people's access to parts of the site -
+for example, people's write access to areas devoted to specific subprojects.
+
+
+ There is a separate
+User Guide
+ which explains how to authenticate to the server with X.509 certificates,
+and how to manage files via a standard web browser or with command-line
+HTTPS clients. You should be familiar with the User Guide to fully
+understand this Admin Guide.
+
+
+ You may also find the
+Config Guide
+ useful to understand how the Apache webserver is configured with GridSite
+extensions. If you are also the Apache webmaster for your site, you will
+definitely need to read the Config Guide to create the httpd.conf file.
+However, if you only need to manage webpages and files, then this Admin
+Guide and the User Guide should be sufficient.
+
+
Groups and DN Lists
+
+
+GridSite defines groups of people using plain text DN Lists - that is, lists
+of people's certificate DNs. Each DN List has a URL which uniquely
+identifies the list (and may also allow other sites to obtain the list and
+use it themselves.) For example, the list of all GridPP members is
+https://www.gridpp.ac.uk/dn-lists/gridpp (note that it's https:// not
+http:// - this means that other sites that download the list can check the
+certificate of www.gridpp.ac.uk and know they're talking to the
+authoritative source of the lists.)
+
+
+The system can also have a number of other DN Lists which are associated with
+specific groups of people and perhaps with specific areas of responsibility
+of the website. If the DN List directory URI is /dn-lists/ then
+there is a full list of the DN Lists exported by the server at that URI
+(for example, https://www.gridpp.ac.uk/dn-lists/ )
+
+
+If you have permission to modify a DN List, you can start changing it by
+going to /dn-lists/ (via HTTPS), using the "Manage directory"
+button and finding the URL of your DN List in the listings. You may
+need to go down into a subdirectory to find your list. For
+example, https://www.gridpp.ac.uk/dn-lists/atlas is in the atlas
+subdirectory of /dn-lists/ (You may wish to bookmark the listing of such
+a directory if you frequently work with one.)
+
+
+DN List directories are managed by the ACLs described in the next section,
+and if you have write permission, you can edit the lists already there, and
+add new lists with the same prefix (this means you can readily create your
+own subgroups.)
+
+
Access Control Lists
+
+
+DN Lists appear in the Grid Access Control Lists (GACL) used by GridSite.
+These are stored as .gacl files in directories: if the .gacl file is
+present, it governs access to the directory; if it is absent, then the
+parent directories are searched upwards until a .gacl is found.
+
+
+The GridSite GACL Reference explains the XML format
+of these files, but they
+can be edited using the ACL editor built into the GridSite system by people
+who have the Admin permission within the ACL.
+
+
+If you have this permission in a given directory, when you view directory
+listings or files in that directory you will see the option "Manage
+Directory" in the page footer. This allows you to get a listing of the
+directory and the .gacl file will appear at the top if it's present. If not,
+then there will be a button to create a new .gacl file with the same
+permissions as have been inherited by that directory from its parent.
+
+
+GACL allows quite complex conditions to be imposed on access, but normally
+you can think of an ACL as being composed of a number of entries, each of
+which contains one condition (the required credential) and a set of allowed
+and denied permissions.
+
+
+Credentials can be individual user's certificate names or whole groups of
+certificate names if a DN List is given. (You can also specifiy hostname
+patterns using Unix shell wildcards (eg *.ac.uk) or EDG VOMS attribute
+certificates - see the GACL Reference for details.)
+
+
+Permissions can be Admin (edit the ACL), Write (create, modify or delete
+files), List (browse the directory) or Read (read files.) Permissions can be
+allowed or denied. If denied by any entry, the permission is not available
+to that user or DN List (depending on what credential type was associated
+with the Deny.)
+
+
diff --git a/org.gridsite.core/doc/build-apache2.sh b/org.gridsite.core/doc/build-apache2.sh
new file mode 100644
index 0000000..f1246d4
--- /dev/null
+++ b/org.gridsite.core/doc/build-apache2.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# Copyright (c) 2002-3, Andrew McNab, University of Manchester
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+# o Redistributions of source code must retain the above
+# copyright notice, this list of conditions and the following
+# disclaimer.
+# o Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#-----------------------------------------------------------------------------
+# For more information about GridSite: http://www.gridpp.ac.uk/gridsite/
+#-----------------------------------------------------------------------------
+#
+# This script takes an Apache .tar.gz as the single command line argument,
+# unpacks the file, modifies the httpd.spec it contains to work without
+# the "-C" option to configure (which RedHat 7.3 doesnt like) and
+# outputs source and binary RPMs in SRPMS and RPMS/i386
+
+if [ "$1" = "" ] ; then
+ echo Must give a tar.gz file name
+ exit
+fi
+
+export MYTOPDIR=`pwd`
+
+if [ -x /usr/bin/rpmbuild ] ; then
+ export RPMCMD=rpmbuild
+else
+ export RPMCMD=rpm
+fi
+
+echo "$1" | grep '\.tar\.gz$' >/dev/null 2>&1
+if [ $? = 0 ] ; then # a gzipped source tar ball
+
+ rm -Rf $MYTOPDIR/BUILD $MYTOPDIR/BUILDROOT $MYTOPDIR/SOURCES
+ mkdir -p $MYTOPDIR/SOURCES $MYTOPDIR/SPECS $MYTOPDIR/BUILD \
+ $MYTOPDIR/SRPMS $MYTOPDIR/RPMS/i386 $MYTOPDIR/BUILDROOT
+
+ shortname=`echo $1 | sed 's:^.*/::' | sed 's:\.tar\.gz$::'`
+
+ cp -f $1 SOURCES
+
+ tar zxvf SOURCES/$shortname.tar.gz $shortname/httpd.spec
+ cp -f $shortname/httpd.spec SPECS
+
+ sed -e 's/configure -C /configure /' \
+ SPECS/httpd.spec >SPECS/httpd-2.spec
+
+ $RPMCMD --define "_topdir $MYTOPDIR" \
+ -ba --buildroot $MYTOPDIR/BUILDROOT SPECS/httpd-2.spec
+
+ exit
+fi
+
+echo I dont recognise the file type (must be .tar.gz)
+
+exit
diff --git a/org.gridsite.core/doc/config.html b/org.gridsite.core/doc/config.html
new file mode 100644
index 0000000..6e747e2
--- /dev/null
+++ b/org.gridsite.core/doc/config.html
@@ -0,0 +1,192 @@
+
GridSite Config Guide
+
+
GridSite Config Guide
+
+
+This Guide is intended for webmasters setting up
+GridSite with an Apache 2.0
+webserver. We assume you have root access to the server machine to do this.
+There is a separate Admin Guide for
+people administrating areas of GridSite
+websites or fileservers, or managing GridSite's DN List groups. That is, for
+people managing files on the server rather than the server itself.
+
+
Installation
+
+
+We assume you have installed Apache 2.0 and GridSite, using the
+Building and Installation Guide where necessary.
+This Config Guide assumes installation has been done under /usr. For an
+alternative tree like /usr/local, the relative paths should be the same.
+
+
+Installation should have given you an Apache 2.0 httpd binary at
+/usr/sbin/httpd and a set of standard Apache 2.0 modules in
+/usr/lib/httpd/modules/ including the standard mod_ssl
+and our mod_gridsite.so module.
+
+
+GridSite also includes some commands and man pages in /usr/bin and
+/usr/share/man/man1: urlencode and
+htcp.
+
+
Certificates
+
+
+You must also install the CA root certificates of the CA's
+used by the users you wish to talk to. These should be installed in
+/etc/grid-security/certificates as files like 01621954.0, and RPMs and tar
+files for many common European and North American CAs are available from
+
+https://datagrid.in2p3.fr/distribution/datagrid/security/
+
+
+This location also has VOMS server certificate RPMs which install into
+the /etc/grid-security/vomsdir directory. You may also manually install VOMS
+server certificates into that directory with any filename. (GridSite
+currently parses the certificate itself when looking for a match, rather
+than checking the filename.)
+
+
+The server itself needs a certificate to supply to clients that use HTTPS
+connections. You should apply for this from your Certification Authority
+(for example, the UK e-Science
+CA) and your request must use the advertised hostname of your server
+(the one that appears in URLs and not, for instance, the canonical name of
+the host itself.) This advertised hostname should appear in the
+Distinguished Name of your request. (For example
+/C=UK/O=eScience/OU=Manchester/L=HEP/CN=www.gridpp.ac.uk) For compatability
+with standard browsers, the /CN= component should not include any
+Globus-style service name (so not /CN=host/www.gridpp.ac.uk) If
+possible, you should also include the advertised hostname as a DNS Subject
+Alternative Name. Consult your CA first if you're in any doubt about how to
+compose your certificate request.
+
+
+Once you've got your certificate,
+Apache uses the certificate and private key in PEM format. If you obtained
+your certificate and key in PKCS#12 or .p12 format (eg by exporting from a web
+browser), you can convert the .p12 file to .pem with the following commands:
+
+Copy the PEM files to /etc/grid-security/ as hostcert.pem (which
+should be world readable) and hostkey.pem (which should only be readable by
+root):
+
+
+/etc/httpd/conf/httpd.conf is the key to configuring the Apache 2.0
+webserver. The directives in this file determine which files the server will
+publish, how they are handled, which areas are writeable and who can access
+them. Through mod_gridsite.so, the GridSite system itself is configured by
+directives in this file.
+
+
+The easiest way to get started is to examine the example httpd.conf files we
+provide.
+
+
+
+
httpd-fileserver.conf
+
+
+httpd-fileserver.conf is an example
+configuration file to use Apache/GridSite as a read/write HTTP(S)
+fileserver, including comments on how to get the server up and running.
+
+
httpd-webserver.conf
+
+
+httpd-webserver.conf is an example
+configuration file to use Apache/GridSite as a Web Server
+(that is, primarily for interactive use with a browser)
+including comments on how to get the server up and running.
+
+
+To start serving files, make a directory /var/www/htdocs owned by
+nobody.nobody, including the .gacl access control file described below,
+and add the following directive to the HTTPS <Directory> section:
+
+
+GridSiteMethods GET PUT DELETE
+
+
+If you wish to accept Globus GSI Proxies as well as full X.509 user
+certificates, set GridSiteGSIProxyLimit to the depth of proxy you
+wish to accept. (As a _rough_ guide: 0=No Proxies; 1=Proxy on user's
+machine; 2=Proxy owned by running Globus job; 3=Proxy delegated by a
+Globus job.)
+
+
GACL access control
+
+
+The GACL reference explains the XML access
+control files used by GridSite. These allow flexible policies to be written,
+in terms of X.509 user certificates, GSI proxies, VOMS attribute
+certificates, DN List groups and DNS hostnames.
+
+
+For example, to give all clients read and list permission:
+
+The GACL file that governs a directory is stored as .gacl in that directory.
+If no .gacl is present, then GridSite will search the parent directories in
+ascending order until one is found.
+
+
+
+
diff --git a/org.gridsite.core/doc/gacl.html b/org.gridsite.core/doc/gacl.html
new file mode 100644
index 0000000..12e58c7
--- /dev/null
+++ b/org.gridsite.core/doc/gacl.html
@@ -0,0 +1,84 @@
+
GridSite: Grid Access Control Language
+
+
GridSite: Grid Access Control Language
+
+
+GACL is the authorization policy language used by
+GridSite GACL allows
+policies to be written in terms of common Grid credentials: X.509
+identities, GSI proxies, VOMS attribute certificates and lists of X.509
+identities.
+
+
+GridSite both uses GACL policies and provides a GACL manipulation API for
+C/C++ in the GridSite library.
+
+
Credentials
+
+
+In GridSite 1.0.x, four credential types are supported:
+
+
+Five permissions are supported: Admin, Write, List, Exec and Read. Admin is
+permission to modify the authorization policy itself, but applications can
+map the other permissions to local methods as appropriate to their
+environment. For filesystems and fileservers, Write, List and Read have
+their usual meanings: creating or modifying files or directories; browsing
+directories; reading files. Exec is not used by GridSite itself, and
+applications are free to give it a meaning within their own contexts.
+
+
+In 1.0.x, only per-directory GACL files are supported, and the file is stored
+in the directory in question, or in one of its parent directories. (GridSite
+searches upwards until it finds one.)
+
+
+In GACL files, the permissions are represented by single tags:
+<admin/>, <write/>, <list/>, <exec/>, <read/>.
+Permission
+tags are contained within Allow or Deny blocks. For example:
+<allow><read/><list/></allow> or
+<deny><admin/></deny>.
+
+
Entries
+
+
+Entries associate credentials with permission statements. Entries consist of
+one or more credential blocks, and either an Allow or a Deny block, or both.
+If multiple credentials are present in one entry, they must all be held by a
+user to receive the association permissions. (So Entries provide logical AND
+of credentials.)
+
+
Access Control Lists
+
+
+ACLs consist of a list of one or more Entry blocks. When a user's credentials
+are compared to the ACL, the permissions given to the user by Allow blocks
+are recorded, along with those forbidden by Deny blocks. When all entries
+have been evaluated, any forbidden permissions are removed from those
+granted. (So Deny always wins over Allow, even between different Entries,
+but otherwise ACLs provide logical OR of credentials.)
+
+
diff --git a/org.gridsite.core/doc/htcp.1 b/org.gridsite.core/doc/htcp.1
new file mode 100644
index 0000000..05b0718
--- /dev/null
+++ b/org.gridsite.core/doc/htcp.1
@@ -0,0 +1,138 @@
+.TH htcp 1 "December 2003" htcp "HTCP Manual"
+.SH NAME
+.B htcp, htrm, htls, htll, htmkdir
+\- get, put, delete or list HTTP/HTTPS files or directories
+.SH SYNOPSIS
+.B htcp [options]
+.I Source-URL[s] [Destination URL]
+.SH DESCRIPTION
+.B htcp
+is a client to fetch files or directory listings from remote servers using
+HTTP or HTTPS, or to put or delete files or directories onto remote servers
+using HTTPS. htcp is similar to scp(1), but uses HTTP/HTTPS rather than ssh
+as its transfer protocol.
+
+When talking to an HTTPS server, htcp can run "anonymously", with a
+standard X.509 user certificate and key, or with a GSI Proxy. This makes
+htcp very useful in Grid environments where many users have certificates
+and where jobs and users have access to GSI proxies.
+
+.SH URLs
+htcp supports the file:, http: and https: URL schemes as sources and
+destinations. If no scheme is given, the URL scheme is assumed to be file:
+and relative to the current directory if not an absolute path.
+
+If multiple sources are given, they will be used in turn and the destination
+must be a directory (directories are indicated by a trailing /) However,
+source and destination cannot both refer to remote servers.
+
+.SH OPTIONS
+.IP "-v/--verbose"
+Turn on debugging information. Used once, this option will enable htcp's
+messages to stderr. Used twice, will also enable the underlying libcurl
+messages.
+
+.IP "--delete"
+Instead of copying files, delete all the URLs given on the command line.
+Calling the program as htrm has the same effect.
+
+.IP "--list"
+.br
+Instead of copying files, output lists of files located in the URL-directories
+given on the command line. Calling the program as htls has the same effect.
+
+.IP "--long-list"
+Instead of copying files, output long listings of files located in the
+URL-directories given on the command line. If available, the size in bytes
+and modification time of each file is given. Calling the program as
+htll has the same effect.
+
+.IP "--mkdir"
+Instead of copying files, attempt to create a directory on a remote server
+with HTTP PUT. The server must support the convention that PUT to a URL with
+a trailing slash means create a directory. No file body is sent. Calling the
+program as htmkdir has the same effect.
+
+.IP "--anon"
+.br
+Do not attempt to use X.509 user certificates or GSI proxies to authenticate
+to the remote HTTPS server. This means you are "anonymous", but the server's
+identity may still be verified and the connection is still encrypted.
+
+.IP "--cert and --key "
+Path to the PEM-encoded
+X.509 or GSI Proxy user certificate and key to use for HTTPS
+connections, intead of "anonymous mode." If only one of --key or --cert
+is given, then that will be tried for both. If neither is given, then the
+following order of precedence is used:
+the file name held by the variable X509_USER_PROXY; the file
+/tmp/x509up_uID (with Unix UID equal to ID); the file names held by
+X509_USER_CERT / X509_USER_KEY; the files ~/.globus/usercert.pem and
+~/.globus/userkey.pem (where ~/ is the home directory of the user.)
+
+.IP "--capath "
+Path to the PEM-encoded CA root certificates to use when
+verifying remote servers' host certificates in HTTPS connections. Ideally
+this should be a directory of hash.0 files as described in the OpenSSL
+verify(1) man page, but a file may be used instead. If --capath is not
+given, the value of the environment variable X509_CERT_DIR will be tried.
+If this is not valid, then /etc/grid-security/certificates will be used.
+
+.IP "--no-verify"
+Do not use CA root certificates to verify remote servers' host certificates.
+This is useful for testing sites before their certificate is set up properly,
+but leaves you vulnerable to "man in the middle" attacks by hostile servers
+masquerading as your target.
+
+.SH FILES
+.IP /tmp/x509up_uID
+Default GSI Proxy file for Unix UID equal to ID.
+
+.IP /etc/grid-security/certificates
+Default location for trusted Certification Authority root certificates to use
+when checking server certificates.
+
+.IP /tmp/.ca-roots-XXXXXX
+Prior to 7.9.8, the underlying curl library did not support the CA root
+certificates directory.
+If built with an old version of libcurl, htcp will concatenate the
+certificates in the CA roots directory into a unique temporary file and use
+that.
+
+.SH ENVIRONMENT
+
+.IP X509_CERT_DIR
+Holds directory to search for Certification Authority root certificates when
+verifying server certificates. (Tried if --capath is not given on the
+command line.)
+
+.IP X509_USER_PROXY
+Holds file name of a GSI Proxy to use as user certificate. (Tried if --cert or
+--key are not given on the command line.)
+
+.IP "X509_USER_CERT and X509_USER_KEY"
+Holds file name of X.509 user certificate and key. (Tried if X509_USER_PROXY
+is not valid.)
+
+.SH EXIT CODES
+0 is returned on complete success. Curl error codes are returned when
+reported by the underlying curl library, and CURLE_HTTP_RETURNED_ERROR (22)
+is returned when the HTTP(S) server returns a code outside the range 200-299.
+The manpage libcurl-errors(3) lists all the curl error codes.
+
+.SH TO DO
+Recursive copying. Server-side wildcards. Parallel streams. Error recovery.
+
+.SH BUGS
+Not enough beta testing (hint hint...)
+
+.SH AUTHOR
+Andrew McNab
+
+htcp is part of GridSite: http://www.gridpp.ac.uk/gridsite/
+.SH "SEE ALSO"
+.BR scp(1),
+.BR curl(1),
+.BR wget(1),
+.BR verify(1),
+.BR libcurl-errors(3)
diff --git a/org.gridsite.core/doc/htll.1 b/org.gridsite.core/doc/htll.1
new file mode 100644
index 0000000..11a60d1
--- /dev/null
+++ b/org.gridsite.core/doc/htll.1
@@ -0,0 +1 @@
+.so man1/htcp.1
diff --git a/org.gridsite.core/doc/htls.1 b/org.gridsite.core/doc/htls.1
new file mode 100644
index 0000000..11a60d1
--- /dev/null
+++ b/org.gridsite.core/doc/htls.1
@@ -0,0 +1 @@
+.so man1/htcp.1
diff --git a/org.gridsite.core/doc/htmkdir.1 b/org.gridsite.core/doc/htmkdir.1
new file mode 100644
index 0000000..11a60d1
--- /dev/null
+++ b/org.gridsite.core/doc/htmkdir.1
@@ -0,0 +1 @@
+.so man1/htcp.1
diff --git a/org.gridsite.core/doc/htrm.1 b/org.gridsite.core/doc/htrm.1
new file mode 100644
index 0000000..11a60d1
--- /dev/null
+++ b/org.gridsite.core/doc/htrm.1
@@ -0,0 +1 @@
+.so man1/htcp.1
diff --git a/org.gridsite.core/doc/httpd-fileserver.conf b/org.gridsite.core/doc/httpd-fileserver.conf
new file mode 100644
index 0000000..1b197e7
--- /dev/null
+++ b/org.gridsite.core/doc/httpd-fileserver.conf
@@ -0,0 +1,145 @@
+##############################################################################
+## GridSite httpd-fileserver.conf - Andrew McNab
+##
+## Example configuration file for GridSite as an HTTP(S) fileserver.
+##
+## For GridSite documentation, see http://www.gridpp.ac.uk/gridsite/
+##
+## This file should be renamed /etc/httpd/conf/httpd.conf and Apache
+## restarted to use Apache2/GridSite as a simple HTTP(S) fileserver.
+##
+## You do not need to install the GridSite mod_ssl.so module if you
+## do not wish to use Globus Proxies or VOMS attributes, but you must
+## have the mod_gridsite.so in /usr/lib/httpd/modules
+##
+## We're assuming you have (a) the host's hostcert.pem and hostkey.pem
+## in /etc/grid-security/ and (b) the Certification Authorities' you
+## trust have their root certs in /etc/grid-security/certificates
+##
+## (You can get RPMs for many European and North American Grid CAs
+## from https://datagrid.in2p3.fr/distribution/datagrid/security/ )
+##
+## If you want to use DN Lists in ACLs, they should be placed/downloaded
+## in /etc/grid-security/dn-lists/
+##
+## To start serving files, make a directory /var/www/htdocs owned by
+## nobody.nobody, including the file .gacl containing:
+##
+##
+##
+##
+##
+##
+##
+##
+## To enable writing, add DN List, Person or VOMS entries to the GACL
+## (see the GridSite GACL document for the syntax.) For example:
+##
+##
+##
+##
+##
+##
+##
+##
+## /C=UK/O=eScience/OU=Manchester/L=HEP/CN=Andrew McNab
+##
+##
+##
+##
+##
+## and add the following directive to the HTTPS section:
+##
+## GridSiteMethods GET PUT DELETE
+##
+## If you wish to accept Globus GSI Proxies as well as full X.509 user
+## certificates, set GridSiteGSIProxyLimit to the depth of proxy you
+## wish to accept.
+##
+## (As a _rough_ guide: 0=No Proxies; 1=Proxy on user's machine; 2=Proxy
+## owned by running Globus job; 3=Proxy delegated by a Globus job.)
+##
+## With this done and Apache restarted, you can upload a file with:
+##
+## curl -v --cert ~/.globus/usercert.pem --key ~/.globus/userkey.pem \
+## --capath /etc/grid-security/certificates --upload-file /tmp/tmp.txt \
+## https://INSERT.HOSTNAME.HERE/tmp.txt
+##
+## (or with --cert /tmp/x509up_u`id -u` --key /tmp/x509up_u`id -u` to use
+## a Globus GSI Proxy created with grid-proxy-init.)
+##############################################################################
+
+ServerRoot "/etc/httpd"
+
+PidFile logs/httpd.pid
+
+Timeout 300
+KeepAlive On
+MaxKeepAliveRequests 100
+KeepAliveTimeout 15
+
+LoadModule log_config_module /usr/lib/httpd/modules/mod_log_config.so
+LoadModule ssl_module /usr/lib/httpd/modules/mod_ssl.so
+LoadModule gridsite_module /usr/lib/httpd/modules/mod_gridsite.so
+LoadModule mime_module /usr/lib/httpd/modules/mod_mime.so
+LoadModule dir_module /usr/lib/httpd/modules/mod_dir.so
+
+TypesConfig /etc/mime.types
+
+# User and group who will own files created by Apache
+User nobody
+Group nobody
+
+DocumentRoot "/var/www/htdocs"
+
+
+ AllowOverride None
+
+
+LogLevel debug
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+
+CustomLog logs/httpd-gridsite-access combined
+ErrorLog logs/httpd-gridsite-errors
+
+HostnameLookups On
+
+######################################################################
+# Plain unauthenticated HTTP on port 80
+######################################################################
+
+Listen 80
+
+
+
+ GridSiteIndexes on
+ GridSiteAuth on
+ GridSiteDNlists /etc/grid-security/dn-lists/
+
+
+
+
+######################################################################
+# Secured and possibly authenticated HTTPS on port 443
+######################################################################
+Listen 443
+
+
+SSLEngine on
+SSLCertificateFile /etc/grid-security/hostcert.pem
+SSLCertificateKeyFile /etc/grid-security/hostkey.pem
+SSLCACertificatePath /etc/grid-security/certificates
+#SSLCARevocationPath YOUR CRL DIRECTORY WOULD GO HERE
+SSLVerifyClient optional
+SSLVerifyDepth 10
+SSLOptions +ExportCertData +StdEnvVars
+
+
+ GridSiteIndexes on
+ GridSiteAuth on
+ GridSiteDNlists /etc/grid-security/dn-lists/
+ GridSiteGSIProxyLimit 0
+# GridSiteMethods GET PUT DELETE
+
+
+
diff --git a/org.gridsite.core/doc/httpd-webserver.conf b/org.gridsite.core/doc/httpd-webserver.conf
new file mode 100644
index 0000000..0662f15
--- /dev/null
+++ b/org.gridsite.core/doc/httpd-webserver.conf
@@ -0,0 +1,217 @@
+##############################################################################
+## GridSite httpd-webserver.conf - Andrew McNab
+##
+## Example configuration file for GridSite as a Web Server
+## (that is, primarily for interactive use with a browser.)
+##
+## For GridSite documentation, see http://www.gridpp.ac.uk/gridsite/
+##
+## This file should be renamed /etc/httpd/conf/httpd.conf and Apache
+## restarted to use Apache2/GridSite as a webserver.
+##
+## You do not need to install the GridSite mod_ssl.so module if you
+## do not wish to use Globus Proxies or VOMS attributes, but you must
+## have the mod_gridsite.so in /usr/lib/httpd/modules
+##
+## We're assuming you have (a) the host's hostcert.pem and hostkey.pem
+## in /etc/grid-security/ and (b) the Certification Authorities' you
+## trust have their root certs in /etc/grid-security/certificates
+##
+## (You can get RPMs for many European and North American Grid CAs
+## from https://datagrid.in2p3.fr/distribution/datagrid/security/ )
+##
+## If you want to use DN Lists in ACLs, they should be placed/downloaded
+## in /etc/grid-security/dn-lists/ or /var/www/htdocs/dn-lists/
+## (Lists in /etc/grid-security/dn-lists/ override lists elsewhere.)
+##
+## To start serving files, make a directory /var/www/htdocs owned by
+## nobody.nobody, including the file .gacl containing:
+##
+##
+##
+##
+##
+##
+##
+##
+## To enable writing, add DN List, Person or VOMS entries to the GACL
+## (see the GridSite GACL document for the syntax.) For example:
+##
+##
+##
+##
+##
+##
+##
+##
+## /C=UK/O=eScience/OU=Manchester/L=HEP/CN=Andrew McNab
+##
+##
+##
+##
+##
+## and add the following directive to the HTTPS section:
+##
+## GridSiteMethods GET PUT DELETE
+##
+## If you wish to accept Globus GSI Proxies as well as full X.509 user
+## certificates, set GridSiteGSIProxyLimit to the depth of proxy you
+## wish to accept.
+##
+## (As a _rough_ guide: 0=No Proxies; 1=Proxy on user's machine; 2=Proxy
+## owned by running Globus job; 3=Proxy delegated by a Globus job.)
+##
+## With this done and Apache restarted, you can upload a file with:
+##
+## curl -v --cert ~/.globus/usercert.pem --key ~/.globus/userkey.pem \
+## --capath /etc/grid-security/certificates --upload-file /tmp/tmp.txt \
+## https://INSERT.HOSTNAME.HERE/tmp.txt
+##
+## (or with --cert /tmp/x509up_u`id -u` --key /tmp/x509up_u`id -u` to use
+## a Globus GSI Proxy created with grid-proxy-init.)
+##############################################################################
+
+ServerRoot "/etc/httpd"
+
+## You MUST put your server's fully qualified domain name here
+## This, the DOMAIN part of the https://DOMAIN/... URLs you want
+ServerName FULL.SERVER.NAME
+
+PidFile logs/httpd.pid
+
+Timeout 300
+KeepAlive On
+MaxKeepAliveRequests 100
+KeepAliveTimeout 15
+
+LoadModule log_config_module /usr/lib/httpd/modules/mod_log_config.so
+LoadModule ssl_module /usr/lib/httpd/modules/mod_ssl.so
+LoadModule gridsite_module /usr/lib/httpd/modules/mod_gridsite.so
+LoadModule mime_module /usr/lib/httpd/modules/mod_mime.so
+LoadModule dir_module /usr/lib/httpd/modules/mod_dir.so
+LoadModule alias_module /usr/lib/httpd/modules/mod_alias.so
+LoadModule cgi_module /usr/lib/httpd/modules/mod_cgi.so
+
+TypesConfig /etc/mime.types
+
+# User and group who will own files created by Apache
+User nobody
+Group nobody
+
+DocumentRoot "/var/www/htdocs"
+
+
+ AllowOverride None
+
+
+LogLevel debug
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+
+CustomLog logs/httpd-gridsite-access combined
+ErrorLog logs/httpd-gridsite-errors
+
+HostnameLookups On
+
+######################################################################
+# Plain unauthenticated HTTP on port 80
+######################################################################
+
+Listen 80
+
+
+## This is used to serve the Manage Directory links in footers,
+## and to allow you to edit files and ACLs via your browser.
+ScriptAlias /real-gridsite-admin.cgi /usr/sbin/real-gridsite-admin.cgi
+
+
+ ## This sets up GACL authorization for this server.
+ GridSiteAuth on
+
+ ## This exports various bits of info into the CGI environment
+ ## variables (and is needed for gridsite-admin.cgi to work.)
+ GridSiteEnvs on
+
+ ## Nice GridSite directory listings (without truncating file names!)
+ GridSiteIndexes on
+
+ ## If this is on, GridSite will look for gridsitehead.txt and
+ ## gridsitefoot.txt in the current directory or its parents, and
+ ## use them to replace the and tags in .html files.
+ GridSiteHtmlFormat on
+
+ ## These directives (and the ScriptAlias above) allow authorized
+ ## people to manage files, ACLs and DN Lists through their web
+ ## browsers. Via HTTP, this just means extended directory listings
+ ## and History pages.
+ GridSiteAdminURI /real-gridsite-admin.cgi
+ GridSiteAdminFile gridsite-admin.cgi
+
+
+
+
+######################################################################
+# Secured and possibly authenticated HTTPS on port 443
+######################################################################
+Listen 443
+
+
+SSLEngine on
+SSLCertificateFile /etc/grid-security/hostcert.pem
+SSLCertificateKeyFile /etc/grid-security/hostkey.pem
+SSLCACertificatePath /etc/grid-security/certificates
+#SSLCARevocationPath YOUR CRL DIRECTORY WOULD GO HERE
+SSLVerifyClient optional
+SSLVerifyDepth 10
+SSLOptions +ExportCertData +StdEnvVars
+
+## This is used to serve the Manage Directory links in footers,
+## and to allow you to edit files and ACLs via your browser.
+ScriptAlias /real-gridsite-admin.cgi /usr/sbin/real-gridsite-admin.cgi
+
+
+ ## This sets up GACL authorization for this server.
+ GridSiteAuth on
+
+ ## This exports various bits of info into the CGI environment
+ ## variables (and is needed for gridsite-admin.cgi to work.)
+ GridSiteEnvs on
+
+ ## Nice GridSite directory listings (without truncating file names!)
+ GridSiteIndexes on
+
+ ## If this is on, GridSite will look for gridsitehead.txt and
+ ## gridsitefoot.txt in the current directory or its parents, and
+ ## use them to replace the and tags in .html files.
+ GridSiteHtmlFormat on
+
+ ## This is the path of directories (and all their subdirectories) for
+ ## GACL to search when it encounters a dn-list credential. The DN List
+ ## files are plain text, one DN per line, and must have the full url
+ ## as the file name, but URL Encoded - eg with urlencode(1)
+ GridSiteDNlists /etc/grid-security/dn-lists/:/var/www/htdocs/dn-lists/
+
+ ## This is used to form the URL at which DN Lists "owned" by this
+ ## server are exported. https://FULL.SERVER.NAME/dn-lists/file
+ ## ALL FILES WITH URLs ON THIS SERVER WILL BE EXPORTED IRRESPECTIVE
+ ## OF WHERE THEY ARE FOUND ON THE DN-LISTS PATH!!
+ GridSiteDNlistsURI /dn-lists/
+
+ ## If this is greater than zero, we will accept GSI Proxies for clients
+ ## (full client certificates - eg inside web browsers - are always ok)
+ GridSiteGSIProxyLimit 0
+
+ ## This directive allows authorized people to write/delete files
+ ## from non-browser clients - eg with htcp(1)
+ GridSiteMethods GET PUT DELETE
+
+ ## These directives (and the ScriptAlias above) allow authorized
+ ## people to manage files, ACLs and DN Lists through their web
+ ## browsers via HTTPS. The value of GridSiteAdminFile appears to
+ ## exist in every directory, but is internally redirected by
+ ## mod_gridsite to the value of GridSiteAdminURI (the ScriptAlias
+ ## then maps that onto the real-gridsite-admin.cgi executable.)
+ GridSiteAdminURI /real-gridsite-admin.cgi
+ GridSiteAdminFile gridsite-admin.cgi
+
+
+
diff --git a/org.gridsite.core/doc/index.html b/org.gridsite.core/doc/index.html
new file mode 100644
index 0000000..11aaa86
--- /dev/null
+++ b/org.gridsite.core/doc/index.html
@@ -0,0 +1,92 @@
+GridSite 1.0.x Documentation
+
+
GridSite 1.0.x Documentation
+
+
+GridSite
+is a set of extensions to the Apache 2.0 webserver, which support
+Grid security based on X.509 certificates. Since GridSite applies access
+control within Apache itself, via mod_gridsite, Grid authorization and
+the associated verified credentials are available to all technologies
+supported by Apache, including static file serving, SSI, CGI, PHP, JSP and
+mod_perl.
+
+
End-user documentation for people managing webpages and files on
+ GridSite servers, either through the web interface or with command
+ line clients like htcp.
+
An Apache 2.0 module which enforces access control via Grid Access
+ Control Lists, and X.509, GSI or VOMS credentials. mod_gridsite also
+ gives Apache built-in support for the HTTP PUT and DELETE methods, and
+ formatting of HTML pages with standard headers and footers.
+
A detailed description of the C API provided by libgridsite, generated
+ from the sources by doxygen.
+
+
+
+
+
diff --git a/org.gridsite.core/doc/install.html b/org.gridsite.core/doc/install.html
new file mode 100644
index 0000000..6755b1e
--- /dev/null
+++ b/org.gridsite.core/doc/install.html
@@ -0,0 +1,148 @@
+GridSite: Building and Installation Guide
+
+
GridSite: Building and Installation Guide
+
+
+This Guide explains how to build GridSite from source, and how to install
+the server components alongside an Apache 2.0 webserver. There is a
+separate Config Guide which explains how to modify
+the httpd.conf file, and how to set up other files and directories used by
+the system. You should look through all of this Building and Installation
+Guide to decide which is the easiest route for your system.
+
+
Installing with RPM
+
+
+If you are installing on Linux with the binary RPM release, you can skip
+most of this Guide, install the binary rpm(s) and go straight
+to the Config Guide.
+
+
+RedHat 9:
+This is the simpler case, since the standard release includes a suitable
+version of Apache 2.0: just install the gridsite-...-1.i386.rpm to get the
+various GridSite components.
+
+
+RedHat 7.3:
+This is more complicated because you must also install a back-ported Apache
+2.0 RPM. We distribute RPMs built on 7.3 aimed at RedHat 7.3
+machines with updates, from our download area. These are built from the
+tar.gz and .spec files distributed by the
+Apache Foundation itself, using the
+build-apache2.sh script in the GridSite
+/usr/share/doc/gridsite directory. The Apache RPMs install in /usr, and you
+should at least install the httpd and mod_ssl RPMs.
+You must also install the gridsite-...-1.i386.rpm as above.
+
+
+GridSite also depends on shared libraries from libcurl and libxml2, and the
+RPMs distributed as part of the standard RedHat 7.3 and 9 releases are
+sufficient.
+
+
+With the RPMs installed, you can proceed to the
+Config Guide.
+
+
Requirements for building GridSite from source
+
+
+GridSite is currently only supported on Linux, but should be
+straightforwardly
+portable to other Unix platforms where the GNU build tools are available.
+
+
+GridSite consists of a core library (libgridsite[.so|.a]), an Apache module
+(mod_gridsite.so), a CGI utility (gridsite-admin.cgi) and some command line
+tools (htcp, urlencode.)
+
+
+All of the components use the GridSite library, and this in turn depends on
+libcurl and libxml2. You will need the development versions of these
+packages installed before you can proceed. (They are available as part of
+RedHat Linux releases 7.x onwards, for instance.)
+
+
Building GridSite with Make
+
+
+Our download area at
+
+https://www.gridpp.ac.uk/gridsite/download/ includes a tar-ball
+distribution of the sources, which can be unpacked and used to build
+GridSite from source. (Bleeding-edge developers can get the current snapshot
+of the same files from our CVS area.)
+
+
+GridSite needs a copy of the Apache 2.0 include files to build, and the
+location of this is set by the MYCFLAGS variable in the top-level Makefile.
+For manual builds, the default
+MYCFLAGS=-I/usr/local/include/httpd is used.
+If you wish to use the GridSite module with Apache
+2.0 installed elsewhere, you should change the MYCFLAGS variable to point to
+the includes directory installed by the development part of that Apache 2.0
+distribution.
+
+
+
+make
+make install
+
+
+
+will build all components and install them all under the default
+locations of /usr/local/[lib|bin|include|sbin] The default prefix for manual
+builds is
+/usr/local, as set by the prefix variable in the top level Makefile
+(/usr is the default for RPMs.)
+
+
Building GridSite with RPM
+
+
+For RedHat Linux and derivatives, building with RPM is recommended.
+The command make rpm in the top level of the source tree
+will build the GridSite and htcp binary RPMs in the
+directory ../RPMTMP/RPMS/i386 relative to the working directory. An SRPM is
+put into ../RPMTMP/SRPMS
+This build assumes the Apache 2.0 includes are in /usr/include/httpd.
+
+
+If you make RPMs on a RedHat 9 system (or a 7.3 system with our httpd RPM
+installed), you can install the resulting GridSite
+RPM alongside the standard Apache 2.0 RPM without having to
+modify shared library or Apache module paths.
+
+
+For other configurations,
+you can modify the assumed location of the Apache 2.0 includes
+by changing the MYCFLAGS variable in the rpm target near the
+foot of the top level Makefile.
+
+
Building Apache 2.0
+
+
+If it is not possible to use binary RPMs of Apache 2.0,
+then it can be built from source using the build-apache2.sh script
+found in the GridSite docs directory.
+The script includes instructions on how to build from the tarballs
+distributed by the Apache Foundation.
+(it removes the -C option from "configure -C" in the .spec file
+and builds the RPMs under the current directory.)
+
+
+If these targets do not work on your build platform,
+the Makefile and the scriptlets in the included SPEC files are a good
+starting point for building Apache by hand yourself. The complexities of
+this are outside of the scope of this Guide, but you are welcome to ask for
+assistance on the
+GridSite
+Discussion List, although
+www.apache.org is a better starting
+point for purely Apache problems.
+
+
diff --git a/org.gridsite.core/doc/library.html b/org.gridsite.core/doc/library.html
new file mode 100644
index 0000000..28458ae
--- /dev/null
+++ b/org.gridsite.core/doc/library.html
@@ -0,0 +1 @@
+library docs
diff --git a/org.gridsite.core/doc/module.html b/org.gridsite.core/doc/module.html
new file mode 100644
index 0000000..7f2096e
--- /dev/null
+++ b/org.gridsite.core/doc/module.html
@@ -0,0 +1,271 @@
+
GridSite Apache module: mod_gridsite
+
+
GridSite Apache module: mod_gridsite
+
+
+mod_gridsite is an Apache 2.0 module which enforces access control via Grid
+Access Control Lists, and X.509, GSI or VOMS credentials. mod_gridsite also
+gives Apache built-in support for the HTTP PUT and DELETE methods, and
+formatting of HTML pages with standard headers and footers.
+
+
+Since mod_gridsite access
+control within Apache itself, Grid authorization and
+the associated verified credentials are available to all technologies
+supported by Apache, including static file serving, SSI, CGI, PHP, mod_perl
+and Java servlets via a connector to Tomcat.
+
+
+Operation of mod_gridsite can be configured using runtime directives
+in Apache's standard httpd.conf configuration file. The module must first be
+loaded with a LoadModule directive:
+
+
+The module's behaviour is then controlled by GridSite... directives within
+Apache <Directory ...> sections, allowing different directories to use
+GridSite features in different ways.
+
+
GridSite directives
+
+
+
GridSiteIndexes on|off
+
Determines whether GridSite generates HTML directory listings. These
+ have some advantages over standard Apache directory listings (eg the
+ displayed filenames are never truncated) and will include standard
+ headers and footers if GridSiteHtmlFormat is on.
+
+ (Default: GridSiteIndexes off)
+
+
+
GridSiteIndexHeader file
+
If the named file is found in the directory being listed, the file
+ is included verbatim at the top of the listing and excluded from
+ the file-by-file listing. The file can either be HTML or plain text (in
+ which case browsers will be treat it as one HTML paragraph.)
+
+ (Default: none)
+
+
+
GridSiteHtmlFormat on|off
+
Determines where HTML pages receive additional formatting before being
+ sent to the client. This includes the "Last modified",
+ "View page history", "Switch to HTTP(S)",
+ "Print View" and "Built with GridSite" footer
+ elements. If header and footer files are found, they will be used too.
+
+ (Default: GridSiteHtmlFormat off)
+
+
+
GridSiteHeadFile file
+ GridSiteFootFile file
+
Set the filenames to be searched for as standard headers and footers
+ for HTML pages. For each HTML page, the directory of that page is tried
+ first, and then parent directories in ascending order until a header /
+ footer file is found. Header files are inserted in place of HTML
+ <body[ ...]> tags; footer files in place of </body>. (These
+ standard files should each include the appropriate body tag as a
+ replacement.)
+
+ (Defaults: GridSiteHeadFile gridsitehead.txt,
+ GridSiteFootFile gridsitefoot.txt)
+
+
+
GridSiteAuth on|off
+
Enables GridSite access control features, using
+ GACL files. The files are named .gacl and are
+ per-directory. The current directory is tried and then parent
+ directories in ascending order until a .gacl file is found.
+
+ (Default: GridSiteAuth off)
+
+
+
GridSiteAdminList uri
+
All members of the DN List with name "uri" receive the full set
+ of permissions, irrespective of per-directory .gacl files. People in
+ this group have full control over the whole site.
+
+ (Default: none)
+
+
+
GridSiteGSIProxyLimit limit
+
When using GSI Proxy credentials,
+ proxies with delegation depth greater than "limit" will
+ be ignored by mod_gridsite authorization decisions. A limit of zero
+ implies only full X.509
+ certificates (and no proxies) will be accepted. A limit of 1 implies
+ that only the initial proxy, usually created on the user's own machine,
+ is acceptable. Higher levels lead to proxies on remote machines, eg
+ used by running jobs, being accepted.
+
+ (Default: GridSiteGSIProxyLimit 1)
+
+
+
GridSiteMethods [GET] [PUT] [DELETE]
+
Specifies which HTTP methods are supported by GridSite. GET (and HEAD)
+ are always supported. PUT and DELETE support is turned on by this
+ directive, subject to a positive statement that write permission is
+ allowed for the directory in question, by a GACL file.
+
+ (Default: GridSite GET)
+
Sets up the DN List path used by GACL for
+ evaluating <dn-list> credentials. If this directive is not used,
+ then GACL will use the GRST_DN_LISTS variable from Apache's own
+ environment. If that is not set either, then /etc/grid-security/dn-lists
+ is searched.
+
+ (Default: none)
+
+
+
GridSiteDNlistsURI uri
+
If GridSiteDNlistsURI is used, then the URI given appears to be
+ populated with all the DN lists on the current DN lists path which
+ match the current server. That is, for server https://example.org/
+ with DN lists URI /dn-lists/, all DN lists with URLs starting
+ https://example.org/dn-lists/ will appear to be present in /dn-lists/,
+ irrespective of where in the path they are stored.
+
+ (Default: none)
+
+
+
GridSiteAdminURI uri
+
GridSiteAdminURI gives the absolute URI on the server of the GridSite
+ Admin CGI program, which is used for file management, HTML and GACL
+ editing. This should be used in conjunction with the standard Apache
+ directive ScriptAlias to map that URI to the real-gridsite-admin.cgi
+ executable. For example:
+
+ ScriptAlias /real-gridsite-admin.cgi
+ /PATH/TO/real-gridsite-admin.cgi
+
+ This URI is always reached by an internal redirection from the value
+ set by GridSiteAdminFile, and is never visible to users.
+
+ (Default: none)
+
+
+
GridSiteAdminFile cgifilename
+
If GridSiteAdminURI is set, then the cgifilename of GridSiteAdminFile
+ appears to be present in all directories when explicitly
+ requested (it does not appear in directory listings.) Requests for these
+ ghost CGI URIs are internally redirected to the value set by
+ GridSiteAdminURI.
+
+ (Default: GridSiteAdminFile gridsite-admin.cgi)
+
+
+
GridSiteEnvs on|off
+
This makes mod_gridsite export several variables into the environment
+ of CGI programs and other dynamic content systems. The variable names
+ are listed below. For gridsite-admin.cgi mechanism to work, this switch
+ must be left in its default state of on.
+
+ (Default: GridSiteEnvs on)
+
+
+
GridSiteEditable [ext1 [ext2 [ext3] ...]]]
+
A space-separated list of file extensions which can safely be edited
+ by the GridSite Text/HTML editor. The extensions are given without the
+ initial dot.
+
+ (Default: GridSiteEditable txt shtml html htm css js php jsp)
+
+
+
GridSiteHelpURI uri
+
If set, gives the URI to use for "Website Help" links in HTML
+ page footers.
+
+ (Default: none)
+
+
+
GridSiteLink on|off
+
Turns off the link in the HTML page footers which gives credit to
+ GridSite.
+
+ (Default: GridSiteLink on)
+
+
+
GridSiteUnzip path
+
If "path" is set by this directive, then real-gridsite-admin.cgi
+ will offer to list the contents of .zip archives on the server.
+ Users with write access are able to unpack the contents into the same
+ directory as the .zip file. The value of "path" must point
+ to the location of the
+ unzip binary.
+
+ (Default: none)
+
+
+
+
+
Environment variables
+
+
+The following variables are present in the environment of CGI programs and
+other dynamic content systems if the GridSiteEnvs on directive is
+in effect.
+
+
+
+
GRST_PERM
+
Numerical value of the permission bit-map obtained by comparing the
+ user with the GACL in force. (These should be tested using the
+ GRSTgaclPermHasXXXX functions from GACL.)
+
+
+
GRST_ADMIN_LIST
+
URI of the DN List, listing people with full admin and write access
+ to the whole site.
+
+
+
GRST_GSIPROXY_LIMIT
+
Maximum valid delegation level for GSI Proxies.
+
+
+
GRST_DIR_PATH
+
Absolute path in the local filesystem to the directory holding the
+ file being requested.
+
+
+
GRST_HELP_URI
+
URI of website help pages set by GridSiteHelpURI directive.
+
+
+
GRST_ADMIN_FILE
+
Filename of per-directory ghost gridsite-admin.cgi program. (This is
+ used by real-gridsite-admin.cgi to construct links in its pages.)
+
+
+
GRST_EDITABLE
+
Space-separated list of extensions which can safely be edited with a
+ Text/HTML editor.
+
+
+
GRST_HEAD_FILE and GRST_FOOT_FILE
+
Filenames of standard header and footer files.
+
+
+
GRST_DN_LISTS
+
DN lists search path.
+
+
+
GRST_DN_LISTS_URI
+
Directory of virtual URIs used to publish this site's DN Lists.
+
+
+
GRST_UNZIP
+
Full path to the unzip binary, used to list and unpack .zip files.
+
+
+
GRST_NO_LINK
+
If set, do not include credit links to GridSite in page footers.
+
+
+
+
+
diff --git a/org.gridsite.core/doc/urlencode.1 b/org.gridsite.core/doc/urlencode.1
new file mode 100644
index 0000000..47d2b91
--- /dev/null
+++ b/org.gridsite.core/doc/urlencode.1
@@ -0,0 +1,46 @@
+.TH urlencode 1 "November 2003" urlencode "URLENCODE Manual"
+.SH NAME
+.B urlencode
+\- convert strings to or from URL-encoded form
+.SH SYNOPSIS
+.B urlencode
+[-m|-d]
+.I string [string ...]
+.SH DESCRIPTION
+.B urlencode
+encodes strings according to RFC 1738.
+
+That is, characters A-Z a-z 0-9 . _
+and - are passed through unmodified, but all other characters are
+represented as %HH, where HH is their two-digit upper-case hexadecimal ASCII
+representation.
+For example, the URL http://www.gridpp.ac.uk/gridsite/ becomes
+http%3A%2F%2Fwww.gridpp.ac.uk%2Fgridsite%2F
+
+.B urlencode
+converts each character in all the strings given on the command line. If
+multiple strings are given, they are concatenated with separating spaces
+before conversion.
+
+.SH OPTIONS
+.IP "-m"
+Instead of full conversion, do GridSite "mild URL encoding" in which A-Z a-z
+0-9 . = - _ @ and / are passed through unmodified. This results in slightly
+more human-readable strings but the application must be prepared to create
+or simulate the directories implied by any slashes.
+
+.IP "-d"
+Do URL-decoding rather than encoding, according to RFC 1738. %HH and %hh
+strings are converted and other characters are passed through unmodified,
+with the exception that + is converted to space.
+
+.SH EXIT CODES
+0 is always returned.
+
+.SH BUGS
+Not enough beta testing (hint hint...)
+
+.SH AUTHOR
+Andrew McNab
+
+urlencode is part of GridSite: http://www.gridpp.ac.uk/gridsite/
diff --git a/org.gridsite.core/doc/user.html b/org.gridsite.core/doc/user.html
new file mode 100644
index 0000000..ae37cdd
--- /dev/null
+++ b/org.gridsite.core/doc/user.html
@@ -0,0 +1,302 @@
+GridSite User Guide
+
+
GridSite User Guide
+
+
If you are setting up a GridSite-based website you may wish to use this
+file as the basis of your end-user documentation. If so, copy all of the
+files from the GridSite doc directory (probably
+/usr/share/doc/gridsite-VERSION/)
+to somewhere on your website like
+/gridsite-doc/ and add GridSiteHelpURI /gridsite-doc/user.html
+to the virtual server configuration in
+httpd.conf - you should also look through the rest of the HTML source since
+there are some comments you may find helpful.
+
+
+This Guide is intended for people using GridSite websites with conventional
+web browsers, especially people with write access to areas of the site.
+ There is a separate
+Administration Guide
+ with additional information for people managing access control and group
+membership. This Guide assumes you are familiar with basic Web and HTML
+concepts. Towards the end we discuss how to access servers with command
+line tools like curl and htcp.
+
+
Reading from HTTP and HTTPS servers
+
+
+GridSite servers are usually accessible both via HTTP and via HTTPS. You can
+always tell which version you are using by looking at whether the URL in your
+browser's location window starts with "http://" or
+"https://" HTTPS means that the connection to the server is
+encrypted, that you can verify you're talking to the real server and not an
+imposter, and gives you the option to authenticate to the site and perhaps
+gain write access.
+
+
+ Simple browsing of the website via HTTP or HTTPS is reasonably
+ self-explanatory. If configured, additional links may appear in the footer
+ of each webpage with links to this help,
+
+ and to switch between HTTP and HTTPS versions of the page. Pages may also
+ have a link to the page History,
+
+ showing the dates of changes to that page and names of its authors.
+
+
+ When looking at HTTPS pages, you may find your browser reports it cannot
+ verify the server's certificate since it does not recognise the
+ Certification Authority (CA) it uses. You should attempt to load the CA's
+ root certificate into your browser to stop these warnings. (This means your
+ browser will be able to identify any servers using fake certificates which
+ you shouldn't trust.) How you obtain the CA Root Certificate from a
+ trust-worthy source depends on the CA. For example, the UK e-Science CA
+ lets you download it from their
+ website.
+
+
+
Authenticating
+
+
+ To go beyond reading pages you need to obtain a user certificate and load it
+ into your web browser. How you do this again depends on the Certification
+ Authority you have access to (for most Grid projects, CAs are organised
+ on a national basis.) To use the UK e-Science CA example again,
+ from their website has links to
+ the procedure for applying for a certificate from within a web browser.
+
+
+
+A user certificate usually has a version of your name and affiliation as its
+Distinguished Name (DN) - for example,
+"/C=UK/O=eScience/OU=Manchester/L=HEP/CN=Andrew McNab"
+
+
+Once you've obtained a user certificate in your name from your CA, you need
+to make sure it is loaded into the browser you normally use to browse the
+web. How you do this is different for different browsers and to some extent
+for different CAs (but if you applied
+for the CA through your browser, you may already have it there.)
+
+
+Browsers want the certificate and private key in the PKCS#12 format, which
+is normally a single file with the extension ".p12".
+Many programs which are based on OpenSSL, such as Globus and curl, prefer
+the PEM (".pem") format for certificates, with separate
+certificate and key files ("usercert.pem" and
+"userkey.pem", for example.) If you only have the files in .pem
+format and have access to openssl, you
+can use its command line tools to convert PEM to PKCS#12:
+
+Be very careful not to accidentally overwrite .pem or .p12 files when
+doing this kind of thing! In particular, if you lose your private key, you
+cannot retrieve it from your CA.
+
+
+ Once your user certificate is loaded, you should be able to see your
+ certificate name appear when you look at an HTTPS GridSite page which has
+ the page footers enabled - for example, the "Switch to HTTP" link
+ present. If GridSite understands your user certificate, it displays a
+ "You are ..." line in the footer. (However, the Apache webserver
+ must also be set up with your CAs root certificate for this to work. The
+ GridPP HTTPS home page is set up
+ to recognise a good range of European and North American Grid CAs.)
+
+
+
Authorization
+
+
+ Once users can prove their identity to the web server, it then becomes
+ possible to give them appropriate rights depending on that identity.
+ GridSite allows site administrators to specify these rights for individuals
+ and groups using
+GACL
+ access control files. (The
+Administration Guide
+ explains how to manage these files.) GACL defines who can
+ read files, who can list directories,
+ who can write or create files and who can modify the GACL policy files. To
+ get increased access to an area of a site, you need to contact the
+ administrator for that area and give the DN of your certificate (it's not
+ necessary to send any certificate files.)
+
+
Managing Directories and Files
+
+
+If you have list permission for the directory containing a page, you should
+see an extra link "Manage Directory" in the page's set of footer
+links, which allows you to browse the directory even if the normal
+index.html is present. If page histories are available, this listing view
+also has links to them.
+
+
+The real power of GridSite becomes available if you have write access to a
+directory. In that case, the "Manage Directory" page has
+additional links to Delete or Rename pages and other files, and to Edit HTML
+and plain text files. An Edit link also appears in the footer links of HTML
+pages.
+
+
+If you use the Edit function, you are presented with an HTML form containing
+the current filename and the full HTML or plain text of the page for you to
+edit. This allows you to maintain the content of the site "in
+place" and to see the result of your changes immediately, in context.
+
+
+If you modify the filename in the form before saving, GridSite will make a
+new file with that name, and the old file will still be present, unmodified.
+(However, you cannot use this feature for creating a file in a different
+directory.)
+As you make changes, the history of the changes and your certificate DN are
+recorded, and available in the history page for that file.
+
+
+ For people with write access, the "Manage Directory" page also has
+ options to upload a file from the computer your browser is running on, and to
+ create files and directories. If it's enabled, you can also view the
+ contents of WinZIP / PKZIP / .zip files, and unpack their contents into the
+ current directory. (This feature is very useful if you have several files
+ to upload at one time.)
+
+
+
HTML Formatting in GridSite
+
+
+As well as providing access control and file management, GridSite provides
+some simple formatting of HTML pages by adding standard headers and footers.
+(If this isn't sufficient, GridSite will happily coexist with HTML
+preprocessor languages like SSI, PHP and JSP.)
+
+
+ If HTML formatting is enabled
+ for the current directory, GridSite looks for the files gridsitehead.txt and
+ gridsitefoot.txt in that directory, or goes up through the parent
+ directories until they are found.
+
+
+
+The <body> and </body> tags from the HTML file are replaced with
+the contents of the gridsitehead.txt and gridsitefoot.txt files, which
+should normally be chunks of HTML including a replacement <body>
+or </body> tag. If either tag is absent from the original page, then
+the header or footer is just added rather than being inserted in place of
+the tag. (One consequence of this absence is that HTML header tags like
+<title> can end up after a <body> tag, and can get ignored by
+browsers - so always include <body> ... </body> in your pages.)
+
+
+This simple system is suprisingly flexible, and allows a variety of top and
+bottom, or sidebar navigation layouts of pages. Since the <body ...>
+tag is under full control of the author of the gridsitehead.txt file,
+backgrounds, colour schemes and style sheets can easily be specified.
+
+
+GridSite adds support for the HTTP PUT and DELETE methods, and this makes it
+easy to create or delete files from within programs and commands without
+using a web browser and HTML forms. It is straightforward, although slightly
+awkward, to use a standard HTTPS-aware client like
+curl to upload files, but GridSite
+provides htcp as a more convenient client program, which is easier to use
+with GSI Proxies and X.509 user certificates, and has a syntax closer to the
+familiar scp command.
+
+
+The following examples assume the GridSite server has GSI support and use a
+GSI proxy as the client certificate. For non-GSI use, just skip the
+grid-proxy-init stage, and replace the proxy
+filename with $HOME/.globus/usercert.pem and $HOME/.globus/userkey.pem (or
+wherever your PEM format certificate and key are stored.)
+
+
+First generate a GSI proxy with grid-proxy-init. This will create a proxy file
+in /tmp/x509up_uXXXXX where XXXXX is your Unix UID (also given by id
+-u.) The GSI proxy contains a
+temporary private key and certificate signed by your long-term user
+certificate.
+
+
+You should make sure you have a copy of the CA root certificates of the CA's
+used by the servers you wish to talk to. These are usually installed in
+/etc/grid-security/certificates as files like 01621954.0, and RPMs and tar
+files for many common European and North American CAs are available from
+
+https://datagrid.in2p3.fr/distribution/datagrid/security/
+
+
+since htcp looks for the GSI proxy and CA certificates automatically. htcp
+can also be used to copy remote files to the local machine by reversing the
+arguments. For more details, see the
+htcp(1) man page.
+
+
+htcp also has options for deleting files, and doing short or long listings,
+and these can also be accessed using the htrm, htls and htll commands (which
+are normally symbolic links to htcp.)
+
+
+Directory indexes are based on parsing the index returned by the web server
+and by using the HTTP HEAD method to obtain the file size and modification
+times.
+
+
+All of the ht** commands can accept multiple source file arguments, and this
+allows you to copy multiple files to or from the server. Shell wildcard
+expansion on the local machine is especially useful:
+
+htcp /tmp/new.*.txt https://server/
+
+
+
diff --git a/org.gridsite.core/interface/gridsite-gacl.h b/org.gridsite.core/interface/gridsite-gacl.h
new file mode 100644
index 0000000..2eec2fa
--- /dev/null
+++ b/org.gridsite.core/interface/gridsite-gacl.h
@@ -0,0 +1,188 @@
+/*
+ Copyright (c) 2002-4, Andrew McNab, University of Manchester
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ o Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ o Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*------------------------------------------------------------------------*
+ * For more about GridSite: http://www.gridpp.ac.uk/gridsite/ *
+ *------------------------------------------------------------------------*/
+
+#ifndef HEADER_GACL_H
+#define HEADER_GACL_H
+#endif
+
+#ifndef GACL_LIB_VERSION
+#define GACL_LIB_VERSION "x.x.x"
+#endif
+
+typedef GRSTgaclCred GACLcred;
+
+typedef int GACLaction;
+typedef unsigned int GACLperm;
+
+typedef GRSTgaclEntry GACLentry;
+
+typedef GRSTgaclAcl GACLacl;
+
+typedef GRSTgaclUser GACLuser;
+
+extern char *gacl_perm_syms[];
+extern GACLperm gacl_perm_vals[];
+
+#define GACL_PERM_NONE GRST_PERM_NONE
+#define GACL_PERM_READ GRST_PERM_READ
+#define GACL_PERM_LIST GRST_PERM_LIST
+#define GACL_PERM_WRITE GRST_PERM_WRITE
+#define GACL_PERM_ADMIN GRST_PERM_ADMIN
+
+#define GACLhasNone(perm) (perm == 0)
+#define GACLhasRead(perm) ((perm & GRST_PERM_READ) != 0)
+#define GACLhasList(perm) ((perm & GRST_PERM_LIST) != 0)
+#define GACLhasWrite(perm) ((perm & GRST_PERM_WRITE) != 0)
+#define GACLhasAdmin(perm) ((perm & GRST_PERM_ADMIN) != 0)
+
+#define GACL_ACTION_ALLOW GRST_ACTION_ALLOW
+#define GACL_ACTION_DENY GRST_ACTION_DENY
+
+#define GACL_ACL_FILE GRST_ACL_FILE
+#define GACL_DN_LISTS GRST_DN_LISTS
+
+#define GACLinit() GRSTgaclInit()
+
+#define GACLnewCred(x) GRSTgaclCredNew((x))
+//GACLcred *GACLnewCred(char *);
+
+#define GACLaddToCred(x,y,z) GRSTgaclCredAddValue((x),(y),(z))
+//int GACLaddToCred(GACLcred *, char *, char *);
+
+#define GACLfreeCred(x) GRSTgaclCredFree((x))
+//int GACLfreeCred(GACLcred *);
+
+#define GACLaddCred(x,y) GRSTgaclEntryAddCred((x),(y))
+//int GACLaddCred(GACLentry *, GACLcred *);
+
+#define GACLdelCred(x,y) GRSTgaclEntryDelCred((x),(y))
+//int GACLdelCred(GACLentry *, GACLcred *);
+
+#define GACLprintCred(x,y) GRSTgaclCredPrint((x),(y))
+// int GACLprintCred(GACLcred *, FILE *);
+
+
+#define GACLnewEntry() GRSTgaclEntryNew()
+// GACLentry *GACLnewEntry(void);
+
+#define GACLfreeEntry(x) GRSTgaclEntryFree((x))
+// int GACLfreeEntry(GACLentry *);
+
+#define GACLaddEntry(x,y) GRSTgaclAclAddEntry((x),(y))
+// int GACLaddEntry(GACLacl *, GACLentry *);
+
+#define GACLprintEntry(x,y) GRSTgaclEntryPrint((x),(y))
+// int GACLprintEntry(GACLentry *, FILE *);
+
+
+#define GACLprintPerm(x,y) GRSTgaclPermPrint((x),(y))
+//int GACLprintPerm(GACLperm, FILE *);
+
+#define GACLallowPerm(x,y) GRSTgaclEntryAllowPerm((x),(y))
+// int GACLallowPerm(GACLentry *, GACLperm);
+
+#define GACLunallowPerm(x,y) GRSTgaclEntryUnallowPerm((x),(y))
+//int GACLunallowPerm(GACLentry *, GACLperm);
+
+#define GACLdenyPerm(x,y) GRSTgaclEntryDenyPerm((x),(y))
+// int GACLdenyPerm(GACLentry *, GACLperm);
+
+#define GACLundenyPerm(x,y) GRSTgaclEntryUndenyPerm((x),(y))
+// int GACLundenyPerm(GACLentry *, GACLperm);
+
+#define GACLpermToChar(x) GRSTgaclPermToChar((x))
+// char *GACLpermToChar(GACLperm);
+
+#define GACLcharToPerm(x) GRSTgaclPermFromChar((x))
+// GACLperm GACLcharToPerm(char *);
+
+#define GACLnewAcl() GRSTgaclAclNew()
+// GACLacl *GACLnewAcl(void);
+
+#define GACLfreeAcl(x) GRSTgaclAclFree((x))
+// int GACLfreeAcl(GACLacl *);
+
+#define GACLprintAcl(x,y) GRSTgaclAclPrint((x),(y))
+// int GACLprintAcl(GACLacl *, FILE *);
+
+#define GACLsaveAcl(x,y) GRSTgaclAclSave((y),(x))
+// int GACLsaveAcl(char *, GACLacl *);
+
+#define GACLloadAcl(x) GRSTgaclAclLoadFile((x))
+// GACLacl *GACLloadAcl(char *);
+
+#define GACLfindAclForFile(x) GRSTgaclFileFindAclname((x))
+// char *GACLfindAclForFile(char *);
+
+#define GACLloadAclForFile(x) GRSTgaclAclLoadforFile((x))
+// GACLacl *GACLloadAclForFile(char *);
+
+#define GACLisAclFile(x) GRSTgaclFileIsAcl((x))
+// int GACLisAclFile(char *);
+
+
+#define GACLnewUser(x) GRSTgaclUserNew((x))
+// GACLuser *GACLnewUser(GACLcred *);
+
+#define GACLfreeUser(x) GRSTgaclUserFree((x))
+// int GACLfreeUser(GACLuser *);
+
+#define GACLuserAddCred(x,y) GRSTgaclUserAddCred((x),(y))
+// int GACLuserAddCred(GACLuser *, GACLcred *);
+
+#define GACLuserHasCred(x,y) GRSTgaclUserHasCred((x),(y))
+// int GACLuserHasCred(GACLuser *, GACLcred *);
+
+#define GACLuserFindCredType(x,y) GRSTgaclUserFindCredtype((x),(y))
+// GACLcred *GACLuserFindCredType(GACLuser *, char *);
+
+#define GACLtestDnList(x,y) GRSTgaclDNlistHasUser((x),(y))
+// int GACLtestDnList(char *, GACLuser *);
+
+#define GACLtestUserAcl(x,y) GRSTgaclAclTestUser((x),(y))
+// GACLperm GACLtestUserAcl(GACLacl *, GACLuser *);
+
+#define GACLtestExclAcl(x,y) GRSTgaclAclTestexclUser((x),(y))
+// GACLperm GACLtestExclAcl(GACLacl *, GACLuser *);
+
+
+#define GACLurlEncode(x) GRSThttpUrlEncode((x))
+// char *GACLurlEncode(char *);
+
+#define GACLmildUrlEncode(x) GRSThttpUrlMildencode((x))
+// char *GACLmildUrlEncode(char *);
+
+GACLparseEntry *GRSTgaclEntryParse(xmlNodePtr cur);
+// special function for legacy EDG LB service
diff --git a/org.gridsite.core/interface/gridsite.h b/org.gridsite.core/interface/gridsite.h
new file mode 100644
index 0000000..9742d15
--- /dev/null
+++ b/org.gridsite.core/interface/gridsite.h
@@ -0,0 +1,269 @@
+/*
+ Copyright (c) 2002-3, Andrew McNab, University of Manchester
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ o Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ o Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*------------------------------------------------------------------------*
+ * For more about GridSite: http://www.gridpp.ac.uk/gridsite/ *
+ *------------------------------------------------------------------------*/
+
+#ifndef HEADER_SSL_H
+#include
+#endif
+
+#ifndef HEADER_CRYPTO_H
+#include
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+/// Everything ok (= OpenSSL X509_V_OK)
+#define GRST_RET_OK 0
+
+/// Failed for unspecified reason
+#define GRST_RET_FAILED 1000
+
+/// Failed to find certificate in some cert store / directory
+#define GRST_RET_CERT_NOT_FOUND 1001
+
+/// Bad signature
+#define GRST_RET_BAD_SIGNATURE 1002
+
+/// No such file or directory
+#define GRST_RET_NO_SUCH_FILE 1003
+
+#define GRST_PROXYCERTINFO_OID "1.3.6.1.4.1.3536.1.222"
+#define GRST_VOMS_OID "1.3.6.1.4.1.8005.100.100.1"
+#define GRST_VOMS_DIR "/etc/grid-security/vomsdir"
+
+typedef struct { char *name;
+ char *value;
+ struct _GRSTgaclNamevalue *next; } GRSTgaclNamevalue;
+
+typedef struct { char *type;
+ int delegation;
+ GRSTgaclNamevalue *firstname;
+ void *next; } GRSTgaclCred;
+
+typedef int GRSTgaclAction;
+typedef unsigned int GRSTgaclPerm;
+
+typedef struct { GRSTgaclCred *firstcred;
+ GRSTgaclPerm allowed;
+ GRSTgaclPerm denied;
+ void *next; } GRSTgaclEntry;
+
+typedef struct { GRSTgaclEntry *firstentry; } GRSTgaclAcl;
+
+typedef struct { GRSTgaclCred *firstcred;
+ char *dnlists; } GRSTgaclUser;
+
+#define GRST_PERM_NONE 0
+#define GRST_PERM_READ 1
+#define GRST_PERM_EXEC 2
+#define GRST_PERM_LIST 4
+#define GRST_PERM_WRITE 8
+#define GRST_PERM_ADMIN 16
+#define GRST_PERM_ALL 31
+
+/* DO NOT USE PermIsNone!! */
+#define GRSTgaclPermIsNone(perm) (perm == 0)
+
+#define GRSTgaclPermHasNone(perm) (perm == 0)
+#define GRSTgaclPermHasRead(perm) ((perm & GRST_PERM_READ ) != 0)
+#define GRSTgaclPermHasExec(perm) ((perm & GRST_PERM_EXEC ) != 0)
+#define GRSTgaclPermHasList(perm) ((perm & GRST_PERM_LIST ) != 0)
+#define GRSTgaclPermHasWrite(perm) ((perm & GRST_PERM_WRITE) != 0)
+#define GRSTgaclPermHasAdmin(perm) ((perm & GRST_PERM_ADMIN) != 0)
+
+#define GRST_ACTION_ALLOW 0
+#define GRST_ACTION_DENY 1
+
+#define GRST_HIST_PREFIX ".grsthist"
+#define GRST_ACL_FILE ".gacl"
+#define GRST_DN_LISTS "/etc/grid-security/dn-lists"
+#define GRST_RECURS_LIMIT 9
+
+int GRSTgaclInit(void);
+
+// #define GACLnewCred(x) GRSTgaclCredNew((x))
+GRSTgaclCred *GRSTgaclCredNew(char *);
+
+// #define GACLaddToCred(x,y,z) GRSTgaclCredAddValue((x),(y),(z))
+int GRSTgaclCredAddValue(GRSTgaclCred *, char *, char *);
+
+#define GRSTgaclCredSetDelegation(cred, level) ((cred)->delegation = (level))
+#define GRSTgaclCredGetDelegation(cred) ((cred)->delegation)
+
+//#define GACLfreeCred(x) GRSTgaclCredFree((x))
+int GRSTgaclCredFree(GRSTgaclCred *);
+
+// #define GACLaddCred(x,y) GRSTgaclEntryAddCred((x),(y))
+int GRSTgaclEntryAddCred(GRSTgaclEntry *, GRSTgaclCred *);
+
+// #define GACLdelCred(x,y) GRSTgaclEntryDelCred((x),(y))
+int GRSTgaclEntryDelCred(GRSTgaclEntry *, GRSTgaclCred *);
+
+// #define GACLprintCred(x,y) GRSTgaclCredPrint((x),(y))
+int GRSTgaclCredCredPrint(GRSTgaclCred *, FILE *);
+
+
+// #define GACLnewEntry(x) GRSTgaclEntryNew((x))
+GRSTgaclEntry *GRSTgaclEntryNew(void);
+
+// #define GACLfreeEntry(x) GRSTgaclEntryFree((x))
+int GRSTgaclEntryFree(GRSTgaclEntry *);
+
+// #define GACLaddEntry(x,y) GRSTgaclAclAddEntry((x),(y))
+int GRSTgaclAclAddEntry(GRSTgaclAcl *, GRSTgaclEntry *);
+
+// #define GACLprintEntry(x,y) GRSTgaclEntryPrint((x),(y))
+int GRSTgaclEntryPrint(GRSTgaclEntry *, FILE *);
+
+
+// #define GACLprintPerm(x,y) GRSTgaclPermPrint((x),(y))
+int GRSTgaclPermPrint(GRSTgaclPerm, FILE *);
+
+// #define GACLallowPerm(x,y) GRSTgaclEntryAllowPerm((x),(y))
+int GRSTgaclEntryAllowPerm(GRSTgaclEntry *, GRSTgaclPerm);
+
+// #define GACLunallowPerm(x,y) GRSTgaclEntryUnallowPerm((x),(y))
+int GRSTgaclEntryUnallowPerm(GRSTgaclEntry *, GRSTgaclPerm);
+
+// #define GACLdenyPerm(x,y) GRSTgaclEntryDenyPerm((x),(y))
+int GRSTgaclEntryDenyPerm(GRSTgaclEntry *, GRSTgaclPerm);
+
+// #define GACLundenyPerm(x,y) GRSTgaclEntryUndenyPerm((x),(y))
+int GRSTgaclUndenyPerm(GRSTgaclEntry *, GRSTgaclPerm);
+
+// #define GACLpermToChar(x) GRSTgaclPermToChar((x))
+char *GRSTgaclPermToChar(GRSTgaclPerm);
+
+// #define GACLcharToPerm(x) GRSTgaclPermFromChar((x))
+GRSTgaclPerm GRSTgaclPermFromChar(char *);
+
+// #define GACLnewAcl(x) GRSTgaclAclNew((x))
+GRSTgaclAcl *GRSTgaclAclNew(void);
+
+// #define GACLfreeAcl(x) GRSTgaclAclFree((x))
+int GRSTgaclAclFree(GRSTgaclAcl *);
+
+// #define GACLprintAcl(x,y) GRSTgaclAclPrint((x),(y))
+int GRSTgaclAclPrint(GRSTgaclAcl *, FILE *);
+
+// #define GACLsaveAcl(x,y) GRSTgaclAclSave((y),(x))
+int GRSTgaclAclSave(GRSTgaclAcl *, char *);
+
+// #define GACLloadAcl(x) GRSTgaclFileLoadAcl((x))
+GRSTgaclAcl *GRSTgaclAclLoadFile(char *);
+
+// #define GACLfindAclForFile(x) GRSTgaclFileFindAclname((x))
+char *GRSTgaclFileFindAclname(char *);
+
+// #define GACLloadAclForFile(x) GRSTgaclFileLoadAcl((x))
+GRSTgaclAcl *GRSTgaclAclLoadforFile(char *);
+
+// #define GACLisAclFile(x) GRSTgaclFileIsAcl((x))
+int GRSTgaclFileIsAcl(char *);
+
+
+// #define GACLnewUser(x) GRSTgaclUserNew((x))
+GRSTgaclUser *GRSTgaclUserNew(GRSTgaclCred *);
+
+// #define GACLfreeUser(x) GRSTgaclUserFree((x))
+int GRSTgaclUserFree(GRSTgaclUser *);
+
+// #define GACLuserAddCred(x,y) GRSTgaclUserAddCred((x),(y))
+int GRSTgaclUserAddCred(GRSTgaclUser *, GRSTgaclCred *);
+
+// #define GACLuserHasCred(x,y) GRSTgaclUserHasCred((x),(y))
+int GRSTgaclUserHasCred(GRSTgaclUser *, GRSTgaclCred *);
+
+int GRSTgaclUserSetDNlists(GRSTgaclUser *, char *);
+
+// #define GACLuserFindCredType(x,y) GRSTgaclUserFindCredtype((x),(y))
+GRSTgaclCred *GRSTgaclUserFindCredtype(GRSTgaclUser *, char *);
+
+// #define GACLtestDnList(x,y) GRSTgaclDNlistHasUser((x),(y))
+int GRSTgaclDNlistHasUser(char *, GRSTgaclUser *);
+
+// #define GACLtestUserAcl(x,y) GRSTgaclAclTestUser((x),(y))
+GRSTgaclPerm GRSTgaclAclTestUser(GRSTgaclAcl *, GRSTgaclUser *);
+
+// #define GACLtestExclAcl(x,y) GRSTgaclAclTestexclUser((x),(y))
+GRSTgaclPerm GRSTgaclAclTestexclUser(GRSTgaclAcl *, GRSTgaclUser *);
+
+
+char *GRSThttpUrlDecode(char *);
+
+// #define GACLurlEncode(x) GRSThttpUrlEncode((x))
+char *GRSThttpUrlEncode(char *);
+
+// #define GACLmildUrlEncode(x) GRSThttpMildUrlEncode((x))
+char *GRSThttpUrlMildencode(char *);
+
+int GRSTx509NameCmp(char *, char *);
+
+int GRSTx509KnownCriticalExts(X509 *);
+
+time_t GRSTasn1TimeToTimeT(char *);
+int GRSTx509IsCA(X509 *);
+int GRSTx509CheckChain(int *, X509_STORE_CTX *);
+int GRSTx509VerifyCallback(int, X509_STORE_CTX *);
+
+int GRSTx509CheckVomsSig(unsigned char *, unsigned int,
+ unsigned char *, unsigned int,
+ char *, char *, char *);
+int GRSTx509GetVomsCreds(int *, int, size_t, char *, X509 *, X509 *, char *);
+GRSTgaclCred *GRSTx509CompactToCred(char *);
+int GRSTx509CompactCreds(int *, int, size_t, char *, STACK_OF(X509) *, char *);
+
+
+#define GRST_HEADFILE "gridsitehead.txt"
+#define GRST_FOOTFILE "gridsitefoot.txt"
+#define GRST_ADMIN_FILE "gridsite-admin.cgi"
+
+typedef struct { char *text;
+ void *next; } GRSThttpCharsList;
+
+typedef struct { size_t size;
+ GRSThttpCharsList *first;
+ GRSThttpCharsList *last; } GRSThttpBody;
+
+void GRSThttpBodyInit(GRSThttpBody *);
+void GRSThttpPrintf(GRSThttpBody *, char *, ...);
+int GRSThttpCopy(GRSThttpBody *, char *);
+void GRSThttpWriteOut(GRSThttpBody *);
+int GRSThttpPrintHeaderFooter(GRSThttpBody *, char *, char *);
+char *GRSThttpGetCGI(char *);
diff --git a/org.gridsite.core/project/build.properties b/org.gridsite.core/project/build.properties
new file mode 100644
index 0000000..e69de29
diff --git a/org.gridsite.core/project/configure.properties.xml b/org.gridsite.core/project/configure.properties.xml
new file mode 100644
index 0000000..82737d0
--- /dev/null
+++ b/org.gridsite.core/project/configure.properties.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/org.gridsite.core/project/dependencies.properties b/org.gridsite.core/project/dependencies.properties
new file mode 100644
index 0000000..2a7383b
--- /dev/null
+++ b/org.gridsite.core/project/dependencies.properties
@@ -0,0 +1,9 @@
+###################################################################
+# System dependencies
+###################################################################
+
+org.glite.version = HEAD
+org.glite.core.version = HEAD
+
+# Component dependencies tag = do not remove this line =
+
diff --git a/org.gridsite.core/project/gridsite.core.csf.xml b/org.gridsite.core/project/gridsite.core.csf.xml
new file mode 100644
index 0000000..c8f21a7
--- /dev/null
+++ b/org.gridsite.core/project/gridsite.core.csf.xml
@@ -0,0 +1,255 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The org.glite and org.glite.wms-utils modules have been updated, please rerun the configuration file
+
+
+
+ The org.glite and org.glite.wms-utils modules have been updated, please rerun the configuration file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.gridsite.core/project/properties.xml b/org.gridsite.core/project/properties.xml
new file mode 100644
index 0000000..74f88dc
--- /dev/null
+++ b/org.gridsite.core/project/properties.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.gridsite.core/project/taskdefs.xml b/org.gridsite.core/project/taskdefs.xml
new file mode 100644
index 0000000..9c35cef
--- /dev/null
+++ b/org.gridsite.core/project/taskdefs.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.gridsite.core/project/version.properties b/org.gridsite.core/project/version.properties
new file mode 100644
index 0000000..1eaa9d4
--- /dev/null
+++ b/org.gridsite.core/project/version.properties
@@ -0,0 +1,3 @@
+module.version=1.0.4
+module.build=1
+module.age=5
diff --git a/org.gridsite.core/src/Doxyfile b/org.gridsite.core/src/Doxyfile
new file mode 100644
index 0000000..e47d005
--- /dev/null
+++ b/org.gridsite.core/src/Doxyfile
@@ -0,0 +1,993 @@
+# Doxyfile 1.2.18
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME =
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
+# (Japanese with english messages), Korean, Norwegian, Polish, Portuguese,
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these class will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH =
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower case letters. If set to YES upper case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are adviced to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consist of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command , where
+# is the value of the INPUT_FILTER tag, and is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = doxygen
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET = doxygen.css
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output dir.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non empty doxygen will try to run
+# the html help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the Html help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = YES
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+,
+# or Internet explorer 4.0+). Note that for large projects the tree generation
+# can take a very long time. In such cases it is better to disable this feature.
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assigments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_XML = NO
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = NO
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yield more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermedate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+CGI_NAME = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for
+# details.
+
+CGI_URL =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+DOC_ABSPATH =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+BIN_ABSPATH = /usr/local/bin/
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS =
diff --git a/org.gridsite.core/src/Makefile b/org.gridsite.core/src/Makefile
new file mode 100644
index 0000000..a2bba0b
--- /dev/null
+++ b/org.gridsite.core/src/Makefile
@@ -0,0 +1,204 @@
+#
+# Andrew McNab and Shiv Kaushal, University of Manchester.
+# Copyright (c) 2002-4. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+# o Redistributions of source code must retain the above
+# copyright notice, this list of conditions and the following
+# disclaimer.
+# o Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#-----------------------------------------------------------------------------
+# For more information about GridSite: http://www.gridpp.ac.uk/gridsite/
+#-----------------------------------------------------------------------------
+
+include ../VERSION
+
+RPMCMD=$(shell if [ -x /usr/bin/rpmbuild ] ; then echo /usr/bin/rpmbuild; else echo rpm; fi)
+
+ifndef MYRPMDIR
+export MYRPMDIR=$(shell pwd)/../RPMTMP
+endif
+
+ifndef prefix
+export prefix=/home/dimeglio/gridsite
+endif
+
+ifndef MYCFLAGS
+export MYCFLAGS=-I. -I../interface -I/usr/include/httpd -I/usr/include/apr-0
+endif
+
+ifndef MYLDFLAGS
+export MYLDFLAGS=-L.
+endif
+
+#
+# Build
+#
+
+build: libgridsite.so.$(VERSION) libgridsite.a htcp mod_gridsite.so \
+ urlencode real-gridsite-admin.cgi apidoc
+
+libgridsite.so.$(VERSION): grst_x509.o grst_gacl.o grst_http.o
+ gcc -shared -Wl,-soname,libgridsite.so.$(MINOR_VERSION) \
+ -o libgridsite.so.$(PATCH_VERSION) grst_x509.o grst_gacl.o grst_http.o
+
+libgridsite.a: grst_x509.o grst_gacl.o grst_http.o
+ ar src libgridsite.a grst_x509.o grst_gacl.o grst_http.o
+
+grst_x509.o: grst_x509.c ../interface/gridsite.h
+ gcc $(MYCFLAGS) -I/usr/include/openssl \
+ -I/usr/kerberos/include -c grst_x509.c
+
+grst_gacl.o: grst_gacl.c ../interface/gridsite.h
+ gcc $(MYCFLAGS) -I/usr/include/openssl \
+ -I/usr/kerberos/include `xml2-config --cflags` -c grst_gacl.c
+
+grst_http.o: grst_http.c ../interface/gridsite.h
+ gcc $(MYCFLAGS) -I/usr/include/openssl \
+ -I/usr/kerberos/include -c grst_http.c
+
+urlencode: urlencode.c libgridsite.a
+ gcc -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
+ -o urlencode urlencode.c -L. \
+ -I/usr/include/openssl -I/usr/kerberos/include -lgridsite
+
+htcp: htcp.c
+ gcc -DVERSION=\"$(PATCH_VERSION)\" -I. -o htcp htcp.c \
+ `curl-config --cflags` `curl-config --libs`
+
+mod_gridsite.so: mod_gridsite.c mod_ssl-private.h
+ gcc $(MYCFLAGS) -shared -Wl,-soname=gridsite_module \
+ -I/usr/include/openssl -I/usr/kerberos/include \
+ -DVERSION=\"$(VERSION)\" -o mod_gridsite.so \
+ mod_gridsite.c $(MYLDFLAGS) -lxml2 -lm -lz -lgridsite
+
+real-gridsite-admin.cgi: grst_admin_main.c grst_admin_gacl.c \
+ grst_admin_file.c grst_admin.h
+ gcc $(MYCFLAGS) $(MYLDFLAGS) -o real-gridsite-admin.cgi \
+ grst_admin_main.c \
+ grst_admin_gacl.c \
+ grst_admin_file.c \
+ -I/usr/include/openssl -I/usr/kerberos/include \
+ -DVERSION=\"$(VERSION)\" -lgridsite -lssl -lcrypto -lxml2 -lz -lm
+
+apidoc: ../interface/gridsite.h grst_x509.c grst_gacl.c grst_http.c \
+ Doxyfile doxygen.css
+ doxygen Doxyfile
+
+gaclexample: gaclexample.c libgridsite.a
+ gcc -o gaclexample gaclexample.c -I. -L. \
+ -I/usr/include/openssl -I/usr/kerberos/include -lgridsite \
+ -lxml2 -lz -lm
+
+#
+# Install
+#
+
+install:
+ mkdir -p $(prefix)/include \
+ $(prefix)/lib \
+ $(prefix)/bin \
+ $(prefix)/sbin \
+ $(prefix)/share/man/man1 \
+ $(prefix)/lib/httpd/modules \
+ $(prefix)/share/doc/gridsite-$(PATCH_VERSION)
+ cp -f ../interface/gridsite.h $(prefix)/include
+ cp -f ../interface/gridsite-gacl.h $(prefix)/include
+ cp -f urlencode $(prefix)/bin
+ cp -f libgridsite.a $(prefix)/lib
+ cp -f real-gridsite-admin.cgi $(prefix)/sbin
+ cp -f libgridsite.so.$(PATCH_VERSION) $(prefix)/lib
+ ln -sf libgridsite.so.$(PATCH_VERSION) \
+ $(prefix)/lib/libgridsite.so
+ ln -sf libgridsite.so.$(PATCH_VERSION) \
+ $(prefix)/lib/libgridsite.so.$(MAJOR_VERSION)
+ ln -sf libgridsite.so.$(PATCH_VERSION) \
+ $(prefix)/lib/libgridsite.so.$(MINOR_VERSION)
+ cp -f doxygen/index.html \
+ $(prefix)/share/doc/gridsite-$(PATCH_VERSION)/doxygen-index.html
+ cp -f doxygen/* $(prefix)/share/doc/gridsite-$(PATCH_VERSION)
+ cp -f ../CHANGES ../README ../INSTALL ../LICENSE ../VERSION \
+ $(prefix)/share/doc/gridsite-$(PATCH_VERSION)
+ cp -f ../doc/*.html ../doc/*.conf ../doc/*.1 ../doc/*.sh \
+ $(prefix)/share/doc/gridsite-$(VERSION)
+ cp -f ../doc/*.1 $(prefix)/share/man/man1
+ gzip -f $(prefix)/share/man/man1/*.1
+ cd ../doc ; for i in *.1 ; do ../src/roffit < $$i \
+ > $(prefix)/share/doc/gridsite-$(VERSION)/$$i.html ; done
+ cp -f htcp $(prefix)/bin
+ ln -sf htcp $(prefix)/bin/htls
+ ln -sf htcp $(prefix)/bin/htll
+ ln -sf htcp $(prefix)/bin/htrm
+ ln -sf htcp $(prefix)/bin/htmkdir
+ cp -f mod_gridsite.so $(prefix)/lib/httpd/modules
+
+#
+# Distributions
+#
+
+# source files tarball
+dist:
+ mkdir -p ../gridsite-$(PATCH_VERSION)/src \
+ ../gridsite-$(PATCH_VERSION)/doc \
+ ../gridsite-$(PATCH_VERSION)/interface
+ cp -f ../VERSION ../README ../LICENSE ../CHANGES ../INSTALL \
+ ../gridsite-$(PATCH_VERSION)
+ cp -f Makefile *.c *.h roffit gridsite.spec \
+ Doxyfile doxygen.css doxyheader.html \
+ ../gridsite-$(PATCH_VERSION)/src
+ cp -f ../doc/*.html ../doc/*.1 ../doc/*.conf ../doc/*.sh \
+ ../gridsite-$(PATCH_VERSION)/doc
+ cp -f ../interface/*.h \
+ ../gridsite-$(PATCH_VERSION)/interface
+ cd .. ; tar zcvf gridsite-$(PATCH_VERSION).src.tar.gz \
+ gridsite-$(PATCH_VERSION)
+ rm -Rf ../gridsite-$(PATCH_VERSION)
+
+
+# binary tarball distribution for htcp users
+htcp-bin: htcp
+ mkdir -p ../htcp-bin-$(PATCH_VERSION)/bin \
+ ../htcp-bin-$(PATCH_VERSION)/man/man1
+ cp -f ../doc/README.htcp-bin ../htcp-bin-$(PATCH_VERSION)
+ cp -f htcp ../htcp-bin-$(PATCH_VERSION)/bin
+ cp -f ../doc/htcp.1 ../doc/htrm.1 ../doc/htls.1 ../doc/htll.1 \
+ ../doc/htmkdir.1 ../htcp-bin-$(PATCH_VERSION)/man/man1
+ ln -sf htcp ../htcp-bin-$(PATCH_VERSION)/bin/htls
+ ln -sf htcp ../htcp-bin-$(PATCH_VERSION)/bin/htll
+ ln -sf htcp ../htcp-bin-$(PATCH_VERSION)/bin/htrm
+ ln -sf htcp ../htcp-bin-$(PATCH_VERSION)/bin/htmkdir
+ cd ../htcp-bin-$(VERSION) ; tar zcvf ../htcp-$(VERSION).bin.tar.gz .
+ rm -Rf ../htcp-bin-$(PATCH_VERSION)
+
+# RPM targets: build and RPMs go into subdirectories of ../RPMTMP/
+rpm: dist gridsite.spec
+ rm -Rf $(MYRPMDIR)/BUILDROOT $(MYRPMDIR)/BUILD
+ mkdir -p $(MYRPMDIR)/SOURCES $(MYRPMDIR)/SPECS $(MYRPMDIR)/BUILD \
+ $(MYRPMDIR)/SRPMS $(MYRPMDIR)/RPMS/i386 $(MYRPMDIR)/BUILDROOT
+ cp -f ../gridsite-$(PATCH_VERSION).src.tar.gz $(MYRPMDIR)/SOURCES
+ cp -f gridsite.spec $(MYRPMDIR)/SPECS
+ export MYPREFIX=/usr ; export MYVERSION=$(PATCH_VERSION) ; \
+ $(RPMCMD) --define "_topdir $(MYRPMDIR)" \
+ -ba --buildroot $(MYRPMDIR)/BUILDROOT gridsite.spec
+
diff --git a/org.gridsite.core/src/doxygen.css b/org.gridsite.core/src/doxygen.css
new file mode 100644
index 0000000..97ebc25
--- /dev/null
+++ b/org.gridsite.core/src/doxygen.css
@@ -0,0 +1,49 @@
+H1 { text-align: center; }
+CAPTION { font-weight: bold }
+A.qindex {}
+A.qindexRef {}
+A.el { text-decoration: none; font-weight: bold }
+A.elRef { font-weight: bold }
+A.code { text-decoration: none; font-weight: normal; color: #4444ee }
+A.codeRef { font-weight: normal; color: #4444ee }
+A:hover { text-decoration: none; background-color: #f2f2ff }
+DL.el { margin-left: -1cm }
+DIV.fragment { width: 100%; border: none; background-color: #eeeeee }
+DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
+TD.md { background-color: #f2f2ff; font-weight: bold; }
+TD.mdname1 { background-color: #f2f2ff; font-weight: bold; color: #602020; }
+TD.mdname { background-color: #f2f2ff; font-weight: bold; color: #602020; width: 600px; }
+DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold }
+DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller }
+XXBODY { background: white }
+TD.indexkey {
+ background-color: #eeeeff;
+ font-weight: bold;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px
+}
+TD.indexvalue {
+ background-color: #eeeeff;
+ font-style: italic;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px
+}
+span.keyword { color: #008000 }
+span.keywordtype { color: #604020 }
+span.keywordflow { color: #e08000 }
+span.comment { color: #800000 }
+span.preprocessor { color: #806020 }
+span.stringliteral { color: #002080 }
+span.charliteral { color: #008080 }
diff --git a/org.gridsite.core/src/doxyheader.html b/org.gridsite.core/src/doxyheader.html
new file mode 100644
index 0000000..ad33993
--- /dev/null
+++ b/org.gridsite.core/src/doxyheader.html
@@ -0,0 +1 @@
+
GridSite Version 0.9.1
diff --git a/org.gridsite.core/src/gaclexample.c b/org.gridsite.core/src/gaclexample.c
new file mode 100644
index 0000000..4cab5bc
--- /dev/null
+++ b/org.gridsite.core/src/gaclexample.c
@@ -0,0 +1,147 @@
+/*
+ Copyright (c) 2002-3, Andrew McNab, University of Manchester
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ o Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ o Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*------------------------------------------------------------------------*
+ * For more about GridSite: http://www.gridpp.ac.uk/gridsite/ *
+ *------------------------------------------------------------------------*/
+
+/*
+ Example program using GACL
+
+ Build with:
+
+ gcc -o gaclexample gaclexample.c -L. -I. -lgridsite -lxml2 -lz -lm
+*/
+
+#include
+#include
+#include
+#include
+
+int main()
+{
+ GRSTgaclCred *cred, *usercred;
+ GRSTgaclEntry *entry;
+ GRSTgaclAcl *acl1, *acl2;
+ GRSTgaclUser *user;
+ GRSTgaclPerm perm0, perm1, perm2;
+ FILE *fp;
+
+ /* must initialise GACL before using it */
+
+ GRSTgaclInit();
+
+ /* build up an ACL, starting with a credential */
+
+ cred = GRSTgaclCredNew("person");
+
+ GRSTgaclCredAddValue(cred, "dn", "/O=Grid/CN=Mr Grid Person");
+
+ /* create an entry to put it in */
+
+ entry = GRSTgaclEntryNew();
+
+ /* add the credential to it */
+
+ GRSTgaclEntryAddCred(entry, cred);
+
+ /* add another credential */
+
+ cred = GRSTgaclCredNew("dn-list");
+ GRSTgaclCredAddValue(cred, "url", "example-dn-list");
+ GRSTgaclEntryAddCred(entry, cred);
+
+ fp = fopen("example-dn-list", "w");
+ fputs("/O=Grid/CN=Mr Grid Person\n", fp);
+ fclose(fp);
+
+ /* associate some permissions and denials to the credential */
+
+ GRSTgaclEntryAllowPerm( entry, GRST_PERM_READ);
+ GRSTgaclEntryAllowPerm( entry, GRST_PERM_WRITE);
+ GRSTgaclEntryAllowPerm( entry, GRST_PERM_ADMIN);
+ GRSTgaclEntryDenyPerm( entry, GRST_PERM_ADMIN);
+ GRSTgaclEntryDenyPerm( entry, GRST_PERM_LIST);
+
+ perm0 = GRST_PERM_READ | GRST_PERM_WRITE;
+
+ printf("test perm should be %d\n", perm0);
+
+ /* create a new ACL and add the entry to it */
+
+ acl1 = GRSTgaclAclNew();
+
+ GRSTgaclAclAddEntry(acl1, entry);
+
+ /* create a GRSTgaclUser to compare with the ACL */
+
+ usercred = GRSTgaclCredNew("person");
+
+ GRSTgaclCredAddValue(usercred, "dn", "/O=Grid/CN=Mr Grid Person");
+
+ user = GRSTgaclUserNew(usercred);
+
+ GRSTgaclUserSetDNlists(user, getcwd(NULL, 0));
+ printf("DN Lists dir %s\n", getcwd(NULL, 0));
+
+// putenv("GRST_DN_LISTS=.");
+
+ perm1 = GRSTgaclAclTestUser(acl1, user);
+
+ printf("test /O=Grid/CN=Mr Grid Person in acl = %d\n", perm1);
+
+ /* print and save the whole ACL */
+
+ GRSTgaclAclPrint(acl1, stdout);
+
+ GRSTgaclAclSave(acl1, "example.gacl");
+
+ puts("gridacl.out saved");
+
+ puts("");
+
+ /* load the ACL back off the disk, print and test it */
+
+ acl2 = GRSTgaclAclLoadFile("example.gacl");
+
+ puts("gridacl.out loaded");
+
+ if (acl2 != NULL) GRSTgaclAclPrint(acl2, stdout); else puts("acl2 is NULL");
+
+ perm2 = GRSTgaclAclTestUser(acl2, user);
+
+ printf("test /O=Grid/CN=Mr Grid Person in acl = %d\n", perm2);
+
+ if (perm1 != perm0) return 1;
+ if (perm2 != perm0) return 2;
+
+ return 0;
+}
diff --git a/org.gridsite.core/src/gridsite.spec b/org.gridsite.core/src/gridsite.spec
new file mode 100644
index 0000000..a6633d3
--- /dev/null
+++ b/org.gridsite.core/src/gridsite.spec
@@ -0,0 +1,76 @@
+Name: gridsite
+Version: %(echo ${MYVERSION:-1.0.x})
+Release: 1
+Summary: GridSite
+Copyright: Modified BSD
+Group: System Environment/Daemons
+Source: %{name}-%{version}.src.tar.gz
+Prefix: %(echo ${MYPREFIX:-/usr})
+URL: http://www.gridpp.ac.uk/gridsite/
+Vendor: GridPP
+#Requires: libxml2,curl-ssl,mod_ssl
+#Buildrequires: libxml2-devel,curl-ssl-devel,httpd-devel
+Packager: Andrew McNab
+
+%description
+GridSite adds GSI, VOMS and GACL support to Apache 2.0 (mod_gridsite),
+a library for manipulating these technologies (libgridsite), and CGI
+programs for interactive management of HTTP(S) servers (gridsite-admin.cgi)
+
+See %(echo ${MYPREFIX:-/usr})/share/doc/gridsite-%{version} and
+http://www.gridpp.ac.uk/gridsite/ for details.
+
+%package -n htcp
+Group: Applications/Internet
+Summary: HTTP(S) read/write client
+#Requires: curl-ssl
+
+%description -n htcp
+htcp is a client to fetch files or directory listings from remote
+servers using HTTP or HTTPS, or to put or delete files or directories
+onto remote servers using HTTPS. htcp is similar to scp(1), but uses
+HTTP/HTTPS rather than ssh as its transfer protocol.
+
+%prep
+
+%setup
+
+%build
+cd src
+make prefix=$RPM_BUILD_ROOT/%(echo ${MYPREFIX:-/usr})
+
+%install
+cd src
+make install prefix=$RPM_BUILD_ROOT/%(echo ${MYPREFIX:-/usr})
+
+%post
+/sbin/ldconfig
+ln -sf %(echo ${MYPREFIX:-/usr})/share/doc/gridsite-%{version} \
+ %(echo ${MYPREFIX:-/usr})/share/doc/gridsite
+
+%postun
+rm -f %(echo ${MYPREFIX:-/usr})/share/doc/gridsite
+
+%files
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/lib/libgridsite.so.%{version}
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/lib/libgridsite.so
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/urlencode
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/doc/gridsite-%{version}
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/urlencode.1.gz
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/include/gridsite.h
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/include/gridsite-gacl.h
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/lib/libgridsite.a
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/lib/httpd/modules/mod_gridsite.so
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/sbin/real-gridsite-admin.cgi
+
+%files -n htcp
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htcp
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htls
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htll
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htrm
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htmkdir
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htcp.1.gz
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htrm.1.gz
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htls.1.gz
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htll.1.gz
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htmkdir.1.gz
diff --git a/org.gridsite.core/src/grst_admin.h b/org.gridsite.core/src/grst_admin.h
new file mode 100644
index 0000000..4da3d11
--- /dev/null
+++ b/org.gridsite.core/src/grst_admin.h
@@ -0,0 +1,57 @@
+/*
+ Copyright (c) 2002-3, Andrew McNab and Shiv Kaushal,
+ University of Manchester. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ o Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ o Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*---------------------------------------------------------------------------*
+ * This program is part of GridSite: http://www.gridpp.ac.uk/gridsite/ *
+ *---------------------------------------------------------------------------*/
+
+void GRSThttpError(char *);
+void adminfooter(GRSThttpBody *, char *, char *, char *, char *);
+int GRSTstrCmpShort(char *, char *);
+char *makevfilename(char *, size_t, char *);
+
+/*CGI GACL - Edit interface functions*/
+void show_acl(int admin, GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void new_entry_form(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void new_entry(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void del_entry(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void edit_entry_form(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void edit_entry(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void add_cred_form(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void add_cred(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void del_cred(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void del_entry_sure(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void del_cred_sure(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+
+/*Functions producing messages*/
+//void error(char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void admin_continue(char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file, GRSThttpBody *bp);
+
diff --git a/org.gridsite.core/src/grst_admin_file.c b/org.gridsite.core/src/grst_admin_file.c
new file mode 100644
index 0000000..fed6c42
--- /dev/null
+++ b/org.gridsite.core/src/grst_admin_file.c
@@ -0,0 +1,1571 @@
+/*
+ Copyright (c) 2002-3, Andrew McNab, University of Manchester
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ o Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ o Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*---------------------------------------------------------------------------*
+ * This program is part of GridSite: http://www.gridpp.ac.uk/gridsite/ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef VERSION
+#define VERSION "x.x.x"
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// when porting: remember that sendfile() is very OS-specific!
+#include
+
+#include
+
+#include "grst_admin.h"
+
+char *storeuploadfile(char *boundary, int *bufferused)
+{
+// rewrite this to copy whole POSTed stdin HTTP body to disk then
+// mmap() and pick apart? How to deal with 100MB uploaded files, say?
+
+ char *filebuffer = NULL;
+ int bufferlen = 0, c, boundarylen;
+
+ *bufferused = 0;
+ boundarylen = strlen(boundary);
+
+ while ((c = getchar()) != EOF)
+ {
+ if (*bufferused > 1024*1024*100) return NULL;
+
+ ++(*bufferused);
+
+ if (*bufferused > bufferlen)
+ {
+ bufferlen = bufferlen + 1000;
+ filebuffer = realloc(filebuffer, (size_t) bufferlen);
+ }
+
+ filebuffer[*bufferused - 1] = c;
+
+ if ( (*bufferused >= boundarylen + 4) &&
+ (boundary[boundarylen-1] == c) &&
+ (boundary[boundarylen-2] == filebuffer[*bufferused - 2]) &&
+ (strncmp(boundary, &filebuffer[*bufferused - boundarylen],
+ boundarylen) == 0))
+ {
+ *bufferused = *bufferused - boundarylen - 4;
+
+ if (filebuffer == NULL) return strdup("");
+ else return filebuffer;
+ }
+ }
+
+ return NULL;
+}
+
+void uploadfile(char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path,
+ char *dir_uri, char *admin_file)
+{
+ char *boundary, *p, oneline[200], *filename = NULL,
+ tmpfilename[256], *filebuffer = NULL, *filepath,
+ *vfile, *dir_path_vfile;
+ int mimestate, bufferused = 0, itworked = 0;
+ FILE *fp;
+ GRSThttpBody bp;
+
+#define MIMESTUNKNOWN 1
+#define MIMESTUPLOAD 2
+#define MIMESTFILENM 3
+
+ if (!GRSTgaclPermHasWrite(perm)) GRSThttpError("403 Forbidden");
+
+ p = getenv("CONTENT_TYPE");
+ boundary = &p[30];
+
+ mimestate = MIMESTUNKNOWN;
+
+ while (fgets(oneline, sizeof(oneline), stdin) != NULL)
+ {
+ if (*oneline == 13) // MIME has CR/LF line breaks, CR=13
+ {
+ if (mimestate == MIMESTUPLOAD)
+ {
+ filebuffer = storeuploadfile(boundary, &bufferused);
+ mimestate = MIMESTUNKNOWN;
+ }
+ else if (mimestate == MIMESTFILENM)
+ {
+ fgets(tmpfilename, sizeof(tmpfilename), stdin);
+ if (*tmpfilename != 13)
+ {
+ p = index(tmpfilename, 13);
+ *p = '\0';
+ filename = strdup(tmpfilename);
+ }
+ mimestate = MIMESTUNKNOWN;
+ }
+ }
+ else if (GRSTstrCmpShort(oneline,
+ "Content-Disposition: form-data; name=\"uploadfile\"; filename=\"")
+ == 0)
+ {
+ mimestate = MIMESTUPLOAD;
+ if (filename == NULL)
+ {
+ filename = strdup(&oneline[61]);
+
+ p = rindex(&oneline[61], '\\');
+ if (p != NULL) { ++p ; filename = p; }
+
+ p = rindex(&oneline[61], '/');
+ if (p != NULL) { ++p ; filename = p; }
+
+ p = index(filename, '"');
+ if (p != NULL) *p = '\0';
+ }
+ }
+ else if (GRSTstrCmpShort(oneline,
+ "Content-Disposition: form-data; name=\"file\"") == 0)
+ {
+ mimestate = MIMESTFILENM;
+ }
+ }
+
+ if ((filebuffer != NULL) && (bufferused >= 0))
+ {
+ if (filename == NULL) GRSThttpError("403 Forbidden");
+ else if ((index(filename, '/') != NULL) ||
+ (strcmp(filename, GRST_ACL_FILE) == 0))
+ {
+ puts("Status: 403 Forbidden filename\nContent-Type: text/html");
+
+ GRSThttpBodyInit(&bp);
+
+ GRSThttpPrintf(&bp,"Forbidden filename %s\n", filename);
+ GRSThttpPrintHeaderFooter(&bp, dir_path, GRST_HEADFILE);
+
+ GRSThttpPrintf(&bp, "
Forbidden filename %s
\n",
+ filename);
+
+ GRSThttpPrintf(&bp,
+ "
New file names cannot include slashes "
+ "or use the reserved ACL name, %s\n", GRST_ACL_FILE);
+
+ GRSThttpPrintf(&bp,"
GridSite considers you are authorized "
+ "to upload the file, but the upload failed. This is "
+ "probably a web server or operating system level "
+ "misconfiguration. Consult the site administrator.");
+
+ GRSThttpPrintf(&bp,"
GridSite considers you are authorized "
+ "to delete %s, but the delete failed. This is "
+ "probably a web server or operating system level "
+ "misconfiguration. Consult the site administrator.",
+ file);
+
+ GRSThttpPrintf(&bp,"
GridSite considers you are authorized "
+ "to write the file, but the write failed. This is "
+ "probably a web server or operating system level "
+ "misconfiguration. Consult the site administrator.");
+
+ GRSThttpPrintf(&bp,"
GridSite considers you are authorized "
+ "to create it, but the create failed. This is "
+ "probably a web server or operating system level "
+ "misconfiguration. Consult the site administrator.");
+
+ GRSThttpPrintf(&bp,"
GridSite considers you are authorized "
+ "to rename it, but the rename failed. This is "
+ "probably a web server or operating system level "
+ "misconfiguration. Consult the site administrator.");
+
+ GRSThttpPrintf(&bp,"
GridSite considers you are authorized "
+ "to create the directory, but the creation failed. This "
+ "is probably a web server or operating system level "
+ "misconfiguration. Consult the site administrator.");
+
+ GRSThttpPrintf(&bp,"
You cannot create a DN List "
+ "with that prefix in this directory. Please see the "
+ "the GridSite User's Guide for an explanation.");
+
+ GRSThttpPrintf(&bp,"
GridSite considers you are authorized "
+ "to write the file, but the write failed. This is "
+ "probably a web server or operating system level "
+ "misconfiguration. Consult the site administrator.");
+
+ GRSThttpPrintf(&bp,"
\n");
+
+ if (!is_dnlists_dir) adminfooter(&bp, dn, help_uri, dir_uri, NULL);
+
+ GRSThttpPrintHeaderFooter(&bp, dir_path, GRST_FOOTFILE);
+ GRSThttpWriteOut(&bp);
+}
+
diff --git a/org.gridsite.core/src/grst_admin_gacl.c b/org.gridsite.core/src/grst_admin_gacl.c
new file mode 100644
index 0000000..318277e
--- /dev/null
+++ b/org.gridsite.core/src/grst_admin_gacl.c
@@ -0,0 +1,968 @@
+/*
+ Copyright (c) 2003, Shiv Kaushal, University of Manchester
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ o Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ o Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*---------------------------------------------------------------------------*
+* This program is part of GridSite: http://www.gridpp.ac.uk/authz/gridsite/ *
+*---------------------------------------------------------------------------*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+extern char *grst_perm_syms[];
+extern int grst_perm_vals[];
+
+#include "grst_admin.h"
+
+// CGI GACL Editor interface functions
+void show_acl(int admin, GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void new_entry_form(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void new_entry(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void del_entry(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void edit_entry_form(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void edit_entry(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void add_cred_form(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void add_cred(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void del_cred(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void del_entry_sure(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void del_cred_sure(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void admin_continue(char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file, GRSThttpBody *bp);
+
+// Functions for producing HTML output
+void StartHTML(GRSThttpBody *bp, char *dir_uri, char* dir_path);
+void StartForm(GRSThttpBody *bp, char* dir_uri, char* dir_path, char* admin_file, int timestamp, char* target_function);
+void EndForm(GRSThttpBody *bp);
+void GRSTgaclCredTableStart(GRSThttpBody *bp);
+void GRSTgaclCredTableAdd(GRSTgaclUser *user, GRSTgaclEntry *entry, GRSTgaclCred *cred, GRSTgaclNamevalue *namevalue, int cred_no, int entry_no, int admin, int timestamp, GRSThttpBody *bp, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+void GRSTgaclCredTableEnd(GRSTgaclEntry* entry, int entry_no, int admin, int timestamp, GRSThttpBody *bp, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+
+// ACL Manipulation functions
+int GACLentriesInAcl(GRSTgaclAcl *acl);
+int GRSTgaclCredsInEntry(GRSTgaclEntry *entry);
+void check_acl_save(char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file, GRSTgaclUser* user, GRSTgaclAcl *acl, GRSThttpBody *bp);
+void GACLeditGetPerms(GRSTgaclEntry *entry);
+GRSTgaclEntry *GACLreturnEntry(GRSTgaclAcl *acl, int entry_no);
+GRSTgaclCred *GACLreturnCred(GRSTgaclEntry *entry, int cred_no);
+
+void StringHTMLEncode (char* string, GRSThttpBody *bp);
+
+void revert_acl(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file);
+
+/*****************************************/
+/********** FUNCTIONS FOLLOW *************/
+/*****************************************/
+
+void show_acl(int admin, GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Shows the contents of the ACL. Gives edit 'buttons' if (int admin) == 1
+ GRSTgaclAcl *acl;
+ GRSTgaclEntry *entry;
+ GRSTgaclCred *cred;
+ GRSTgaclNamevalue *namevalue;
+ int entry_no, cred_no, allow, deny,timestamp;
+ GRSThttpBody bp;
+ char* AclFilename;
+ struct stat file_info;
+ int history_mode=0;
+
+ if (admin==2){
+ history_mode=1;
+ admin=0;
+ }
+
+ /*double-check access permision*/
+ if (!GRSTgaclPermHasAdmin(perm)) admin=0;
+
+ StartHTML(&bp, dir_uri, dir_path);
+
+ /* Load ACL from file and get timestamp*/
+ if (history_mode==1) {
+ AclFilename=malloc(strlen(dir_path)+strlen(file)+2);
+ strcpy(AclFilename, dir_path);
+ strcat(AclFilename, "/");
+ strcat(AclFilename, file);
+ }
+ else AclFilename=GRSTgaclFileFindAclname(dir_path);
+
+ if (AclFilename==NULL){
+ GRSThttpPrintf ( &bp,"The ACL was not found !!! \n");
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, &bp);
+ return;
+ }
+
+ stat(GRSTgaclFileFindAclname(dir_path), &file_info);
+ timestamp=file_info.st_mtime;
+ acl = GRSTgaclAclLoadFile(AclFilename);
+
+ if (acl==NULL){
+ GRSThttpPrintf ( &bp,"The ACL was found but could not be loaded - it could be incorrectly formatted \n");
+ adminfooter(&bp, dn, help_uri, dir_uri, NULL);
+ GRSThttpPrintHeaderFooter(&bp, dir_path, GRST_FOOTFILE);
+ GRSThttpWriteOut(&bp);
+ return;
+ }
+
+ if (admin) GRSThttpPrintf (&bp,"New Entry \n", dir_uri, admin_file, dir_uri, timestamp );
+
+ // Start with the first entry in the list and work through
+ entry=acl->firstentry;
+ entry_no=1;
+ while (entry!=NULL){
+
+ GRSThttpPrintf (&bp," Entry %d:\n", entry_no);
+ if (admin){
+ GRSThttpPrintf (&bp,"Edit Entry ", dir_uri, admin_file, entry_no, dir_uri, timestamp );
+ GRSThttpPrintf (&bp,"Delete Entry ",dir_uri, admin_file, entry_no, dir_uri, timestamp );
+ GRSThttpPrintf (&bp,"
\n");
+ }
+
+ GRSTgaclCredTableStart(&bp);
+
+ // Start with the first credential in the entry and work through
+ cred=entry->firstcred;
+ cred_no=1;
+ while (cred!=NULL){
+ namevalue=cred->firstname;
+ GRSTgaclCredTableAdd(user, entry, cred, namevalue, cred_no, entry_no, admin, timestamp, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+ // Change to next credential
+ cred=cred->next;
+ cred_no++;
+ }
+
+ GRSTgaclCredTableEnd (entry, entry_no, admin, timestamp, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+ // Change to next entry
+ entry=entry->next;
+ entry_no++;
+ }
+
+ if (!admin && GRSTgaclPermHasAdmin(perm) && !history_mode) //Print a link for admin mode, if not in admin mode but the user has admin permissions
+ GRSThttpPrintf (&bp,"Admin Mode", dir_uri, admin_file, dir_uri, timestamp );
+ if (history_mode==1 && GRSTgaclDNlistHasUser(getenv("REDIRECT_GRST_ADMIN_LIST"), user)){
+ StartForm(&bp, dir_uri, dir_path, admin_file, timestamp, "revert_acl");
+//GRSThttpPrintf (&bp,"Revert to this Version", dir_uri, admin_file, dir_uri, timestamp, file );
+ GRSThttpPrintf (&bp, "\n", file);
+ // Revert Button
+ GRSThttpPrintf (&bp, "
\n\n");
+ }
+
+ adminfooter(&bp, dn, help_uri, dir_uri, NULL);
+ GRSThttpPrintHeaderFooter(&bp, dir_path, GRST_FOOTFILE); GRSThttpWriteOut(&bp); return;
+}
+
+
+void new_entry_form(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm,char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Presents the user with a form asking for details required to create a new entry
+ GRSThttpBody bp;
+ int timestamp=atol(GRSThttpGetCGI("timestamp"));
+ GRSTgaclCred* cred;
+ GRSTgaclEntry *entry;
+ GRSTgaclNamevalue* namevalue;
+
+ if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+
+ StartHTML(&bp, dir_uri, dir_path);
+ StartForm(&bp, dir_uri, dir_path, admin_file, timestamp, "new_entry");
+ GRSThttpPrintf (&bp, "NEW ENTRY IN ACL FOR %s
\n", dir_uri);
+
+ GRSTgaclCredTableStart(&bp);
+ GRSTgaclCredTableAdd(user, entry,cred, namevalue, 0, 0, 0, timestamp, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+ GRSTgaclCredTableEnd (entry, 0, 0, timestamp, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+
+ /*Submit and reset buttons - submit button sends the data in the form back to the script & new_entry() to be called*/
+ EndForm(&bp);
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, &bp);
+ return;
+}
+
+void new_entry(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Processes the information entered into the form from new_entry_form() and adds a new entry to the ACL
+ GRSTgaclAcl *acl;
+ GRSTgaclEntry *entry;
+ GRSTgaclCred *cred;
+ char *type, *value;
+ GRSThttpBody bp;
+ if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+
+ // Get new credential info and perform checks
+ type=GRSThttpGetCGI("type");
+ value=GRSThttpGetCGI("cred0_value");
+
+ if (strcmp(type, "not_chosen")==0){
+ GRSThttpError ("500 Invalid input - credential type not chosen");
+ return;
+ }
+
+ // Create the credential
+ cred=GRSTgaclCredNew(type);
+ if (strcmp(type, "person")==0) GRSTgaclCredAddValue(cred,"dn", value);
+ else if (strcmp(type, "dn-list")==0) GRSTgaclCredAddValue(cred, "url", value);
+ else if (strcmp(type, "voms")==0) GRSTgaclCredAddValue(cred, "fqan", value);
+ else if (strcmp(type, "dns")==0) GRSTgaclCredAddValue(cred, "hostname", value);
+ else if (strcmp(type, "any-user")==0) {} // namevalue not entered for any-user credential
+ else{
+ GRSThttpError ("500 Invalid input - credential type not valid");
+ return;
+ }
+
+ // Create and empty entry, add the credential and get permissions
+ entry = GRSTgaclEntryNew();
+ GRSTgaclEntryAddCred(entry, cred);
+ GACLeditGetPerms(entry);
+
+ // Load the ACL, add the entry and save
+ acl = GRSTgaclAclLoadFile(GRSTgaclFileFindAclname(dir_path));
+ GRSTgaclAclAddEntry(acl, entry);
+ check_acl_save(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, user, acl, &bp);
+ return;
+}
+
+void del_entry(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Deletes the entry denoted by the GCI variable "entry_no"*/
+ int entry_no;
+ GRSTgaclAcl *acl;
+ GRSTgaclEntry *previous, *entry;
+ GRSThttpBody bp;
+
+ if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+
+ // Load the ACL
+ acl = GRSTgaclAclLoadFile(GRSTgaclFileFindAclname(dir_path));
+
+ // Get the number of the entry to be deleted and check okay to delete
+ entry_no=atol(GRSThttpGetCGI("entry_no"));
+ if(GACLentriesInAcl(acl)<=1){
+ StartHTML(&bp, dir_uri, dir_path);
+ GRSThttpPrintf (&bp, "ERROR: Cannot delete all entries from the ACL \n");
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, &bp);
+ return;
+ }
+
+ // Get pointer to entry and previous entry
+ entry = GACLreturnEntry(acl, entry_no);
+ if (entry_no!=1) previous = GACLreturnEntry(acl, entry_no-1);
+
+ if(entry==NULL || entry_no<1 || entry_no>GACLentriesInAcl(acl) ){
+ GRSThttpError ("500 Unable to read entry from ACL file");
+ return;
+ }
+
+ // Perform deletion from the list by changing pointers
+ if (entry_no==1) acl->firstentry=entry->next;
+ else if (entry_no==GACLentriesInAcl(acl)) previous->next=NULL;
+ else previous->next=entry->next;
+
+ // Save ACL and exit
+ check_acl_save(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, user, acl, &bp);
+
+ return;
+}
+
+
+void edit_entry_form(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Presents the user with an editable form containing details of entry denoted by CGI variable entry_no*/
+ int entry_no, cred_no, i, admin=0, timestamp=atol(GRSThttpGetCGI("timestamp"));
+ GRSTgaclAcl *acl;
+ GRSTgaclEntry *entry;
+ GRSTgaclCred *cred;
+ GRSTgaclNamevalue *namevalue;
+ // struct _GACLnamevalue *namevalue;
+ GRSThttpBody bp;
+
+ if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+
+ // Load ACL from file
+ acl = GRSTgaclAclLoadFile(GRSTgaclFileFindAclname(dir_path));
+
+ // Get pointer to the entry and check okay
+ entry_no=atol(GRSThttpGetCGI("entry_no"));
+ entry = GACLreturnEntry(acl, entry_no);
+ if(entry==NULL || entry_no<1 || entry_no>GACLentriesInAcl(acl) ){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+
+ StartHTML(&bp, dir_uri, dir_path);
+ GRSThttpPrintf (&bp, "EDITING ENTRY %d IN ACL FOR %s
\n", entry_no, dir_uri);
+
+ // Start with first credential in the entry and display them in order*/
+ cred=entry->firstcred;
+ cred_no=1;
+ StartForm(&bp, dir_uri, dir_path, admin_file, timestamp, "edit_entry");
+ GRSThttpPrintf (&bp, "\n", entry_no);
+
+ GRSTgaclCredTableStart(&bp);
+
+ while (cred!=NULL){
+ // Start with the first namevalue in the credential
+ namevalue=cred->firstname;
+ GRSTgaclCredTableAdd(user, entry, cred, namevalue, cred_no, entry_no, admin, timestamp, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+ // Change to next credential
+ cred=cred->next;
+ cred_no++;
+ }
+ GRSTgaclCredTableEnd (entry, entry_no, admin, timestamp, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+ EndForm(&bp);
+
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, &bp);
+ return;
+}
+
+
+void edit_entry(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ //Processes the information entered into the form from edit_entry_form() and updates the entry corresponding to entry_no*/
+ int entry_no, cred_no, i;
+ GRSTgaclAcl *acl;
+ GRSTgaclEntry *entry;
+ GRSTgaclCred *cred;
+ GRSTgaclNamevalue *namevalue;
+ char variable[30];
+ GRSThttpBody bp;
+
+ if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+
+ // Load the ACL
+ acl = GRSTgaclAclLoadFile(GRSTgaclFileFindAclname(dir_path));
+
+ // Get pointer to the entry and perform checks
+ entry_no=atol(GRSThttpGetCGI("entry_no"));
+ entry = GACLreturnEntry(acl, entry_no);
+ if(entry==NULL || entry_no<1 || entry_no>GACLentriesInAcl(acl) ){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+
+ // Start with the first credential and update each one
+ cred=entry->firstcred;
+ cred_no=1;
+
+ while (cred!=NULL){
+ if (strcmp(cred->type, "any-user")!=0){
+ namevalue=cred->firstname;
+ sprintf(variable, "cred%d_value", cred_no);
+ namevalue->value=GRSThttpGetCGI(variable);
+ }
+ //Change to next credential*/
+ cred=cred->next;
+ cred_no++;
+ }
+
+ // Update permissions
+ GACLeditGetPerms(entry);
+ check_acl_save(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, user, acl, &bp);
+ return;
+}
+
+
+void add_cred_form(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Presents the user with a form asking for details required to create a new credential in the entry denoted by entry_no
+ GRSThttpBody bp;
+ int timestamp=atol(GRSThttpGetCGI("timestamp")), entry_no=atol(GRSThttpGetCGI("entry_no"));
+ GRSTgaclAcl *acl;
+ GRSTgaclEntry* entry;
+ GRSTgaclCred* cred;
+ GRSTgaclNamevalue* namevalue;
+
+ if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+
+ acl = GRSTgaclAclLoadFile(GRSTgaclFileFindAclname(dir_path)); // Load the ACL
+
+ //Get pointer to the entry and perform checks
+ entry = GACLreturnEntry(acl, entry_no);
+ if(entry==NULL || entry_no<1 || entry_no>GACLentriesInAcl(acl) ){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+
+
+ if (strcmp(GRSThttpGetCGI("cmd"), "add_cred_form")==0){ //if not a new entry check to see if cred exists
+ cred=entry->firstcred;
+ while (cred!=NULL) {
+ if (strcmp (cred->type, "any-user")==0) {
+ StartHTML(&bp, dir_uri, dir_path);
+ GRSThttpPrintf (&bp, "ERROR: AND-ing \"any-user\" credential with other credential does not make sense \n");
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, &bp);
+ return;
+ }
+ cred=cred->next;
+ }
+ }
+
+ StartHTML(&bp, dir_uri, dir_path);
+ GRSThttpPrintf (&bp, " NEW CREDENTIAL IN ENTRY %d OF ACL FOR %s
\n", entry_no, dir_uri);
+ StartForm(&bp, dir_uri, dir_path, admin_file, timestamp, "add_cred");
+
+ GRSThttpPrintf (&bp, " \n", entry_no);
+
+ GRSTgaclCredTableStart(&bp);
+ GRSTgaclCredTableAdd(user, entry, cred, namevalue, 0, 0, 0, timestamp, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+ GRSTgaclCredTableEnd (entry, 0, 0, timestamp, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+
+ EndForm(&bp);
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, &bp);
+ return;
+}
+
+
+void add_cred(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Processes the information entered into the form [add_cred_form()]and adds a new credential to the entry corresponding to entry_no
+ int entry_no;
+ GRSTgaclAcl *acl;
+ GRSTgaclEntry *entry;
+ GRSTgaclCred *cred;
+ GRSThttpBody bp;
+ char *type, *value;
+
+ if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+
+ acl = GRSTgaclAclLoadFile(GRSTgaclFileFindAclname(dir_path));// Load the ACL
+
+ // Get pointer to the entry and perform checks
+ entry_no=atol(GRSThttpGetCGI("entry_no"));
+ entry = GACLreturnEntry(acl, entry_no);
+ if(entry==NULL || entry_no<1 || entry_no>GACLentriesInAcl(acl)){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+
+ // Create new credential and add it to entry
+ type=GRSThttpGetCGI("type");
+ value=GRSThttpGetCGI("cred0_value");
+ cred=GRSTgaclCredNew(type);
+ if (strcmp(type, "person") ==0) GRSTgaclCredAddValue(cred,"dn", value);
+ else if (strcmp(type, "dn-list") ==0) GRSTgaclCredAddValue(cred, "url", value);
+ else if (strcmp(type, "voms") ==0) GRSTgaclCredAddValue(cred, "fqan", value);
+ else if (strcmp(type, "dns") ==0) GRSTgaclCredAddValue(cred, "hostname", value);
+ else if (strcmp(type, "any-user")==0) {}// namevalue not entered for any-user credential
+ else{
+ GRSThttpError ("500 Credential type not valid");
+ return;
+ }
+ GRSTgaclEntryAddCred(entry, cred);
+
+ check_acl_save(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, user, acl, &bp);
+ return;
+}
+
+
+void del_cred(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Deletes the credential denoted by the GCI variable "cred_no", in the entry denoted by "entry_no"
+ int entry_no, cred_no;
+ GRSTgaclAcl *acl;
+ GRSTgaclEntry *entry;
+ GRSTgaclCred *previous, *cred;
+ GRSThttpBody bp;
+
+ if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+
+ acl = GRSTgaclAclLoadFile(GRSTgaclFileFindAclname(dir_path));
+
+ // Get pointer to the entry and perform checks
+ entry_no=atol(GRSThttpGetCGI("entry_no"));
+ entry = GACLreturnEntry(acl, entry_no);
+ if(entry==NULL || entry_no<1 || entry_no>GACLentriesInAcl(acl) ){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+ // Get pointer the the credential and perform checks
+ cred_no=atol(GRSThttpGetCGI("cred_no"));
+ cred=GACLreturnCred(entry, cred_no);
+ if(entry==NULL || entry_no<1 || cred_no>GRSTgaclCredsInEntry(entry)){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+ // Get pointer to previous credential - if needed
+ if (cred_no!=1) previous = GACLreturnCred(entry, cred_no-1);
+
+ // Perform deletion from the list by changing pointers
+ if (cred_no==1) entry->firstcred=cred->next;
+ else if (cred_no==GRSTgaclCredsInEntry(entry)) previous->next=NULL;
+ else previous->next=cred->next;
+
+ check_acl_save(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, user, acl, &bp);
+ return;
+}
+
+void admin_continue(char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file, GRSThttpBody *bp){
+ // Single line printed out to forward users back to show_acl in admin mode
+ // Should ALWAYS called from another function so no HTML header required
+ // Should ALWAYS be the end of a page
+ GRSThttpPrintf (bp, "\n Click Here to return to the editor", dir_uri,admin_file,dir_uri, time(NULL));
+ adminfooter(bp, dn, help_uri, dir_uri, NULL);
+ GRSThttpPrintHeaderFooter(bp, dir_path, GRST_FOOTFILE);
+ GRSThttpWriteOut(bp);
+ return;
+}
+
+
+void del_entry_sure(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Prints out entry denoted by entry_no and asks if the user really wants to delete it
+ GRSTgaclAcl *acl;
+ GRSTgaclEntry *entry;
+ GRSTgaclCred *cred;
+ GRSTgaclNamevalue *namevalue;
+ int entry_no, cred_no, allow, deny, i, timestamp;
+ GRSThttpBody bp;
+
+ if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+
+ acl = GRSTgaclAclLoadFile(GRSTgaclFileFindAclname(dir_path));// Load ACL from file
+
+ if (acl==NULL){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+
+ // Get pointer to the entry and check okay
+ entry_no=atol(GRSThttpGetCGI("entry_no"));
+ entry = GACLreturnEntry(acl, entry_no);
+ if(entry==NULL || entry_no<1 || entry_no>GACLentriesInAcl(acl) ){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+
+ StartHTML(&bp, dir_uri, dir_path);
+ GRSThttpPrintf (&bp, "
Do you really want to delete the following entry?
\n");
+ GRSThttpPrintf (&bp," Entry %d: \n", entry_no);
+
+ // Print the entry out
+ // Start with the first credential in the entry and work through
+ cred=entry->firstcred;
+ cred_no=1;
+
+ GRSTgaclCredTableStart(&bp);
+ while (cred!=NULL){
+ // Start with the first namevalue in the credential
+ namevalue=cred->firstname;
+ GRSTgaclCredTableAdd(user, entry, cred, namevalue, cred_no, entry_no, 0, 0, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+ // Change to next credential
+ cred=cred->next;
+ cred_no++;
+ }
+
+ GRSTgaclCredTableEnd (entry, entry_no, 0, 0, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+
+ StartForm(&bp, dir_uri, dir_path, admin_file, atol(GRSThttpGetCGI("timestamp")), "del_entry");
+ GRSThttpPrintf (&bp, "\n", entry_no);
+ GRSThttpPrintf (&bp, " \n\n");
+
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, &bp);
+ return;
+}
+
+void del_cred_sure(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Prints out credential denoted by entry_no/cred_no and asks if the user really wants to delete it
+ GRSTgaclAcl *acl;
+ GRSTgaclEntry *entry;
+ GRSTgaclCred *cred;
+ GRSTgaclNamevalue *namevalue;
+ int entry_no, cred_no, allow, deny, timestamp, i;
+ GRSThttpBody bp;
+
+ if (!GRSTgaclPermHasAdmin(perm)) GRSThttpError ("403 Forbidden");
+
+ acl = GRSTgaclAclLoadFile(GRSTgaclFileFindAclname(dir_path));// Load ACL from file
+
+ if (acl==NULL){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+
+ // Get pointer to the entry and check okay
+ entry_no=atol(GRSThttpGetCGI("entry_no"));
+ entry = GACLreturnEntry(acl, entry_no);
+ if(entry==NULL || entry_no<1 || entry_no>GACLentriesInAcl(acl) ){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+
+ // Get pointer to the credential and check okay
+ cred_no=atol(GRSThttpGetCGI("cred_no"));
+ cred=GACLreturnCred(entry, cred_no);
+ if(entry==NULL || entry_no<1 || cred_no>GRSTgaclCredsInEntry(entry)){
+ GRSThttpError ("500 Unable to read from ACL file");
+ return;
+ }
+
+ if(GRSTgaclCredsInEntry(entry)<=1){
+ del_entry_sure(user, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+ return;
+ }
+
+ StartHTML(&bp, dir_uri, dir_path);
+ GRSThttpPrintf (&bp, "
Do you really want to delete the following credential from entry %d?
", entry_no);
+
+ // Print the credential out
+ GRSTgaclCredTableStart(&bp);
+ GRSTgaclCredTableAdd(user, entry, cred, cred->firstname, cred_no, entry_no, 0, 0, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+ GRSTgaclCredTableEnd (entry, entry_no, 0, 0, &bp, dn, perm, help_uri, dir_path, file, dir_uri, admin_file);
+ GRSThttpPrintf (&bp," \n");
+
+ // Yes Button
+ StartForm(&bp, dir_uri, dir_path, admin_file, atol(GRSThttpGetCGI("timestamp")), "del_cred");
+ GRSThttpPrintf (&bp, "\n", entry_no);
+ GRSThttpPrintf (&bp, "\n", cred_no);
+ GRSThttpPrintf (&bp, " \n\n");
+
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, &bp);
+ return;
+}
+
+
+int GACLentriesInAcl(GRSTgaclAcl *acl){
+ // Returns the number of entries in acl
+ GRSTgaclEntry *entry;
+ int number;
+
+ entry=acl->firstentry;
+ number=0;
+
+ while (entry!=NULL)
+ {
+ number++;
+ entry=entry->next;
+ }
+
+ return number;
+}
+
+int GRSTgaclCredsInEntry(GRSTgaclEntry *entry){
+ // Returns the number of credentials in entry
+ int number;
+ GRSTgaclCred *cred;
+
+ cred=entry->firstcred;
+ number=0;
+
+ while (cred!=NULL)
+ {
+ number++;
+ cred=cred->next;
+ }
+
+ return number;
+}
+
+
+void GACLeditGetPerms(GRSTgaclEntry *entry){
+ // Updates the permissions entry using permissions from a form produced using GRSTgaclCredTableEnd
+ int i;
+ char buf[30];
+
+
+ for (i=0; grst_perm_syms[i]!=NULL; i++) /* Print the list of allowed permissions*/
+ {
+ sprintf (buf, "allow_%s", grst_perm_syms[i]); // Update allowed
+ if (strcmp (GRSThttpGetCGI(buf), "ON") == 0 ) GRSTgaclEntryAllowPerm(entry, grst_perm_vals[i]); else GRSTgaclEntryUnallowPerm(entry, grst_perm_vals[i]);
+
+ sprintf (buf, "deny_%s", grst_perm_syms[i]); // Update denied
+ if (strcmp (GRSThttpGetCGI(buf), "ON") == 0 ) GRSTgaclEntryDenyPerm(entry, grst_perm_vals[i]); else GRSTgaclEntryUndenyPerm(entry, grst_perm_vals[i]);
+
+ }
+
+ return;
+}
+
+GRSTgaclEntry *GACLreturnEntry(GRSTgaclAcl *acl, int entry_no){
+ // Returns a pointer to entry in ACL denoted by entry_no, returns NULL if not found
+ int number;
+ GRSTgaclEntry *entry;
+
+ if (acl==NULL) return NULL;
+
+ entry=acl->firstentry;
+ number=1;
+
+ while (entry!=NULL)
+ {
+ if (number==entry_no) return entry;
+ number++;
+ entry=entry->next;
+ }
+
+ return NULL;
+}
+
+
+GRSTgaclCred *GACLreturnCred(GRSTgaclEntry *entry, int cred_no){
+ // Returns a pointer to credential denoted by cred_no in entry, returns NULL if not found
+ int number;
+ GRSTgaclCred *cred;
+
+ if (entry==NULL) return NULL;
+
+ cred=entry->firstcred;
+ number=1;
+
+ while (cred!=NULL)
+ {
+ if (number==cred_no) return cred;
+ number++;
+ cred=cred->next;
+ }
+
+ return NULL;
+}
+void StartHTML(GRSThttpBody *bp, char *dir_uri, char* dir_path){
+ //Start HTML output and insert page title
+ printf("Status: 200 OK\nContent-Type: text/html\n");
+ GRSThttpBodyInit(bp);
+ GRSThttpPrintf(bp, "Access Control List for %s\n", dir_uri);
+ GRSThttpPrintHeaderFooter(bp, dir_path, GRST_HEADFILE);
+ return;
+}
+void StartForm(GRSThttpBody *bp, char* dir_uri, char* dir_path, char* admin_file, int timestamp, char* target_function){
+ // Starts an HTML form with gridsite admin as the target and target_function as the value of cmd.
+ // Also inputs the dir_uri and the timestamp
+ GRSThttpPrintf (bp, "\n");
+ return;
+}
+
+void GRSTgaclCredTableStart(GRSThttpBody *bp){
+ //Starts an HTML table of credentials by setting the column widths and inputting the headings
+ GRSThttpPrintf (bp,"
");
+ GRSThttpPrintf (bp,"
Credential No.
Type
Value
");
+ return;
+}
+
+void GRSTgaclCredTableAdd(GRSTgaclUser *user, GRSTgaclEntry *entry, GRSTgaclCred *cred, GRSTgaclNamevalue *namevalue, int cred_no, int entry_no, int admin, int timestamp, GRSThttpBody *bp, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Adds the credential "cred" to a table started byGRSTgaclCredTableStart allowing the user to edit if appropriate
+ char* cmd = GRSThttpGetCGI("cmd");
+ int edit_values=0, new_cred=0, allow_new_person=1;
+ int site_admin=GRSTgaclDNlistHasUser(getenv("REDIRECT_GRST_ADMIN_LIST"), user);
+
+ if (strcmp(cmd, "new_entry_form")==0 || strcmp(cmd, "add_cred_form")==0) new_cred=1;
+ if (new_cred || strcmp(cmd, "edit_entry_form")==0) edit_values=1;
+
+ if (new_cred) { /*Print out type and descriptor*/
+ if (strcmp(cmd, "add_cred_form")==0){ /*if not a new entry check to see if cred exists.*/
+ cred=entry->firstcred;
+ while (cred!=NULL) {if (strcmp (cred->type, "person")==0) allow_new_person=0; cred=cred->next;}
+ }
+ //create dummy credential for the user to edit
+ cred=GRSTgaclCredNew("new");
+ GRSTgaclCredAddValue(cred, "", "");
+ namevalue=cred->firstname;
+ //Drop down list of types
+ GRSThttpPrintf(bp,"
New
");
+ GRSThttpPrintf(bp,"
");
+ GRSThttpPrintf (bp, "
");
+ }
+
+ else { //Print out type and descriptor for existing cred
+
+ GRSThttpPrintf(bp,"
"); /* Do not print out namevalue for any-user credential*/
+ else{
+ if (edit_values){ // Place namevalue in an editable box if appropriate
+ GRSThttpPrintf (bp, "
"); StringHTMLEncode(namevalue->value, bp);}
+
+ }
+ //Print out warning symbol if cred being printed relates to current user - but NOT for users in site admin list
+ if (GRSTgaclUserHasCred(user, cred) && !site_admin) GRSThttpPrintf(bp, " <--");
+ GRSThttpPrintf(bp, "
");
+}
+
+void GRSTgaclCredTableEnd(GRSTgaclEntry* entry, int entry_no, int admin, int timestamp, GRSThttpBody *bp, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ // Finishes off a table of credentials by inputting "Add Credential" link and a list of premissions in the final row
+ int i, blank_perms, edit_perms, show_perms;
+ char* cmd = GRSThttpGetCGI("cmd");
+
+ if (strcmp(cmd, "add_cred_form")==0 ||strcmp(cmd, "del_cred_sure")==0) show_perms=0; else show_perms=1;
+ if (strcmp(cmd, "edit_entry_form")==0 || strcmp(cmd, "new_entry_form")==0) edit_perms=1; else edit_perms=0;
+ if (strcmp(cmd, "new_entry_form")==0) blank_perms=1; else blank_perms=0;
+
+ // If showing the last row is not required then exit
+ if (show_perms==0){GRSThttpPrintf (bp,"
");
+
+ if (blank_perms) entry->allowed=entry->denied=GRST_PERM_NONE;
+
+ // Show Permissions - will produce a list or a list of check boxes depending on whether the permissions are to be edited or not
+ GRSThttpPrintf (bp, "Allowed: ");
+ for (i=0; grst_perm_syms[i]!=NULL; i++) /* Print the list of allowed permissions*/
+ {
+ if ( entry->allowed & grst_perm_vals[i]){
+ if (edit_perms) GRSThttpPrintf (bp, "%s \n", grst_perm_syms[i],grst_perm_syms[i]);
+ else GRSThttpPrintf(bp,"%s ", grst_perm_syms[i]); if (strcmp(grst_perm_syms[i], "none")==0) break;
+ }
+ else if (strcmp(grst_perm_syms[i], "none")!=0 && edit_perms) GRSThttpPrintf (bp, "%s \n", grst_perm_syms[i],grst_perm_syms[i]);
+ }
+
+ if (edit_perms) GRSThttpPrintf (bp, "
");
+ GRSThttpPrintf (bp, "Denied: ");
+ for (i=0; grst_perm_syms[i]!=NULL; i++) /* Print the list of denied permissions*/
+ {
+ if ( entry->denied & grst_perm_vals[i])
+ {
+ if (edit_perms) GRSThttpPrintf (bp, "%s \n", grst_perm_syms[i],grst_perm_syms[i]);
+ else GRSThttpPrintf(bp,"%s ", grst_perm_syms[i]);
+ if (strcmp(grst_perm_syms[i], "none")==0) break;
+ }
+ else if (strcmp(grst_perm_syms[i], "none")!=0 && edit_perms) GRSThttpPrintf (bp, "%s \n", grst_perm_syms[i],grst_perm_syms[i]);
+ }
+
+ GRSThttpPrintf (bp, "
");
+ GRSThttpPrintf (bp," \n");
+ GRSThttpPrintf (bp,"\n");
+}
+
+void check_acl_save(char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file, GRSTgaclUser* user, GRSTgaclAcl *acl, GRSThttpBody *bp){
+ // Checks if the acl for the current directory has been changed, check the current user's permissions.
+ // If all is okay the ACl is saved -> returns 1 else returns 0
+ struct stat file_info;
+ GRSTgaclPerm new_perm;
+ char *vfile, *dir_path_vfile, *dir_path_file;
+ FILE *fp;
+
+
+ /*Check ACL has not been modified*/
+ stat(GRSTgaclFileFindAclname(dir_path), &file_info);
+ if (atol(GRSThttpGetCGI("timestamp"))!=file_info.st_mtime){
+ StartHTML(bp, dir_uri, dir_path);
+ GRSThttpPrintf (bp, "ERROR: CANNOT SAVE CHANGES
The ACL has been modified since it was last viewed\n
");
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, bp);
+ return;
+ }
+
+ // check users permissions in the new ACL
+
+ if (!GRSTgaclDNlistHasUser(getenv("REDIRECT_GRST_ADMIN_LIST"), user))
+ {
+ new_perm = GRSTgaclAclTestUser(acl, user);
+ if (new_perm != perm){
+ StartHTML(bp, dir_uri, dir_path);
+ if (!GRSTgaclPermHasAdmin(new_perm)){//Check that user still has Admin permissions - if not then exit without saving the new ACL
+ GRSThttpPrintf (bp, "ERROR: CANNOT SAVE CHANGES\n\n
You cannot deny yourself admin access from within the editor\n");
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, bp);
+ return;
+ }
+ //Functions to inform of other permission changes come next
+ GRSThttpPrintf (bp, "WARNING: OPERATION CHANGED YOUR PERMISSIONS!\n\n
You still have Admin permissions
\n");
+ admin_continue(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, bp);
+ return;
+ }
+ }
+ // ACL not modified, notified of permission changes - can now save
+
+ dir_path_file=GRSTgaclFileFindAclname(dir_path);
+ vfile=makevfilename(".gacl", file_info.st_size, dn); // Make temporary file name
+ dir_path_vfile = malloc(strlen(dir_path) + strlen(vfile) + 2);
+ strcpy(dir_path_vfile, dir_path);
+ strcat(dir_path_vfile, "/");
+ strcat(dir_path_vfile, vfile);
+
+ GRSTgaclAclSave(acl, dir_path_vfile); // save the new ACL to the temporary file
+ unlink(dir_path_file);
+ if (link (dir_path_vfile,dir_path_file)!=0) GRSThttpError("403 Forbidden");
+
+ printf ("Status: 302 Moved Temporarily\n Content Length: 0\nLocation: %s%s?cmd=admin_acl\n\n", dir_uri, admin_file);
+ return;
+}
+
+void StringHTMLEncode (char* string, GRSThttpBody *bp){
+
+ char* current_char;
+ char* tmp;
+ int n;
+ tmp=malloc(2);
+
+ *(tmp+1)='\0';
+ current_char=string;
+ while(*current_char != '\0'){
+
+ if (*current_char == '<') GRSThttpPrintf (bp,"<");
+ else if (*current_char == '>') GRSThttpPrintf (bp,">");
+ else if (*current_char == '&') GRSThttpPrintf (bp,"&");
+ else if (*current_char == '\'') GRSThttpPrintf (bp,"'");
+ else if (*current_char == '"') GRSThttpPrintf (bp,""");
+ else{
+ *tmp=*current_char;
+ GRSThttpPrintf(bp, "%s", tmp);
+
+ }
+ current_char++;
+ }
+ return;
+}
+
+void revert_acl(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri, char *dir_path, char *file, char *dir_uri, char *admin_file){
+ char *AclFilename;
+ GRSTgaclAcl *acl;
+ GRSThttpBody bp;
+ // Load the old ACL, add the entry and save
+ AclFilename=malloc(strlen(dir_path)+strlen(file)+2);
+ strcpy(AclFilename, dir_path);
+ strcat(AclFilename, "/");
+ strcat(AclFilename, file);
+
+ acl = GRSTgaclAclLoadFile(AclFilename);
+ check_acl_save(dn, perm, help_uri, dir_path, file, dir_uri, admin_file, user, acl, &bp);
+ return;
+}
diff --git a/org.gridsite.core/src/grst_admin_main.c b/org.gridsite.core/src/grst_admin_main.c
new file mode 100644
index 0000000..9390dd1
--- /dev/null
+++ b/org.gridsite.core/src/grst_admin_main.c
@@ -0,0 +1,365 @@
+/*
+ Andrew McNab and Shiv Kaushal, University of Manchester.
+ Copyright (c) 2002-3. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ o Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ o Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*---------------------------------------------------------------------------*
+ * This program is part of GridSite: http://www.gridpp.ac.uk/gridsite/ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef VERSION
+#define VERSION "x.x.x"
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// when porting: remember that sendfile() is very OS-specific!
+#include
+
+#include
+
+#include "grst_admin.h"
+
+/*
+
+ GridSite human/interactive management interface. This should produce
+ a CGI executable, usually ./sbin/real-gridsite-admin.cgi, which is
+ called from HTML forms either by GET or POST methods or both (ie input
+ present in both QUERY_STRING and the stdin of the CGI process.)
+
+ The CGI name/value pairs used are:
+
+ cmd = edit, managedir, print, history
+ file = short name of file, without path
+
+ If real-gridsite-admin.cgi is run by an internal redirection inside
+ mod_gridsite (as should ALWAYS be the case) then the environment
+ variable REDIRECT_GRST_DIR_PATH will be set to the full path of
+ the directory holding the file in question. This respects any complex
+ URI -> file path mapping done by Apache.
+
+*/
+
+void GRSThttpError(char *status)
+{
+ printf("Status: %s\n", status);
+ printf("Server-CGI: GridSite Admin %s\n", VERSION);
+ printf("Content-Length: %d\n", 2 * strlen(status) + 58);
+ puts("Content-Type: text/html\n");
+
+ printf("%s\n", status);
+ printf("
\n", NULL);
+
+ if (conf->format)
+ {
+ /* **** set up dynamic part of footer to go at end of body **** */
+
+ admin_formatted = make_admin_footer(r, conf, TRUE);
+
+ /* **** try to find a footer file in this or parent directories **** */
+
+ /* first make a buffer big enough to hold path names we want to try */
+ fd = -1;
+ s = malloc(strlen(r->filename) + strlen(conf->footfile));
+ strcpy(s, r->filename);
+
+ for (;;)
+ {
+ p = rindex(s, '/');
+ if (p == NULL) break; /* failed to find one */
+
+ p[1] = '\0';
+ strcat(p, conf->footfile);
+
+ fd = open(s, O_RDONLY);
+ if (fd != -1) break; /* found one */
+
+ *p = '\0';
+ }
+
+ free(s);
+
+ if (fd == -1) /* failed to find a footer, so use standard default */
+ {
+ footer_formatted = apr_pstrdup(r->pool, "");
+ }
+ else /* found a footer, so set up to use it */
+ {
+ fstat(fd, &statbuf);
+ footer_formatted = apr_palloc(r->pool, statbuf.st_size + 1);
+ read(fd, footer_formatted, statbuf.st_size);
+ footer_formatted[statbuf.st_size] = '\0';
+ close(fd);
+ }
+ }
+ else
+ {
+ admin_formatted = apr_pstrdup(r->pool, "");
+ footer_formatted = apr_pstrdup(r->pool, "");
+ }
+ else /* found a header file, so set up head and body to surround it */
+ {
+ fstat(fd, &statbuf);
+ header_formatted = apr_palloc(r->pool, statbuf.st_size + 1);
+ read(fd, header_formatted, statbuf.st_size);
+ header_formatted[statbuf.st_size] = '\0';
+ close(fd);
+ }
+ }
+ else header_formatted = apr_pstrdup(r->pool, "");
+
+ body = apr_psprintf(r->pool,
+ "
Directory listing %s
\n
", r->uri);
+
+ if ((r->uri)[1] != '\0')
+ body = apr_pstrcat(r->pool, body,
+ "
\n", NULL);
+
+ free(encfulluri); /* libgridsite doesnt use pools */
+
+ if (conf->format)
+ {
+ /* **** try to find a footer file in this or parent directories **** */
+
+ /* first make a buffer big enough to hold path names we want to try */
+ fd = -1;
+ s = malloc(strlen(r->filename) + strlen(conf->footfile));
+ strcpy(s, r->filename);
+
+ for (;;)
+ {
+ p = rindex(s, '/');
+ if (p == NULL) break; /* failed to find one */
+
+ p[1] = '\0';
+ strcat(p, conf->footfile);
+
+ fd = open(s, O_RDONLY);
+ if (fd != -1) break; /* found one */
+
+ *p = '\0';
+ }
+
+ free(s);
+
+ if (fd == -1) /* failed to find a footer, so use standard default */
+ {
+ footer_formatted = apr_pstrdup(r->pool, "");
+ }
+ else /* found a footer, so set up to use it */
+ {
+ fstat(fd, &statbuf);
+ footer_formatted = apr_palloc(r->pool, statbuf.st_size + 1);
+ read(fd, footer_formatted, statbuf.st_size);
+ footer_formatted[statbuf.st_size] = '\0';
+ close(fd);
+ }
+ }
+ else footer_formatted = apr_pstrdup(r->pool, "
filename) + strlen(conf->footfile));
+ strcpy(s, r->filename);
+
+ for (;;)
+ {
+ p = rindex(s, '/');
+ if (p == NULL) break; /* failed to find one */
+
+ p[1] = '\0';
+ strcat(p, conf->footfile);
+
+ fd = open(s, O_RDONLY);
+ if (fd != -1) break; /* found one */
+
+ *p = '\0';
+ }
+
+ free(s);
+
+ if (fd == -1) /* failed to find a footer, so set up empty default */
+ {
+ footer_formatted = apr_pstrdup(r->pool, "");
+ }
+ else /* found a footer, so set up to use it */
+ {
+ fstat(fd, &statbuf);
+ footer_formatted = apr_palloc(r->pool, statbuf.st_size + 1);
+ read(fd, footer_formatted, statbuf.st_size);
+ footer_formatted[statbuf.st_size] = '\0';
+ close(fd);
+ }
+
+ /* **** can now calculate the Content-Length and output headers **** */
+
+ length = strlen(head_formatted) + strlen(header_formatted) +
+ strlen(body_formatted) + strlen(admin_formatted) +
+ strlen(footer_formatted);
+
+ ap_set_content_length(r, length);
+ ap_set_content_type(r, "text/html");
+
+ /* ** output the HTTP body (HTML Head+Body) ** */
+
+ ap_rputs(head_formatted, r);
+ ap_rputs(header_formatted, r);
+ ap_rputs(body_formatted, r);
+ ap_rputs(admin_formatted, r);
+ ap_rputs(footer_formatted, r);
+
+ return OK;
+}
+
+int html_dir_list(request_rec *r, mod_gridsite_cfg *conf)
+/*
+ output HTML directory listing, with level of formatting controlled
+ by GridSiteHtmlFormat/conf->format
+*/
+{
+ int i, fd, n;
+ char *buf, *p, *s, *head_formatted, *header_formatted,
+ *body_formatted, *admin_formatted, *footer_formatted, *temp,
+ modified[99], *d_namepath, *indexheaderpath, *indexheadertext;
+ size_t length;
+ struct stat statbuf;
+ struct tm mtime_tm;
+ struct dirent **namelist;
+
+ if (r->finfo.filetype == APR_NOFILE) return HTTP_NOT_FOUND;
+
+ head_formatted = apr_psprintf(r->pool,
+ "
\n", r->uri);
+
+ if (conf->format)
+ {
+ /* **** try to find a header file in this or parent directories **** */
+
+ /* first make a buffer big enough to hold path names we want to try */
+ fd = -1;
+ s = malloc(strlen(r->filename) + strlen(conf->headfile) + 1);
+ strcpy(s, r->filename);
+
+ for (;;)
+ {
+ p = rindex(s, '/');
+ if (p == NULL) break; /* failed to find one */
+ p[1] = '\0';
+ strcat(p, conf->headfile);
+
+ fd = open(s, O_RDONLY);
+ if (fd != -1) break; /* found one */
+
+ *p = '\0';
+ }
+
+ free(s);
+
+ if (fd == -1) /* not found, so set up to output sensible default */
+ {
+ header_formatted = apr_pstrdup(r->pool, "
");
+ }
+
+ /* **** can now calculate the Content-Length and output headers **** */
+
+ length = strlen(head_formatted) + strlen(header_formatted) +
+ strlen(body_formatted) + strlen(admin_formatted) +
+ strlen(footer_formatted);
+
+ ap_set_content_length(r, length);
+ ap_set_content_type(r, "text/html");
+
+ /* ** output the HTTP body (HTML Head+Body) ** */
+
+ ap_rputs(head_formatted, r);
+ ap_rputs(header_formatted, r);
+ ap_rputs(body_formatted, r);
+ ap_rputs(admin_formatted, r);
+ ap_rputs(footer_formatted, r);
+
+ return OK;
+}
+
+int http_put_method(request_rec *r, mod_gridsite_cfg *conf)
+{
+ char buf[2048];
+ size_t length;
+ int retcode;
+ apr_file_t *fp;
+
+ /* *** check if directory creation: PUT /.../ *** */
+
+ if ((r->unparsed_uri != NULL) &&
+ (r->unparsed_uri[0] != '\0') &&
+ (r->unparsed_uri[strlen(r->unparsed_uri) - 1] == '/'))
+ {
+ if (apr_dir_make(r->filename, APR_UREAD | APR_UWRITE | APR_UEXECUTE,
+ r->pool) != 0) return HTTP_INTERNAL_SERVER_ERROR;
+
+ ap_set_content_length(r, 0);
+ ap_set_content_type(r, "text/html");
+ return OK;
+ }
+
+ /* *** otherwise assume trying to create a regular file *** */
+
+ if (apr_file_open(&fp, r->filename, APR_WRITE | APR_CREATE | APR_BUFFERED,
+ APR_UREAD | APR_UWRITE, r->pool) != 0) return HTTP_INTERNAL_SERVER_ERROR;
+
+// need to add Range: support at some point too
+
+ retcode = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
+ if (retcode == OK)
+ {
+ if (ap_should_client_block(r))
+ while ((length = ap_get_client_block(r, buf, sizeof(buf))) > 0)
+ if (apr_file_write(fp, buf, &length) != 0)
+ {
+ retcode = HTTP_INTERNAL_SERVER_ERROR;
+ break;
+ }
+
+ ap_set_content_length(r, 0);
+ ap_set_content_type(r, "text/html");
+ }
+
+ if (apr_file_close(fp) != 0) return HTTP_INTERNAL_SERVER_ERROR;
+
+ return retcode;
+}
+
+int http_delete_method(request_rec *r, mod_gridsite_cfg *conf)
+{
+ if (remove(r->filename) != 0) return HTTP_FORBIDDEN;
+
+ ap_set_content_length(r, 0);
+ ap_set_content_type(r, "text/html");
+
+ return OK;
+}
+
+static int mod_gridsite_dir_handler(request_rec *r, mod_gridsite_cfg *conf)
+/*
+ handler switch for directories
+*/
+{
+ /* *** is this a write method? only possible if GridSiteAuth on *** */
+
+ if (conf->auth)
+ {
+ if ((r->method_number == M_PUT) &&
+ (conf->methods != NULL) &&
+ (strstr(conf->methods, " PUT " ) != NULL))
+ return http_put_method(r, conf);
+
+ if ((r->method_number == M_DELETE) &&
+ (conf->methods != NULL) &&
+ (strstr(conf->methods, " DELETE ") != NULL))
+ return http_delete_method(r, conf);
+ }
+
+ /* *** directory listing? *** */
+
+ if ((r->method_number == M_GET) && (conf->indexes))
+ return html_dir_list(r, conf); /* directory listing */
+
+ return DECLINED; /* *** nothing to see here, move along *** */
+}
+
+static int mod_gridsite_nondir_handler(request_rec *r, mod_gridsite_cfg *conf)
+/*
+ one big handler switch for everything other than directories, since we
+ might be responding to MIME * / * for local PUT, MOVE, COPY and DELETE,
+ and GET inside ghost directories.
+*/
+{
+ /* *** is this a write method? only possible if GridSiteAuth on *** */
+
+ if (conf->auth)
+ {
+ if ((r->method_number == M_PUT) &&
+ (conf->methods != NULL) &&
+ (strstr(conf->methods, " PUT " ) != NULL))
+ return http_put_method(r, conf);
+
+ if ((r->method_number == M_DELETE) &&
+ (conf->methods != NULL) &&
+ (strstr(conf->methods, " DELETE ") != NULL))
+ return http_delete_method(r, conf);
+ }
+
+ /* *** check if a special ghost admin CGI *** */
+
+ if (conf->adminfile && conf->adminuri &&
+ (strlen(r->filename) > strlen(conf->adminfile) + 1) &&
+ (strcmp(&(r->filename[strlen(r->filename) - strlen(conf->adminfile)]),
+ conf->adminfile) == 0) &&
+ (r->filename[strlen(r->filename)-strlen(conf->adminfile)-1] == '/') &&
+ ((r->method_number == M_POST) ||
+ (r->method_number == M_GET)))
+ {
+ ap_internal_redirect(conf->adminuri, r);
+ return OK;
+ }
+
+ /* *** finally look for .html files that we should format *** */
+
+ if ((conf->format) && /* conf->format set by GridSiteHtmlFormat on */
+ (strlen(r->filename) > 5) &&
+ (strcmp(&(r->filename[strlen(r->filename)-5]), ".html") == 0) &&
+ (r->method_number == M_GET)) return html_format(r, conf);
+
+ return DECLINED; /* *** nothing to see here, move along *** */
+}
+
+static void recurse4dirlist(char *dirname, time_t *dirs_time,
+ char *fulluri, int fullurilen,
+ char *encfulluri, int enclen,
+ apr_pool_t *pool, char **body,
+ int recurse_level)
+/* try to find DN Lists in dir[] and its subdirs that match the fulluri[]
+ prefix. add blobs of HTML to body as they are found. */
+{
+ char *unencname, modified[99], *oneline, *d_namepath;
+ DIR *oneDIR;
+ struct dirent *onedirent;
+ struct tm mtime_tm;
+ size_t length;
+ struct stat statbuf;
+
+ if ((stat(dirname, &statbuf) != 0) ||
+ (!S_ISDIR(statbuf.st_mode)) ||
+ ((oneDIR = opendir(dirname)) == NULL)) return;
+
+ if (statbuf.st_mtime > *dirs_time) *dirs_time = statbuf.st_mtime;
+
+ while ((onedirent = readdir(oneDIR)) != NULL)
+ {
+ if (onedirent->d_name[0] == '.') continue;
+
+ d_namepath = apr_psprintf(pool, "%s/%s", dirname, onedirent->d_name);
+ if (stat(d_namepath, &statbuf) != 0) continue;
+
+ if (S_ISDIR(statbuf.st_mode) && (recurse_level < GRST_RECURS_LIMIT))
+ recurse4dirlist(d_namepath, dirs_time, fulluri,
+ fullurilen, encfulluri, enclen,
+ pool, body, recurse_level + 1);
+ else if ((strncmp(onedirent->d_name, encfulluri, enclen) == 0) &&
+ (onedirent->d_name[strlen(onedirent->d_name) - 1] != '~'))
+ {
+ unencname = GRSThttpUrlDecode(onedirent->d_name);
+
+ if (strncmp(unencname, fulluri, fullurilen) == 0)
+ {
+
+ if (statbuf.st_mtime > *dirs_time)
+ *dirs_time = statbuf.st_mtime;
+
+ localtime_r(&(statbuf.st_mtime), &mtime_tm);
+ strftime(modified, sizeof(modified),
+ "
\n",
+ &unencname[fullurilen], statbuf.st_size,
+ statbuf.st_mtime, unencname,
+ statbuf.st_size, modified);
+
+ *body = apr_pstrcat(pool, *body, oneline, NULL);
+ }
+
+ free(unencname); /* libgridsite doesnt use pools */
+ }
+ }
+
+ closedir(oneDIR);
+}
+
+static int mod_gridsite_dnlistsuri_dir_handler(request_rec *r,
+ mod_gridsite_cfg *conf)
+/*
+ virtual DN-list file lister: make all DN lists on the dn-lists
+ path of this server appear to be in the dn-lists directory itself
+ (ie where they appear in the DN lists path doesnt matter, as long
+ as their name matches)
+*/
+{
+ int enclen, fullurilen, fd;
+ char *fulluri, *encfulluri, *dn_list_ptr, *dirname, *unencname,
+ *body, *oneline, *p, *s,
+ *head_formatted, *header_formatted, *footer_formatted,
+ *permstr = NULL;
+ struct stat statbuf;
+ size_t length;
+ time_t dirs_time = 0;
+ GRSTgaclPerm perm = GRST_PERM_NONE;
+
+ if (r->notes != NULL)
+ permstr = (char *) apr_table_get(r->notes, "GRST_PERM");
+
+ if (permstr != NULL) sscanf(permstr, "%d", &perm);
+
+ fulluri = apr_psprintf(r->pool, "https://%s%s",
+ ap_get_server_name(r), conf->dnlistsuri);
+ fullurilen = strlen(fulluri);
+
+ encfulluri = GRSThttpUrlEncode(fulluri);
+ enclen = strlen(encfulluri);
+
+ if (conf->dnlists != NULL) p = conf->dnlists;
+ else p = getenv("GRST_DN_LISTS");
+
+ if (p == NULL) p = GRST_DN_LISTS;
+ dn_list_ptr = apr_pstrdup(r->pool, p);
+
+ head_formatted = apr_psprintf(r->pool,
+ "
\n", r->uri);
+
+ if (conf->format)
+ {
+ /* **** try to find a header file in this or parent directories **** */
+
+ /* first make a buffer big enough to hold path names we want to try */
+ fd = -1;
+ s = malloc(strlen(r->filename) + strlen(conf->headfile) + 1);
+ strcpy(s, r->filename);
+
+ for (;;)
+ {
+ p = rindex(s, '/');
+ if (p == NULL) break; /* failed to find one */
+ p[1] = '\0';
+ strcat(p, conf->headfile);
+
+ fd = open(s, O_RDONLY);
+ if (fd != -1) break; /* found one */
+
+ *p = '\0';
+ }
+
+ free(s);
+
+ if (fd == -1) /* not found, so set up to output sensible default */
+ {
+ header_formatted = apr_pstrdup(r->pool, "
");
+
+ /* **** can now calculate the Content-Length and output headers **** */
+
+ length = strlen(head_formatted) + strlen(header_formatted) +
+ strlen(body) + strlen(footer_formatted);
+
+ ap_set_content_length(r, length);
+ r->mtime = apr_time_from_sec(dirs_time);
+ ap_set_last_modified(r);
+ ap_set_content_type(r, "text/html");
+
+ /* ** output the HTTP body (HTML Head+Body) ** */
+ ap_rputs(head_formatted, r);
+ ap_rputs(header_formatted, r);
+ ap_rputs(body, r);
+ ap_rputs(footer_formatted, r);
+
+ return OK;
+}
+
+static char *recurse4file(char *dir, char *file, apr_pool_t *pool,
+ int recurse_level)
+/* try to find file[] in dir[]. try subdirs if not found.
+ return full path to first found version or NULL on failure */
+{
+ char *fullfilename, *fulldirname;
+ struct stat statbuf;
+ DIR *dirDIR;
+ struct dirent *file_ent;
+
+ /* try to find in current directory */
+
+ fullfilename = apr_psprintf(pool, "%s/%s", dir, file);
+
+ if (stat(fullfilename, &statbuf) == 0) return fullfilename;
+
+ /* maybe search in subdirectories */
+
+ if (recurse_level >= GRST_RECURS_LIMIT) return NULL;
+
+ dirDIR = opendir(dir);
+
+ if (dirDIR == NULL) return NULL;
+
+ while ((file_ent = readdir(dirDIR)) != NULL)
+ {
+ if (file_ent->d_name[0] == '.') continue;
+
+ fulldirname = apr_psprintf(pool, "%s/%s", dir, file_ent->d_name);
+ if ((stat(fulldirname, &statbuf) == 0) &&
+ S_ISDIR(statbuf.st_mode) &&
+ ((fullfilename = recurse4file(fulldirname, file,
+ pool, recurse_level + 1)) != NULL))
+ {
+ closedir(dirDIR);
+ return fullfilename;
+ }
+ }
+
+ closedir(dirDIR);
+
+ return NULL;
+}
+
+static int mod_gridsite_dnlistsuri_handler(request_rec *r,
+ mod_gridsite_cfg *conf)
+/*
+ virtual DN-list file generator
+*/
+{
+ int fd;
+ char *fulluri, *encfulluri, *dn_list_ptr, *filename, *dirname, *p,
+ *buf;
+ struct stat statbuf;
+
+ /* *** check if a special ghost admin CGI *** */
+
+ if (conf->adminfile && conf->adminuri &&
+ (strlen(r->filename) > strlen(conf->adminfile) + 1) &&
+ (strcmp(&(r->filename[strlen(r->filename) - strlen(conf->adminfile)]),
+ conf->adminfile) == 0) &&
+ (r->filename[strlen(r->filename)-strlen(conf->adminfile)-1] == '/') &&
+ ((r->method_number == M_POST) ||
+ (r->method_number == M_GET)))
+ {
+ ap_internal_redirect(conf->adminuri, r);
+ return OK;
+ }
+
+ fulluri = apr_psprintf(r->pool, "https://%s%s",
+ ap_get_server_name(r), r->uri);
+
+ encfulluri = GRSThttpUrlEncode(fulluri);
+
+ if (conf->dnlists != NULL) p = conf->dnlists;
+ else p = getenv("GRST_DN_LISTS");
+
+ if (p == NULL) p = GRST_DN_LISTS;
+ dn_list_ptr = apr_pstrdup(r->pool, p);
+
+ while ((dirname = strsep(&dn_list_ptr, ":")) != NULL)
+ {
+ filename = recurse4file(dirname, encfulluri, r->pool, 0);
+
+ if (filename == NULL) continue;
+
+ fd = open(filename, O_RDONLY);
+
+ if (fd == -1) continue;
+
+ fstat(fd, &statbuf);
+ ap_set_content_length(r, (apr_off_t) statbuf.st_size);
+ r->mtime = apr_time_from_sec(statbuf.st_mtime);
+ ap_set_content_type(r, "text/plain");
+ ap_set_last_modified(r);
+
+ buf = apr_palloc(r->pool, statbuf.st_size + 1);
+ read(fd, buf, statbuf.st_size);
+ buf[statbuf.st_size] = '\0';
+
+ ap_rputs(buf, r);
+
+ close(fd);
+
+ return OK;
+ }
+
+ return HTTP_NOT_FOUND;
+}
+
+static void *create_gridsite_dir_config(apr_pool_t *p, char *path)
+{
+ mod_gridsite_cfg *conf = apr_palloc(p, sizeof(*conf));
+
+ if (path == NULL) /* set up server defaults */
+ {
+ conf->auth = 0; /* GridSiteAuth on/off */
+ conf->envs = 1; /* GridSiteEnvs on/off */
+ conf->format = 0; /* GridSiteHtmlFormat on/off */
+ conf->indexes = 0; /* GridSiteIndexes on/off */
+ conf->indexheader = NULL; /* GridSiteIndexHeader File-value */
+ conf->gridsitelink = 1; /* GridSiteLink on/off */
+ conf->adminfile = apr_pstrdup(p, GRST_ADMIN_FILE);
+ /* GridSiteAdminFile File-value */
+ conf->adminuri = NULL; /* GridSiteAdminURI URI-value */
+ conf->helpuri = NULL; /* GridSiteHelpURI URI-value */
+ conf->dnlists = NULL; /* GridSiteDNlists Search-path */
+ conf->dnlistsuri = NULL; /* GridSiteDNlistsURI URI-value */
+ conf->adminlist = NULL; /* GridSiteAdminList URI-value */
+ conf->gsiproxylimit = 1; /* GridSiteGSIProxyLimit number */
+ conf->unzip = NULL; /* GridSiteUnzip file-path */
+
+ conf->methods = apr_pstrdup(p, " GET ");
+ /* GridSiteMethods methods */
+
+ conf->editable = apr_pstrdup(p, " txt shtml html htm css js php jsp ");
+ /* GridSiteEditable types */
+
+ conf->headfile = apr_pstrdup(p, GRST_HEADFILE);
+ conf->footfile = apr_pstrdup(p, GRST_FOOTFILE);
+ /* GridSiteHeadFile and GridSiteFootFile file name */
+ }
+ else
+ {
+ conf->auth = UNSET; /* GridSiteAuth on/off */
+ conf->envs = UNSET; /* GridSiteEnvs on/off */
+ conf->format = UNSET; /* GridSiteHtmlFormat on/off */
+ conf->indexes = UNSET; /* GridSiteIndexes on/off */
+ conf->indexheader = NULL; /* GridSiteIndexHeader File-value */
+ conf->gridsitelink = UNSET; /* GridSiteLink on/off */
+ conf->adminfile = NULL; /* GridSiteAdminFile File-value */
+ conf->adminuri = NULL; /* GridSiteAdminURI URI-value */
+ conf->helpuri = NULL; /* GridSiteHelpURI URI-value */
+ conf->dnlists = NULL; /* GridSiteDNlists Search-path */
+ conf->dnlistsuri = NULL; /* GridSiteDNlistsURI URI-value */
+ conf->adminlist = NULL; /* GridSiteAdminList URI-value */
+ conf->gsiproxylimit = UNSET; /* GridSiteGSIProxyLimit number */
+ conf->unzip = NULL; /* GridSiteUnzip file-path */
+ conf->methods = NULL; /* GridSiteMethods methods */
+ conf->editable = NULL; /* GridSiteEditable types */
+ conf->headfile = NULL; /* GridSiteHeadFile file name */
+ conf->footfile = NULL; /* GridSiteFootFile file name */
+ }
+
+ return conf;
+}
+
+static void *merge_gridsite_dir_config(apr_pool_t *p, void *vserver,
+ void *vdirect)
+/* merge directory with server-wide directory configs */
+{
+ mod_gridsite_cfg *conf, *server, *direct;
+
+ server = (mod_gridsite_cfg *) vserver;
+ direct = (mod_gridsite_cfg *) vdirect;
+ conf = apr_palloc(p, sizeof(*conf));
+
+ if (direct->auth != UNSET) conf->auth = direct->auth;
+ else conf->auth = server->auth;
+
+ if (direct->envs != UNSET) conf->envs = direct->envs;
+ else conf->envs = server->envs;
+
+ if (direct->format != UNSET) conf->format = direct->format;
+ else conf->format = server->format;
+
+ if (direct->indexes != UNSET) conf->indexes = direct->indexes;
+ else conf->indexes = server->indexes;
+
+ if (direct->gridsitelink != UNSET) conf->gridsitelink=direct->gridsitelink;
+ else conf->gridsitelink=server->gridsitelink;
+
+ if (direct->indexheader != NULL) conf->indexheader = direct->indexheader;
+ else conf->indexheader = server->indexheader;
+
+ if (direct->adminfile != NULL) conf->adminfile = direct->adminfile;
+ else conf->adminfile = server->adminfile;
+
+ if (direct->adminuri != NULL) conf->adminuri = direct->adminuri;
+ else conf->adminuri = server->adminuri;
+
+ if (direct->helpuri != NULL) conf->helpuri = direct->helpuri;
+ else conf->helpuri = server->helpuri;
+
+ if (direct->dnlists != NULL) conf->dnlists = direct->dnlists;
+ else conf->dnlists = server->dnlists;
+
+ if (direct->dnlistsuri != NULL) conf->dnlistsuri = direct->dnlistsuri;
+ else conf->dnlistsuri = server->dnlistsuri;
+
+ if (direct->adminlist != NULL) conf->adminlist = direct->adminlist;
+ else conf->adminlist = server->adminlist;
+
+ if (direct->gsiproxylimit != UNSET)
+ conf->gsiproxylimit = direct->gsiproxylimit;
+ else conf->gsiproxylimit = server->gsiproxylimit;
+
+ if (direct->unzip != NULL) conf->unzip = direct->unzip;
+ else conf->unzip = server->unzip;
+
+ if (direct->methods != NULL) conf->methods = direct->methods;
+ else conf->methods = server->methods;
+
+ if (direct->editable != NULL) conf->editable = direct->editable;
+ else conf->editable = server->editable;
+
+ if (direct->headfile != NULL) conf->headfile = direct->headfile;
+ else conf->headfile = server->headfile;
+
+ if (direct->footfile != NULL) conf->footfile = direct->footfile;
+ else conf->footfile = server->footfile;
+
+ return conf;
+}
+
+static const char *mod_gridsite_take1_cmds(cmd_parms *a, void *cfg,
+ const char *parm)
+{
+ int n;
+ char *p;
+
+ if (strcasecmp(a->cmd->name, "GridSiteAdminFile") == 0)
+ {
+ if (index(parm, '/') != NULL)
+ return "/ not permitted in GridSiteAdminFile";
+
+ ((mod_gridsite_cfg *) cfg)->adminfile =
+ apr_pstrdup(a->pool, parm);
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteAdminURI") == 0)
+ {
+ if (*parm != '/') return "GridSiteAdminURI must begin with /";
+
+ ((mod_gridsite_cfg *) cfg)->adminuri =
+ apr_pstrdup(a->pool, parm);
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteHelpURI") == 0)
+ {
+ if (*parm != '/') return "GridSiteHelpURI must begin with /";
+
+ ((mod_gridsite_cfg *) cfg)->helpuri =
+ apr_pstrdup(a->pool, parm);
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteDNlists") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->dnlists =
+ apr_pstrdup(a->pool, parm);
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteDNlistsURI") == 0)
+ {
+ if (*parm != '/') return "GridSiteDNlistsURI must begin with /";
+
+ if ((*parm != '\0') && (parm[strlen(parm) - 1] == '/'))
+ ((mod_gridsite_cfg *) cfg)->dnlistsuri =
+ apr_pstrdup(a->pool, parm);
+ else
+ ((mod_gridsite_cfg *) cfg)->dnlistsuri =
+ apr_pstrcat(a->pool, parm, "/", NULL);
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteAdminList") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->adminlist =
+ apr_pstrdup(a->pool, parm);
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteGSIProxyLimit") == 0)
+ {
+ n = -1;
+
+ if ((sscanf(parm, "%d", &n) == 1) && (n >= 0))
+ ((mod_gridsite_cfg *) cfg)->gsiproxylimit = n;
+ else return "GridSiteGSIProxyLimit must be a number >= 0";
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteUnzip") == 0)
+ {
+ if (*parm != '/') return "GridSiteUnzip must begin with /";
+
+ ((mod_gridsite_cfg *) cfg)->unzip =
+ apr_pstrdup(a->pool, parm);
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteMethods") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->methods =
+ apr_psprintf(a->pool, " %s ", parm);
+
+ for (p = ((mod_gridsite_cfg *) cfg)->methods;
+ *p != '\0';
+ ++p) if (*p == '\t') *p = ' ';
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteEditable") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->editable =
+ apr_psprintf(a->pool, " %s ", parm);
+
+ for (p = ((mod_gridsite_cfg *) cfg)->editable;
+ *p != '\0';
+ ++p) if (*p == '\t') *p = ' ';
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteHeadFile") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->headfile =
+ apr_pstrdup(a->pool, parm);
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteFootFile") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->footfile =
+ apr_pstrdup(a->pool, parm);
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteIndexHeader") == 0)
+ {
+ if (index(parm, '/') != NULL)
+ return "/ not permitted in GridSiteIndexHeader";
+
+ ((mod_gridsite_cfg *) cfg)->indexheader =
+ apr_pstrdup(a->pool, parm);
+ }
+
+ return NULL;
+}
+
+static const char *mod_gridsite_flag_cmds(cmd_parms *a, void *cfg,
+ int flag)
+{
+ if (strcasecmp(a->cmd->name, "GridSiteAuth") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->auth = flag;
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteEnvs") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->envs = flag;
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteHtmlFormat") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->format = flag;
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteIndexes") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->indexes = flag;
+ }
+ else if (strcasecmp(a->cmd->name, "GridSiteLink") == 0)
+ {
+ ((mod_gridsite_cfg *) cfg)->gridsitelink = flag;
+ }
+
+ return NULL;
+}
+
+static const command_rec mod_gridsite_cmds[] =
+{
+ AP_INIT_FLAG("GridSiteAuth", mod_gridsite_flag_cmds,
+ NULL, OR_FILEINFO, "on or off"),
+ AP_INIT_FLAG("GridSiteEnvs", mod_gridsite_flag_cmds,
+ NULL, OR_FILEINFO, "on or off"),
+ AP_INIT_FLAG("GridSiteHtmlFormat", mod_gridsite_flag_cmds,
+ NULL, OR_FILEINFO, "on or off"),
+ AP_INIT_FLAG("GridSiteIndexes", mod_gridsite_flag_cmds,
+ NULL, OR_FILEINFO, "on or off"),
+ AP_INIT_FLAG("GridSiteLink", mod_gridsite_flag_cmds,
+ NULL, OR_FILEINFO, "on or off"),
+
+ AP_INIT_TAKE1("GridSiteAdminFile", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "Ghost per-directory admin CGI"),
+ AP_INIT_TAKE1("GridSiteAdminURI", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "URI of real gridsite-admin.cgi"),
+ AP_INIT_TAKE1("GridSiteHelpURI", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "URI of Website Help pages"),
+ AP_INIT_TAKE1("GridSiteDNlists", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "DN Lists directories search path"),
+ AP_INIT_TAKE1("GridSiteDNlistsURI", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "URI of published DN lists"),
+ AP_INIT_TAKE1("GridSiteAdminList", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "URI of admin DN List"),
+ AP_INIT_TAKE1("GridSiteGSIProxyLimit", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "Max level of GSI proxy validity"),
+ AP_INIT_TAKE1("GridSiteUnzip", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "Absolute path to unzip command"),
+
+ AP_INIT_RAW_ARGS("GridSiteMethods", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "permitted HTTP methods"),
+ AP_INIT_RAW_ARGS("GridSiteEditable", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "editable file extensions"),
+ AP_INIT_TAKE1("GridSiteHeadFile", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "filename of HTML header"),
+ AP_INIT_TAKE1("GridSiteFootFile", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "filename of HTML footer"),
+ AP_INIT_TAKE1("GridSiteIndexHeader", mod_gridsite_take1_cmds,
+ NULL, OR_FILEINFO, "filename of directory header"),
+
+ {NULL}
+};
+
+static int mod_gridsite_first_fixups(request_rec *r)
+{
+ mod_gridsite_cfg *conf;
+
+ if (r->finfo.filetype != APR_DIR) return DECLINED;
+
+ conf = (mod_gridsite_cfg *)
+ ap_get_module_config(r->per_dir_config, &gridsite_module);
+
+ if ((conf != NULL) &&
+ (conf->dnlistsuri != NULL) &&
+ (strncmp(r->uri, conf->dnlistsuri, strlen(conf->dnlistsuri)) == 0) &&
+ (strcmp(r->uri, conf->dnlistsuri) != 0))
+ {
+ r->finfo.filetype = APR_REG;
+ }
+
+ return DECLINED;
+}
+
+static int mod_gridsite_perm_handler(request_rec *r)
+/*
+ Do authentication/authorization here rather than in the normal module
+ auth functions since the results of mod_ssl are available.
+
+ We also publish environment variables here if requested by GridSiteEnv.
+*/
+{
+ int retcode = DECLINED, i, n;
+ char *dn, *p, envname[14], *grst_cred_0 = NULL, *dir_path,
+ *remotehost, s[99], *grst_cred_i, *file;
+ const char *content_type;
+ time_t now, notbefore, notafter;
+ apr_table_t *env;
+ GRSTgaclCred *cred = NULL, *cred_0 = NULL;
+ GRSTgaclUser *user = NULL;
+ GRSTgaclPerm perm = GRST_PERM_NONE;
+ GRSTgaclAcl *acl = NULL;
+ mod_gridsite_cfg *cfg;
+
+ cfg = (mod_gridsite_cfg *)
+ ap_get_module_config(r->per_dir_config, &gridsite_module);
+
+ if (cfg == NULL) return DECLINED;
+
+ if ((cfg->auth == 0) &&
+ (cfg->envs == 0))
+ return DECLINED; /* if not turned on, look invisible */
+
+ env = r->subprocess_env;
+
+ if (r->connection->notes != NULL)
+ grst_cred_0 = (char *) apr_table_get(r->connection->notes, "GRST_CRED_0");
+
+ if (grst_cred_0 != NULL) /* do we have per-connection cred variable(s)? */
+ {
+ if (((mod_gridsite_cfg *) cfg)->envs)
+ apr_table_setn(env, "GRST_CRED_0", grst_cred_0);
+
+ cred_0 = GRSTx509CompactToCred(grst_cred_0);
+ if ((cred_0 != NULL) &&
+ (GRSTgaclCredGetDelegation(cred_0)
+ <= ((mod_gridsite_cfg *) cfg)->gsiproxylimit))
+ {
+ user = GRSTgaclUserNew(cred_0);
+
+ /* check for VOMS GRST_CRED_i too */
+
+ for (i=1; ; ++i)
+ {
+ snprintf(envname, sizeof(envname), "GRST_CRED_%d", i);
+ if (grst_cred_i = (char *)
+ apr_table_get(r->connection->notes,envname))
+ {
+ if (((mod_gridsite_cfg *) cfg)->envs)
+ apr_table_setn(env,
+ apr_pstrdup(r->pool, envname),
+ grst_cred_i);
+
+ if (cred = GRSTx509CompactToCred(grst_cred_i))
+ GRSTgaclUserAddCred(user, cred);
+ }
+ else break; /* GRST_CRED_i are numbered consecutively */
+ }
+ }
+ }
+
+ if ((user != NULL) && ((mod_gridsite_cfg *) cfg)->dnlists)
+ GRSTgaclUserSetDNlists(user, ((mod_gridsite_cfg *) cfg)->dnlists);
+
+ /* this checks for NULL arguments itself */
+ if (GRSTgaclDNlistHasUser(((mod_gridsite_cfg *) cfg)->adminlist, user))
+ perm = GRST_PERM_ALL;
+ else
+ {
+ remotehost = (char *) ap_get_remote_host(r->connection,
+ r->per_dir_config, REMOTE_DOUBLE_REV, NULL);
+ if ((remotehost != NULL) && (*remotehost != '\0'))
+ {
+ cred = GRSTgaclCredNew("dns");
+ GRSTgaclCredAddValue(cred, "hostname", remotehost);
+
+ if (user == NULL) user = GRSTgaclUserNew(cred);
+ else GRSTgaclUserAddCred(user, cred);
+ }
+
+ acl = GRSTgaclAclLoadforFile(r->filename);
+ if (acl != NULL) perm = GRSTgaclAclTestUser(acl, user);
+ }
+
+ apr_table_setn(r->notes, "GRST_PERM", apr_psprintf(r->pool, "%d", perm));
+
+ if (((mod_gridsite_cfg *) cfg)->envs)
+ {
+ apr_table_setn(env, "GRST_PERM", apr_psprintf(r->pool, "%d", perm));
+
+ if (((dir_path = apr_pstrdup(r->pool, r->filename)) != NULL) &&
+ ((p = rindex(dir_path, '/')) != NULL))
+ {
+ *p = '\0';
+ apr_table_setn(env, "GRST_DIR_PATH", dir_path);
+ }
+
+ if (((mod_gridsite_cfg *) cfg)->helpuri != NULL)
+ apr_table_setn(env, "GRST_HELP_URI",
+ ((mod_gridsite_cfg *) cfg)->helpuri);
+
+ if (((mod_gridsite_cfg *) cfg)->adminfile != NULL)
+ apr_table_setn(env, "GRST_ADMIN_FILE",
+ ((mod_gridsite_cfg *) cfg)->adminfile);
+
+ if (((mod_gridsite_cfg *) cfg)->editable != NULL)
+ apr_table_setn(env, "GRST_EDITABLE",
+ ((mod_gridsite_cfg *) cfg)->editable);
+
+ if (((mod_gridsite_cfg *) cfg)->headfile != NULL)
+ apr_table_setn(env, "GRST_HEAD_FILE",
+ ((mod_gridsite_cfg *) cfg)->headfile);
+
+ if (((mod_gridsite_cfg *) cfg)->footfile != NULL)
+ apr_table_setn(env, "GRST_FOOT_FILE",
+ ((mod_gridsite_cfg *) cfg)->footfile);
+
+ if (((mod_gridsite_cfg *) cfg)->dnlists != NULL)
+ apr_table_setn(env, "GRST_DN_LISTS",
+ ((mod_gridsite_cfg *) cfg)->dnlists);
+
+ if (((mod_gridsite_cfg *) cfg)->dnlistsuri != NULL)
+ apr_table_setn(env, "GRST_DN_LISTS_URI",
+ ((mod_gridsite_cfg *) cfg)->dnlistsuri);
+
+ if (((mod_gridsite_cfg *) cfg)->adminlist != NULL)
+ apr_table_setn(env, "GRST_ADMIN_LIST",
+ ((mod_gridsite_cfg *) cfg)->adminlist);
+
+ apr_table_setn(env, "GRST_GSIPROXY_LIMIT",
+ apr_psprintf(r->pool, "%d",
+ ((mod_gridsite_cfg *)cfg)->gsiproxylimit));
+
+ if (((mod_gridsite_cfg *) cfg)->unzip != NULL)
+ apr_table_setn(env, "GRST_UNZIP",
+ ((mod_gridsite_cfg *) cfg)->unzip);
+
+ if (!(((mod_gridsite_cfg *) cfg)->gridsitelink))
+ apr_table_setn(env, "GRST_NO_LINK", "1");
+ }
+
+ if (((mod_gridsite_cfg *) cfg)->auth)
+ {
+ /* *** Check HTTP method to decide which perm bits to check *** */
+
+ if (r->filename != NULL)
+ {
+ file = rindex(r->filename, '/');
+ if (file != NULL) ++file;
+ else file = r->filename;
+ }
+ else file = NULL;
+
+ content_type = r->content_type;
+ if ((content_type != NULL) &&
+ (strcmp(content_type, DIR_MAGIC_TYPE) == 0) &&
+ (((mod_gridsite_cfg *) cfg)->dnlistsuri != NULL) &&
+ (strncmp(r->uri,
+ ((mod_gridsite_cfg *) cfg)->dnlistsuri,
+ strlen(((mod_gridsite_cfg *) cfg)->dnlistsuri)) == 0) &&
+ (strlen(r->uri) > strlen(((mod_gridsite_cfg *) cfg)->dnlistsuri)))
+ content_type = "text/html";
+
+ if ( GRSTgaclPermHasNone(perm) ||
+
+ /* first two M_GET conditions make the subtle distinction
+ between .../ that maps to .../index.html (governed by
+ Read perm) or to dir list (governed by List perm);
+ third M_GET condition deals with typeless CGI requests */
+
+ ((r->method_number == M_GET) &&
+ !GRSTgaclPermHasRead(perm) &&
+ (content_type != NULL) &&
+ (strcmp(content_type, DIR_MAGIC_TYPE) != 0)) ||
+
+ ((r->method_number == M_GET) &&
+ !GRSTgaclPermHasList(perm) &&
+ (content_type != NULL) &&
+ (strcmp(content_type, DIR_MAGIC_TYPE) == 0)) ||
+
+ ((r->method_number == M_GET) &&
+ !GRSTgaclPermHasRead(perm) &&
+ (content_type == NULL)) ||
+
+ ((r->method_number == M_POST) && !GRSTgaclPermHasRead(perm) ) ||
+
+ (((r->method_number == M_PUT) || (r->method_number == M_DELETE)) &&
+ !GRSTgaclPermHasWrite(perm) &&
+ ((file == NULL) || (strcmp(file, GRST_ACL_FILE) != 0)) ) ||
+
+ (((r->method_number == M_PUT) || (r->method_number == M_DELETE)) &&
+ !GRSTgaclPermHasAdmin(perm) &&
+ (file != NULL) &&
+ (strcmp(file, GRST_ACL_FILE) == 0) ) ) retcode = HTTP_FORBIDDEN;
+ }
+
+ return retcode;
+}
+
+int GRST_X509_check_issued_wrapper(X509_STORE_CTX *ctx,X509 *x,X509 *issuer)
+/* We change the default callback to use our wrapper and discard errors
+ due to GSI proxy chains (ie where users certs act as CAs) */
+{
+ int ret;
+ ret = X509_check_issued(issuer, x);
+ if (ret == X509_V_OK)
+ return 1;
+
+ /* Non self-signed certs without signing are ok if they passed
+ the other checks inside X509_check_issued. Is this enough? */
+ if ((ret == X509_V_ERR_KEYUSAGE_NO_CERTSIGN) &&
+ (X509_NAME_cmp(X509_get_subject_name(issuer),
+ X509_get_subject_name(x)) != 0)) return 1;
+
+ /* If we haven't asked for issuer errors don't set ctx */
+ if (!(ctx->flags & X509_V_FLAG_CB_ISSUER_CHECK)) return 0;
+
+ ctx->error = ret;
+ ctx->current_cert = x;
+ ctx->current_issuer = issuer;
+ return ctx->verify_cb(0, ctx);
+}
+
+/* Later OpenSSL versions add a second pointer ... */
+int GRST_verify_cert_wrapper(X509_STORE_CTX *ctx, void *p)
+
+/* Earlier ones have a single argument ... */
+// int GRST_verify_cert_wrapper(X509_STORE_CTX *ctx)
+
+/* Before 0.9.7 we cannot change the check_issued callback directly in
+ the X509_STORE, so we must insert it in another callback that gets
+ called early enough */
+{
+ ctx->check_issued = GRST_X509_check_issued_wrapper;
+
+ return X509_verify_cert(ctx);
+}
+
+int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
+{
+ SSL *ssl = (SSL *) X509_STORE_CTX_get_app_data(ctx);
+ conn_rec *conn = (conn_rec *) SSL_get_app_data(ssl);
+ server_rec *s = conn->base_server;
+ SSLConnRec *sslconn =
+ (SSLConnRec *) ap_get_module_config(conn->conn_config, &ssl_module);
+ int errnum = X509_STORE_CTX_get_error(ctx);
+ int errdepth = X509_STORE_CTX_get_error_depth(ctx);
+ int returned_ok;
+ int first_non_ca;
+
+ /*
+ * GSI Proxy user-cert-as-CA handling:
+ * we skip Invalid CA errors at this stage, since we will check this
+ * again at errdepth=0 for the full chain using GRSTx509CheckChain
+ */
+ if (errnum == X509_V_ERR_INVALID_CA)
+ {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+ "Skip Invalid CA error in case a GSI Proxy");
+
+ sslconn->verify_error = NULL;
+ ok = TRUE;
+ errnum = X509_V_OK;
+ X509_STORE_CTX_set_error(ctx, errnum);
+ }
+
+ /*
+ * New style GSI Proxy handling, with critical ProxyCertInfo
+ * extension: we use GRSTx509KnownCriticalExts() to check this
+ */
+#ifndef X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
+#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
+#endif
+ if (errnum == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)
+ {
+ if (GRSTx509KnownCriticalExts(X509_STORE_CTX_get_current_cert(ctx))
+ == GRST_RET_OK)
+ {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+ "GRSTx509KnownCriticalExts() accepts previously "
+ "Unhandled Critical Extension (GSI Proxy?)");
+
+ sslconn->verify_error = NULL;
+ ok = TRUE;
+ errnum = X509_V_OK;
+ X509_STORE_CTX_set_error(ctx, errnum);
+ }
+ }
+
+ returned_ok = ssl_callback_SSLVerify(ok, ctx);
+
+ /* in case ssl_callback_SSLVerify changed it */
+ errnum = X509_STORE_CTX_get_error(ctx);
+
+ if ((errdepth == 0) && (errnum == X509_V_OK))
+ /*
+ * We've now got the last certificate - the identity being used for
+ * this connection. At this point we check the whole chain for valid
+ * CAs or, failing that, GSI-proxy validity using GRSTx509CheckChain.
+ */
+ {
+ errnum = GRSTx509CheckChain(&first_non_ca, ctx);
+
+ if (errnum != X509_V_OK)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+ "Invalid certificate chain reported by "
+ "GRSTx509CheckChain()");
+
+ sslconn->verify_error = X509_verify_cert_error_string(errnum);
+ ok = FALSE;
+ }
+ else
+ {
+ int i, lastcred;
+ STACK_OF(X509) *peer_certs;
+ const int maxcreds = 99;
+ const size_t credlen = 1024;
+ char creds[maxcreds][credlen+1], envname[14];
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Valid certificate"
+ " chain reported by GRSTx509CheckChain()");
+
+ /*
+ * Always put result of GRSTx509CompactCreds() into environment
+ */
+ if (peer_certs = (STACK_OF(X509) *) X509_STORE_CTX_get_chain(ctx))
+ {
+ if (GRSTx509CompactCreds(&lastcred, maxcreds, credlen,
+ (char *) creds, peer_certs, GRST_VOMS_DIR) == GRST_RET_OK)
+ {
+ for (i=0; i <= lastcred; ++i)
+ {
+ apr_table_setn(conn->notes,
+ apr_psprintf(conn->pool, "GRST_CRED_%d", i),
+ apr_pstrdup(conn->pool, creds[i]));
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+ "store GRST_CRED_%d=%s", i, creds[i]);
+ }
+ }
+ /* free remaining dup'd certs? */
+ }
+ }
+ }
+
+ return returned_ok;
+}
+
+static int mod_gridsite_server_post_config(apr_pool_t *pPool,
+ apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *main_server)
+{
+ SSL_CTX *ctx;
+ SSLSrvConfigRec *sc;
+ server_rec *this_server;
+
+ ap_add_version_component(pPool,
+ apr_psprintf(pPool, "mod_gridsite/%s", VERSION));
+
+ for (this_server = main_server;
+ this_server != NULL;
+ this_server = this_server->next)
+ {
+ sc = ap_get_module_config(this_server->module_config, &ssl_module);
+
+ if ((sc != NULL) &&
+ (sc->enabled) &&
+ (sc->server != NULL) &&
+ (sc->server->ssl_ctx != NULL))
+ {
+ ctx = sc->server->ssl_ctx;
+
+ /* in 0.9.7 we could set the issuer-checking callback directly */
+// ctx->cert_store->check_issued = GRST_X509_check_issued_wrapper;
+
+ /* but in case 0.9.6 we do it indirectly with another wrapper */
+ SSL_CTX_set_cert_verify_callback(ctx,
+ GRST_verify_cert_wrapper,
+ (void *) NULL);
+
+ /* whatever version, we can set the SSLVerify wrapper properly */
+ SSL_CTX_set_verify(ctx, ctx->verify_mode,
+ GRST_callback_SSLVerify_wrapper);
+
+ if (main_server->loglevel >= APLOG_DEBUG)
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
+ "Set mod_ssl verify callbacks to GridSite wrappers");
+ }
+ }
+
+ return OK;
+}
+
+static void mod_gridsite_child_init(apr_pool_t *pPool, server_rec *pServer)
+{
+ GRSTgaclInit();
+}
+
+static int mod_gridsite_handler(request_rec *r)
+{
+ mod_gridsite_cfg *conf;
+
+ conf = (mod_gridsite_cfg *)
+ ap_get_module_config(r->per_dir_config, &gridsite_module);
+
+ if ((conf->dnlistsuri != NULL) &&
+ (strncmp(r->uri, conf->dnlistsuri, strlen(conf->dnlistsuri)) == 0))
+ {
+ if (strcmp(r->uri, conf->dnlistsuri) == 0)
+ return mod_gridsite_dnlistsuri_dir_handler(r, conf);
+
+ return mod_gridsite_dnlistsuri_handler(r, conf);
+ }
+
+ if (strcmp(r->handler, DIR_MAGIC_TYPE) == 0)
+ return mod_gridsite_dir_handler(r, conf);
+
+ return mod_gridsite_nondir_handler(r, conf);
+}
+
+static void register_hooks(apr_pool_t *p)
+{
+ ap_hook_post_config(mod_gridsite_server_post_config, NULL, NULL,
+ APR_HOOK_LAST);
+ ap_hook_child_init(mod_gridsite_child_init, NULL, NULL, APR_HOOK_MIDDLE);
+
+ ap_hook_fixups(mod_gridsite_first_fixups,NULL,NULL,APR_HOOK_FIRST);
+
+ ap_hook_fixups(mod_gridsite_perm_handler,NULL,NULL,APR_HOOK_REALLY_LAST);
+
+ ap_hook_handler(mod_gridsite_handler, NULL, NULL, APR_HOOK_FIRST);
+}
+
+module AP_MODULE_DECLARE_DATA gridsite_module =
+{
+ STANDARD20_MODULE_STUFF,
+ create_gridsite_dir_config, /* dir config creater */
+ merge_gridsite_dir_config, /* dir merger */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ mod_gridsite_cmds, /* command apr_table_t */
+ register_hooks /* register hooks */
+};
diff --git a/org.gridsite.core/src/mod_ssl-private.h b/org.gridsite.core/src/mod_ssl-private.h
new file mode 100644
index 0000000..bcf759a
--- /dev/null
+++ b/org.gridsite.core/src/mod_ssl-private.h
@@ -0,0 +1,106 @@
+/*
+ Copyright (c) 2003-4, Andrew McNab, University of Manchester
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ o Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ o Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+
+ Portions of this code are derived from Apache mod_ssl, and are covered
+ by the Apache Software License:
+
+ * Copyright 2001-2004 The Apache Software Foundation
+ *
+ * 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.
+ */
+
+/*---------------------------------------------------------------------------*
+ * This program is part of GridSite: http://www.gridpp.ac.uk/gridsite/ *
+ *---------------------------------------------------------------------------*/
+
+
+/*
+ * After 2.0.49, Apache mod_ssl has most of the mod_ssl structures defined
+ * in ssl_private.h, which is not installed along with httpd-devel (eg in
+ * the FC2 RPM.) This include file provides SIMPLIFIED structures for use
+ * by mod_gridsite: for example, pointers to unused structures are replaced
+ * by void * and some of the structures are truncated when only the early
+ * members are used.
+ *
+ * CLEARLY, THIS WILL BREAK IF THERE ARE MAJOR CHANGES TO ssl_private.h!!!
+ */
+
+#include
+
+typedef enum {
+ SSL_SHUTDOWN_TYPE_UNSET,
+ SSL_SHUTDOWN_TYPE_STANDARD,
+ SSL_SHUTDOWN_TYPE_UNCLEAN,
+ SSL_SHUTDOWN_TYPE_ACCURATE
+} ssl_shutdown_type_e;
+
+typedef struct {
+ SSL *ssl;
+ const char *client_dn;
+ X509 *client_cert;
+ ssl_shutdown_type_e shutdown_type;
+ const char *verify_info;
+ const char *verify_error;
+ int verify_depth;
+ int is_proxy;
+ int disabled;
+ int non_ssl_request;
+} SSLConnRec;
+
+typedef struct {
+ void *sc; /* pointer back to server config */
+ SSL_CTX *ssl_ctx;
+} modssl_ctx_t;
+
+typedef struct {
+ void *mc;
+ unsigned int enabled;
+ unsigned int proxy_enabled;
+ const char *vhost_id;
+ int vhost_id_len;
+ int session_cache_timeout;
+ modssl_ctx_t *server;
+ modssl_ctx_t *proxy;
+} SSLSrvConfigRec;
+
+extern module AP_MODULE_DECLARE_DATA ssl_module;
diff --git a/org.gridsite.core/src/real-gridsite-admin.cgi b/org.gridsite.core/src/real-gridsite-admin.cgi
new file mode 100644
index 0000000000000000000000000000000000000000..0b34aae2d9027fafada5ce3ebd3381e6ae0d0493
GIT binary patch
literal 81444
zcmd44dw5jU^#*(h0V75e6*Vf=sGxX*sGul_K^O%^7`Z53Lm85=)G+
z@m6iMinrEQYq5g0Rcur$SZ$4!UrTMQX`9wPPTGz&)u_~b@4MFCXU>G6e1Ck;^P!V-
z*4}Hay>5H$%embcnSIWXAwxX(FUuS15n6v=cFqJG`wq~$30|SMhd0(c)GP3YqnvdU
z>Vbn_7tZ+`hF>;*L-894vXN`DbNJgIFn_EgH|2;E(DG;Y9^&ywdN1GB=L4&4SPp+Z
zS!iw##~)dNWZ!6LtKh0Q1Lsw!z<6kdH;%{1pP`&(&S{_gERgo&Guc@s$-z##fe|
zSXogOUpcO>dfdrMi>5{PbLT7+TFSv6-a6kkN;-lcb1%G{<*}01vnm!-^HQo
zi8vo&VYYA%ewX5R9)6U4Jbv!q44hnnpO4=%{7%6yg5O2>mE*S@KmMb9^YOb1ztQ-G
z|E&lC6*w=(?=t)j$ItzvO^(NJ0eGh9E^rz1;eR8;z#!*iLS=_@f5Emcz?}zey)U$uH{y5+l0;bIfe+_UE;FB$UD)5T|GX_}C
zcA|h8Lxg9belg%03qJ+1DAF~D7b>37z%FQ))A<_OP1JKjCnImcUj-HBs9;2UiFb)YW@u0Q<<^-;hnOW%oh7X$v5g+Bp)4d8t(90PtmV2-(ze<b`HmX(!U1!e86mn@WFr!0lRn{2e=6EM9{JRJhWd7m}4s8GXX~d
zUvJ^hfVUVh^DpcBP+tSMz{=MKe)WLgu=S?^zYXwf7Tyc>>i~0%C;dl&!~VDxWwUQj
z=f5KXuLu6mE&gx}Hhm%godf>usCV`#0o(zY;|uw3f_$k^|9Sv$7x`Iv9|leeu#3OD
zA&-YStMlj20OkWe9!K)K5A{#NUqss%qs-elDYSE3)^7t`6oQ)p7X$vfZSN-96Y%dX
zzhC3%{uSb68SodQz82@?w*vaq0A6X~cR*hc*!kl;;I{$he24gd#?SpL#L0=kUx)f4
zoU`7;oV2d4lC#kXUgV-^$wlS070XtgQ&Ck~=`EUAbb86M+VXO*WX2_Prd=>=x>t8~
zNmYD>)?8H{E2)Vuxw?FnS5i?`5fl14zw{(xT~k^aFHhsu#g{BEUm7c^DqT@7crz-l
zDzA$ztSKvvf&DVjdnM=2o_qGR*(Gz&IcI)kLCJz?XU~q5q*+wd)y2zem4ise_RCks
zN|si~t72ZsdDoQ8E5E9uE>>PUy|T2fuDs4GDY(QbJvq)~>3FRj1We
zF=kPE;R!7xCDm2sn4^cJM=M%Af5F^&k&@{P7L`cjwYAl?C1vF`G2fee_IV}MOO~G;
z8yt11Us_S6JR*x0MCQz&HFu8iSXx^Vt61uco#tOh<;Z_9A~XbJYE5+Eyy)Ed5n;Au
zRY{##SaeAT5{o0!9I%}xR=2Z4*g!zm8umdEB*SH~ii3MuJM-PSVt7n)hw-~
zu~1!oZF#M?qO`ISI?_C46}8^7WtH(d->VU(@Dw`=7?zc<^y$RQrIj^)X&ubj6n7SF>ViXnG0>p;0M~ky%{DQyWO3CB^uwjG
zRW;=$OG>CQex;SHDG_0p@zh&(EjmKESH2QGahcelWY%2tTxeJluPZMD4|ZSMmshYi
zp(TW*v{dJb5R~nj(mHFU6;~53DOrjBkNi-w%$}4>WS5j6@hLm61ZsKb&YpGl^pcau
zof4dd&rb?UnL0hBVf^$zUBPk<&(h2~?t2gmX;=O!-4I*KBFDoWvolH@h7hC1!5BV5
z5NX+Zx)tT-q$KVT!62QssZx{5waj%J&lNk{I|}SL@8ZAxD=IJ~4)gW`63glisld`N
z+dII*`%3*#?+6R$3!LR0Pp0^1Fy;=g*0FsU7JVFphb_i>9b@|*5bAOs(ez>-(QX-!
z7|VPf!K0GL;TZdP#3DMzBW7(Yd4wd_^N2}KJ&(Db*T^FzUdtmUm$&kmhp~}IC~y~#
zn6%x?BL>3zdBmb<9gkR0KguH(!H@HJAjWteF)3cpBPQz`c*KUob37j6c`xvY1!y~u
zqp2MPq~~qt@hGe-c^r+o2#;etubaoCVK*Kz`Rn0v
zEbPYPv7Xn^9p#x
zsym}s^@IQ|i!v8$Zga3J)5C8MH0RHE3A^gwdMesk57sLNNE`tAgyafK|
z@pAZ|$1CA~90xu?v$oCTM0+$g+BzuYV0{esu39l2llJHo7;`V-dcs`--%ofg;SPb<5pE;gF7Ts-?j~EjJc00YglhzzM7W*sVu7a+-by$sa53Qy!o>p5AiSM$
zk-#$vcM&cWcs5}}IA7o>;S^y{;01*H2&X=${)-56^iFgMd^zD9!W{xHCY(>WUEngp
z1%%fN>=P~|yiVXs!ea@y30y7%Bgj1hM|0i5exJ%&s39lvGA@DlFZG_te
zew6UNgx3rFIN^1K*9rV2;l~NL3A~>0dcySrZy@{};TnOTBiv4SvA{17-by$sa691+
z!o>n_CcK?+k-%FCcM&cW_zl8_aK6ADgj0k)fwvLvBb@qF`afaL025sTcM{Ga+#zrm
z;e5jF0(TQGAiN&%N&mdE`7aIKspx`ve&-z2+=V|EUgZD&L0m_>5go3#tqo(*d?qCC
zvNf+%{}*F6c5ex$Kerd
zzL=>H5OpZ>UjXcHX5q0xVM9+gP)z~)O~dA#x4IhI&xrbeBhD~~lk0y%xCy3JM&z9z
zMbTe{io97=#G*G{QSNd~Y{4Rs$d96)ZJqsn&m*JNxn8V5+Rybbw{=HrU2=cQTVo6N
zbp!<<=#S(7k^V|s_ut2aS@J+(G}7N-%iq=VhSm9AOzZOfZd><~t%L1GTnL#z?-R|M
z+T$nCo(Hk){h*8@s_BYQK?T-0dUP^dRHa3)y&~#nx3xra>nC~ftmK52NKVVb+*`ae
zvToROOJoOv!b={VE?mt*#AttV-~LEWYb3YdOTLUEI=Cf*xDke9VUFcqYose`{)`^3
zZdg8!!rZ0?Z;tdetnTyTdu)mH-2|ba2y3rTjYN&X(dI+90r4=PS4qv-du+=22!_9}#A7M?+UO
z9DJahp%2A#8TVHR9
zbkmhvA}{D+0}oXFL#n>!W0AHw(#4{jc_^xKMTSL3u;?;Z)Wf1lESl+xwl%Eo@nX3R
ztBn^M-mrR`7e9bVGl=xIA|-x?#h*EFt+xAX*6iuX-)LCVBFj;d`|-rtk%t^Zniw>GTa>ctL%aatogqW(vy?2m6XFCkqbI9np^EydZBBRlfG
z#iR&<`s3~9#Ct5~7Z}ZjY^>DD(b=%N6OCa4k0|f#2Z>;GnzIIA+`ALT*D^3-*JaZ8
zJBg)**ySye&f?}scXB?h^f7h%U$51vyJ2;=7dwL$!{?)7|8EACV3O?i_eLodsnQCo
z)rRfo4q)aS+0K!D{jxIi0unC`{SGY<1d)w?h`Ij@Pa>)$Yp|@
z9W`6-mpbJ8+%1s}SSfo6m{Ou>4iP6iuBxM`b}1_^yxEG@F4?iuzY?X?;7P4$Sp9-Z
z$Fke*w#Y9eRjzi*b%1Ioy7rhu9L{qMtDo~?BURk~_;aS^0ZY9>P`8<*KeA@+r7zFw
zkN29tY2R#)sGLYWov%`joaN(Ly*aab54uX~bN#ER%>u`9d&BDOUaS~|eoPeF?gl6H
z=3_-B1BQ~2kcu|IcjmEil&^40gv%5!@#r3GIM=_EjIYup!4!(3d!#K_lw#5SESlzu
zI@s_d(r}-t{*S1MhL0S);XKLLg^81;#T@@fmhjZCB0S0xemY!iI6
z;7~QuZV8{agqs7xF%k}Hqf~~OR$w22w2hYbB}=<@H)!jy_dwd2mi9GEJ9{^1kGV`~
zb1m&QOPe3iuB6rfD8(J-Snbv55lBHf{`P@24y6FiSgP0sCv8*>g8&r<|&^yo^bs
z>}zR%^Y5>g`8;fYQRY@ldzhuYeK%;2##R_-*bWrG3%TZnLy6?*?sFp3>fAY2UT9HwUyw?lLxd)XvFSbWqX~Ua%X4
zx93ZvNh~FE{az57Q#A3nMAmcZEbHqvJ)0rZmZlk4E#bs#Se=s<-&bK67;|j6imRrP
z4PBhqV<{vBlI1bEAKe;x4$BK%nc(_q6WI)jmq}k8We$=M%x-?AKVE1?DA1Z+(9oV0
zHBYDp%@NFPkdDD>gZYDIC@Px2kV$%j*{o44IGEjTFwbZKr&E{!k225RB2AOe>J45T
zGtC@-B#1?>6LfaW^Zxi)NDD!vEiQNaX6{h1bX5w>EF
zrhGkHBHV9;d_7#n&%-*nr8oym;X!?)PJ?*R9c^RI2|TQZF}KP!4-4aB;gAc?SjA(h
z{r%lxlrqJKQYtK)Q!T|HPPIn5`@O`g*yX0V?U|25vxf|p!
zaAg;{GHeHB23WUrj-3MRIj{U4GPv9N22Yk55#w&tnT+YK=h=rn}H;L8!a0ET3;;n8dQaThv1^;tp)nyrY@l
zZi`GB#2W8tG6P3{uSKxVa$Y4gn%|pe|H0q>@bWaW~(wwTqpe(
zNzRyeuN4a+&`Er;C7u}&W3L5a)9qg=H9h8tm4csmp1lnerIzBrohT|S#lN+MM6;z>
zVJW)1oq*i3V;i-WVv|xNkw$X-Yc2Z5ozTBw(QmWp#}mELqTd{#XC?QesoGFsZv8;o
zOkQui>pkW*kZ9L8e_Q231&P4?MY1=85MAvKwMt3wJ^5*(4Qj;Y?PmP)n{wh==7358s
zU&^E)zoBo)jdMf&XnWMWiW>z~Sbrfa^xD3((V$9w>I1%MZk=jDUPMa5W=O)+^8mTTPGfv^
zIO)W<03|b}g3CXJi>B0G|6a%C6y*X{glWWf6m0S6z`I=rULE@f<~veIJ4RzjhAL!Q
zNwdcaCk(vcfU$FXE9NvZ@D9?I1~BS0TlS}Jns_1m8nu9;4MJ~9b$KEofDO0>gY?D4
zI!IaX{;-}6z`HYU6f4>UEZ+Tnn-qz6uY51v7hzL)*O-UYff(*&%QEa;WA>LJAYXe!
z+Pi<%e46+%T-1Vb5+3Vv9$Vc-TVIJtmvq;H8A_44TN}nqU?K{{37yjSQ~s}=?@Bc(
zwp@W4b>E>Xdh_&bA%fkz)b8IEy}QkJS=S&DB8DD^^WZtCHJC{|WSA^UkNuOtLVMK4
zZ>0@%=AT`UVzt=s+o9^iTy@tVF8PhhFQOHg1H}_?$*7d!qM8+PB)gBW
zd6&yTo#sJFXs~%#Mvtme_K7E@N9Fi`fZhDR!bJvWlr(hP?p)(Q9nck(!Sp1-|xuIb!0kyx?Kc4PXq-3*ZwpuHGUJ+I2_+9dbM)=c4-OrP%4q0vT6w+z*AG9KaZiAq|&s!ksu}=3wOthYsw-U(?nTB@$3}2KV@_wrwu?bOv{~
zE9wwIx0!RREDmOQZdSI<{8YulT3Kgh9d=e`OpD?Vn3Zia^*d4Mtjw58EJfz5Y@3-A
zQ0T0z!_LZ#IYueMv$AdG@SV_gR%T4!3Q>V$x0{u1GpTpPu+YGc{BI)E%*S0)nw$(&
z$uK=;VU19u;Hw7nOJqjlCRKw?q3==lHU_$`BWJ|GH*~@$GhdsC_HMDQA_ngMi`
zG23O-Kn!5Yg9~`!80azQ$!^(BF>tW9p7^JXwYmO3sqv#h$BLR0TtkROsE=ujFoaXlIav<0ugRk=lE^XugY;2_dO`M+tT5QR1YT)-tE*fp#YhuGlKeFsZ
zZN4%$RiYE~lHJxAiR5E0&^;1y=xCGrrbz8(bAt>U-_|^A1K>Sb!5{#xb4wrHYDtg1
z%M?HHYujyQkoquaG-_7;!NvwxT#`(C%?oNg&e5?+!r16`15U5uvq)mu?hKdx?_J@O
zD3yk?-Fg-in8Vb^VDB%!%+B9_F3W*@N%-CV)2{eoEgrZNVh8xgEF;|*iH0^t1{uRS
zU()4ocjmT8j%g7-#RIlQ9^b`S5Mq-u$B&@$Mbu?8gw`p+!{Rk~;l$t52HA)T2oy|V
zYs8v5Aa$oFpU>+0i>x{V{k3e@bG^9U8So_mf(fYJq=8jNfqC&7$_vphiHp~`uHs%?
zIzVvAoA`-^+(&b>n2wtT8*tPt`aeP7j4ucf9jsw{w8(O-}53nE}$N={3<~BTbI@?f#Hbgcu3&PGT7LnMhA0%4P
zN6lKfPoyw${!S5mxk_Q9b=2iHh#g;!4{=1r1
zWCY-kB=<=G-st40baLeQO(@f#+*|SxJb&-oH0!{i{F69or=UE-vC2lL@!MPrBV2JP
zRzI#6?ROokugP6oZbpLzbq?p3J8+i}vO3cG4o)+%q14xpIp7YN1MW!THlaQn-HxKq
z-jgIZ841M>QuGN$A1U0uN|UxkddVAW_l7A=xoy1JZCIj*t@U70(Az&j3jLQvudPut
zYP*CS`{1u#**58eFkGG(j@$W%071#ef+sz8gPjpzVlkj*wbo=d_#4Ok3C*?{4K8&J
zKJYt{X3z$w?XtmQt--BM*q+Vm@9($f!;LvmANP2PNs?2o{b|i1Vt?GSm6a@n^(IGh
z4YrpdB(Y_Dg*sqmQ0gBq
zMI2^Lf4$(k01^(!gBWRZ{VA4ms!(d=kMb*R>DYiD(x!jEE!|H`)BF(sw(1jIsL_)X
zuT+`3wJ3~TY^z>NV|Uo1XEU%7NV&Q`TcCX{-BYXw+=`h=7`K#idwElbc5PD_n*Zha
zSC&wo9cGSHBY^c*1ug+ue3~ofWvX6{1q=ytJHrY~x_=mlw=<)^_Tnz7r8uR^j#u(c
z7qXLaQycp?Zm!H{V98vWd$5?qVEy=VfQUv@;D=6{FFiOv`5WrK8ZDbcmx%w!1=FN8
zD3U+C1{KpPp~BUWk(8oQq#bLn4z?}*M{LoebkTFRD3UJPZi`N~MI6L%s}wG%EvAje
znuF80QCl=TU38Z%`bd{vBmQ8XQD+c+Ga&dJVMqe=YG4&
z^5}1ziI%crrX{#@5WaGIkn&w((JBW)yTZ;D!EKpEizr(17&dXWEi4*@_K1L1XYXdX
zuHev-4wkEO;>YVPhkv=v_8k8Qw&+hESZ!b`2AL=nbc*82M-Snrzq{p5EW6duorVaA-=cLDysExndasNJMH$kCfxpbQGa{_{`%b(Z?oVbJn=-rQbtaJdD@X8
z&_=c_L^$MZDaHl_E~%f5>6ErpZjl=mIem+AXpnysxI(|9CA*2E^igNyrrTHr(^d>O
zJ@2q%fBMW{Y1y8rY?EJ;e&Z1Rt+sj}DdQF~r;9<>@!|65ldJ5IzH
zou*Bn`P*ze-`6FajK7J)F^&t3gxb+%YOMxEVN=K1q8csQU7PS0{x7phv1NO(vfY(U
zK9gmIbnXEkOs%tMRF!8hyE<%^2i~eF+%+(_4i}Tm?
zV1dclZH?TERoY1NKm|aqkFsv!2{f|XyuWq58Y`fSwu(-ZBim!MU3eq=o?vF^ZKL!@
zw={Qx>C$x;YInXw${ETAxp|{7@th8%Nai|}|3}(@APc`Pf^b*%DV0?c{#f&9om4bO
z?rMqLg(+KJ<84x}-A&}#p!XxAUN1yXqGVIb89XPLbG|~dL#$+n*&%+NrQ7E#=>97A
zjuj^UA<}TRWoG(T)U{$RG{4#Z4D8I0bQaJYX_KkhNOP!k5xMuJ&FrIqyZ7ZMYWC*H
ztx!X9%B|*4ny;vr-urT^*{Z!vaN7Fgx0;`Y3U1|K{=KEnxBc<8=D986O~GGF{2ypL
z=o#XExo|&T2P6?+ws*W`5PyYoPG1&aYG0mZhB-<5FpK7m!$@P8zoC=!iHBi{7hxI!
zrf5Qqf*CTTc}88DxXaZ~<-$D2Uuf&^)cWMLLVUDVUTQ0^v6YufTRFv6V(#D9vT(;O`>loI2%|o~%3>U%7~1b9x;4f8hMv*lw*s?N!#ok-4*GFr~WCP$XzqZ^NNSxfP3D#
zc=QtQYB3i^nB-25^xg0^tXtQ3W+++0mwlXAk8@!F&jW2}WJhbX|CUJa+AKVVgFP)g
zX?1$m^{qG?8p)ZN_aYee<~3ah^J-D+%rDY}U)(a}jI6w-%cVBAWg+ejI<^BW#ZxIH
zuN*T+wP32Ck6JE3BM!5{WH%3yHMVT^#Nb%74^-97lw=;_0@Dx<_M#znB*b!Sdd6aK
z-_kS^{HXbsrtB}=SqghkTGnIF&|E_opJ>*Yi*)PFh#G~
z15#2o5jWjH@_P+}KQw+9?WS#c;Mv-g1B$3QUfZhQL~!reL@fvJ<$FiX)UfR6)d(I(
z_sYw*JsK+AUg9`_p!VCKyVIvkvj*Mtb1|uCfU|~8V&=T2UP@2qRJ5V}%&1u!<{y+(
zuFIq5z#w{Mdv+hW$_eu}i`z1=$48BE-BCAl2Vj%sk^LJfh?(<>Dy7@Ld5u>UehV4Rx6-Gc!|-(-XxKe*LWpoi<=~P^44A`fT+!!l