Import 1.1.3
authorAndrew McNab <andrew.mcnab@manchester.ac.uk>
Mon, 15 Nov 2004 15:49:51 +0000 (15:49 +0000)
committerAndrew McNab <andrew.mcnab@manchester.ac.uk>
Mon, 15 Nov 2004 15:49:51 +0000 (15:49 +0000)
36 files changed:
org.gridsite.core/CHANGES
org.gridsite.core/INSTALL
org.gridsite.core/README
org.gridsite.core/VERSION
org.gridsite.core/doc/README.htcp-bin [new file with mode: 0644]
org.gridsite.core/doc/build-apache2.sh
org.gridsite.core/doc/config.html
org.gridsite.core/doc/findproxyfile.1 [new file with mode: 0644]
org.gridsite.core/doc/gacl.html
org.gridsite.core/doc/htcp.1
org.gridsite.core/doc/httpd-fileserver.conf
org.gridsite.core/doc/httpd-webserver.conf
org.gridsite.core/doc/index.html
org.gridsite.core/doc/install.html
org.gridsite.core/doc/urlencode.1
org.gridsite.core/interface/gridsite-gacl.h
org.gridsite.core/interface/gridsite.h
org.gridsite.core/src/Makefile
org.gridsite.core/src/delegation.h [new file with mode: 0644]
org.gridsite.core/src/doxyheader.html
org.gridsite.core/src/findproxyfile.c [new file with mode: 0644]
org.gridsite.core/src/gaclexample.c
org.gridsite.core/src/gridsite.spec
org.gridsite.core/src/grst-delegation.c [new file with mode: 0644]
org.gridsite.core/src/grst_admin.h
org.gridsite.core/src/grst_admin_file.c
org.gridsite.core/src/grst_admin_gacl.c
org.gridsite.core/src/grst_admin_main.c
org.gridsite.core/src/grst_gacl.c
org.gridsite.core/src/grst_x509.c
org.gridsite.core/src/htcp.c
org.gridsite.core/src/htproxyput.c [new file with mode: 0644]
org.gridsite.core/src/mod_gridsite.c
org.gridsite.core/src/mod_ssl-private.h
org.gridsite.core/src/proxyput-example.c [new file with mode: 0644]
org.gridsite.core/src/urlencode.c

index c7c17d5..e46eee6 100644 (file)
@@ -1,5 +1,39 @@
+* Mon Nov 15 2004 Andrew McNab <Andrew.McNab@man.ac.uk>
+- Back out of (most of) redone VOMS support for committing
+  to JRA1 CVS.
+* Thu Oct 19 2004 Andrew McNab <Andrew.McNab@man.ac.uk>
+- ==== GridSite version 1.1.3 ====
+* Thu Oct 19 2004 Andrew McNab <Andrew.McNab@man.ac.uk>
+- Fix Bug #5203 from Martijn Steenbakkers <msteenba>
+  by fixing GACLparseEntry in gridsite-gacl.h
+- Change to C style comments (mostly) in gridsite.h and
+  gridsite-gacl.h (fixes part of Bug #4222 from 
+  <aleks@fys.uio.no>)
+- Fix Bug #4225 from <aleks@fys.uio.no> in
+  GRSTgaclCredsFree()
+- Add GRSTx509CachedProxyFind() and findproxyfile
+  command to allow proxies to be found in proxy cache
+- Change GRSTx509StoreProxy() to GRSTx509CacheProxy() for
+  consistency with this and GRSTx509CachedProxyKeyFind()
+* Wed Oct 18 2004 Andrew McNab <Andrew.McNab@man.ac.uk>
+- ==== GridSite version 1.1.2 ====
+* Tue Oct 19 2004 Andrew McNab <Andrew.McNab@man.ac.uk>
+- Copy code from delegation prototype into grst_x509.c
+  and include htproxyput.c and grst-delegation.c
+  optional targets (which depend on gSOAP.)
+* Wed Oct 13 2004 Andrew McNab <Andrew.McNab@man.ac.uk>
+- Include per-file patch to GRSTgaclFileFindAclname: 
+  .gacl:FILENAME controls FILENAME if it exists.
+* Tue Jul 27 2004 Andrew McNab <Andrew.McNab@man.ac.uk>
+- ==== GridSite version 1.1.1 ====
+* Tue Jul 27 2004 Andrew McNab <mcnab@hep.man.ac.uk>
+- Include HTTP Downgrade support in htcp
+* Sat Jul 24 2004 Andrew McNab <mcnab@hep.man.ac.uk>
+- Include HTTP Downgrade support in mod_gridsite.
 * Thu Jul 22 2004 Andrew McNab <mcnab@hep.man.ac.uk>
-- ==== GridSite version 1.0.4 ====
+- Begin development version 1.1.x
+* Thu Jul 22 2004 Andrew McNab <mcnab@hep.man.ac.uk>
+- ==== GridSite version 1.1.0 ====
 * Mon Jul 19 2004 Andrew McNab <mcnab@hep.man.ac.uk>
 - Changes in line with EGEE SCM - most importantly
   the top level directory becomes org.gridsite.core
index 68e150a..3da6cde 100644 (file)
@@ -4,7 +4,7 @@ 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
+installed, or http://www.gridsite.org/1.1.x/install.html
 
 GridSite is currently only supported on Linux, but should be
 trivially portable to other Unix platforms where the GNU build
index 5fbb1db..62730a6 100644 (file)
@@ -1,3 +1,3 @@
 See INSTALL for build and installation instructions, and 
-http://www.gridpp.ac.uk/gridsite/ for configuration and
-usage guides.
+the Documentation section of http://www.gridsite.org/
+for configuration and usage guides.
index 10c4a0f..372ce91 100644 (file)
@@ -1,4 +1,4 @@
 MAJOR_VERSION=1
-MINOR_VERSION=1.0
-PATCH_VERSION=1.0.4
+MINOR_VERSION=1.1
+PATCH_VERSION=1.1.3
 VERSION=$(PATCH_VERSION)
diff --git a/org.gridsite.core/doc/README.htcp-bin b/org.gridsite.core/doc/README.htcp-bin
new file mode 100644 (file)
index 0000000..ac546fc
--- /dev/null
@@ -0,0 +1,13 @@
+Binaries (and links) are in ./bin; man pages are in ./man/man1
+
+Install by copying binaries/links onto your path, or by copying htcp
+and making symbolic links to htcp from htls, htll, htrm and htmkdir.
+
+All the .1 man pages should be copied to a suitable ./man/man1 
+directory on your man path.
+
+If you just want to install htcp in /usr/local, then unpacking this
+tgz file in /usr/local should do the trick. (Delete this README when
+you're finished!)
+
+For more about htcp see http://www.gridsite.org/
index f1246d4..507be31 100644 (file)
@@ -29,9 +29,9 @@
 #   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/
-#-----------------------------------------------------------------------------
+#---------------------------------------------------------------
+# For more information about GridSite: http://www.gridsite.org/
+#---------------------------------------------------------------
 #
 # 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
index 6e747e2..825bf49 100644 (file)
@@ -4,7 +4,7 @@
 
 <p> 
 This Guide is intended for webmasters setting up 
-<a href="http://www.gridpp.ac.uk/">GridSite</a> with an Apache 2.0
+<a href="http://www.gridsite.org/">GridSite</a> with an Apache 2.0
 webserver. We assume you have root access to the server machine to do this.
 There is a separate <a href="admin.html">Admin Guide</a> for
 people administrating areas of GridSite
diff --git a/org.gridsite.core/doc/findproxyfile.1 b/org.gridsite.core/doc/findproxyfile.1
new file mode 100644 (file)
index 0000000..ae2f944
--- /dev/null
@@ -0,0 +1,63 @@
+.TH findproxyfile 1 "October 2004" findproxyfile "FINDPROXYFILE Manual"
+.SH NAME
+.B findproxyfile
+\- returns full path to GSI Proxy file
+.SH SYNOPSIS
+.B findproxyfile 
+[--proxycache=PATH] [--delegation-id=ID] [--user-dn=DN] [--outsidecache]
+.SH DESCRIPTION
+.B findproxyfile
+returns full path to a GSI Proxy file, either in the proxy cache maintained
+by the GridSite G-HTTPS and delegation portType functions, or in other
+standard places.
+
+If a User DN is given
+.B findproxyfile 
+uses the value of the 
+.B --proxycache
+argument, the GRST_PROXY_PATH or the
+compile time default to detemine the location of the proxy cache directory.
+The directory is searched for a proxy having the given User DN and 
+Delegation ID. (If no Delegation ID is specificed, then the default value is
+used.)
+
+If
+.B findproxyfile
+does not find a proxy or if a User DN is not given, but
+.B --outsidecache
+was given, then the environment variable X509_USER_PROXY and the standard
+location /tmp/x509up_uUID are searched as well.
+
+.SH OPTIONS
+
+.IP "--proxycache=PATH"
+Give the path of the proxy cache directory explicitly, overriding the
+default and the GRST_PROXY_PATH environment variable if present.
+
+.IP "--delegation-id=ID"
+The optional delegation ID is search for in the proxy cache in addition to
+the User DN. If absent, the default Delegation ID value is searched for.
+
+.IP "--user-dn=DN"
+The DN of the full user certificate associated with the proxy to be searched
+for in the proxy cache. (This is not the DN of any proxy earlier in the
+chain: it is a the DN of a certificate issued by a recognised CA.)
+
+.IP "--outsidecache"
+If a User DN is not given, or a proxy not found in the cache, then search
+for a proxy using X509_USER_PROXY environment variable and file name of
+form /tmp/x509up_uUID as well.
+
+.SH RETURN VALUE
+If a proxy is found, its full path is output on standard out.
+
+.SH EXIT CODES
+0 is returned on succcess. Non-zero otherwise.
+
+.SH BUGS
+In this version, no attempt is made to verify or validate the proxies.
+
+.SH AUTHOR
+Andrew McNab <Andrew.McNab@man.ac.uk>
+
+findproxyfile is part of GridSite: http://www.gridsite.org/
index 12e58c7..40efdd2 100644 (file)
@@ -4,7 +4,7 @@
 
 <p> 
 GACL is the authorization policy language used by 
-<a href="http://www.gridpp.ac.uk/gridsite/">GridSite</a> GACL allows
+<a href="http://www.gridsite.org/">GridSite</a> 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.
index 05b0718..984aaaf 100644 (file)
@@ -1,4 +1,4 @@
-.TH htcp 1 "December 2003" htcp "HTCP Manual"
+.TH htcp 1 "July 2004" htcp "HTCP Manual"
 .SH NAME
 .B htcp, htrm, htls, htll, htmkdir
 \- get, put, delete or list HTTP/HTTPS files or directories
@@ -84,6 +84,15 @@ 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.
 
+.IP "--downgrade-size <minimum file size for downgrade>"
+Try to use HTTP-Downgrade for HTTPS URLs. Compatible servers will perform
+authentication and authorization on the HTTPS connection and then redirect
+to HTTP for the GET or PUT file transfer. htcp makes the HTTP request using
+the GRID_AUTH_ONETIME single-use passcode obtained via HTTPS. The downgrade
+option will be ignored for directory operations, HTTP URLs, or if the file
+size is less than the value given. If a downgraded transfer isn't possible,
+a normal HTTPS data transfer will be done.
+
 .SH FILES
 .IP /tmp/x509up_uID
 Default GSI Proxy file for Unix UID equal to ID.
@@ -127,9 +136,9 @@ Recursive copying. Server-side wildcards. Parallel streams. Error recovery.
 Not enough beta testing (hint hint...)
 
 .SH AUTHOR
-Andrew McNab <mcnab@hep.man.ac.uk>
+Andrew McNab <Andrew.McNab@man.ac.uk>
 
-htcp is part of GridSite: http://www.gridpp.ac.uk/gridsite/
+htcp is part of GridSite: http://www.gridsite.org/
 .SH "SEE ALSO"
 .BR scp(1),
 .BR curl(1),
index 1b197e7..9bd51e2 100644 (file)
@@ -1,9 +1,9 @@
 ##############################################################################
-## GridSite httpd-fileserver.conf - Andrew McNab <mcnab@hep.man.ac.uk>
+## GridSite httpd-fileserver.conf - Andrew McNab <Andrew.McNab@man.ac.uk>
 ##
 ## Example configuration file for GridSite as an HTTP(S) fileserver.
 ##
-## For GridSite documentation, see http://www.gridpp.ac.uk/gridsite/
+## For GridSite documentation, see http://www.gridsite.org/
 ##
 ## This file should be renamed /etc/httpd/conf/httpd.conf and Apache
 ## restarted to use Apache2/GridSite as a simple HTTP(S) fileserver. 
@@ -130,6 +130,8 @@ SSLCertificateFile      /etc/grid-security/hostcert.pem
 SSLCertificateKeyFile   /etc/grid-security/hostkey.pem
 SSLCACertificatePath    /etc/grid-security/certificates
 #SSLCARevocationPath    YOUR CRL DIRECTORY WOULD GO HERE
+SSLSessionCache         dbm:/var/cache/mod_ssl/scache
+SSLSessionCacheTimeout  300
 SSLVerifyClient         optional
 SSLVerifyDepth          10
 SSLOptions              +ExportCertData +StdEnvVars
index 0662f15..da332a0 100644 (file)
@@ -1,10 +1,10 @@
 ##############################################################################
-## GridSite httpd-webserver.conf - Andrew McNab <mcnab@hep.man.ac.uk>
+## GridSite httpd-webserver.conf - Andrew McNab <Andrew.McNab@man.ac.uk>
 ##
 ## 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/
+## For GridSite documentation, see http://www.gridsite.org/
 ##
 ## This file should be renamed /etc/httpd/conf/httpd.conf and Apache
 ## restarted to use Apache2/GridSite as a webserver. 
@@ -160,6 +160,8 @@ SSLCertificateFile      /etc/grid-security/hostcert.pem
 SSLCertificateKeyFile   /etc/grid-security/hostkey.pem
 SSLCACertificatePath    /etc/grid-security/certificates
 #SSLCARevocationPath    YOUR CRL DIRECTORY WOULD GO HERE
+SSLSessionCache         dbm:/var/cache/mod_ssl/scache
+SSLSessionCacheTimeout  300
 SSLVerifyClient         optional
 SSLVerifyDepth          10
 SSLOptions              +ExportCertData +StdEnvVars
index 11aaa86..a93f2cb 100644 (file)
@@ -1,9 +1,9 @@
-<title>GridSite 1.0.x Documentation</title>
+<title>GridSite 1.1.x Documentation</title>
 <body>
-<h1 align=center>GridSite 1.0.x Documentation</h1>
+<h1 align=center>GridSite 1.1.x Documentation</h1>
 
 <p>
-<a href="http://www.gridpp.ac.uk/gridsite/">GridSite</a>
+<a href="http://www.gridsite.org/">GridSite</a>
 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
index 6755b1e..91a60d2 100644 (file)
@@ -20,8 +20,8 @@ to the Config Guide.
 <p>
 We currently distribute GridSite RPMs for RedHat Linux versions 9 and 7.3
 from our download area at 
-<a href="https://www.gridpp.ac.uk/gridsite/download/">
-https://www.gridpp.ac.uk/gridsite/download/</a>
+<a href="https://www.gridsite.org/download/">
+https://www.gridsite.org/download/</a>
 
 <p>
 <b>RedHat 9</b>:
@@ -72,8 +72,8 @@ RedHat Linux releases 7.x onwards, for instance.)
 
 <p>
 Our download area at
-<a href="https://www.gridpp.ac.uk/gridsite/download/">
-https://www.gridpp.ac.uk/gridsite/download/</a> includes a tar-ball
+<a href="https://www.gridsite.org/download/">
+https://www.gridsite.org/download/</a> 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.)
@@ -140,7 +140,7 @@ 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 
-<a href="http://www.gridpp.ac.uk/gridsite/discuss.html">GridSite
+<a href="http://www.gridsite.org/discuss.html">GridSite
 Discussion List</a>, although 
 <a href="http://www.apache.org/">www.apache.org</a> is a better starting
 point for purely Apache problems.
index 47d2b91..fe84405 100644 (file)
@@ -14,8 +14,8 @@ 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
+For example, the URL http://www.gridpp.ac.uk/ becomes
+http%3A%2F%2Fwww.gridpp.ac.uk%2F
 
 .B urlencode
 converts each character in all the strings given on the command line. If
@@ -41,6 +41,6 @@ with the exception that + is converted to space.
 Not enough beta testing (hint hint...)
 
 .SH AUTHOR
-Andrew McNab <mcnab@hep.man.ac.uk>
+Andrew McNab <Andrew.McNab@man.ac.uk>
 
-urlencode is part of GridSite: http://www.gridpp.ac.uk/gridsite/
+urlencode is part of GridSite: http://www.gridsite.org/
index 2eec2fa..f739c00 100644 (file)
@@ -29,9 +29,9 @@
    POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*------------------------------------------------------------------------*
- * For more about GridSite: http://www.gridpp.ac.uk/gridsite/             *
- *------------------------------------------------------------------------*/
+/*---------------------------------------------------------------*
+ * For more about GridSite: http://www.gridsite.org/             *
+ *---------------------------------------------------------------*/
 
 #ifndef HEADER_GACL_H
 #define HEADER_GACL_H
@@ -76,113 +76,113 @@ extern GACLperm   gacl_perm_vals[];
 #define GACLinit() GRSTgaclInit()
 
 #define GACLnewCred(x)         GRSTgaclCredNew((x))
-//GACLcred  *GACLnewCred(char *);
+/* GACLcred  *GACLnewCred(char *); */
 
 #define GACLaddToCred(x,y,z)   GRSTgaclCredAddValue((x),(y),(z))
-//int        GACLaddToCred(GACLcred *, char *, char *);
+/* int        GACLaddToCred(GACLcred *, char *, char *); */
 
 #define GACLfreeCred(x)                GRSTgaclCredFree((x))
-//int        GACLfreeCred(GACLcred *);
+/* int        GACLfreeCred(GACLcred *); */
 
 #define GACLaddCred(x,y)       GRSTgaclEntryAddCred((x),(y))
-//int        GACLaddCred(GACLentry *, GACLcred *);
+/* int        GACLaddCred(GACLentry *, GACLcred *); */
 
 #define GACLdelCred(x,y)       GRSTgaclEntryDelCred((x),(y))
-//int        GACLdelCred(GACLentry *, GACLcred *);
+/* int        GACLdelCred(GACLentry *, GACLcred *); */
 
 #define GACLprintCred(x,y)     GRSTgaclCredPrint((x),(y))
-// int        GACLprintCred(GACLcred *, FILE *);
+/*  int        GACLprintCred(GACLcred *, FILE *); */
 
 
 #define GACLnewEntry()         GRSTgaclEntryNew()
-// GACLentry *GACLnewEntry(void);
+/*  GACLentry *GACLnewEntry(void); */
 
 #define GACLfreeEntry(x)       GRSTgaclEntryFree((x))
-// int        GACLfreeEntry(GACLentry *);
+/*  int        GACLfreeEntry(GACLentry *); */
 
 #define GACLaddEntry(x,y)      GRSTgaclAclAddEntry((x),(y))
-// int        GACLaddEntry(GACLacl *, GACLentry *);
+/*  int        GACLaddEntry(GACLacl *, GACLentry *); */
 
 #define GACLprintEntry(x,y)    GRSTgaclEntryPrint((x),(y))
-// int        GACLprintEntry(GACLentry *, FILE *);
+/*  int        GACLprintEntry(GACLentry *, FILE *); */
 
 
 #define GACLprintPerm(x,y)     GRSTgaclPermPrint((x),(y))
-//int        GACLprintPerm(GACLperm, FILE *);
+/* int        GACLprintPerm(GACLperm, FILE *); */
 
 #define GACLallowPerm(x,y)     GRSTgaclEntryAllowPerm((x),(y))
-// int        GACLallowPerm(GACLentry *, GACLperm);
+/*  int        GACLallowPerm(GACLentry *, GACLperm); */
 
 #define GACLunallowPerm(x,y)   GRSTgaclEntryUnallowPerm((x),(y))
-//int        GACLunallowPerm(GACLentry *, GACLperm);
+/* int        GACLunallowPerm(GACLentry *, GACLperm); */
 
 #define GACLdenyPerm(x,y)      GRSTgaclEntryDenyPerm((x),(y))
-// int        GACLdenyPerm(GACLentry *, GACLperm);
+/*  int        GACLdenyPerm(GACLentry *, GACLperm); */
 
 #define GACLundenyPerm(x,y)    GRSTgaclEntryUndenyPerm((x),(y))
-// int        GACLundenyPerm(GACLentry *, GACLperm);
+/*  int        GACLundenyPerm(GACLentry *, GACLperm); */
 
 #define GACLpermToChar(x)      GRSTgaclPermToChar((x))
-// char      *GACLpermToChar(GACLperm);
+/*  char      *GACLpermToChar(GACLperm); */
 
 #define GACLcharToPerm(x)      GRSTgaclPermFromChar((x))
-// GACLperm   GACLcharToPerm(char *);
+/*  GACLperm   GACLcharToPerm(char *); */
 
 #define GACLnewAcl()           GRSTgaclAclNew()
-// GACLacl   *GACLnewAcl(void);
+/*  GACLacl   *GACLnewAcl(void); */
 
 #define GACLfreeAcl(x)         GRSTgaclAclFree((x))
-// int        GACLfreeAcl(GACLacl *);
+/*  int        GACLfreeAcl(GACLacl *); */
 
 #define GACLprintAcl(x,y)      GRSTgaclAclPrint((x),(y))
-// int        GACLprintAcl(GACLacl *, FILE *);
+/*  int        GACLprintAcl(GACLacl *, FILE *); */
 
 #define GACLsaveAcl(x,y)       GRSTgaclAclSave((y),(x))
-// int        GACLsaveAcl(char *, GACLacl *);
+/*  int        GACLsaveAcl(char *, GACLacl *); */
 
 #define GACLloadAcl(x)         GRSTgaclAclLoadFile((x))
-// GACLacl   *GACLloadAcl(char *);
+/*  GACLacl   *GACLloadAcl(char *); */
 
 #define GACLfindAclForFile(x)  GRSTgaclFileFindAclname((x))
-// char      *GACLfindAclForFile(char *);
+/*  char      *GACLfindAclForFile(char *); */
 
 #define GACLloadAclForFile(x)  GRSTgaclAclLoadforFile((x))
-// GACLacl   *GACLloadAclForFile(char *);
+/*  GACLacl   *GACLloadAclForFile(char *); */
 
 #define GACLisAclFile(x)       GRSTgaclFileIsAcl((x))
-// int        GACLisAclFile(char *);
+/*  int        GACLisAclFile(char *); */
 
 
 #define GACLnewUser(x)         GRSTgaclUserNew((x))
-// GACLuser *GACLnewUser(GACLcred *);
+/*  GACLuser *GACLnewUser(GACLcred *); */
 
 #define GACLfreeUser(x)                GRSTgaclUserFree((x))
-// int       GACLfreeUser(GACLuser *);
+/*  int       GACLfreeUser(GACLuser *); */
 
 #define GACLuserAddCred(x,y)   GRSTgaclUserAddCred((x),(y))
-// int       GACLuserAddCred(GACLuser *, GACLcred *);
+/*  int       GACLuserAddCred(GACLuser *, GACLcred *); */
 
 #define GACLuserHasCred(x,y)   GRSTgaclUserHasCred((x),(y))
-// int       GACLuserHasCred(GACLuser *, GACLcred *);
+/*  int       GACLuserHasCred(GACLuser *, GACLcred *); */
 
 #define GACLuserFindCredType(x,y) GRSTgaclUserFindCredtype((x),(y))
-// GACLcred *GACLuserFindCredType(GACLuser *, char *);
+/*  GACLcred *GACLuserFindCredType(GACLuser *, char *); */
 
 #define GACLtestDnList(x,y)    GRSTgaclDNlistHasUser((x),(y))
-// int        GACLtestDnList(char *, GACLuser *);
+/*  int        GACLtestDnList(char *, GACLuser *); */
 
 #define GACLtestUserAcl(x,y)   GRSTgaclAclTestUser((x),(y))
-// GACLperm   GACLtestUserAcl(GACLacl *, GACLuser *);
+/*  GACLperm   GACLtestUserAcl(GACLacl *, GACLuser *); */
 
 #define GACLtestExclAcl(x,y)   GRSTgaclAclTestexclUser((x),(y))
-// GACLperm   GACLtestExclAcl(GACLacl *, GACLuser *);
+/*  GACLperm   GACLtestExclAcl(GACLacl *, GACLuser *); */
 
 
 #define GACLurlEncode(x)       GRSThttpUrlEncode((x))
-// char      *GACLurlEncode(char *);
+/*  char      *GACLurlEncode(char *); */
 
 #define GACLmildUrlEncode(x)   GRSThttpUrlMildencode((x))
-// char      *GACLmildUrlEncode(char *);
+/*  char      *GACLmildUrlEncode(char *); */
 
-GACLparseEntry *GRSTgaclEntryParse(xmlNodePtr cur);
-// special function for legacy EDG LB service
+GACLentry *GRSTgaclEntryParse(xmlNodePtr cur);
+/*  special function for legacy EDG LB service */
index 9742d15..7f614f5 100644 (file)
@@ -29,9 +29,9 @@
    POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*------------------------------------------------------------------------*
- * For more about GridSite: http://www.gridpp.ac.uk/gridsite/             *
- *------------------------------------------------------------------------*/
+/*---------------------------------------------------------------*
+ * For more about GridSite: http://www.gridsite.org/             *
+ *---------------------------------------------------------------*/
 
 #ifndef HEADER_SSL_H
 #include <ssl.h>
 #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;
-  
+                 void                      *next;  } GRSTgaclNamevalue;
+
 typedef struct { char                      *type;
                  int                        delegation;
                  GRSTgaclNamevalue         *firstname;
@@ -117,120 +119,120 @@ typedef struct { GRSTgaclCred *firstcred;
 
 int GRSTgaclInit(void);
 
-// #define GACLnewCred(x)              GRSTgaclCredNew((x))
+/* #define GACLnewCred(x)              GRSTgaclCredNew((x)) */
 GRSTgaclCred  *GRSTgaclCredNew(char *);
 
-// #define GACLaddToCred(x,y,z)        GRSTgaclCredAddValue((x),(y),(z))
+/* #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))
+/* #define GACLfreeCred(x)             GRSTgaclCredFree((x)) */
 int        GRSTgaclCredFree(GRSTgaclCred *);
 
-// #define GACLaddCred(x,y)    GRSTgaclEntryAddCred((x),(y))
+/*  #define GACLaddCred(x,y)   GRSTgaclEntryAddCred((x),(y)) */
 int        GRSTgaclEntryAddCred(GRSTgaclEntry *, GRSTgaclCred *);
 
-// #define GACLdelCred(x,y)    GRSTgaclEntryDelCred((x),(y))
+/*  #define GACLdelCred(x,y)   GRSTgaclEntryDelCred((x),(y)) */
 int        GRSTgaclEntryDelCred(GRSTgaclEntry *, GRSTgaclCred *);
 
-// #define GACLprintCred(x,y)  GRSTgaclCredPrint((x),(y))
+/*  #define GACLprintCred(x,y) GRSTgaclCredPrint((x),(y)) */
 int        GRSTgaclCredCredPrint(GRSTgaclCred *, FILE *);
 
 
-// #define GACLnewEntry(x)             GRSTgaclEntryNew((x))
+/*  #define GACLnewEntry(x)            GRSTgaclEntryNew((x)) */
 GRSTgaclEntry *GRSTgaclEntryNew(void);
 
-// #define GACLfreeEntry(x)    GRSTgaclEntryFree((x))
+/*  #define GACLfreeEntry(x)   GRSTgaclEntryFree((x)) */
 int        GRSTgaclEntryFree(GRSTgaclEntry *);
 
-// #define GACLaddEntry(x,y)   GRSTgaclAclAddEntry((x),(y))
+/*  #define GACLaddEntry(x,y)  GRSTgaclAclAddEntry((x),(y)) */
 int        GRSTgaclAclAddEntry(GRSTgaclAcl *, GRSTgaclEntry *);
 
-// #define GACLprintEntry(x,y) GRSTgaclEntryPrint((x),(y))
+/*  #define GACLprintEntry(x,y)        GRSTgaclEntryPrint((x),(y)) */
 int        GRSTgaclEntryPrint(GRSTgaclEntry *, FILE *);
 
 
-// #define GACLprintPerm(x,y)  GRSTgaclPermPrint((x),(y))
+/*  #define GACLprintPerm(x,y) GRSTgaclPermPrint((x),(y)) */
 int        GRSTgaclPermPrint(GRSTgaclPerm, FILE *);
 
-// #define GACLallowPerm(x,y)  GRSTgaclEntryAllowPerm((x),(y))
+/*  #define GACLallowPerm(x,y) GRSTgaclEntryAllowPerm((x),(y)) */
 int        GRSTgaclEntryAllowPerm(GRSTgaclEntry *, GRSTgaclPerm);
 
-// #define GACLunallowPerm(x,y)        GRSTgaclEntryUnallowPerm((x),(y))
+/*  #define GACLunallowPerm(x,y)       GRSTgaclEntryUnallowPerm((x),(y)) */
 int        GRSTgaclEntryUnallowPerm(GRSTgaclEntry *, GRSTgaclPerm);
 
-// #define GACLdenyPerm(x,y)   GRSTgaclEntryDenyPerm((x),(y))
+/*  #define GACLdenyPerm(x,y)  GRSTgaclEntryDenyPerm((x),(y)) */
 int        GRSTgaclEntryDenyPerm(GRSTgaclEntry *, GRSTgaclPerm);
 
-// #define GACLundenyPerm(x,y) GRSTgaclEntryUndenyPerm((x),(y))
+/*  #define GACLundenyPerm(x,y)        GRSTgaclEntryUndenyPerm((x),(y)) */
 int        GRSTgaclUndenyPerm(GRSTgaclEntry *, GRSTgaclPerm);
 
-// #define GACLpermToChar(x)   GRSTgaclPermToChar((x))
+/*  #define GACLpermToChar(x)  GRSTgaclPermToChar((x)) */
 char      *GRSTgaclPermToChar(GRSTgaclPerm);
 
-// #define GACLcharToPerm(x)   GRSTgaclPermFromChar((x))
+/*  #define GACLcharToPerm(x)  GRSTgaclPermFromChar((x)) */
 GRSTgaclPerm   GRSTgaclPermFromChar(char *);
 
-// #define GACLnewAcl(x)               GRSTgaclAclNew((x))
+/*  #define GACLnewAcl(x)              GRSTgaclAclNew((x)) */
 GRSTgaclAcl   *GRSTgaclAclNew(void);
 
-// #define GACLfreeAcl(x)              GRSTgaclAclFree((x))
+/*  #define GACLfreeAcl(x)             GRSTgaclAclFree((x)) */
 int        GRSTgaclAclFree(GRSTgaclAcl *);
 
-// #define GACLprintAcl(x,y)   GRSTgaclAclPrint((x),(y))
+/*  #define GACLprintAcl(x,y)  GRSTgaclAclPrint((x),(y)) */
 int        GRSTgaclAclPrint(GRSTgaclAcl *, FILE *);
 
-// #define GACLsaveAcl(x,y)    GRSTgaclAclSave((y),(x))
+/*  #define GACLsaveAcl(x,y)   GRSTgaclAclSave((y),(x)) */
 int        GRSTgaclAclSave(GRSTgaclAcl *, char *);
 
-// #define GACLloadAcl(x)              GRSTgaclFileLoadAcl((x))
+/*  #define GACLloadAcl(x)             GRSTgaclFileLoadAcl((x)) */
 GRSTgaclAcl   *GRSTgaclAclLoadFile(char *);
 
-// #define GACLfindAclForFile(x)       GRSTgaclFileFindAclname((x))
+/*  #define GACLfindAclForFile(x)      GRSTgaclFileFindAclname((x)) */
 char      *GRSTgaclFileFindAclname(char *);
 
-// #define GACLloadAclForFile(x)       GRSTgaclFileLoadAcl((x))
+/*  #define GACLloadAclForFile(x)      GRSTgaclFileLoadAcl((x)) */
 GRSTgaclAcl   *GRSTgaclAclLoadforFile(char *);
 
-// #define GACLisAclFile(x)    GRSTgaclFileIsAcl((x))
+/*  #define GACLisAclFile(x)   GRSTgaclFileIsAcl((x)) */
 int        GRSTgaclFileIsAcl(char *);
 
 
-// #define GACLnewUser(x)              GRSTgaclUserNew((x))
+/*  #define GACLnewUser(x)             GRSTgaclUserNew((x)) */
 GRSTgaclUser *GRSTgaclUserNew(GRSTgaclCred *);
 
-// #define GACLfreeUser(x)             GRSTgaclUserFree((x))
+/*  #define GACLfreeUser(x)            GRSTgaclUserFree((x)) */
 int       GRSTgaclUserFree(GRSTgaclUser *);
 
-// #define GACLuserAddCred(x,y)        GRSTgaclUserAddCred((x),(y))
+/*  #define GACLuserAddCred(x,y)       GRSTgaclUserAddCred((x),(y)) */
 int       GRSTgaclUserAddCred(GRSTgaclUser *, GRSTgaclCred *);
 
-// #define GACLuserHasCred(x,y)        GRSTgaclUserHasCred((x),(y))
+/*  #define GACLuserHasCred(x,y)       GRSTgaclUserHasCred((x),(y)) */
 int       GRSTgaclUserHasCred(GRSTgaclUser *, GRSTgaclCred *);
 
 int       GRSTgaclUserSetDNlists(GRSTgaclUser *, char *);
 
-// #define GACLuserFindCredType(x,y) GRSTgaclUserFindCredtype((x),(y))
+/*  #define GACLuserFindCredType(x,y) GRSTgaclUserFindCredtype((x),(y)) */
 GRSTgaclCred *GRSTgaclUserFindCredtype(GRSTgaclUser *, char *);
 
-// #define GACLtestDnList(x,y) GRSTgaclDNlistHasUser((x),(y))
+/*  #define GACLtestDnList(x,y)        GRSTgaclDNlistHasUser((x),(y)) */
 int GRSTgaclDNlistHasUser(char *, GRSTgaclUser *);
 
-// #define GACLtestUserAcl(x,y)        GRSTgaclAclTestUser((x),(y))
+/*  #define GACLtestUserAcl(x,y)       GRSTgaclAclTestUser((x),(y)) */
 GRSTgaclPerm   GRSTgaclAclTestUser(GRSTgaclAcl *, GRSTgaclUser *);
 
-// #define GACLtestExclAcl(x,y)        GRSTgaclAclTestexclUser((x),(y))
+/*  #define GACLtestExclAcl(x,y)       GRSTgaclAclTestexclUser((x),(y)) */
 GRSTgaclPerm   GRSTgaclAclTestexclUser(GRSTgaclAcl *, GRSTgaclUser *);
 
 
 char      *GRSThttpUrlDecode(char *);
 
-// #define GACLurlEncode(x)    GRSThttpUrlEncode((x))
+/*  #define GACLurlEncode(x)   GRSThttpUrlEncode((x)) */
 char      *GRSThttpUrlEncode(char *);
 
-// #define GACLmildUrlEncode(x)        GRSThttpMildUrlEncode((x))
+/*  #define GACLmildUrlEncode(x)       GRSThttpMildUrlEncode((x)) */
 char      *GRSThttpUrlMildencode(char *);
 
 int GRSTx509NameCmp(char *, char *);
@@ -242,13 +244,15 @@ 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 *);
+int GRSTx509GetVomsCreds(int *, int, size_t, char *, X509 *, STACK_OF(X509) *, char *);
 GRSTgaclCred *GRSTx509CompactToCred(char *);
 int GRSTx509CompactCreds(int *, int, size_t, char *, STACK_OF(X509) *, char *);
-
+char *GRSTx509CachedProxyFind(char *, char *, char *);
+char *GRSTx509FindProxyFileName(void);
+int GRSTx509MakeProxyCert(char **, FILE *, char *, char *, char *, int);
+char *GRSTx509CachedProxyKeyFind(char *, char *, char *);
+int GRSTx509MakeProxyRequest(char **, char *, char *, char *);
+int GRSTx509CacheProxy(char *, char *, char *, char *);
 
 #define GRST_HEADFILE   "gridsitehead.txt"
 #define GRST_FOOTFILE   "gridsitefoot.txt"
index a2bba0b..2971a33 100644 (file)
@@ -28,9 +28,9 @@
 #   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
-#-----------------------------------------------------------------------------
+#---------------------------------------------------------------
+# For more information about GridSite: http://www.gridsite.org
+#---------------------------------------------------------------
 
 include ../VERSION
 
@@ -41,15 +41,16 @@ export MYRPMDIR=$(shell pwd)/../RPMTMP
 endif
 
 ifndef prefix
-export prefix=/home/dimeglio/gridsite
+export prefix=/usr/local
 endif
 
 ifndef MYCFLAGS
-export MYCFLAGS=-I. -I../interface -I/usr/include/httpd -I/usr/include/apr-0
+export MYCFLAGS=-I. -I../interface -I/usr/include/httpd -I/usr/include/apr-0 -I/opt/glite/include
 endif
 
 ifndef MYLDFLAGS
 export MYLDFLAGS=-L.
+# export MYLDFLAGS=-L. -L/opt/glite/lib -lvomsc
 endif
 
 #
@@ -57,7 +58,7 @@ endif
 #
 
 build: libgridsite.so.$(VERSION) libgridsite.a htcp mod_gridsite.so \
-       urlencode real-gridsite-admin.cgi apidoc
+       urlencode findproxyfile real-gridsite-admin.cgi
 
 libgridsite.so.$(VERSION): grst_x509.o grst_gacl.o grst_http.o
        gcc -shared -Wl,-soname,libgridsite.so.$(MINOR_VERSION) \
@@ -87,9 +88,10 @@ 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
+mod_gridsite.so: mod_gridsite.c mod_ssl-private.h libgridsite.a
        gcc $(MYCFLAGS) -shared -Wl,-soname=gridsite_module \
            -I/usr/include/openssl -I/usr/kerberos/include \
+           -I/usr/include/libxml2 \
            -DVERSION=\"$(VERSION)\" -o mod_gridsite.so \
            mod_gridsite.c $(MYLDFLAGS) -lxml2 -lm -lz -lgridsite
 
@@ -102,20 +104,69 @@ real-gridsite-admin.cgi: grst_admin_main.c grst_admin_gacl.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
+findproxyfile: findproxyfile.c libgridsite.a
+       gcc -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) $(MYLDFLAGS) \
+            -o findproxyfile findproxyfile.c -L. \
+            -I/usr/include/openssl -I/usr/kerberos/include -lgridsite \
+            -lssl -lcrypto -lxml2 -lz -lm
+
+apidoc:
        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 
+            -lssl -lcrypto -lxml2 -lz -lm 
+
+#
+# Delegation machinery, including SOAP delegation portType. To build this
+# you need to install gSOAP and set GSOAPDIR to the directory containing
+# soapcpp2 and stdsoap2.h 
+#
+
+GSOAPDIR=/usr/local/lib/gsoap
+
+delegation.wsdl: delegation.h
+       $(GSOAPDIR)/soapcpp2 -c delegation.h
+
+libstdsoap2.a: $(GSOAPDIR)/stdsoap2.c
+       gcc -c -DWITH_OPENSSL $(GSOAPDIR)/stdsoap2.c
+       ar src libstdsoap2.a stdsoap2.o
+
+gridsite-delegation.cgi: grst-delegation.c delegation.h delegation.wsdl \
+                         libstdsoap2.a soapC.c soapServer.c
+       gcc $(MYCFLAGS) $(MYLDFLAGS) -o gridsite-delegation.cgi \
+            grst-delegation.c \
+            -I/usr/include/openssl -I/usr/kerberos/include -I$(GSOAPDIR) \
+            -DVERSION=\"$(VERSION)\" \
+            soapC.c soapServer.c libstdsoap2.a \
+            -lgridsite -lcurl -lz -lssl -lcrypto -lxml2 -lm
+
+htproxyput: htproxyput.c delegation.h delegation.wsdl \
+            soapC.c soapServer.c libstdsoap2.a
+       gcc $(MYCFLAGS) $(MYLDFLAGS) -o htproxyput \
+            htproxyput.c \
+            -I/usr/include/openssl -I/usr/kerberos/include \
+            -g -DVERSION=\"$(VERSION)\" \
+            -I$(GSOAPDIR) -DWITH_OPENSSL \
+            soapC.c soapClient.c libstdsoap2.a \
+            -lgridsite -lcurl -lz -lssl -lcrypto -lxml2 -lm
+
+proxyput-example: proxyput-example.c delegation.h delegation.wsdl \
+            soapC.c soapServer.c libstdsoap2.a
+       gcc $(MYCFLAGS) $(MYLDFLAGS) -o proxyput-example \
+            proxyput-example.c \
+            -I/usr/include/openssl -I/usr/kerberos/include \
+            -g -DVERSION=\"$(VERSION)\" \
+            -I$(GSOAPDIR) -DWITH_OPENSSL \
+            soapC.c soapClient.c libstdsoap2.a \
+            -lgridsite -lcurl -lz -lssl -lcrypto -lxml2 -lm
 
 #
 # Install
 #
 
-install:
+install: apidoc
        mkdir -p $(prefix)/include \
                  $(prefix)/lib \
                  $(prefix)/bin \
@@ -126,6 +177,7 @@ install:
        cp -f ../interface/gridsite.h $(prefix)/include
        cp -f ../interface/gridsite-gacl.h $(prefix)/include
        cp -f urlencode $(prefix)/bin
+       cp -f findproxyfile $(prefix)/bin
        cp -f libgridsite.a $(prefix)/lib
        cp -f real-gridsite-admin.cgi $(prefix)/sbin
        cp -f  libgridsite.so.$(PATCH_VERSION) $(prefix)/lib
@@ -143,7 +195,7 @@ install:
        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
+       gzip $(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
@@ -164,7 +216,10 @@ dist:
                  ../gridsite-$(PATCH_VERSION)/interface
        cp -f ../VERSION ../README ../LICENSE ../CHANGES ../INSTALL \
                  ../gridsite-$(PATCH_VERSION)
-       cp -f Makefile *.c *.h roffit gridsite.spec \
+       cp -f Makefile grst*.c htproxyput.c proxyput-example.c htcp.c \
+                 urlencode.c findproxyfile.c gaclexample.c mod_gridsite.c \
+                 delegation.h grst_admin.h mod_ssl-private.h \
+                 roffit gridsite.spec \
                  Doxyfile doxygen.css doxyheader.html \
                  ../gridsite-$(PATCH_VERSION)/src
        cp -f ../doc/*.html ../doc/*.1 ../doc/*.conf ../doc/*.sh \
diff --git a/org.gridsite.core/src/delegation.h b/org.gridsite.core/src/delegation.h
new file mode 100644 (file)
index 0000000..e612498
--- /dev/null
@@ -0,0 +1,12 @@
+//gsoap ns service name:       delegation
+//gsoap ns service style:      rpc
+//gsoap ns service encoding:   encoded
+//gsoap ns service namespace:  http://www.gridsite.org/ns/delegation.wsdl
+//gsoap ns service location:   http://localhost/delegserver.cgi
+
+struct ns__putProxyResponse { } ;
+
+//gsoap ns schema namespace: urn:delegation
+int ns__getProxyReq(char *delegationID, char **request);
+int ns__putProxy(char *delegationID, char *proxy, 
+                 struct ns__putProxyResponse *unused);
index ad33993..af78b52 100644 (file)
@@ -1 +1 @@
-<p><a href=http://www.gridpp.ac.uk/authz/>GridSite</a> Version 0.9.1
+<p><a href=http://www.gridsite.org/>GridSite</a> Version 1.1.x
diff --git a/org.gridsite.core/src/findproxyfile.c b/org.gridsite.core/src/findproxyfile.c
new file mode 100644 (file)
index 0000000..4485cc5
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+   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.
+*/
+
+#ifndef VERSION
+#define VERSION "0.0.0"
+#endif
+
+#define _GNU_SOURCE
+
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+
+#include "gridsite.h"
+  
+void printsyntax(char *argv0)
+{
+  char *p;
+
+  p = rindex(argv0, '/');
+  if (p != NULL) ++p;
+  else           p = argv0;
+
+  fprintf(stderr, "%s [--outsidecache] [--proxycache=PATH] "
+                  "[--delegation-id=DELEGATION-ID] [--user-dn=USER-DN]\n"
+                  "(Version: %s)\n", p, VERSION);
+}
+  
+#define GRST_PROXY_CACHE "/var/www/proxycache"
+  
+int main(int argc, char *argv[])
+{
+  char  *delegation_id = "_", *proxycache = "", *user_dn = "",
+        *proxyfile = NULL;        
+  int    c, outsidecache = 0, verbose = 0, option_index;
+  struct option long_options[] = {      {"verbose",            0, 0, 'v'},
+                                        {"outsidecache",       0, 0, 0},
+                                        {"proxycache",         1, 0, 0},
+                                        {"delegation-id",      1, 0, 0},
+                                        {"user-dn",            1, 0, 0},
+                                        {0, 0, 0, 0}  };
+
+  if (argc == 1)
+    {
+      printsyntax(argv[0]);
+      return 0;
+    }
+
+  while (1)
+       {
+         option_index = 0;
+                                                                                
+         c = getopt_long(argc, argv, "v", long_options, &option_index);
+
+         if      (c == -1) break;
+         else if (c == 0)
+           {
+             if      (option_index == 1) outsidecache  = 1;
+             else if (option_index == 2) proxycache    = optarg;
+             else if (option_index == 3) delegation_id = optarg;
+             else if (option_index == 4) user_dn       = optarg;
+           }
+         else if (c == 'v') ++verbose;
+       }
+       
+  if (*user_dn != '\0') /* try to find in proxy cache */
+    {
+      if ((proxycache == NULL) || (*proxycache == '\0'))
+        proxycache = getenv("GRST_PROXY_CACHE");
+
+      if ((proxycache == NULL) || (*proxycache == '\0'))
+        proxycache = GRST_PROXY_CACHE;
+
+      proxyfile = GRSTx509CachedProxyFind(proxycache, delegation_id, user_dn);
+    }
+    
+  if (((proxyfile == NULL) || (*proxyfile == '\0')) && outsidecache)
+    {
+      proxyfile = GRSTx509FindProxyFileName();
+    }
+
+  if ((proxyfile != NULL) && (*proxyfile != '\0'))
+    {
+      puts(proxyfile);
+      return 0;   
+    }
+    
+  fputs("No proxy file found\n", stderr);
+    
+  return 1;
+}
index 4cab5bc..5ad29b7 100644 (file)
@@ -29,9 +29,9 @@
    POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*------------------------------------------------------------------------*
- * For more about GridSite: http://www.gridpp.ac.uk/gridsite/             *
- *------------------------------------------------------------------------*/
+/*---------------------------------------------------------------*
+ * For more about GridSite: http://www.gridsite.org/             *
+ *---------------------------------------------------------------*/
 
 /*
    Example program using GACL 
index a6633d3..c2bbe80 100644 (file)
@@ -6,11 +6,11 @@ Copyright: Modified BSD
 Group: System Environment/Daemons
 Source: %{name}-%{version}.src.tar.gz
 Prefix: %(echo ${MYPREFIX:-/usr})
-URL: http://www.gridpp.ac.uk/gridsite/
+URL: http://www.gridsite.org/
 Vendor: GridPP
 #Requires: libxml2,curl-ssl,mod_ssl
 #Buildrequires: libxml2-devel,curl-ssl-devel,httpd-devel
-Packager: Andrew McNab <mcnab@hep.man.ac.uk>
+Packager: Andrew McNab <Andrew.McNab@man.ac.uk>
 
 %description
 GridSite adds GSI, VOMS and GACL support to Apache 2.0 (mod_gridsite),
@@ -18,7 +18,7 @@ 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.
+http://www.gridsite.org/ for details.
 
 %package -n htcp
 Group: Applications/Internet
@@ -55,6 +55,7 @@ rm -f %(echo ${MYPREFIX:-/usr})/share/doc/gridsite
 %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})/bin/findproxyfile
 %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
@@ -74,3 +75,4 @@ rm -f %(echo ${MYPREFIX:-/usr})/share/doc/gridsite
 %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
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/findproxyfile.1.gz
diff --git a/org.gridsite.core/src/grst-delegation.c b/org.gridsite.core/src/grst-delegation.c
new file mode 100644 (file)
index 0000000..2a8a9b2
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+   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.
+*/
+
+/*---------------------------------------------------------------------------*
+ * This program is part of GridSite: http://www.gridpp.ac.uk/authz/gridsite/ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef VERSION
+#define VERSION "0.0.1"
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include <time.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>    
+#include <openssl/des.h>    
+#include <openssl/rand.h>
+
+#include <curl/curl.h>
+/* #include <gacl.h> */
+
+#include "gridsite.h"
+
+#include "soapH.h"
+#include "delegation.nsmap"
+
+#include <time.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>    
+#include <openssl/des.h>    
+#include <openssl/rand.h>
+
+#define GRST_KEYSIZE       512
+#define GRST_PROXYCACHE    "/../proxycache/"
+#define GRST_SUPPORT_G_HTTPS
+
+#ifdef GRST_SUPPORT_G_HTTPS
+void GRSThttpError(char *status)
+{
+  printf("Status: %s\n", status);
+  printf("Server-CGI: GridSite %s\n", VERSION);
+  printf("Content-Length: %d\n", 2 * strlen(status) + 58);
+  puts("Content-Type: text/html\n");
+   
+  printf("<head><title>%s</title></head>\n", status);
+  printf("<body><h1   >%s</h1   ></body>\n", status);
+   
+  exit(0);
+}
+
+int GRSTmethodPutProxy(char *delegation_id, char *user_dn)
+/* return 0 on success; non-zero on error */
+{
+  int   c, len = 0, i;
+  char *docroot, *contentlen, *contenttype, *proxychain, *proxydir;
+  FILE *fp;
+
+  if (((contenttype = getenv("CONTENT_TYPE")) == NULL) ||
+       (strcmp(contenttype, "application/x-x509-user-cert-chain") != 0))
+                               return 2;
+  
+  contentlen = getenv("CONTENT_LENGTH");
+  if (contentlen == NULL) return 2;
+  len = atoi(contentlen);
+  
+  if ((delegation_id == NULL) || (*delegation_id == '\0')) 
+                                                    delegation_id = "_";
+  
+  docroot = getenv("DOCUMENT_ROOT");
+  asprintf(&proxydir, "%s/%s", docroot, GRST_PROXYCACHE);
+
+  if ((user_dn == NULL) || (user_dn[0] == '\0') ||
+      (GRSTx509CacheProxy(proxydir, delegation_id, user_dn, proxychain) 
+                                                      != GRST_RET_OK))
+    {
+      return GRST_RET_FAILED;
+    }
+    
+  free(proxydir);
+      
+  return GRST_RET_OK;
+}
+#endif
+
+int main(int argn, char *argv[])
+{
+  char      *docroot, *method, *request, *p, *client_dn, *user_dn,
+            *delegation_id, *reqtxt, *proxydir;
+  struct soap soap;
+  
+  method  = getenv("REQUEST_METHOD");
+  if (strcmp(method, "POST") == 0)
+    {
+      soap_init(&soap);
+      soap_serve(&soap); /* CGI application */
+      return 0;
+    }
+    
+#ifdef GRST_SUPPORT_G_HTTPS
+  docroot = getenv("DOCUMENT_ROOT");
+
+  request = strdup(getenv("REQUEST_URI"));
+  p = index(request, '?');
+  if (p != NULL) *p = '\0';
+
+      
+  /* non HTTP POST methods - ie special G-HTTPS methods */
+
+  delegation_id = getenv("HTTP_DELEGATION_ID");
+  if ((delegation_id == NULL) || (*delegation_id == '\0')) delegation_id = "_";
+
+  user_dn = NULL;
+  client_dn = getenv("SSL_CLIENT_S_DN"); 
+  if (client_dn != NULL) 
+    {
+      user_dn = strdup(client_dn);
+
+      /* we assume here that mod_ssl has verified proxy chain already ... */
+
+      p = strstr(user_dn, "/CN=proxy");
+      if (p != NULL) *p = '\0';      
+
+      p = strstr(user_dn, "/CN=limited proxy");
+      if (p != NULL) *p = '\0';      
+    }
+  
+  if (user_dn == NULL) /* all methods require client auth */
+    {
+      GRSThttpError("403 Forbidden");
+    }  
+  else if (strcmp(method, "GET-PROXY-REQ") == 0)
+    {
+      docroot = getenv("DOCUMENT_ROOT");
+      asprintf(&proxydir, "%s/%s", docroot, GRST_PROXYCACHE);
+    
+      if (GRSTx509MakeProxyRequest(&reqtxt, proxydir,
+                                   delegation_id, user_dn) == 0)
+        {
+          puts("Status: 200 OK");
+          puts("Content-Type: application/x-x509-cert-request");
+          printf("Content-Length: %d\n\n", strlen(reqtxt));
+          fputs(reqtxt, stdout);
+          free(proxydir);
+          return 0;
+        }
+      
+      puts("Status: 500 Internal Server Error\n");
+      free(proxydir);
+      return 0;
+    }  
+  else if (strcmp(method, "PUT-PROXY-CERT") == 0)
+    {
+      if (GRSTmethodPutProxy(delegation_id, user_dn) == 0)
+        {
+          puts("Status: 200 OK\n");
+          return 0;
+        }
+        
+      puts("Status: 500 Internal Server Error\n");
+      return 0;
+    }  
+  else 
+    {
+      GRSThttpError("501 Method Not Implemented");
+    }
+#endif
+}
+
+int ns__getProxyReq(struct soap *soap, char *delegation_id,                                        
+                                       char **request)
+{ 
+  char *p, *client_dn, *user_dn, *docroot, *proxydir;
+  
+  user_dn = NULL;
+  client_dn = getenv("SSL_CLIENT_S_DN"); 
+  if (client_dn != NULL) 
+    {
+      user_dn = strdup(client_dn);
+
+      /* we assume here that mod_ssl has verified proxy chain already ... */
+
+      p = strstr(user_dn, "/CN=proxy");
+      if (p != NULL) *p = '\0';      
+
+      p = strstr(user_dn, "/CN=limited proxy");
+      if (p != NULL) *p = '\0';      
+    }
+
+  if ((delegation_id == NULL) || (*delegation_id == '\0')) delegation_id = "_";
+  
+  docroot = getenv("DOCUMENT_ROOT");
+  asprintf(&proxydir, "%s/%s", docroot, GRST_PROXYCACHE);
+
+  if ((user_dn != NULL) && (user_dn[0] != '\0') && 
+      (GRSTx509MakeProxyRequest(request, proxydir,  
+                                delegation_id, user_dn) == 0))
+    {
+      return SOAP_OK;
+    }
+      
+  return SOAP_ERR;
+} 
+
+int ns__putProxy(struct soap *soap, char *delegation_id, 
+                                    char *proxy,
+                                    struct ns__putProxyResponse *unused)
+{ 
+  int   fd, c, len = 0, i;
+  char *docroot, *proxydir, *p, *client_dn, *user_dn;
+  
+  user_dn = NULL;
+  client_dn = getenv("SSL_CLIENT_S_DN"); 
+  if (client_dn != NULL) 
+    {
+      user_dn = strdup(client_dn);
+
+      /* we assume here that mod_ssl has verified proxy chain already ... */
+
+      p = strstr(user_dn, "/CN=proxy");
+      if (p != NULL) *p = '\0';      
+
+      p = strstr(user_dn, "/CN=limited proxy");
+      if (p != NULL) *p = '\0';      
+    }
+  
+  if ((delegation_id == NULL) || (*delegation_id == '\0')) 
+                                                    delegation_id = "_";
+  
+  docroot = getenv("DOCUMENT_ROOT");
+  asprintf(&proxydir, "%s/%s", docroot, GRST_PROXYCACHE);
+
+  if ((user_dn == NULL) || (user_dn[0] == '\0') ||
+      (GRSTx509CacheProxy(proxydir, delegation_id, user_dn, proxy) 
+                                                      != GRST_RET_OK))
+    {
+      return SOAP_ERR;
+    }
+      
+  return SOAP_OK;
+} 
+
index 4da3d11..cddc415 100644 (file)
@@ -29,9 +29,9 @@
    POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*---------------------------------------------------------------------------*
- * This program is part of GridSite: http://www.gridpp.ac.uk/gridsite/       *
- *---------------------------------------------------------------------------*/
+/*------------------------------------------------------------------*
+ * This program is part of GridSite: http://www.gridsite.org/       *
+ *------------------------------------------------------------------*/
 
 void  GRSThttpError(char *);
 void  adminfooter(GRSThttpBody *, char *, char *, char *, char *);
index fed6c42..f89a004 100644 (file)
@@ -29,9 +29,9 @@
    POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*---------------------------------------------------------------------------*
- * This program is part of GridSite: http://www.gridpp.ac.uk/gridsite/       *
- *---------------------------------------------------------------------------*/
+/*------------------------------------------------------------------*
+ * This program is part of GridSite: http://www.gridsite.org/       *
+ *------------------------------------------------------------------*/
 
 #ifndef VERSION
 #define VERSION "x.x.x"
index ba5ba1e..2a40b28 100644 (file)
@@ -29,9 +29,9 @@
    POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*---------------------------------------------------------------------------*
-* This program is part of GridSite: http://www.gridpp.ac.uk/authz/gridsite/ *
-*---------------------------------------------------------------------------*/
+/*-----------------------------------------------------------*
+* This program is part of GridSite: http://www.gridsite.org/ *
+*------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -84,7 +84,7 @@ void revert_acl(GRSTgaclUser *user, char *dn, GRSTgaclPerm perm, char *help_uri,
 /*****************************************/
 
 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*/
+  // Shows the contents of the ACL. Gives edit 'buttons' if (int admin) == 1
   GRSTgaclAcl *acl;
   GRSTgaclEntry *entry;
   GRSTgaclCred *cred;
index 9390dd1..d884bf5 100644 (file)
@@ -29,9 +29,9 @@
    POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*---------------------------------------------------------------------------*
- * This program is part of GridSite: http://www.gridpp.ac.uk/gridsite/       *
- *---------------------------------------------------------------------------*/
+/*------------------------------------------------------------------*
+ * This program is part of GridSite: http://www.gridsite.org/       *
+ *------------------------------------------------------------------*/
 
 #ifndef VERSION
 #define VERSION "x.x.x"
@@ -115,7 +115,7 @@ void adminfooter(GRSThttpBody *bp, char *dn, char *help_uri, char *dir_uri,
   if ((getenv("GRST_NO_LINK") == NULL) &&
       (getenv("REDIRECT_GRST_NO_LINK") == NULL))
     GRSThttpPrintf(bp, "Built with "
-     "<a href=\"http://www.gridpp.ac.uk/gridsite/\">GridSite</a> %s\n",
+     "<a href=\"http://www.gridsite.org/\">GridSite</a> %s\n",
      VERSION);
    
   GRSThttpPrintf(bp, "</small>\n");
index 3c99002..13b46c8 100644 (file)
@@ -28,9 +28,9 @@
    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/ *
- *------------------------------------------------------------------------*/
+/*---------------------------------------------------------------*
+ * For more information about GridSite: http://www.gridsite.org/ *
+ *---------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -187,7 +187,7 @@ static int GRSTgaclCredsFree(GRSTgaclCred *firstcred)
   
   if (firstcred->next != NULL) GRSTgaclCredsFree(firstcred->next);
   
-  return GRSTgaclCredsFree(firstcred);
+  return GRSTgaclCredFree(firstcred);
 }
 
 static int GRSTgaclCredInsert(GRSTgaclCred *firstcred, GRSTgaclCred *newcred)
@@ -691,18 +691,36 @@ char *GRSTgaclFileFindAclname(char *pathandfile)
    (for directories, the ACL file is in the directory itself), or NULL if none
    can be found. */
 {
-  char        *path, *p;
+  int          len;
+  char        *path, *file, *p;
   struct stat  statbuf;
+   
+  len = strlen(pathandfile);
+  if (len == 0) return NULL;
   
-  path = malloc(strlen(pathandfile) + sizeof(GRST_ACL_FILE) + 1);
+  path = malloc(len + sizeof(GRST_ACL_FILE) + 2);
   strcpy(path, pathandfile);
 
-  if (stat(path, &statbuf) == 0)
+  if ((stat(path, &statbuf) == 0)      && 
+       S_ISDIR(statbuf.st_mode)                &&
+      (path[len-1] != '/'))
     {
-      if (!S_ISDIR(statbuf.st_mode)) /* can strip this / off straightaway */
+      strcat(path, "/");
+      ++len;
+    }
+    
+  if (path[len-1] != '/')
+    {
+      p = rindex(pathandfile, '/');
+      if (p != NULL)
         {
-          p = rindex(path, '/');
-          if (p != NULL) *p = '\0';
+          file = &p[1];          
+          p = rindex(path, '/');          
+          sprintf(p, "/%s:%s", GRST_ACL_FILE, file);
+
+          if (stat(path, &statbuf) == 0) return path;
+
+          *p = '\0'; /* otherwise strip off any filename */
         }
     }
 
index 797786d..37b60e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2002-3, Andrew McNab, University of Manchester
+   Copyright (c) 2002-4, Andrew McNab, University of Manchester
    All rights reserved.
 
    Redistribution and use in source and binary forms, with or
    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/
-   ------------------------------------------------------------------------
+   ---------------------------------------------------------------
+    For more information about GridSite: http://www.gridsite.org/
+   ---------------------------------------------------------------
 */ 
 
+#define _GNU_SOURCE
+
 #include <stdio.h>
-#include <sys/stat.h>
 #include <unistd.h>       
-#include <sys/types.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdarg.h>
 #include <dirent.h>
 #include <string.h>
-#include <openssl/evp.h>
+#include <pwd.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>    
+#include <openssl/des.h>    
+#include <openssl/rand.h>
+
+#ifdef GRST_VOMS_SUPPORT
+#include <glite/security/voms/voms_apic.h>
+#endif
 
 #include "gridsite.h"
 
+#define GRST_KEYSIZE   512
+#define GRST_PROXYCACHE        "/../proxycache/"
+#define GRST_MAX_CHAIN_LEN 9
+
 /// Compare X509 Distinguished Name strings
 int GRSTx509NameCmp(char *a, char *b)
 /**
@@ -370,100 +397,6 @@ int GRSTx509VerifyCallback (int ok, X509_STORE_CTX *ctx)
 //   else    return GRST_RET_FAILED;
 }
 
-/// Check VOMS signature
-/** 
- *  Return GRST_RET_OK if signature starting at *sig matches *data and is 
- *  from VOMS *vo; return GRST_RET_FAILED otherwise.
- */
-int GRSTx509CheckVomsSig(unsigned char *sig, unsigned int siglen, 
-                         unsigned char *data, unsigned int datalen,
-                         char *vomsdir, char *vo, char *vomsdn)
-{
-   int            ret = 0;
-   char          *certfilename, *certdn;
-   FILE          *fp;
-   DIR           *vomsDIR;
-   struct dirent *certdirent;
-   X509          *cert;
-   EVP_PKEY      *pubkey;
-   EVP_MD_CTX     ctx;   
-   struct stat    statbuf;
-   time_t         now;
-   
-   time(&now);
-
-   vomsDIR = opendir(vomsdir);
-   if (vomsDIR == NULL) 
-     {
-       return GRST_RET_NO_SUCH_FILE;
-     }
-
-   while ((certdirent = readdir(vomsDIR)) != NULL)
-        {
-          certfilename = malloc(strlen(vomsdir) + 
-                                strlen(certdirent->d_name) + 2);
-                                
-          strcpy(certfilename, vomsdir);
-          strcat(certfilename, "/");
-          strcat(certfilename, certdirent->d_name);
-          
-          if ((stat(certfilename, &statbuf) != 0) || S_ISDIR(statbuf.st_mode))
-            {
-              free(certfilename);
-              continue;
-            }
-          
-          fp = fopen(certfilename, "r");
-          free(certfilename);
-          
-          if (fp == NULL) continue;
-                                  
-          cert = PEM_read_X509(fp, NULL, NULL, NULL);
-          fclose(fp);
-          
-          if (cert == NULL) continue;
-
-          certdn = X509_NAME_oneline(X509_get_subject_name(cert),NULL,0);
-
-          if ((now <
-     GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(cert))) ) ||
-              (now >
-     GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter( cert))) ) ||          
-              (GRSTx509NameCmp(certdn, vomsdn) != 0))
-            {
-              X509_free(cert);
-              continue;
-            }
-                    
-          pubkey = X509_extract_key(cert);
-
-          if (pubkey != NULL)
-            {   
-//              EVP_MD_CTX_init(&ctx);
-              EVP_VerifyInit(&ctx, EVP_sha1());
-              EVP_VerifyUpdate(&ctx, (unsigned char *) data, datalen);
-     
-              ret=EVP_VerifyFinal(&ctx, (unsigned char *) sig, siglen, pubkey);
-                 
-//              EVP_MD_CTX_cleanup(&ctx);
-            }
-
-          closedir(vomsDIR); /* we're finished now, one way or the other */
-
-          X509_free(cert);
-
-          /* since we matched cert names and times, we always return */
-
-          if (ret == 1) return GRST_RET_OK;
-          else          return GRST_RET_BAD_SIGNATURE;
-        }
-
-   closedir(vomsDIR);
-
-   return GRST_RET_CERT_NOT_FOUND; /* didnt find a matching VOMS cert */
-}
-
 /// Get the VOMS attributes in the extensions to the given cert
 /*
  *  Puts any VOMS credentials found into the Compact Creds string array
@@ -471,10 +404,16 @@ int GRSTx509CheckVomsSig(unsigned char *sig, unsigned int siglen,
  */
 
 int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen, 
-                         char *creds, X509 *cert, X509 *usercert, 
+                         char *creds, X509 *cert, STACK_OF(X509) *certstack,
                          char *vomsdir)
 {
-   int  i, j;   
+#ifndef GRST_VOMS_SUPPORT
+   return GRST_RET_OK;
+}
+#else
+
+/*
+   int  j;   
    unsigned int siglen=-1, datalength=-1, dataoffset = -1;
    char s[80];
    unsigned char *charstr, *p, *time1 = NULL, *time2 = NULL, *vo = NULL,
@@ -485,6 +424,51 @@ int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen,
    ASN1_STRING    *asn1str;
    time_t          now, time1_time = 0, time2_time = 0, 
                    uctime1_time, uctime2_time;
+*/
+
+
+   struct vomsdata *vd;
+   int    i, j, vomserror;
+
+   vd = VOMS_Init(NULL, NULL);
+
+   if (VOMS_Retrieve(cert, certstack, RECURSE_CHAIN, vd, &vomserror) &&
+       (vd->data != NULL))
+     {     
+       for (i = 0; vd->data[i] != NULL; ++i)
+          {
+            if (vd->data[i]->fqan != NULL)
+                for (j = 0; vd->data[i]->fqan[j] != NULL; ++j)
+                   {
+                     if (*lastcred >= maxcreds - 1)
+                       {
+                         VOMS_Destroy(vd);
+                         return GRST_RET_OK;
+                       }
+
+                     ++(*lastcred);
+            
+                     snprintf(&creds[*lastcred * (credlen + 1)], 
+                           credlen+1,
+                           "VOMS %010lu %010lu 0 %s",
+                           GRSTasn1TimeToTimeT(vd->data[i]->date1), 
+                           GRSTasn1TimeToTimeT(vd->data[i]->date2),
+                           vd->data[i]->fqan[j]);
+                   }
+          }
+     }
+   else
+     {
+       FILE *fp = fopen("/tmp/getvoms.log", "w");
+       fprintf(fp, "%d\n", vomserror);
+       fclose(fp);
+     }
+   
+   VOMS_Destroy(vd);   
+   return GRST_RET_OK;
+}
+
+#if 0
 
    time(&now);
 
@@ -622,9 +606,8 @@ int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen,
                    ++p;
                  }
              }
-             
-            if (
-                (now >= time1_time) &&
+/*             
+            if ((now >= time1_time) &&
                 (now <= time2_time) &&
                 (signature != NULL) &&
                 (data != NULL) &&
@@ -635,7 +618,9 @@ int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen,
                 (GRSTx509CheckVomsSig(signature, siglen, 
                                     &((ASN1_STRING_data(asn1str))[dataoffset]),
                                     datalength, vomsdir, vo, 
-                                    server) == GRST_RET_OK)) while (1)
+                                    server) == GRST_RET_OK)) 
+                                    while (1)
+*/
              {
                if (strncmp(p, "GROUP:", sizeof("GROUP:") - 1) == 0)
                  {
@@ -713,6 +698,9 @@ int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen,
 
    return GRST_RET_OK;
 }
+#endif
+
+#endif
 
 /// Turn a Compact Cred line into a GRSTgaclCred object
 /**
@@ -839,8 +827,572 @@ int GRSTx509CompactCreds(int *lastcred, int maxcreds, size_t credlen,
        strcpy(&creds[*lastcred * (credlen + 1)], credtemp);
        
        GRSTx509GetVomsCreds(lastcred, maxcreds, credlen, creds, 
-                            gsiproxycert, usercert, vomsdir);
+                            gsiproxycert, certstack, vomsdir);
      }
          
    return GRST_RET_OK;
 }
+
+/// Find proxy file name of the current user
+/**
+ *  Return a string with the proxy file name or NULL if not present.
+ *  This function does not check if the proxy has expired.
+ */
+char *GRSTx509FindProxyFileName(void)
+{
+  char *p;
+  
+  p = getenv("X509_USER_PROXY");
+  
+  if (p != NULL) return strdup(p);
+  
+  p = malloc(sizeof("/tmp/x509up_uXYYYXXXYYY"));
+  
+  sprintf(p, "/tmp/x509up_u%d", getuid());  
+
+  return p;
+}
+
+static void mpcerror(FILE *debugfp, char *msg)
+{
+  if (debugfp != NULL)
+    {
+      fputs(msg, debugfp);
+      ERR_print_errors_fp(debugfp);
+    }
+}
+
+/// Make a GSI Proxy chain from a request, certificate and private key
+/**
+ *  The proxy chain is returned in *proxychain. If debugfp is non-NULL,
+ *  errors are output to that file pointer. The proxy will expired in
+ *  the given number of minutes starting from the current time.
+ */
+
+int GRSTx509MakeProxyCert(char **proxychain, FILE *debugfp, 
+                           char *reqtxt, char *cert, char *key, int minutes)
+{
+  char *ptr, *certchain;
+  int i, subjAltName_pos, ncerts;
+  long serial = 1, ptrlen;
+  EVP_PKEY *pkey, *CApkey;
+  const EVP_MD *digest;
+  X509 *certs[GRST_MAX_CHAIN_LEN];
+  X509_REQ *req;
+  X509_NAME *name, *CAsubject, *newsubject;
+  X509_NAME_ENTRY *ent;
+  X509V3_CTX ctx;
+  X509_EXTENSION *subjAltName;
+  STACK_OF (X509_EXTENSION) * req_exts;
+  FILE *fp;
+  BIO *reqmem, *certmem;
+
+  /* read in the request */
+  reqmem = BIO_new(BIO_s_mem());
+  BIO_puts(reqmem, reqtxt);
+    
+  if (!(req = PEM_read_bio_X509_REQ(reqmem, NULL, NULL, NULL)))
+    {
+      mpcerror(debugfp,
+              "GRSTx509MakeProxyCert(): error reading request from BIO memory\n");
+      BIO_free(reqmem);
+      return GRST_RET_FAILED;
+    }
+    
+  BIO_free(reqmem);
+
+  /* verify signature on the request */
+  if (!(pkey = X509_REQ_get_pubkey (req)))
+    {
+      mpcerror(debugfp,
+              "GRSTx509MakeProxyCert(): error getting public key from request\n");
+      return GRST_RET_FAILED;
+    }
+
+  if (X509_REQ_verify(req, pkey) != 1)
+    {
+      mpcerror(debugfp,
+            "GRSTx509MakeProxyCert(): error verifying signature on certificate\n");
+      return GRST_RET_FAILED;
+    }
+    
+  /* read in the signing certificate */
+  if (!(fp = fopen(cert, "r")))
+    {
+      mpcerror(debugfp,
+            "GRSTx509MakeProxyCert(): error opening signing certificate file\n");
+      return GRST_RET_FAILED;
+    }    
+
+  for (ncerts = 1; ncerts < GRST_MAX_CHAIN_LEN; ++ncerts)
+   if (!(certs[ncerts] = PEM_read_X509(fp, NULL, NULL, NULL))) break;
+
+  if (ncerts == 1) /* zeroth cert with be new proxy cert */
+    {
+      mpcerror(debugfp,
+            "GRSTx509MakeProxyCert(): error reading signing certificate file\n");
+      return GRST_RET_FAILED;
+    }    
+
+  fclose(fp);
+  
+  CAsubject = X509_get_subject_name(certs[1]);
+
+  /* read in the CA private key */
+  if (!(fp = fopen(key, "r")))
+    {
+      mpcerror(debugfp,
+            "GRSTx509MakeProxyCert(): error reading signing private key file\n");
+      return GRST_RET_FAILED;
+    }    
+
+  if (!(CApkey = PEM_read_PrivateKey (fp, NULL, NULL, NULL)))
+    {
+      mpcerror(debugfp,
+            "GRSTx509MakeProxyCert(): error reading signing private key in file\n");
+      return GRST_RET_FAILED;
+    }    
+
+  fclose(fp);
+  
+  /* get subject name */
+  if (!(name = X509_REQ_get_subject_name (req)))
+    {
+      mpcerror(debugfp,
+            "GRSTx509MakeProxyCert(): error getting subject name from request\n");
+      return GRST_RET_FAILED;
+    }    
+
+  /* create new certificate */
+  if (!(certs[0] = X509_new ()))
+    {
+      mpcerror(debugfp,
+            "GRSTx509MakeProxyCert(): error creating X509 object\n");
+      return GRST_RET_FAILED;
+    }    
+
+  /* set version number for the certificate (X509v3) and the serial number   
+     need 3 = v4 for GSI proxy?? */
+  if (X509_set_version (certs[0], 3L) != 1)
+    {
+      mpcerror(debugfp,
+            "GRSTx509MakeProxyCert(): error setting certificate version\n");
+      return GRST_RET_FAILED;
+    }    
+
+  ASN1_INTEGER_set (X509_get_serialNumber (certs[0]), serial++);
+
+  if (!(name = X509_get_subject_name(certs[1])))
+    {
+      mpcerror(debugfp,
+      "GRSTx509MakeProxyCert(): error getting subject name from CA certificate\n");
+      return GRST_RET_FAILED;
+    }    
+
+  if (X509_set_issuer_name (certs[0], name) != 1)
+    {
+      mpcerror(debugfp,
+      "GRSTx509MakeProxyCert(): error setting issuer name of certificate\n");
+      return GRST_RET_FAILED;
+    }    
+
+  /* set issuer and subject name of the cert from the req and the CA */
+  ent = X509_NAME_ENTRY_create_by_NID(NULL, OBJ_txt2nid("commonName"), 
+                                      MBSTRING_ASC, "proxy", -1);
+
+  newsubject = X509_NAME_dup(CAsubject);
+
+  X509_NAME_add_entry(newsubject, ent, -1, 0);
+
+  if (X509_set_subject_name(certs[0], newsubject) != 1)
+    {
+      mpcerror(debugfp,
+      "GRSTx509MakeProxyCert(): error setting subject name of certificate\n");
+      return GRST_RET_FAILED;
+    }    
+
+  /* set public key in the certificate */
+  if (X509_set_pubkey(certs[0], pkey) != 1)
+    {
+      mpcerror(debugfp,
+      "GRSTx509MakeProxyCert(): error setting public key of the certificate\n");
+      return GRST_RET_FAILED;
+    }    
+
+// need to set validity within limits of earlier certificates in the chain
+
+  /* set duration for the certificate */
+  if (!(X509_gmtime_adj (X509_get_notBefore(certs[0]), 0)))
+    {
+      mpcerror(debugfp,
+      "GRSTx509MakeProxyCert(): error setting beginning time of the certificate\n");
+      return GRST_RET_FAILED;
+    }    
+
+  if (!(X509_gmtime_adj (X509_get_notAfter(certs[0]), 60 * minutes)))
+    {
+      mpcerror(debugfp,
+      "GRSTx509MakeProxyCert(): error setting ending time of the certificate\n");
+      return GRST_RET_FAILED;
+    }    
+
+  /* sign the certificate with the signing private key */
+  if (EVP_PKEY_type (CApkey->type) == EVP_PKEY_RSA)
+    digest = EVP_md5();
+  else
+    {
+      mpcerror(debugfp,
+      "GRSTx509MakeProxyCert(): error checking signing private key for a valid digest\n");
+      return GRST_RET_FAILED;
+    }    
+
+  if (!(X509_sign (certs[0], CApkey, digest)))
+    {
+      mpcerror(debugfp,
+      "GRSTx509MakeProxyCert(): error signing certificate\n");
+      return GRST_RET_FAILED;
+    }    
+
+  /* store the completed certificate chain */
+
+  certchain = strdup("");
+
+  for (i=0; i < ncerts; ++i)
+     {
+       certmem = BIO_new(BIO_s_mem());
+
+       if (PEM_write_bio_X509(certmem, certs[i]) != 1)
+         {
+           mpcerror(debugfp,
+            "GRSTx509MakeProxyCert(): error writing certificate to memory BIO\n");            
+           return GRST_RET_FAILED;
+         }
+
+       ptrlen = BIO_get_mem_data(certmem, &ptr);
+  
+       certchain = realloc(certchain, strlen(certchain) + ptrlen + 1);
+       
+       strncat(certchain, ptr, ptrlen);
+    
+       BIO_free(certmem);
+     }
+    
+  *proxychain = certchain;
+    
+  return GRST_RET_OK;
+}
+
+/// Find a proxy file in the proxy cache
+/**
+ *  Returns the full path and file name of proxy file associated
+ *  with given delegation ID and user DN.
+ */
+
+char *GRSTx509CachedProxyFind(char *proxydir, char *delegation_id, 
+                              char *user_dn)
+/* 
+    Return a pointer to a malloc'd string with the full path of the 
+    proxy file corresponding to the given delegation_id, or NULL
+    if not found.
+*/
+{
+  int   ret, len;
+  char *filename = NULL, *line, *p, *proxyfile = NULL;
+  DIR *proxyDIR;
+  FILE *fp;  
+  struct dirent *ent;
+  struct stat entstat;
+     
+  if ((proxyDIR = opendir(proxydir)) == NULL) return NULL;
+  len = strlen(delegation_id);
+  if (strlen(user_dn) > len) len = strlen(user_dn);
+  if ((line = malloc(len + 2)) == NULL) return NULL;
+  while ((ent = readdir(proxyDIR)) != NULL)
+       {
+         if (ent->d_name[0] != '.') /* private keys begin with . */
+           {       
+             if (asprintf(&filename, "%s/%s", proxydir, ent->d_name) == -1)
+                                                                      break;
+             if ((stat(filename, &entstat) != 0) 
+                 || !S_ISREG(entstat.st_mode))
+               {
+                 free(filename);
+                 continue;
+               }
+               
+             fp = fopen(filename, "r");
+             if (fp != NULL)
+               {
+                 if (fgets(line, len + 2, fp) != NULL)
+                   {
+                     p = index(line, '\n');
+                     
+                     if (p != NULL)
+                       {
+                         *p = '\0';
+                         if (strcmp(line, delegation_id) == 0)
+                           {
+                             if (fgets(line, len + 2, fp) != NULL)
+                               {
+                                 p = index(line, '\n');
+
+                                 if (p != NULL)
+                                   {
+                                     *p = '\0';
+                           
+                                     if (strcmp(line, user_dn) == 0)
+                                       {                           
+                                         proxyfile = filename;
+                                         fclose(fp);
+                                         break;
+                                       }
+                                   }
+                               }
+                           }
+                       }
+                   }
+               
+                 fclose(fp);
+               }
+               
+             free(filename);
+           }         
+       }
+  
+  closedir(proxyDIR);
+  free(line);
+  return proxyfile;
+}
+
+/// Find a temporary proxy private key file in the proxy cache
+/**
+ *  Returns the full path and file name of the private key file associated
+ *  with given delegation ID and user DN.
+ */
+
+char *GRSTx509CachedProxyKeyFind(char *proxydir, char *delegation_id, 
+                                 char *user_dn)
+/* 
+    Return a pointer to a malloc'd string with the full path of the 
+    private proxy key corresponding to the given delegation_id, or NULL
+    if not found.
+*/
+{
+  int   ret, len;
+  char *filename = NULL, *line, *p, *keyfile = NULL;
+  DIR *proxyDIR;
+  FILE *fp;  
+  struct dirent *ent;
+  struct stat entstat;
+     
+  if ((proxyDIR = opendir(proxydir)) == NULL) return NULL;
+  len = strlen(delegation_id);
+  if (strlen(user_dn) > len) len = strlen(user_dn);
+  if ((line = malloc(len + 2)) == NULL) return NULL;
+  while ((ent = readdir(proxyDIR)) != NULL)
+       {
+         if (ent->d_name[0] == '.') /* private keys begin with . */
+           {       
+             if (asprintf(&filename, "%s/%s", proxydir, ent->d_name) == -1)
+                                                                      break;             
+             if ((stat(filename, &entstat) != 0) 
+                 || !S_ISREG(entstat.st_mode))
+               {
+                 free(filename);
+                 continue;
+               }
+               
+             fp = fopen(filename, "r");
+             if (fp != NULL)
+               {
+                 if (fgets(line, len + 2, fp) != NULL)
+                   {
+                     p = index(line, '\n');
+                     
+                     if (p != NULL)
+                       {
+                         *p = '\0';
+                         if (strcmp(line, delegation_id) == 0)
+                           {
+                             if (fgets(line, len + 2, fp) != NULL)
+                               {
+                                 p = index(line, '\n');
+
+                                 if (p != NULL)
+                                   {
+                                     *p = '\0';
+                           
+                                     if (strcmp(line, user_dn) == 0)
+                                       {                           
+                                         keyfile = filename;
+                                         fclose(fp);
+                                         break;
+                                       }
+                                   }
+                               }
+                           }
+                       }
+                   }
+               
+                 fclose(fp);
+               }
+               
+             free(filename);
+           }         
+       }
+  
+  closedir(proxyDIR);
+  free(line);
+  return keyfile;
+}
+
+/// Make and store a X.509 request for a GSI proxy
+/**
+ *  Returns GRST_RET_OK on success, non-zero otherwise. Request string
+ *  is PEM encoded, and the key is stored in proxydir as temporary file
+ *  with a filename like .XXXXXX
+ */ 
+
+int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir, 
+                             char *delegation_id, char *user_dn)
+{
+  int              i, fd;
+  char            *docroot, *reqfile, *prvkeyfile, *ptr;
+  size_t           ptrlen;
+  FILE            *fp;
+  RSA             *keypair;
+  X509_NAME       *subject;
+  X509_NAME_ENTRY *ent;
+  EVP_PKEY        *pkey;
+  X509_REQ        *certreq;
+  BIO             *reqmem;
+  const EVP_MD          *digest;
+  struct stat      statbuf;
+
+  if ((keypair = RSA_generate_key(GRST_KEYSIZE, 3, NULL, NULL)) == NULL)
+                                                               return 1;
+  asprintf(&prvkeyfile, "%s/.XXXXXX", proxydir);
+          
+  fd = mkstemp(prvkeyfile);
+    
+  if ((fp = fdopen(fd, "w")) == NULL) return 1;
+                               
+  fprintf(fp, "%s\n%s\n", delegation_id, user_dn);
+    
+  if (!PEM_write_RSAPrivateKey(fp, keypair, NULL, NULL, 0, NULL, NULL))
+                               return 1;
+  
+  if (fclose(fp) != 0) return 1;
+  
+  /* now create the certificate request */
+
+  certreq = X509_REQ_new();
+  if (certreq == NULL) return 1;
+
+  OpenSSL_add_all_algorithms();
+
+  pkey = EVP_PKEY_new();
+  EVP_PKEY_assign_RSA(pkey, keypair);
+
+  X509_REQ_set_pubkey(certreq, pkey);
+  
+  subject = X509_NAME_new();
+  ent = X509_NAME_ENTRY_create_by_NID(NULL, OBJ_txt2nid("organizationName"), 
+                                      MBSTRING_ASC, "Dummy", -1);
+  X509_NAME_add_entry (subject, ent, -1, 0);
+  X509_REQ_set_subject_name (certreq, subject);
+  
+  digest = EVP_md5();
+  X509_REQ_sign(certreq, pkey, digest);
+
+  reqmem = BIO_new(BIO_s_mem());
+  PEM_write_bio_X509_REQ(reqmem, certreq);
+  ptrlen = BIO_get_mem_data(reqmem, &ptr);
+  
+  *reqtxt = malloc(ptrlen + 1);
+  memcpy(*reqtxt, ptr, ptrlen);
+  (*reqtxt)[ptrlen] = '\0';
+
+  BIO_free(reqmem);
+
+  X509_REQ_free(certreq);
+  
+  return 0;
+}
+
+/// Store a GSI proxy chain in the proxy cache, along with the private key
+/**
+ *  Returns GRST_RET_OK on success, non-zero otherwise. The existing
+ *  private key with the same delegation ID and user DN is appended to
+ *  make a valid proxy file, and the temporary private key file deleted.
+ */
+
+int GRSTx509CacheProxy(char *proxydir, char *delegation_id, 
+                                       char *user_dn, char *proxychain)
+{
+  int   fd, c, len = 0, i;
+  char *cert, *upcertfile, *prvkeyfile, *p;
+  FILE *ifp, *ofp;
+    
+  prvkeyfile = GRSTx509CachedProxyKeyFind(proxydir, delegation_id, user_dn);
+
+  if (prvkeyfile == NULL)  
+    {
+      free(proxydir);
+      return GRST_RET_FAILED;
+    }
+        
+  if ((ifp = fopen(prvkeyfile, "r")) == NULL) 
+    {
+      free(prvkeyfile);
+      free(proxydir);
+      return GRST_RET_FAILED;
+    }
+
+  if (asprintf(&upcertfile, "%s/XXXXXX", proxydir) == -1) 
+                                                    return GRST_RET_FAILED;
+
+  if ((fd = mkstemp(upcertfile)) == -1)
+    {
+      fclose(ifp);
+      free(prvkeyfile);
+      free(upcertfile);
+      return GRST_RET_FAILED;
+    }
+    
+  if ((ofp = fdopen(fd, "w")) == NULL)
+    {
+      close(fd);
+      fclose(ifp);
+      free(prvkeyfile);
+      free(upcertfile);
+      return GRST_RET_FAILED;
+    }
+
+  fprintf(ofp, "%s\n%s\n", delegation_id, user_dn);
+  fputs(proxychain, ofp); /* write out certificates */
+  
+  while ((c = fgetc(ifp)) != EOF) fputc(c, ofp); /* append proxy private key */
+      
+  if (fclose(ifp) != 0) return GRST_RET_FAILED;
+  if (fclose(ofp) != 0) return GRST_RET_FAILED;
+  
+  unlink(prvkeyfile);
+  
+  free(prvkeyfile);
+  free(upcertfile);
+  
+/* should also check validity of proxy cert to avoid suprises? */
+      
+  return GRST_RET_OK;
+} 
index 8f0ba7f..3275806 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2002-3, Andrew McNab, University of Manchester
+   Copyright (c) 2002-4, Andrew McNab, University of Manchester
    All rights reserved.
 
    Redistribution and use in source and binary forms, with or
@@ -29,9 +29,9 @@
    POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*------------------------------------------------------------------------*
- * For more about GridSite: http://www.gridpp.ac.uk/gridsite/             *
- *------------------------------------------------------------------------*/
+/*---------------------------------------------------------------*
+ * For more about GridSite: http://www.gridsite.org/             *
+ *---------------------------------------------------------------*/
 
 #ifndef VERSION
 #define VERSION "0.0.0"
@@ -85,6 +85,7 @@ struct grst_stream_data { char *source;
                           char *errorbuf;
                           int   noverify;
                           int   anonymous;
+                          long long downgrade;
                           int   verbose;       } ;
                           
 struct grst_index_blob { char   *text;
@@ -97,19 +98,21 @@ struct grst_dir_list { char   *filename;
                        time_t  modified;
                        int     modified_set; } ; 
 
-struct grst_header_data { int    retcode;
+struct grst_header_data { int    retcode;                         
                           char  *location;
+                          char  *gridauthonetime;
                           size_t length;
                           int    length_set;
                           time_t modified;                           
-                          int    modified_set; } ;
+                          int    modified_set;
+                          struct grst_stream_data *common_data; } ;
 
 size_t headers_callback(void *ptr, size_t size, size_t nmemb, void *p)
 /* Find the values of the return code, Content-Length, Last-Modified
    and Location headers */
 {
   float f;
-  char  *s;
+  char  *s, *q;
   size_t realsize;
   struct tm modified_tm;
   struct grst_header_data *header_data;
@@ -124,7 +127,22 @@ size_t headers_callback(void *ptr, size_t size, size_t nmemb, void *p)
             header_data->length_set = 1;
   else if (sscanf(s, "HTTP/%f %d ", &f, &(header_data->retcode)) == 2) ;
   else if (strncmp(s, "Location: ", 10) == 0) 
-                                 header_data->location = strdup(&s[10]);
+      {
+        header_data->location = strdup(&s[10]);
+         
+        if (header_data->common_data->verbose > 0)
+             fprintf(stderr, "Received Location: %s\n", header_data->location);
+      }
+  else if (strncmp(s, "Set-Cookie: GRID_AUTH_ONETIME=", 30) == 0) 
+      {
+        header_data->gridauthonetime = strdup(&s[12]);
+        q = index(header_data->gridauthonetime, ';');
+        if (q != NULL) *q = '\0';       
+
+        if (header_data->common_data->verbose > 0)
+             fprintf(stderr, "Received Grid Auth Cookie: %s\n", 
+                             header_data->gridauthonetime);
+      }
   else if (strncmp(s, "Last-Modified: ", 15) == 0)
       {
         /* follow RFC 2616: first try RFC 822 (kosher), then RFC 850 and 
@@ -196,9 +214,20 @@ int do_copies(char *sources[], char *destination,
   CURL        *easyhandle;
   struct stat  statbuf;
   struct       grst_header_data header_data;
+  struct curl_slist *dgheader_slist = NULL, *nodgheader_slist = NULL;
   
   easyhandle = curl_easy_init();
   
+  if (common_data->downgrade >= (long long) 0)
+    {               
+      asprintf(&p, "HTTP-Downgrade-Size: %lld", common_data->downgrade);      
+      dgheader_slist = curl_slist_append(dgheader_slist, p);
+      free(p);
+      
+      nodgheader_slist = curl_slist_append(nodgheader_slist,
+                                           "HTTP-Downgrade-Size:");
+    }
+  
   curl_easy_setopt(easyhandle, CURLOPT_USERAGENT, common_data->useragent);
   if (common_data->verbose > 1)
                    curl_easy_setopt(easyhandle, CURLOPT_VERBOSE, 1);
@@ -245,6 +274,18 @@ int do_copies(char *sources[], char *destination,
 
            curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, common_data->fp);
            curl_easy_setopt(easyhandle, CURLOPT_URL,       sources[isrc]);
+           
+           if ((common_data->downgrade >= (long long) 0) &&
+               (strncmp(sources[isrc], "https://", 8) == 0))
+             {
+               if (common_data->verbose > 0)
+                 fprintf(stderr, "Add  HTTP-Downgrade-Size: %lld  header\n",
+                         common_data->downgrade);
+                 
+               curl_easy_setopt(easyhandle,CURLOPT_HTTPHEADER,dgheader_slist);
+             }
+           else 
+             curl_easy_setopt(easyhandle,CURLOPT_HTTPHEADER,nodgheader_slist);
          }
        else if (common_data->method == HTCP_PUT)
          {
@@ -270,25 +311,82 @@ int do_copies(char *sources[], char *destination,
            curl_easy_setopt(easyhandle, CURLOPT_URL,        thisdestination);
            curl_easy_setopt(easyhandle, CURLOPT_INFILESIZE, statbuf.st_size);
            curl_easy_setopt(easyhandle, CURLOPT_UPLOAD,   1);
+
+           if (((long long) statbuf.st_size >= common_data->downgrade) &&
+               (strncmp(thisdestination, "https://", 8) == 0))
+               curl_easy_setopt(easyhandle,CURLOPT_HTTPHEADER,dgheader_slist);
+           else 
+             curl_easy_setopt(easyhandle,CURLOPT_HTTPHEADER,nodgheader_slist);
          }
 
-       header_data.retcode = 0;
+       header_data.retcode  = 0;
+       header_data.location = NULL;
+       header_data.gridauthonetime = NULL;
+       header_data.common_data = common_data;
        thiserror = curl_easy_perform(easyhandle);
        
+       fclose(common_data->fp);
+
+       if ((common_data->downgrade >= (long long) 0) &&
+           (thiserror == 0) &&
+           (header_data.retcode == 302) &&
+           (header_data.location != NULL) &&
+           (strncmp(header_data.location, "http://", 7) == 0) &&
+           (header_data.gridauthonetime != NULL))
+         {
+           if (common_data->verbose > 0)
+             fprintf(stderr, "... Found (%d)\nHTTP-Downgrade to %s\n", 
+                     header_data.retcode, header_data.location);
+
+           /* try again with new URL and all the previous CURL options */
+
+           if (common_data->method == HTCP_GET)
+             {
+               common_data->fp = fopen(thisdestination, "w");
+               if (common_data->fp == NULL)
+                 {
+                   fprintf(stderr, "... failed to open destination source "
+                                   "file %s\n", thisdestination);
+                   anyerror = 99;
+                   if (isdirdest) free(thisdestination);
+                   continue;
+                 }
+             }
+           else if (common_data->method == HTCP_PUT)
+             {
+               common_data->fp = fopen(sources[isrc], "r");
+               if (common_data->fp == NULL)
+                 {
+                   fprintf(stderr, "... failed to open source file %s\n",
+                               sources[isrc]);
+                   anyerror = 99;
+                   if (isdirdest) free(thisdestination);
+                   continue;
+                 }
+             }
+
+           header_data.retcode  = 0;           
+           curl_easy_setopt(easyhandle, CURLOPT_URL, header_data.location);
+           curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, nodgheader_slist);
+           curl_easy_setopt(easyhandle, CURLOPT_COOKIE, 
+                                                  header_data.gridauthonetime);
+           thiserror = curl_easy_perform(easyhandle);
+
+           fclose(common_data->fp);
+         }
+
        if ((thiserror != 0) ||
            (header_data.retcode <  200) ||
            (header_data.retcode >= 300))
          {
            fprintf(stderr, "... curl error: %s (%d), HTTP error: %d\n",
                    common_data->errorbuf, thiserror, header_data.retcode);
-           
+                   
            if (thiserror != 0) anyerror = thiserror;
            else                anyerror = header_data.retcode;
          }
        else if (common_data->verbose > 0) 
                   fprintf(stderr, "... OK (%d)\n", header_data.retcode);
-
-       fclose(common_data->fp);
         
        if (isdirdest) free(thisdestination);
      }
@@ -304,6 +402,8 @@ int do_deletes(char *sources[], struct grst_stream_data *common_data)
   CURL  *easyhandle;
   struct grst_header_data header_data;
   
+  header_data.common_data = common_data;
+
   easyhandle = curl_easy_init();
   
   curl_easy_setopt(easyhandle, CURLOPT_USERAGENT, common_data->useragent);
@@ -354,6 +454,8 @@ int do_mkdirs(char *sources[], struct grst_stream_data *common_data)
   CURL  *easyhandle;
   struct grst_header_data header_data;
   
+  header_data.common_data = common_data;
+
   easyhandle = curl_easy_init();
   
   curl_easy_setopt(easyhandle, CURLOPT_USERAGENT, common_data->useragent);
@@ -520,7 +622,8 @@ struct grst_dir_list *index_to_dir_list(char *text, char *source)
                  {
                    allocated += 256;
                    list = (struct grst_dir_list *)
-                             malloc(allocated * sizeof(struct grst_dir_list));
+                           realloc((void *) list,
+                                   allocated * sizeof(struct grst_dir_list));
                  }
                  
                list[used].filename     = NULL;
@@ -631,6 +734,8 @@ int do_listings(char *sources[], struct grst_stream_data *common_data,
 
   time(&now);
 
+  header_data.common_data = common_data;
+
   easyhandle = curl_easy_init();
   
   curl_easy_setopt(easyhandle, CURLOPT_USERAGENT, common_data->useragent);
@@ -671,6 +776,7 @@ int do_listings(char *sources[], struct grst_stream_data *common_data,
            curl_easy_setopt(easyhandle, CURLOPT_NOBODY, 1);
          }
 
+       header_data.gridauthonetime = NULL;
        header_data.length_set   = 0;
        header_data.modified_set = 0;
        header_data.retcode      = 0;
@@ -719,6 +825,7 @@ int do_listings(char *sources[], struct grst_stream_data *common_data,
                         asprintf(&s, "%s%s", sources[isrc], list[i].filename);                        
                         curl_easy_setopt(easyhandle, CURLOPT_URL, s);
 
+                        header_data.gridauthonetime = NULL;
                         header_data.length_set   = 0;
                         header_data.modified_set = 0;
                         header_data.retcode = 0;
@@ -859,7 +966,7 @@ void printsyntax(char *argv0)
 "from remote servers using HTTP or HTTPS, or to put or delete files or\n"
 "directories onto remote servers using HTTPS. htcp is similar to scp(1)\n"
 "but uses HTTP/HTTPS rather than ssh as its transfer protocol.\n"
-"See the htcp(1) or http://www.gridpp.ac.uk/gridsite/ for details.\n"
+"See the htcp(1) or http://www.gridsite.org/ for details.\n"
 "(Version: %s)\n", p, p, VERSION);
 }
 
@@ -870,19 +977,20 @@ int main(int argc, char *argv[])
   struct stat statbuf;
   struct grst_stream_data common_data;
   struct passwd *userpasswd;
-  struct option long_options[] = {     {"verbose",     0, 0, 'v'},
-                                       {"cert",        1, 0, 0},
-                                       {"key",         1, 0, 0},
-                                       {"capath",      1, 0, 0},
-                                       {"delete",      0, 0, 0},
-                                       {"list",        0, 0, 0},
-                                       {"long-list",   0, 0, 0},
-                                       {"mkdir",       0, 0, 0},
-                                       {"no-verify",   0, 0, 0},
-                                       {"anon",        0, 0, 0},
-//                                     {"streams",     1, 0, 0},
-//                                     {"blocksize",   1, 0, 0},
-//                                     {"recursive",   0, 0, 0},
+  struct option long_options[] = {     {"verbose",             0, 0, 'v'},
+                                       {"cert",                1, 0, 0},
+                                       {"key",                 1, 0, 0},
+                                       {"capath",              1, 0, 0},
+                                       {"delete",              0, 0, 0},
+                                       {"list",                0, 0, 0},
+                                       {"long-list",           0, 0, 0},
+                                       {"mkdir",               0, 0, 0},
+                                       {"no-verify",           0, 0, 0},
+                                       {"anon",                0, 0, 0},
+                                       {"downgrade-size",      1, 0, 0},
+//                                     {"streams",             1, 0, 0},
+//                                     {"blocksize",           1, 0, 0},
+//                                     {"recursive",           0, 0, 0},
                                        {0, 0, 0, 0}  };
 
 #if (LIBCURL_VERSION_NUM < 0x070908)
@@ -901,10 +1009,11 @@ int main(int argc, char *argv[])
   common_data.method    = 0;
   common_data.errorbuf  = malloc(CURL_ERROR_SIZE);
   asprintf(&(common_data.useragent),
-           "htcp/%s (http://www.gridpp.ac.uk/gridsite/)", VERSION);
+                          "htcp/%s (http://www.gridsite.org/)", VERSION);
   common_data.verbose   = 0;
   common_data.noverify  = 0;
   common_data.anonymous = 0;
+  common_data.downgrade = (long long) -1;
   
   while (1)
        {
@@ -924,6 +1033,7 @@ int main(int argc, char *argv[])
              else if (option_index == 7) common_data.method    = HTCP_MKDIR;
              else if (option_index == 8) common_data.noverify  = 1;
              else if (option_index == 9) common_data.anonymous = 1;
+             else if (option_index ==10) common_data.downgrade = atoll(optarg);
            }
          else if (c == 'v') ++(common_data.verbose);
        }
diff --git a/org.gridsite.core/src/htproxyput.c b/org.gridsite.core/src/htproxyput.c
new file mode 100644 (file)
index 0000000..834bea2
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+   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.
+*/
+
+/*
+
+Build with:
+
+gcc -lcurl -lssl -lcrypto -o grst-proxy-put grst-proxy-put.c libgridsite.a
+
+http://www.gridpp.ac.uk/authz/gridsite/
+
+*/
+
+#ifndef VERSION
+#define VERSION "0.0.0"
+#endif
+
+#define _GNU_SOURCE
+
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <curl/curl.h>
+#include <curl/types.h>
+#include <curl/easy.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+
+#include <curl/curl.h>
+#include <curl/types.h>
+#include <curl/easy.h>
+
+#include <getopt.h>
+
+#include "gridsite.h"
+
+#include "soapH.h"
+#include "delegation.nsmap"
+
+#define USE_SOAP               0
+#define USE_G_HTTPS            1
+#define HTPROXY_PUT            0
+
+int debugfunction(CURL *curl, curl_infotype type, char *s, size_t n, void *p)
+{
+  fwrite(s, sizeof(char), n, (FILE *) p);
+
+  return 0;
+}
+
+size_t parsegprheaders(void *ptr, size_t size, size_t nmemb, void *p)
+{
+  int   i;
+  
+  if ((size * nmemb > 15) && 
+      (strncmp((char *) ptr, "Delegation-ID: ", 15) == 0))
+    {
+      *((char **) p) = malloc( size * nmemb - 14 );
+      
+      memcpy(*((char **) p), &(((char *) ptr)[15]), size * nmemb - 15);
+  
+      for (i=0; i < size * nmemb - 15; ++i) 
+        if (((*((char **) p))[i] == '\n') || ((*((char **) p))[i] == '\r'))
+          {
+            (*((char **) p))[i] = '\0'; /* drop trailing newline */
+            break;
+          }
+          
+      (*((char **) p))[size * nmemb - 15] = '\0';
+    }
+    
+  return size * nmemb;
+}
+
+struct gprparams { char *req; size_t len; } ;
+
+size_t storegprbody(void *ptr, size_t size, size_t nmemb, void *p)
+{
+  ((struct gprparams *) p)->req = realloc( ((struct gprparams *) p)->req,
+                          ((struct gprparams *) p)->len + size * nmemb + 1);
+
+  memcpy( &((((struct gprparams *) p)->req)[((struct gprparams *) p)->len]),
+           ptr, size * nmemb);
+         
+  ((struct gprparams *) p)->len += size * nmemb;
+
+  return size * nmemb;
+}
+
+int GRSTgetProxyReq(CURL *curl, FILE *debugfp, char *delegid, char **reqtxt, 
+                    char *requrl, char *cert, char *key)
+{
+  char     *delheader;
+  struct    curl_slist *headerlist = NULL;
+  CURLcode  res;
+  struct    gprparams params;
+
+  params.req = NULL;
+  params.len = 0;
+
+  curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &params);
+  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, storegprbody);
+
+  curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE,  "PEM");
+  curl_easy_setopt(curl, CURLOPT_SSLCERT,      cert);
+
+  curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE,   "PEM");
+  curl_easy_setopt(curl, CURLOPT_SSLKEY,       key);    
+  curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, NULL);
+
+//  curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parsegprheaders);
+//  curl_easy_setopt(curl, CURLOPT_WRITEHEADER,    (void *) delegid);
+  
+  curl_easy_setopt(curl, CURLOPT_CAPATH, "/etc/grid-security/certificates/");
+
+  curl_easy_setopt(curl, CURLOPT_URL,           requrl);
+  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET-PROXY-REQ");
+
+  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER,0);
+  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST,0);
+
+  asprintf(&delheader, "Delegation-ID: %s", delegid);
+  headerlist = curl_slist_append(headerlist, delheader);                                                                           
+  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
+
+  if (debugfp != NULL)
+    {
+      curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);       
+      curl_easy_setopt(curl, CURLOPT_DEBUGDATA,     debugfp);
+      curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debugfunction);
+    }
+       
+  res = curl_easy_perform(curl);
+  
+  if (params.req != NULL)
+    {
+      params.req[params.len] = '\0';
+      *reqtxt = params.req;
+    }
+  else *reqtxt = NULL;
+  
+  return (int) res;
+}
+
+struct ppcparams{ char *cert; size_t len; };
+
+size_t getppcbody(void *ptr, size_t size, size_t nmemb, void *p)
+{
+  size_t i;
+  
+  if (((struct ppcparams *) p)->len == 0) return 0;
+  
+  if (size * nmemb < ((struct ppcparams *) p)->len) i = size * nmemb;
+  else                             i = ((struct ppcparams *) p)->len;
+  
+  memcpy(ptr, ((struct ppcparams *) p)->cert, i);
+  
+  ((struct ppcparams *) p)->len -= i;   
+  ((struct ppcparams *) p)->cert = &((((struct ppcparams *) p)->cert)[i+1]);
+     
+  return i;
+}
+
+int GRSTputProxyCerts(CURL *curl, FILE *debugfp, char *delegid, char *certtxt,
+                      char *requrl, char *cert, char *key)
+{
+  CURLcode    res;
+  char       *delheader;
+  long        httpcode;
+  struct curl_slist *headerlist = NULL;
+  struct ppcparams params;
+
+  params.cert = certtxt;
+  params.len  = strlen(certtxt);
+
+  curl_easy_setopt(curl, CURLOPT_READDATA,     &params);
+  curl_easy_setopt(curl, CURLOPT_READFUNCTION, getppcbody);
+  curl_easy_setopt(curl, CURLOPT_INFILESIZE,   strlen(certtxt));
+  curl_easy_setopt(curl, CURLOPT_UPLOAD,       1);
+
+  curl_easy_setopt(curl, CURLOPT_NOBODY,       1);  
+
+  curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE,  "PEM");
+  curl_easy_setopt(curl, CURLOPT_SSLCERT,      cert);
+
+  curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE,   "PEM");
+  curl_easy_setopt(curl, CURLOPT_SSLKEY,       key);    
+//  curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, NULL);
+
+  curl_easy_setopt(curl, CURLOPT_CAPATH, "/etc/grid-security/certificates/");
+
+  curl_easy_setopt(curl, CURLOPT_URL,           requrl);
+  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT-PROXY-CERT");
+
+  headerlist = curl_slist_append(headerlist, 
+                 "Content-Type: application/x-x509-user-cert-chain");
+                                   
+  asprintf(&delheader, "Delegation-ID: %s", delegid);
+  headerlist = curl_slist_append(headerlist, delheader);
+  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
+  
+curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
+
+  if (debugfp != NULL)
+    {
+      curl_easy_setopt(curl, CURLOPT_VERBOSE,       1);       
+      curl_easy_setopt(curl, CURLOPT_DEBUGDATA,     debugfp);
+      curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debugfunction);
+    } 
+     
+  res = curl_easy_perform(curl);
+
+  curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &httpcode);
+  
+  curl_slist_free_all(headerlist);
+
+  free(delheader);
+  
+  return (int) res;
+}
+
+
+#if (LIBCURL_VERSION_NUM < 0x070908)
+char *make_tmp_ca_roots(char *dir)
+/* libcurl before 7.9.8 doesnt support CURLOPT_CAPATH and the directory,
+   so we make a temporary file with the concatenated CA root certs: that
+   is, all the files in that directory which end in .0 */
+{
+  int    ofd, ifd, c;
+  size_t size;
+  char   tmp_ca_roots[] = "/tmp/.ca-roots-XXXXXX", buffer[4096], *s;
+  DIR   *rootsDIR;
+  struct dirent *root_ent;
+
+  if ((rootsDIR = opendir(dir)) == NULL) return NULL;
+
+  if ((ofd = mkstemp(tmp_ca_roots)) == -1)
+    {
+      closedir(rootsDIR);
+      return NULL;
+    }
+
+  while ((root_ent = readdir(rootsDIR)) != NULL)
+       {
+         if ((root_ent->d_name[0] != '.') &&
+             (strlen(root_ent->d_name) > 2) &&
+             (strncmp(&(root_ent->d_name[strlen(root_ent->d_name)-2]),
+                                                        ".0", 2) == 0))
+           {
+             asprintf(&s, "%s/%s", dir, root_ent->d_name);
+             ifd = open(s, O_RDONLY);
+             free(s);
+
+             if (ifd != -1)
+               {
+                 while ((size = read(ifd, buffer, sizeof(buffer))) > 0)
+                                                 write(ofd, buffer, size);
+
+                 close(ifd);
+               }
+           }
+       }
+
+  closedir(rootsDIR);
+
+  if (close(ofd) == 0) return strdup(tmp_ca_roots);
+
+  unlink(tmp_ca_roots); /* try to clean up if errors */
+
+  return NULL;
+}
+#endif
+  
+void printsyntax(char *argv0)
+{
+  char *p;
+
+  p = rindex(argv0, '/');
+  if (p != NULL) ++p;
+  else           p = argv0;
+
+  fprintf(stderr, "%s [options] URL\n"
+          "(Version: %s)\n", p, VERSION);
+}
+  
+int main(int argc, char *argv[])
+{
+  char  *delegation_id = "", *reqtxt, *certtxt, *valid = NULL, 
+        *cert = NULL, *key = NULL, *capath = NULL, *keycert;
+  struct ns__putProxyResponse *unused;
+  int    option_index, c, protocol = USE_SOAP, noverify = 0, 
+         method = HTPROXY_PUT, verbose = 0, fd, minutes;
+  struct soap soap_get, soap_put;
+  FILE   *ifp, *ofp;
+  struct stat statbuf;
+  struct passwd *userpasswd; 
+  struct option long_options[] = {      {"verbose",     0, 0, 'v'},
+                                        {"cert",        1, 0, 0},
+                                        {"key",         1, 0, 0},
+                                        {"capath",      1, 0, 0},
+                                        {"soap",        0, 0, 0},
+                                        {"g-https",     0, 0, 0},
+                                        {"no-verify",   0, 0, 0},
+                                        {"valid",       1, 0, 0},
+                                        {"delegation-id",1, 0, 0},
+                                        {"put",         0, 0, 0},
+                                        {0, 0, 0, 0}  };
+  CURL *curl;
+
+  if (argc == 1)
+    {
+      printsyntax(argv[0]);
+      return 0;
+    }
+
+  while (1)
+       {
+         option_index = 0;
+                                                                                
+         c = getopt_long(argc, argv, "v", long_options, &option_index);
+
+         if      (c == -1) break;
+         else if (c == 0)
+           {
+             if      (option_index == 1) cert      = optarg;
+             else if (option_index == 2) key       = optarg;
+             else if (option_index == 3) capath    = optarg;
+             else if (option_index == 4) protocol  = USE_SOAP;
+             else if (option_index == 5) protocol  = USE_G_HTTPS;
+             else if (option_index == 6) noverify  = 1;
+             else if (option_index == 7) valid     = optarg;
+             else if (option_index == 8) delegation_id = optarg;
+             else if (option_index == 9) method    = HTPROXY_PUT;
+           }
+         else if (c == 'v') ++verbose;
+       }
+
+  if (optind + 1 != argc)
+    {
+      fprintf(stderr, "Must specify a target URL!\n");
+      return 1;
+    }
+    
+  if (valid == NULL) minutes = 60 * 12;
+  else minutes = atoi(valid);
+  
+  if (verbose) fprintf(stderr, "Proxy valid for %d minutes\n", minutes);
+  ERR_load_crypto_strings ();
+  OpenSSL_add_all_algorithms();
+
+  if      ((cert == NULL) && (key != NULL)) cert = key;
+  else if ((cert != NULL) && (key == NULL)) key = cert;
+  else if ((cert == NULL) && (key == NULL))
+    {
+      cert = getenv("X509_USER_PROXY");
+      if (cert != NULL) key = cert;
+      else
+        {
+          asprintf(&(cert), "/tmp/x509up_u%d", geteuid());
+                                                                                
+          /* one fine day, we will check the proxy file for 
+             expiry too to avoid suprises when we try to use it ... */
+
+          if (stat(cert, &statbuf) == 0) key = cert;
+          else
+            {
+              cert = getenv("X509_USER_CERT");
+              key  = getenv("X509_USER_KEY");
+                                                                                
+              userpasswd = getpwuid(geteuid());
+                                                                                
+              if ((cert == NULL) &&
+                  (userpasswd != NULL) &&
+                  (userpasswd->pw_dir != NULL))
+                asprintf(&(cert), "%s/.globus/usercert.pem",
+                                                    userpasswd->pw_dir);
+                                                                                
+              if ((key == NULL) &&
+                  (userpasswd != NULL) &&
+                  (userpasswd->pw_dir != NULL))
+                asprintf(&(key), "%s/.globus/userkey.pem",
+                                                    userpasswd->pw_dir);
+                                                                                
+            }
+        }
+    }
+                                                                                
+  if (capath == NULL) capath = getenv("X509_CERT_DIR");
+  if (capath == NULL) capath = "/etc/grid-security/certificates";
+
+  if (verbose) fprintf(stderr, "key=%s\ncert=%s\ncapath=%s\n",
+                       key, cert, capath);
+
+#if (LIBCURL_VERSION_NUM < 0x070908)
+  /* libcurl before 7.9.8 doesnt support CURLOPT_CAPATH and the directory */
+
+  if ((capath != NULL) &&
+      (stat(capath, &statbuf) == 0) && S_ISDIR(statbuf.st_mode))
+    {
+      tmp_ca_roots = make_tmp_ca_roots(capath);
+      capath = tmp_ca_roots;
+    }
+#endif
+
+  if (protocol == USE_G_HTTPS)
+    {
+      if (verbose) fprintf(stderr, "Using G-HTTPS delegation protocol\n");
+
+      if (verbose) fprintf(stderr, "Delegation-ID: %s\n", delegation_id);
+
+      curl_global_init(CURL_GLOBAL_DEFAULT);   
+      curl = curl_easy_init();
+      
+//  curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, NULL);
+
+      GRSTgetProxyReq(curl, stderr, delegation_id, &reqtxt, 
+                      argv[optind], cert, key);
+  
+      if (GRSTx509MakeProxyCert(&certtxt, stderr, reqtxt, cert, key, minutes)
+          != GRST_RET_OK)     
+        {
+          return 1;
+        }
+
+      GRSTputProxyCerts(curl, stderr, delegation_id, certtxt, 
+                        argv[optind], cert, key);
+
+      curl_easy_cleanup(curl);  
+      curl_global_cleanup();
+  
+      return 0;
+    }
+  else if (protocol == USE_SOAP)
+    {
+      if (strcmp(key, cert) != 0) /* we have to concatenate for gSOAP */
+        {
+          keycert = strdup("/tmp/XXXXXX");
+        
+          fd = mkstemp(keycert);          
+          ofp = fdopen(fd, "w");
+          
+          ifp = fopen(key, "r");          
+          while ((c = fgetc(ifp)) != EOF) fputc(c, ofp);          
+          fclose(ifp);
+          
+          ifp = fopen(cert, "r");          
+          while ((c = fgetc(ifp)) != EOF) fputc(c, ofp);          
+          fclose(ifp);
+          
+          fclose(ofp);       
+          
+          if (verbose) fprintf(stderr, "Created %s key/cert file\n", keycert);            
+        }
+      else keycert = key;
+
+      if (verbose) 
+        {
+          fprintf(stderr, "Using SOAP delegation protocol\n");
+          fprintf(stderr, "Delegation-ID: %s\n", delegation_id);
+          fprintf(stderr, "Send getProxyReq to service\n");
+        }
+
+      soap_init(&soap_get);
+  
+      if (soap_ssl_client_context(&soap_get,
+                                  SOAP_SSL_DEFAULT,
+                                  keycert, 
+                                  "",
+                                  NULL,
+                                  capath,
+                                  NULL))
+        {
+          soap_print_fault(&soap_get, stderr);
+          return 1;
+        } 
+
+      soap_call_ns__getProxyReq(&soap_get, 
+                                argv[optind],  /* HTTPS url of service */
+                                "",            /* no password on proxy */
+                                delegation_id, 
+                                &reqtxt);
+      
+      if (soap_get.error)
+        {
+          soap_print_fault(&soap_get, stderr);
+          return 1;        
+        }
+        
+      if (verbose) fprintf(stderr, "reqtxt:\n%s", reqtxt);
+      
+      if (GRSTx509MakeProxyCert(&certtxt, stderr, reqtxt, cert, key, minutes) 
+          != GRST_RET_OK)
+        {
+          return 1;
+        }
+
+      soap_init(&soap_put);
+  
+      if (verbose) fprintf(stderr, "Send putProxy to service:\n%s\n", certtxt);
+
+      if (soap_ssl_client_context(&soap_put,
+                                  SOAP_SSL_DEFAULT,
+                                  keycert, 
+                                  "",
+                                  NULL,
+                                  capath,
+                                  NULL))
+        {
+          soap_print_fault(&soap_put, stderr);
+          return 1;
+        } 
+
+      soap_call_ns__putProxy(&soap_put, argv[optind], "", delegation_id, 
+                             certtxt, unused);      
+      if (soap_put.error)
+        {
+          soap_print_fault(&soap_put, stderr);
+          return 1;        
+        }
+
+      return 0;
+    }  
+
+  /* weirdness */
+}
+
index 05ae8ff..78d853c 100644 (file)
@@ -29,9 +29,9 @@
    POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*---------------------------------------------------------------------------*
- * This program is part of GridSite: http://www.gridpp.ac.uk/gridsite/       *
- *---------------------------------------------------------------------------*/
+/*------------------------------------------------------------------*
+ * This program is part of GridSite: http://www.gridsite.org/       *
+ *------------------------------------------------------------------*/
 
 #ifndef VERSION
 #define VERSION "x.x.x"
 #include <sys/stat.h>
 #include <fcntl.h>              
 #include <malloc.h>
+#include <stdlib.h>
 #include <string.h>
 #include <dirent.h>
-
+#include <ctype.h>
 #include <time.h>
 
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+
 #include "mod_ssl-private.h"
 
 #include "gridsite.h"
@@ -91,8 +96,257 @@ typedef struct
    char *editable;
    char *headfile;
    char *footfile;
+   int   downgrade;
+   char *authcookiesdir;
+   int   soap2cgi;
 }  mod_gridsite_cfg; /* per-directory config choices */
 
+
+typedef struct
+{
+  xmlDocPtr doc;
+//  char *outbuffer;
+} soap2cgi_ctx; /* store per-request context for Soap2cgi in/out filters */
+
+static const char Soap2cgiFilterName[]="Soap2cgiFilter";
+
+static void mod_gridsite_soap2cgi_insert(request_rec *r)
+{
+    mod_gridsite_cfg *conf;
+    soap2cgi_ctx     *ctx;
+    
+    conf = (mod_gridsite_cfg *) ap_get_module_config(r->per_dir_config,
+                                                      &gridsite_module);
+                                                      
+    if (conf->soap2cgi) 
+      {
+        ctx = (soap2cgi_ctx *) malloc(sizeof(soap2cgi_ctx));        
+        ctx->doc = NULL;
+        
+        ap_add_output_filter(Soap2cgiFilterName, ctx, r, r->connection);
+
+        ap_add_input_filter(Soap2cgiFilterName, NULL, r, r->connection);
+      }
+}
+
+xmlNodePtr find_one_child(xmlNodePtr parent_node, char *name)
+{
+    xmlNodePtr cur;
+
+    for (cur = parent_node->children; cur != NULL; cur = cur->next)
+       {
+         if ((cur->type == XML_ELEMENT_NODE) &&
+             (strcmp(cur->name, name) == 0)) return cur;
+       }
+
+    return NULL;
+}
+
+int add_one_node(xmlDocPtr doc, char *line)
+{
+    char *p, *name, *aftername, *attrname = NULL, *value = NULL;
+    xmlNodePtr cur, cur_child;
+
+    cur = xmlDocGetRootElement(doc);
+
+    p = index(line, '=');
+    if (p == NULL) return 1;
+
+    *p = '\0';
+    value = &p[1];
+
+    name = line;
+
+    while (1) /* go through each .-deliminated segment of line[] */
+         {
+           if ((p = index(name, '.')) != NULL)
+             {
+               *p = '\0';
+               aftername = &p[1];
+             }
+           else aftername = &name[strlen(name)];
+
+           if ((p = index(name, '_')) != NULL)
+             {
+               *p = '\0';
+               attrname = &p[1];
+             }
+
+           cur_child = find_one_child(cur, name);
+
+           if (cur_child == NULL)
+                    cur_child = xmlNewChild(cur, NULL, name, NULL);
+
+           cur = cur_child;
+
+           name = aftername;
+
+           if (attrname != NULL)
+             {
+               xmlSetProp(cur, attrname, value);
+               return 0;
+             }
+
+           if (*name == '\0')
+             {
+               xmlNodeSetContent(cur, value);
+               return 0;
+             }             
+         }
+}
+
+static apr_status_t mod_gridsite_soap2cgi_out(ap_filter_t *f,
+                                              apr_bucket_brigade *bbIn)
+{
+    char        *p, *name, *outbuffer;
+    request_rec *r = f->r;
+    conn_rec    *c = r->connection;
+    apr_bucket         *bucketIn, *pbktEOS;
+    apr_bucket_brigade *bbOut;
+
+    const char *data;
+    apr_size_t len;
+    char *buf;
+    apr_size_t n;
+    apr_bucket *pbktOut;
+
+    soap2cgi_ctx *ctx;
+    xmlNodePtr   root_node = NULL;
+    xmlBufferPtr buff;
+
+    ctx = (soap2cgi_ctx *) f->ctx;
+
+// LIBXML_TEST_VERSION;
+
+    bbOut = apr_brigade_create(r->pool, c->bucket_alloc);
+
+    if (ctx->doc == NULL)
+      {
+        ctx->doc = xmlNewDoc("1.0");
+             
+        root_node = xmlNewNode(NULL, "Envelope");
+        xmlDocSetRootElement(ctx->doc, root_node);
+                                                                                
+        xmlNewChild(root_node, NULL, "Header", NULL);
+        xmlNewChild(root_node, NULL, "Body",   NULL);
+      }
+    
+    apr_brigade_pflatten(bbIn, &outbuffer, &len, r->pool);
+       
+    /* split up buffer and feed each line to add_one_node() */
+    
+    name = outbuffer;
+    
+    while (*name != '\0')
+         {
+           p = index(name, '\n');
+           if (p != NULL) 
+             {
+               *p = '\0';
+               ++p;             
+             }
+           else p = &name[strlen(name)]; /* point to final NUL */
+           
+           add_one_node(ctx->doc, name);
+           
+           name = p;
+         }
+
+    APR_BRIGADE_FOREACH(bucketIn, bbIn)
+       {
+         if (APR_BUCKET_IS_EOS(bucketIn))
+           {
+             /* write out XML tree we have built */
+
+             buff = xmlBufferCreate();
+             xmlNodeDump(buff, ctx->doc, root_node, 0, 0);
+
+// TODO: simplify/reduce number of copies or libxml vs APR buffers?
+
+             buf = (char *) xmlBufferContent(buff);
+
+             pbktOut = apr_bucket_heap_create(buf, strlen(buf), NULL, 
+                                              c->bucket_alloc);
+
+             APR_BRIGADE_INSERT_TAIL(bbOut, pbktOut);
+       
+             xmlBufferFree(buff);
+
+             pbktEOS = apr_bucket_eos_create(c->bucket_alloc);
+             APR_BRIGADE_INSERT_TAIL(bbOut, pbktEOS);
+
+             continue;
+           }
+       }
+       
+    return ap_pass_brigade(f->next, bbOut);
+}
+
+static apr_status_t mod_gridsite_soap2cgi_in(ap_filter_t *f,
+                                             apr_bucket_brigade *pbbOut,
+                                             ap_input_mode_t eMode,
+                                             apr_read_type_e eBlock,
+                                             apr_off_t nBytes)
+{
+    request_rec *r = f->r;
+    conn_rec *c = r->connection;
+//    CaseFilterInContext *pCtx;
+    apr_status_t ret;
+
+#ifdef NEVERDEFINED
+
+    ret = ap_get_brigade(f->next, pCtx->pbbTmp, eMode, eBlock, nBytes);    
+    if (!(pCtx = f->ctx)) {
+        f->ctx = pCtx = apr_palloc(r->pool, sizeof *pCtx);
+        pCtx->pbbTmp = apr_brigade_create(r->pool, c->bucket_alloc);
+    }
+    if (APR_BRIGADE_EMPTY(pCtx->pbbTmp)) {
+        ret = ap_get_brigade(f->next, pCtx->pbbTmp, eMode, eBlock, nBytes);
+        if (eMode == AP_MODE_EATCRLF || ret != APR_SUCCESS)
+            return ret;
+    }
+    while(!APR_BRIGADE_EMPTY(pCtx->pbbTmp)) {
+        apr_bucket *pbktIn = APR_BRIGADE_FIRST(pCtx->pbbTmp);
+        apr_bucket *pbktOut;
+        const char *data;
+        apr_size_t len;
+        char *buf;
+        int n;
+        /* It is tempting to do this...
+         * APR_BUCKET_REMOVE(pB);
+         * APR_BRIGADE_INSERT_TAIL(pbbOut,pB);
+         * and change the case of the bucket data, but that would be wrong
+         * for a file or socket buffer, for example...
+         */
+                                                                                
+        if(APR_BUCKET_IS_EOS(pbktIn)) {
+            APR_BUCKET_REMOVE(pbktIn);
+            APR_BRIGADE_INSERT_TAIL(pbbOut, pbktIn);
+            break;
+        }
+                                                                                
+        ret=apr_bucket_read(pbktIn, &data, &len, eBlock);
+        if(ret != APR_SUCCESS)
+            return ret;
+                                                                                
+        buf = malloc(len);
+        for(n=0 ; n < len ; ++n)
+            buf[n] = apr_toupper(data[n]);
+                                                                                
+        pbktOut = apr_bucket_heap_create(buf, len, 0, c->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(pbbOut, pbktOut);
+        apr_bucket_delete(pbktIn);
+    }
+#endif
+                                                                                
+    return APR_SUCCESS;
+}
+
 char *make_admin_footer(request_rec *r, mod_gridsite_cfg *conf,
                         int isdirectory)
 /*
@@ -236,7 +490,7 @@ char *make_admin_footer(request_rec *r, mod_gridsite_cfg *conf,
     if (conf->gridsitelink)
       {
         temp = apr_psprintf(r->pool,
-           ". Built with <a href=\"http://www.gridpp.ac.uk/gridsite/\">"
+           ". Built with <a href=\"http://www.gridsite.org/\">"
            "GridSite</a>&nbsp;%s\n", VERSION);
         out = apr_pstrcat(r->pool, out, temp, NULL);
       }
@@ -511,10 +765,11 @@ int html_dir_list(request_rec *r, mod_gridsite_cfg *conf)
                               
                if (S_ISDIR(statbuf.st_mode))
                     temp = apr_psprintf(r->pool, 
-                      "<tr><td><a href=\"%s/\" "
-                      "last-modified=\"%ld\">%s/</a></td>"
+                      "<tr><td><a href=\"%s/\" content-length=\"%ld\" "
+                      "last-modified=\"%ld\">"
+                      "%s/</a></td>"
                       "<td align=right>%ld</td>%s</tr>\n", 
-                      namelist[n]->d_name, statbuf.st_mtime,
+                      namelist[n]->d_name, statbuf.st_size, statbuf.st_mtime,
                       namelist[n]->d_name, 
                       statbuf.st_size, modified);
                else temp = apr_psprintf(r->pool, 
@@ -604,6 +859,81 @@ int html_dir_list(request_rec *r, mod_gridsite_cfg *conf)
     return OK;
 }
 
+int http_downgrade(request_rec *r, mod_gridsite_cfg *conf)
+{ 
+    int          i;
+    char        *httpurl, *filetemplate, *cookievalue, *envname_i, 
+                *grst_cred_i, expires_str[APR_RFC822_DATE_LEN];
+    apr_uint64_t gridauthcookie;
+    apr_table_t *env;
+    apr_time_t   expires_time;
+    apr_file_t  *fp;
+
+    /* create random cookie and gridauthcookie file */
+
+    if (apr_generate_random_bytes((char *) &gridauthcookie, 
+                                  sizeof(gridauthcookie))
+         != APR_SUCCESS) return HTTP_INTERNAL_SERVER_ERROR;
+    
+    filetemplate = apr_psprintf(r->pool, "%s/%016llxXXXXXX", 
+                                ap_server_root_relative(r->pool,
+                                                        conf->authcookiesdir),
+                                gridauthcookie);
+                                    
+    if (apr_file_mktemp(&fp, 
+                        filetemplate, 
+                        APR_CREATE | APR_WRITE | APR_EXCL,
+                        r->pool)
+                      != APR_SUCCESS) return HTTP_INTERNAL_SERVER_ERROR;
+
+    expires_time = apr_time_now() + apr_time_from_sec(300); 
+    /* onetime cookies are valid for only 5 mins! */
+
+    apr_file_printf(fp, "expires=%lu\ndomain=%s\npath=%s\nonetime=yes\n", 
+                   (time_t) apr_time_sec(expires_time), r->hostname, r->uri);
+
+    for (i=0; ; ++i)
+       {
+         envname_i = apr_psprintf(r->pool, "GRST_CRED_%d", i);
+         if (grst_cred_i = (char *)
+                           apr_table_get(r->connection->notes, envname_i))
+           {
+             apr_file_printf(fp, "%s=%s\n", envname_i, grst_cred_i);
+           }
+         else break; /* GRST_CRED_i are numbered consecutively */
+       }
+
+    if (apr_file_close(fp) != APR_SUCCESS) 
+      {
+        apr_file_remove(filetemplate, r->pool); /* try to clean up */
+        return HTTP_INTERNAL_SERVER_ERROR;
+      }
+    
+    /* send redirection header back to client */
+       
+    cookievalue = rindex(filetemplate, '/');
+    if (cookievalue != NULL) ++cookievalue;
+    else cookievalue = filetemplate;
+       
+    apr_rfc822_date(expires_str, expires_time);
+
+    apr_table_add(r->headers_out, 
+                  apr_pstrdup(r->pool, "Set-Cookie"), 
+                  apr_psprintf(r->pool, 
+                  "GRID_AUTH_ONETIME=%s; "
+                  "expires=%s; "
+                  "domain=%s; "
+                  "path=%s",
+                  cookievalue, expires_str, r->hostname, r->uri));
+    
+    httpurl = apr_pstrcat(r->pool, "http://", r->hostname,
+                        ap_escape_uri(r->pool, r->uri), NULL);
+    apr_table_setn(r->headers_out, apr_pstrdup(r->pool, "Location"), httpurl);
+
+    r->status = HTTP_MOVED_TEMPORARILY;  
+    return OK;
+}
+
 int http_put_method(request_rec *r, mod_gridsite_cfg *conf)
 {
   char        buf[2048];
@@ -630,7 +960,7 @@ int http_put_method(request_rec *r, mod_gridsite_cfg *conf)
   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
+// TODO: need to add Range: support at some point too
 
   retcode = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
   if (retcode == OK)
@@ -697,10 +1027,26 @@ static int mod_gridsite_nondir_handler(request_rec *r, mod_gridsite_cfg *conf)
    and GET inside ghost directories.
 */
 {
-    /* *** is this a write method? only possible if  GridSiteAuth on *** */
+    char      *downgradesize;
+    apr_off_t  numericsize;
+
+    /* *** is this a write method or HTTP downgrade? 
+           only possible if  GridSiteAuth on *** */
     
     if (conf->auth)
       {
+        if ((conf->downgrade) &&
+            ((downgradesize = (char *) apr_table_get(r->headers_in, 
+                                       "HTTP-Downgrade-Size")) != NULL) &&
+            ((numericsize = (apr_off_t) atoll(downgradesize)) >= 0) &&
+
+// TODO: what if we're pointing at a CGI or some dynamic content???
+            (((r->method_number == M_GET) && (r->finfo.size >= numericsize))
+             || (r->method_number == M_PUT)) &&
+
+            (strcasecmp(apr_table_get(r->subprocess_env, "HTTPS"), "on") == 0))
+            return http_downgrade(r, conf);
+      
         if ((r->method_number == M_PUT) && 
             (conf->methods != NULL) &&
             (strstr(conf->methods, " PUT "   ) != NULL))
@@ -1113,6 +1459,11 @@ static void *create_gridsite_dir_config(apr_pool_t *p, char *path)
         conf->headfile = apr_pstrdup(p, GRST_HEADFILE);
         conf->footfile = apr_pstrdup(p, GRST_FOOTFILE); 
                /* GridSiteHeadFile and GridSiteFootFile  file name */
+
+        conf->downgrade     = 0;     /* GridSiteDowngrade     on/off       */
+        conf->authcookiesdir = apr_pstrdup(p, "gridauthcookies");
+                                     /* GridSiteAuthCookiesDir dir-path     */
+        conf->soap2cgi      = 0;     /* GridSiteSoap2cgi      on/off       */
       }
     else
       {
@@ -1132,8 +1483,11 @@ static void *create_gridsite_dir_config(apr_pool_t *p, char *path)
         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 */
+        conf->headfile      = NULL;  /* GridSiteHeadFile      file name    */
+        conf->footfile      = NULL;  /* GridSiteFootFile      file name    */
+        conf->downgrade     = UNSET; /* GridSiteDowngrade     on/off       */
+        conf->authcookiesdir= NULL;  /* GridSiteAuthCookiesDir dir-path    */
+        conf->soap2cgi      = UNSET; /* GridSiteSoap2cgi      on/off       */
       }
       
     return conf;
@@ -1204,6 +1558,16 @@ static void *merge_gridsite_dir_config(apr_pool_t *p, void *vserver,
     if (direct->footfile != NULL) conf->footfile = direct->footfile;
     else                          conf->footfile = server->footfile;
         
+    if (direct->downgrade != UNSET) conf->downgrade = direct->downgrade;
+    else                            conf->downgrade = server->downgrade;
+        
+    if (direct->authcookiesdir != NULL)
+                                conf->authcookiesdir = direct->authcookiesdir;
+    else                        conf->authcookiesdir = server->authcookiesdir;
+        
+    if (direct->soap2cgi != UNSET) conf->soap2cgi = direct->soap2cgi;
+    else                           conf->soap2cgi = server->soap2cgi;
+        
     return conf;
 }
 
@@ -1307,6 +1671,14 @@ static const char *mod_gridsite_take1_cmds(cmd_parms *a, void *cfg,
       ((mod_gridsite_cfg *) cfg)->indexheader =
         apr_pstrdup(a->pool, parm);
     }
+    else if (strcasecmp(a->cmd->name, "GridSiteAuthCookiesDir") == 0)
+    {
+      if (index(parm, '/') != NULL) 
+           return "/ not permitted in GridSiteAuthCookiesDir";
+
+      ((mod_gridsite_cfg *) cfg)->authcookiesdir =
+        apr_pstrdup(a->pool, parm);
+    }
         
     return NULL;
 }
@@ -1334,12 +1706,24 @@ static const char *mod_gridsite_flag_cmds(cmd_parms *a, void *cfg,
     {
       ((mod_gridsite_cfg *) cfg)->gridsitelink = flag;
     }
+    else if (strcasecmp(a->cmd->name, "GridSiteDowngrade") == 0)
+    {
+// TODO: return error if try this on non-HTTPS virtual server
+
+      ((mod_gridsite_cfg *) cfg)->downgrade = flag;
+    }
+    else if (strcasecmp(a->cmd->name, "GridSiteSoap2cgi") == 0)
+    {
+      ((mod_gridsite_cfg *) cfg)->soap2cgi = flag;
+    }
 
     return NULL;
 }
 
 static const command_rec mod_gridsite_cmds[] =
 {
+// TODO: need to check and document valid contexts for each command!
+
     AP_INIT_FLAG("GridSiteAuth", mod_gridsite_flag_cmds, 
                  NULL, OR_FILEINFO, "on or off"),
     AP_INIT_FLAG("GridSiteEnvs", mod_gridsite_flag_cmds, 
@@ -1379,6 +1763,13 @@ static const command_rec mod_gridsite_cmds[] =
     AP_INIT_TAKE1("GridSiteIndexHeader", mod_gridsite_take1_cmds,
                    NULL, OR_FILEINFO, "filename of directory header"),
     
+    AP_INIT_FLAG("GridSiteDowngrade", mod_gridsite_flag_cmds, 
+                 NULL, OR_FILEINFO, "on or off"),
+    AP_INIT_TAKE1("GridSiteAuthCookiesDir", mod_gridsite_take1_cmds,
+                 NULL, OR_FILEINFO, "directory with Grid Auth Cookies"),
+
+    AP_INIT_FLAG("GridSiteSoap2cgi", mod_gridsite_flag_cmds,
+                 NULL, OR_FILEINFO, "on or off"),
     {NULL}
 };
 
@@ -1391,6 +1782,9 @@ static int mod_gridsite_first_fixups(request_rec *r)
     conf = (mod_gridsite_cfg *)
                     ap_get_module_config(r->per_dir_config, &gridsite_module);
 
+    /* we handle DN Lists as regular files, even if they also match
+       directory names  */
+
     if ((conf != NULL) &&
         (conf->dnlistsuri != NULL) &&
         (strncmp(r->uri, conf->dnlistsuri, strlen(conf->dnlistsuri)) == 0) &&
@@ -1412,10 +1806,13 @@ static int mod_gridsite_perm_handler(request_rec *r)
 {
     int          retcode = DECLINED, i, n;
     char        *dn, *p, envname[14], *grst_cred_0 = NULL, *dir_path, 
-                *remotehost, s[99], *grst_cred_i, *file;
+                *remotehost, s[99], *grst_cred_i, *file, *cookies,
+                *gridauthonetime, *cookiefile, oneline[1025], *key_i;
     const char  *content_type;
     time_t       now, notbefore, notafter;
     apr_table_t *env;
+    apr_finfo_t  cookiefile_info;
+    apr_file_t  *fp;
     GRSTgaclCred    *cred = NULL, *cred_0 = NULL;
     GRSTgaclUser    *user = NULL;
     GRSTgaclPerm     perm = GRST_PERM_NONE;
@@ -1430,13 +1827,104 @@ static int mod_gridsite_perm_handler(request_rec *r)
     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 ((p = (char *) apr_table_get(r->headers_in, "Cookie")) != NULL)
+      {
+        cookies = apr_pstrcat(r->pool, " ", p, NULL);
+        gridauthonetime = strstr(cookies, " GRID_AUTH_ONETIME=");
+                
+        if (gridauthonetime != NULL)
+          {
+            for (p = &gridauthonetime[19]; (*p != '\0') && (*p != ';'); ++p)
+                                                if (!isalnum(*p)) *p = '_';
+        
+            cookiefile = apr_psprintf(r->pool, "%s/%s",
+                                      ap_server_root_relative(r->pool, 
+                                                   cfg->authcookiesdir),
+                                      &gridauthonetime[19]);
+                                      
+            if ((apr_stat(&cookiefile_info , cookiefile, 
+                          APR_FINFO_TYPE, r->pool) == APR_SUCCESS) &&
+                (cookiefile_info.filetype == APR_REG) &&
+                (apr_file_open(&fp, cookiefile, APR_READ, 0, r->pool)
+                                                         == APR_SUCCESS))
+              {
+                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                             "Open Grid Auth Cookie file %s", cookiefile);
+              
+                while (apr_file_gets(oneline, 
+                                     sizeof(oneline), fp) == APR_SUCCESS)
+                     {
+                       p = index(oneline, '\n');
+                       if (p != NULL) *p = '\0';
+                       
+                       ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                                    "%s: %s", cookiefile, oneline);
+
+                       if ((strncmp(oneline, "expires=", 8) == 0) &&
+                           (apr_time_from_sec(atoll(&oneline[8])) < 
+                                                       apr_time_now()))
+                                  break;                
+                       else if ((strncmp(oneline, "domain=", 7) == 0) &&
+                                (strcmp(&oneline[7], r->hostname) != 0))
+                                  break; /* exact needed in the version */
+                       else if ((strncmp(oneline, "path=", 5) == 0) &&
+                                (strcmp(&oneline[5], r->uri) != 0))
+                                  break;
+                       else if  (strncmp(oneline, "onetime=yes", 11) == 0)
+                                  apr_file_remove(cookiefile, r->pool);
+                       else if  (strncmp(oneline, "GRST_CRED_", 10) == 0)
+                           {
+                             grst_cred_i = index(oneline, '=');
+                             if (grst_cred_i == NULL) continue;       
+                             *grst_cred_i = '\0';
+                             ++grst_cred_i;
+
+                             i = atoi(&oneline[10]);
+                             cred = GRSTx509CompactToCred(grst_cred_i);
+                             
+                             if (cred == NULL) continue;
+
+                             if ((i == 0) && (user == NULL))
+                               {           
+                                 if (GRSTgaclCredGetDelegation(cred) 
+                                   <= ((mod_gridsite_cfg *) cfg)->gsiproxylimit)
+                                   {
+                                     user = GRSTgaclUserNew(cred);
+                                   
+                                     ap_log_error(APLOG_MARK, APLOG_DEBUG, 
+                                                  0, r->server,
+                                                  "Using identity %s from "
+                                                  "GRID_AUTH_ONETIME", 
+                                                  grst_cred_i);
+
+                                     if (((mod_gridsite_cfg *) cfg)->envs)
+                                      apr_table_setn(env, oneline, grst_cred_i);
+                                   }
+                               }
+                             else if ((i > 0) && (user != NULL))
+                               {
+                                 GRSTgaclUserAddCred(user, cred);
+                                     
+                                 if (((mod_gridsite_cfg *) cfg)->envs)
+                                       apr_table_set(env,oneline,grst_cred_i);
+                               }                             
+                           }
+                     }
+
+                apr_file_close(fp);
+              }            
+          }
+      }
+    
+    /* do we need/have per-connection (SSL) cred variable(s)? */
 
-    if (grst_cred_0 != NULL) /* do we have per-connection cred variable(s)? */
+    if ((user == NULL) && 
+        (r->connection->notes != NULL) &&
+        ((grst_cred_0 = (char *) 
+            apr_table_get(r->connection->notes, "GRST_CRED_0")) != NULL))
       {
         if (((mod_gridsite_cfg *) cfg)->envs)
                             apr_table_setn(env, "GRST_CRED_0", grst_cred_0);
@@ -1446,6 +1934,9 @@ static int mod_gridsite_perm_handler(request_rec *r)
             (GRSTgaclCredGetDelegation(cred_0) 
                          <= ((mod_gridsite_cfg *) cfg)->gsiproxylimit))
           {
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                         "Using identity %s from SSL/TLS", grst_cred_0);
+
             user = GRSTgaclUserNew(cred_0);
 
             /* check for VOMS GRST_CRED_i too */
@@ -1830,6 +2321,19 @@ static int mod_gridsite_handler(request_rec *r)
 
 static void register_hooks(apr_pool_t *p)
 {
+    /* set up the Soap2cgi input and output filters */
+
+    ap_hook_insert_filter(mod_gridsite_soap2cgi_insert, NULL, NULL,
+                          APR_HOOK_MIDDLE);
+
+    ap_register_output_filter(Soap2cgiFilterName, mod_gridsite_soap2cgi_out,
+                              NULL, AP_FTYPE_RESOURCE);
+
+//    ap_register_input_filter(Soap2cgiFilterName, mod_gridsite_soap2cgi_in,
+//                              NULL, AP_FTYPE_RESOURCE);
+
+    /* config and handler stuff */
+
     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);
@@ -1838,7 +2342,7 @@ static void register_hooks(apr_pool_t *p)
     
     ap_hook_fixups(mod_gridsite_perm_handler,NULL,NULL,APR_HOOK_REALLY_LAST);
     
-    ap_hook_handler(mod_gridsite_handler, NULL, NULL, APR_HOOK_FIRST);
+    ap_hook_handler(mod_gridsite_handler, NULL, NULL, APR_HOOK_FIRST);    
 }
 
 module AP_MODULE_DECLARE_DATA gridsite_module =
index bcf759a..2a60edf 100644 (file)
@@ -49,9 +49,9 @@
  * limitations under the License.
  */
 
-/*---------------------------------------------------------------------------*
- * This program is part of GridSite: http://www.gridpp.ac.uk/gridsite/       *
- *---------------------------------------------------------------------------*/
+/*------------------------------------------------------------------*
+ * This program is part of GridSite: http://www.gridsite.org/       *
+ *------------------------------------------------------------------*/
 
 
 /*
diff --git a/org.gridsite.core/src/proxyput-example.c b/org.gridsite.core/src/proxyput-example.c
new file mode 100644 (file)
index 0000000..f0fe834
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+   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.
+*/
+
+/* 
+    Change the hard-coded defaults below to your set up. 
+*/
+
+#define LOCALPROXY     "/tmp/x509up"
+#define DELEGATIONURL  "https://testing.hep.man.ac.uk/gridsite-delegation.cgi"
+#define CAPATH         "/etc/grid-security/certificates"
+#define DELEGATIONID    "1234567890"
+#define EXPIREMINUTES  60 
+  
+#ifndef VERSION
+#define VERSION "0.0.0"
+#endif
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+
+#include "gridsite.h"
+
+#include "soapH.h"
+#include "delegation.nsmap"
+
+int main(int argc, char *argv[])
+{
+  char *reqtxt, *certtxt;
+  struct ns__putProxyResponse *unused;
+  struct soap soap_get, soap_put;
+  ERR_load_crypto_strings ();
+  OpenSSL_add_all_algorithms();
+
+  soap_init(&soap_get);
+  
+  if (soap_ssl_client_context(&soap_get,
+                                  SOAP_SSL_DEFAULT,
+                                  LOCALPROXY, 
+                                  "",
+                                  NULL,
+                                  CAPATH,
+                                  NULL))
+        {
+          soap_print_fault(&soap_get, stderr);
+          return 1;
+        } 
+
+  soap_call_ns__getProxyReq(&soap_get, 
+                                DELEGATIONURL, /* HTTPS url of service */
+                                "",            /* no password on proxy */
+                                DELEGATIONID, 
+                                &reqtxt);
+      
+  if (soap_get.error)
+    {
+          soap_print_fault(&soap_get, stderr);
+          return 1;        
+    }
+        
+  if (GRSTx509MakeProxyCert(&certtxt, stderr, reqtxt, 
+                            LOCALPROXY, LOCALPROXY, EXPIREMINUTES) 
+          != GRST_RET_OK)
+    {
+          return 1;
+    }
+
+  soap_init(&soap_put);
+  
+  if (soap_ssl_client_context(&soap_put,
+                                  SOAP_SSL_DEFAULT,
+                                  LOCALPROXY, 
+                                  "",
+                                  NULL,
+                                  CAPATH,
+                                  NULL))
+        {
+          soap_print_fault(&soap_put, stderr);
+          return 1;
+        } 
+
+  soap_call_ns__putProxy(&soap_put, DELEGATIONURL, "", DELEGATIONID, 
+                             certtxt, unused);      
+  if (soap_put.error)
+    {
+          soap_print_fault(&soap_put, stderr);
+          return 1;        
+    }
+
+  return 0;
+}
+
index 8890689..bea36a9 100644 (file)
@@ -29,9 +29,9 @@
    POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*------------------------------------------------------------------------*
- * For more about GridSite: http://www.gridpp.ac.uk/gridsite/             *
- *------------------------------------------------------------------------*/
+/*---------------------------------------------------------------*
+ * For more about GridSite: http://www.gridsite.org/             *
+ *---------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <string.h>