From: Andrew McNab Date: Thu, 29 Sep 2005 19:34:30 +0000 (+0000) Subject: SiteCast in mod_gridsite X-Git-Tag: gridsite-core_R_1_1_12~73 X-Git-Url: http://scientific.zcu.cz/git/?a=commitdiff_plain;h=b40822b55eb984db1b941cd2417497e0cacf9c52;p=jra1mw.git SiteCast in mod_gridsite --- diff --git a/org.gridsite.core/CHANGES b/org.gridsite.core/CHANGES index e68d642..beef484 100644 --- a/org.gridsite.core/CHANGES +++ b/org.gridsite.core/CHANGES @@ -1,3 +1,11 @@ +* Thu Sep 29 2005 Andrew McNab +- Add SiteCast support to mod_gridsite (file location + discovery via UDP multicast of HTCP messages.) +* Wed Sep 21 2005 Andrew McNab +- Add ports 777 and 488 to example httpd.conf files in + docs. See http://www.gridsite.org/wiki/IP_Ports +* Tue Sep 13 2005 Andrew McNab +- ==== GridSite version 1.1.12 ==== * Tue Sep 13 2005 Andrew McNab - Fix bug #10031 submitted by Fabrizio Pacini (invalid free in diff --git a/org.gridsite.core/VERSION b/org.gridsite.core/VERSION index 2e3c1a3..9429197 100644 --- a/org.gridsite.core/VERSION +++ b/org.gridsite.core/VERSION @@ -1,4 +1,4 @@ MAJOR_VERSION=1 MINOR_VERSION=1.1 -PATCH_VERSION=1.1.11 +PATCH_VERSION=1.1.12 VERSION=$(PATCH_VERSION) diff --git a/org.gridsite.core/doc/httpd-fileserver.conf b/org.gridsite.core/doc/httpd-fileserver.conf index eddad08..a14a559 100644 --- a/org.gridsite.core/doc/httpd-fileserver.conf +++ b/org.gridsite.core/doc/httpd-fileserver.conf @@ -1,10 +1,14 @@ ############################################################################## ## GridSite httpd-fileserver.conf - Andrew McNab ## -## Example configuration file for GridSite as an HTTP(S) fileserver. -## ## For GridSite documentation, see http://www.gridsite.org/ ## +## Example configuration file for GridSite as an HTTP(S) fileserver, +## listening on ports 80/777 (HTTP) and 443/488 (HTTPS) +## +## (777/488 is to allow firewalls to distinguish between Grid and +## Web HTTP(S) traffic. See http://www.gridsite.org/wiki/IP_Ports ) +## ## This file should be renamed /etc/httpd/conf/httpd.conf and Apache ## restarted to use Apache2/GridSite as a simple HTTP(S) fileserver. ## @@ -67,6 +71,7 @@ ## ## (or with --cert /tmp/x509up_u`id -u` --key /tmp/x509up_u`id -u` to use ## a Globus GSI Proxy created with grid-proxy-init.) +## ############################################################################## ServerRoot "/etc/httpd" @@ -105,11 +110,12 @@ ErrorLog logs/httpd-gridsite-errors HostnameLookups On ###################################################################### -# Plain unauthenticated HTTP on port 80 +# Plain unauthenticated HTTP on ports 80 and 777 ###################################################################### Listen 80 - +Listen 777 + GridSiteIndexes on @@ -120,13 +126,14 @@ Listen 80 ###################################################################### -# Secured and possibly authenticated HTTPS on port 443 +# Secured and possibly authenticated HTTPS on ports 443 and 488 ###################################################################### Listen 443 +Listen 488 SSLSessionCacheTimeout 300 SSLSessionCache dbm:/var/cache/mod_ssl/scache # This version of GridSite is NOT compatible with the SHM SSL cache!!! - + SSLEngine on SSLCertificateFile /etc/grid-security/hostcert.pem diff --git a/org.gridsite.core/doc/httpd-webserver.conf b/org.gridsite.core/doc/httpd-webserver.conf index 57adb5d..59b7487 100644 --- a/org.gridsite.core/doc/httpd-webserver.conf +++ b/org.gridsite.core/doc/httpd-webserver.conf @@ -1,10 +1,14 @@ ############################################################################## ## GridSite httpd-webserver.conf - Andrew McNab ## +## For GridSite documentation, see http://www.gridsite.org/ +## ## Example configuration file for GridSite as a Web Server ## (that is, primarily for interactive use with a browser.) +## Listening is on ports 80/777 (HTTP) and 443/488 (HTTPS). ## -## For GridSite documentation, see http://www.gridsite.org/ +## (777/488 is to allow firewalls to distinguish between Grid and +## Web HTTP(S) traffic. See http://www.gridsite.org/wiki/IP_Ports ) ## ## This file should be renamed /etc/httpd/conf/httpd.conf and Apache ## restarted to use Apache2/GridSite as a webserver. @@ -113,11 +117,12 @@ ErrorLog logs/httpd-gridsite-errors HostnameLookups On ###################################################################### -# Plain unauthenticated HTTP on port 80 +# Plain unauthenticated HTTP on ports 80 and 777 ###################################################################### Listen 80 - +Listen 777 + ## This is used to serve the Manage Directory links in footers, ## and to allow you to edit files and ACLs via your browser. @@ -150,13 +155,14 @@ ScriptAlias /real-gridsite-admin.cgi /usr/sbin/real-gridsite-admin.cgi ###################################################################### -# Secured and possibly authenticated HTTPS on port 443 +# Secured and possibly authenticated HTTPS on ports 443 and 488 ###################################################################### Listen 443 +Listen 488 SSLSessionCacheTimeout 300 SSLSessionCache dbm:/var/cache/mod_ssl/scache # This version of GridSite is NOT compatible with the SHM SSL cache!!! - + SSLEngine on SSLCertificateFile /etc/grid-security/hostcert.pem diff --git a/org.gridsite.core/interface/gridsite.h b/org.gridsite.core/interface/gridsite.h index e252019..9e6b302 100644 --- a/org.gridsite.core/interface/gridsite.h +++ b/org.gridsite.core/interface/gridsite.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2002-3, Andrew McNab, University of Manchester + Copyright (c) 2002-5, Andrew McNab, University of Manchester All rights reserved. Redistribution and use in source and binary forms, with or @@ -124,6 +124,39 @@ struct GRSTasn1TagList { char treecoords[GRST_ASN1_MAXCOORDLEN+1]; int length; int tag; } ; +#define GRST_HTTP_PORT 777 +#define GRST_HTTPS_PORT 488 +#define GRST_HTCP_PORT 777 + +#define GRSThtcpNOPop 0 +#define GRSThtcpTSTop 1 + +typedef struct { unsigned char length_msb; + unsigned char length_lsb; + char text[1]; } GRSThtcpCountstr; + +#define GRSThtcpCountstrLen(string) (256*((string)->length_msb) + (string)->length_lsb) + +typedef struct { unsigned char total_length_msb; + unsigned char total_length_lsb; + unsigned char version_msb; + unsigned char version_lsb; + unsigned char data_length_msb; + unsigned char data_length_lsb; + unsigned int response : 4; + unsigned int opcode : 4; + unsigned int rr : 1; + unsigned int f1 : 1; + unsigned int reserved : 6; + unsigned int trans_id; /* must be 4 bytes */ + GRSThtcpCountstr *method; + GRSThtcpCountstr *uri; + GRSThtcpCountstr *version; + GRSThtcpCountstr *req_hdrs; + GRSThtcpCountstr *resp_hdrs; + GRSThtcpCountstr *entity_hdrs; + GRSThtcpCountstr *cache_hdrs; } GRSThtcpMessage; + int GRSTgaclInit(void); /* #define GACLnewCred(x) GRSTgaclCredNew((x)) */ @@ -285,3 +318,9 @@ int GRSTasn1ParseDump(BIO *, unsigned char *, long, struct GRSTasn1TagList taglist[], int, int *); int GRSTasn1GetX509Name(char *, int, char *, char *, struct GRSTasn1TagList taglist[], int); + +int GRSThtcpNOPrequestMake(char **, int *, unsigned int); +int GRSThtcpNOPresponseMake(char **, int *, unsigned int); +int GRSThtcpTSTrequestMake(char **, int *, unsigned int, char *, char *, char *); +int GRSThtcpTSTresponseMake(char **, int *, unsigned int, char *, char *, char *); +int GRSThtcpMessageParse(GRSThtcpMessage *, char *, int); diff --git a/org.gridsite.core/project/version.properties b/org.gridsite.core/project/version.properties index 87511c8..6c6d643 100644 --- a/org.gridsite.core/project/version.properties +++ b/org.gridsite.core/project/version.properties @@ -1,2 +1,2 @@ -module.version=1.1.11 +module.version=1.1.12 module.age=1 diff --git a/org.gridsite.core/src/Makefile b/org.gridsite.core/src/Makefile index 381def9..5eeac2e 100644 --- a/org.gridsite.core/src/Makefile +++ b/org.gridsite.core/src/Makefile @@ -64,40 +64,44 @@ build: libgridsite_globus.so.$(VERSION) libgridsite_globus.a # First, normal versions using system OpenSSL rather than Globus OpenSSL -libgridsite.so.$(VERSION): grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o +libgridsite.so.$(VERSION): grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o grst_htcp.o gcc -shared -Wl,-soname,libgridsite.so.$(MINOR_VERSION) \ - -o libgridsite.so.$(PATCH_VERSION) grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o + -o libgridsite.so.$(PATCH_VERSION) grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o grst_htcp.o -libgridsite.a: grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o - ar src libgridsite.a grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o +libgridsite.a: grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o grst_htcp.o + ar src libgridsite.a grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o grst_htcp.o grst_x509.o: grst_x509.c ../interface/gridsite.h - gcc $(MYCFLAGS) \ + gcc -g $(MYCFLAGS) \ -I/usr/kerberos/include -c grst_x509.c grst_gacl.o: grst_gacl.c ../interface/gridsite.h - gcc $(MYCFLAGS) \ + gcc -g $(MYCFLAGS) \ -I/usr/kerberos/include `xml2-config --cflags` -c grst_gacl.c grst_xacml.o: grst_xacml.c ../interface/gridsite.h - gcc $(MYCFLAGS) \ + gcc -g $(MYCFLAGS) \ -I/usr/kerberos/include `xml2-config --cflags` -c grst_xacml.c grst_http.o: grst_http.c ../interface/gridsite.h - gcc $(MYCFLAGS) \ + gcc -g $(MYCFLAGS) \ -I/usr/kerberos/include -c grst_http.c grst_asn1.o: grst_asn1.c ../interface/gridsite.h - gcc $(MYCFLAGS) \ + gcc -g $(MYCFLAGS) \ -I/usr/kerberos/include -c grst_asn1.c +grst_htcp.o: grst_htcp.c ../interface/gridsite.h + gcc -g $(MYCFLAGS) \ + -I/usr/kerberos/include -c grst_htcp.c + # Then build versions using Globus OpenSSL if configured ifdef OPENSSL_GLOBUS_LIBS libgridsite_globus.so.$(VERSION): \ grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o \ - grst_asn1_globus.o grst_xacml_globus.o + grst_asn1_globus.o grst_xacml_globus.o grst_htcp_globus.o gcc -shared -Wl,-soname,libgridsite_globus.so.$(MINOR_VERSION) \ -o libgridsite_globus.so.$(PATCH_VERSION) \ grst_x509_globus.o grst_gacl_globus.o grst_xacml_globus.o grst_http_globus.o grst_asn1_globus.o @@ -107,30 +111,35 @@ libgridsite_globus.a: grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o g grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o grst_asn1_globus.o grst_x509_globus.o: grst_x509.c ../interface/gridsite.h - gcc $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ + gcc -g $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ -I/usr/kerberos/include -c grst_x509.c \ -o grst_x509_globus.o grst_gacl_globus.o: grst_gacl.c ../interface/gridsite.h - gcc $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ + gcc -g $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ -I/usr/kerberos/include `xml2-config --cflags` -c grst_gacl.c \ -o grst_gacl_globus.o grst_xacml_globus.o: grst_xacml.c ../interface/gridsite.h - gcc $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ + gcc -g $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ -I/usr/kerberos/include `xml2-config --cflags` -c grst_xacml.c \ -o grst_xacml_globus.o grst_http_globus.o: grst_http.c ../interface/gridsite.h - gcc $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ + gcc -g $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ -I/usr/kerberos/include -c grst_http.c \ -o grst_http_globus.o grst_asn1_globus.o: grst_asn1.c ../interface/gridsite.h - gcc $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ + gcc -g $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ -I/usr/kerberos/include -c grst_asn1.c \ -o grst_asn1_globus.o +grst_htcp_globus.o: grst_htcp.c ../interface/gridsite.h + gcc -g $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ + -I/usr/kerberos/include -c grst_htcp.c \ + -o grst_htcp_globus.o + else libgridsite_globus.so.$(VERSION): libgridsite.so.$(VERSION) @@ -142,21 +151,21 @@ libgridsite_globus.a: libgridsite.a endif gsexec: gsexec.c gsexec.h - gcc -DVERSION=\"$(PATCH_VERSION)\" -I/usr/include/httpd \ + gcc -g -DVERSION=\"$(PATCH_VERSION)\" -I/usr/include/httpd \ -I/usr/include/apr-0 \ -o gsexec gsexec.c urlencode: urlencode.c libgridsite.a - gcc -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \ + gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \ -o urlencode urlencode.c -L. \ -I/usr/kerberos/include -lgridsite htcp: htcp.c - gcc -DVERSION=\"$(PATCH_VERSION)\" -I. -o htcp htcp.c \ + gcc -g -DVERSION=\"$(PATCH_VERSION)\" -I. -o htcp htcp.c \ `curl-config --cflags` `curl-config --libs` mod_gridsite.so: mod_gridsite.c mod_ssl-private.h libgridsite.a - gcc $(MYCFLAGS) -shared -Wl,-soname=gridsite_module \ + gcc -g $(MYCFLAGS) -shared -Wl,-soname=gridsite_module \ -I/usr/kerberos/include \ -I/usr/include/libxml2 \ -DVERSION=\"$(VERSION)\" -o mod_gridsite.so \ @@ -164,7 +173,7 @@ mod_gridsite.so: mod_gridsite.c mod_ssl-private.h libgridsite.a real-gridsite-admin.cgi: grst_admin_main.c grst_admin_gacl.c \ grst_admin_file.c grst_admin.h - gcc $(MYCFLAGS) $(MYLDFLAGS) -o real-gridsite-admin.cgi \ + gcc -g $(MYCFLAGS) $(MYLDFLAGS) -o real-gridsite-admin.cgi \ grst_admin_main.c \ grst_admin_gacl.c \ grst_admin_file.c \ @@ -172,13 +181,13 @@ real-gridsite-admin.cgi: grst_admin_main.c grst_admin_gacl.c \ -DVERSION=\"$(VERSION)\" -lgridsite -lssl -lcrypto -lxml2 -lz -lm findproxyfile: findproxyfile.c libgridsite.a - gcc -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) $(MYLDFLAGS) \ + gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) $(MYLDFLAGS) \ -o findproxyfile findproxyfile.c -L. \ -I/usr/kerberos/include -lgridsite \ -lssl -lcrypto -lxml2 -lz -lm showx509exts: showx509exts.c libgridsite.a - gcc -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) $(MYLDFLAGS) \ + gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) $(MYLDFLAGS) \ -o showx509exts showx509exts.c -L. \ -I/usr/kerberos/include \ -lgridsite \ @@ -188,12 +197,12 @@ apidoc: doxygen Doxyfile gaclexample: gaclexample.c libgridsite.a - gcc -o gaclexample gaclexample.c -I. -L. \ + gcc -g -o gaclexample gaclexample.c -I. -L. \ -I/usr/kerberos/include -lgridsite \ -lssl -lcrypto -lxml2 -lz -lm xacmlexample: xacmlexample.c libgridsite.a - gcc -o xacmlexample xacmlexample.c -I. -L. \ + gcc -g -o xacmlexample xacmlexample.c -I. -L. \ -I/usr/kerberos/include -lgridsite \ -lssl -lcrypto -lxml2 -lz -lm @@ -212,12 +221,12 @@ delegation.wsdl: delegation.h $(GSOAPDIR)/bin/soapcpp2 -c delegation.h libstdsoap2.a: $(GSOAPDIR)/stdsoap2.c - gcc -c -DWITH_OPENSSL $(GSOAPDIR)/stdsoap2.c + gcc -g -c -DWITH_OPENSSL $(GSOAPDIR)/stdsoap2.c ar src libstdsoap2.a stdsoap2.o gridsite-delegation.cgi: grst-delegation.c delegation.h delegation.wsdl \ soapC.c soapServer.c - gcc $(MYCFLAGS) $(MYLDFLAGS) -o gridsite-delegation.cgi \ + gcc -g $(MYCFLAGS) $(MYLDFLAGS) -o gridsite-delegation.cgi \ grst-delegation.c \ -I/usr/kerberos/include -I$(GSOAPDIR)/include \ -DVERSION=\"$(VERSION)\" -L$(GSOAPDIR)/lib \ @@ -226,7 +235,7 @@ gridsite-delegation.cgi: grst-delegation.c delegation.h delegation.wsdl \ htproxyput: htproxyput.c delegation.h delegation.wsdl \ soapC.c soapServer.c - gcc $(MYCFLAGS) $(MYLDFLAGS) -o htproxyput \ + gcc -g $(MYCFLAGS) $(MYLDFLAGS) -o htproxyput \ htproxyput.c \ -I/usr/kerberos/include \ -g -DVERSION=\"$(VERSION)\" \ @@ -236,7 +245,7 @@ htproxyput: htproxyput.c delegation.h delegation.wsdl \ proxyput-example: proxyput-example.c delegation.h delegation.wsdl \ soapC.c soapServer.c - gcc $(MYCFLAGS) $(MYLDFLAGS) -o proxyput-example \ + gcc -g $(MYCFLAGS) $(MYLDFLAGS) -o proxyput-example \ proxyput-example.c \ -I/usr/kerberos/include \ -g -DVERSION=\"$(VERSION)\" \ diff --git a/org.gridsite.core/src/grst_htcp.c b/org.gridsite.core/src/grst_htcp.c new file mode 100644 index 0000000..55a32e6 --- /dev/null +++ b/org.gridsite.core/src/grst_htcp.c @@ -0,0 +1,307 @@ +/* + Copyright (c) 2002-5, 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 "x.x.x" +#endif + +#define _GNU_SOURCE +#include + +#include +#include +#include +#include +#include + +#include "gridsite.h" + +int GRSThtcpNOPrequestMake(char **request, int *request_length, + unsigned int trans_id) +/* + Make a complete HTCP NOP request and return a pointer to malloc'd + memory pointing to it. +*/ +{ + *request_length = + asprintf(request,"%c%c" /* place holder for total length */ + "%c%c" /* HTCP version 0.0 */ + "%c%c" /* DATA length place holder */ + "%c%c" /* OPCODE,RESPONSE,RESERVED,F1,RR */ + "%c%c%c%c" /* TRANS-ID placeholder */ + "%c%c", /* AUTH (LENGTH=2 means no AUTH) */ + 0, 0, + 0, 0, + 0, 0, + GRSThtcpNOPop * 16, 2, + 0, 0, 0, 0, + 0, 2); + + if (*request_length < 0) return GRST_RET_FAILED; + + (*request)[0] = *request_length / 256; + (*request)[1] = *request_length % 256; + + (*request)[4] = (*request_length - 6) / 256; + (*request)[5] = (*request_length - 6) % 256; + + memcpy(&((*request)[8]), &trans_id, 4); + + return GRST_RET_OK; +} + +int GRSThtcpNOPresponseMake(char **message, int *message_length, + unsigned int trans_id) +/* + Make a complete HTCP NOP response for a found file and return a pointer + to malloc'd memory pointing to it. +*/ +{ + *message_length = + asprintf(message, + "%c%c" /* place holder for total length */ + "%c%c" /* HTCP version 0.0 */ + "%c%c" /* DATA length place holder */ + "%c%c" /* OPCODE,RESPONSE,RESERVED,F1,RR */ + "%c%c%c%c" /* TRANS-ID place holder */ + "%c%c", /* AUTH (LENGTH=2 means no AUTH) */ + 0, 0, + 0, 0, + 0, 0, + GRSThtcpNOPop * 16, 1, /* RR=1, MO=0, RESPONSE=0 (ie found) */ + 0, 0, 0, 0, + 0, 2); + + if (*message_length < 0) return GRST_RET_FAILED; + + (*message)[0] = *message_length / 256; + (*message)[1] = *message_length % 256; + + (*message)[4] = (*message_length - 6) / 256; + (*message)[5] = (*message_length - 6) % 256; + + memcpy(&((*message)[8]), &trans_id, 4); + + return GRST_RET_OK; +} + +int GRSThtcpTSTrequestMake(char **request, int *request_length, + unsigned int trans_id, + char *method, char *uri, char *req_hdrs) +/* + Make a complete HTCP TST request and return a pointer to malloc'd + memory pointing to it. +*/ +{ + if ((method == NULL) || (uri == NULL) || (req_hdrs == NULL)) + return GRST_RET_FAILED; + + *request_length = + asprintf(request,"%c%c" /* place holder for total length */ + "%c%c" /* HTCP version 0.0 */ + "%c%c" /* DATA length place holder */ + "%c%c" /* OPCODE,RESPONSE,RESERVED,F1,RR */ + "%c%c%c%c" /* TRANS-ID placeholder */ + "%c%c%s" /* OP-DATA: METHOD */ + "%c%c%s" /* OP-DATA: URI */ + "%c%c%s" /* OP-DATA: VERSION */ + "%c%c%s" /* OP-DATA: REQ-HDRS */ + "%c%c", /* AUTH (LENGTH=2 means no AUTH) */ + 0, 0, + 0, 0, + 0, 0, + GRSThtcpTSTop * 16, 2, + 0, 0, 0, 0, + strlen(method) / 256, strlen(method) % 256, method, + strlen(uri) / 256, strlen(uri) % 256, uri, + 0, 8, "HTTP/1.1", + strlen(req_hdrs)/256, strlen(req_hdrs) % 256, req_hdrs, + 0, 2); + + if (*request_length < 0) return GRST_RET_FAILED; + + (*request)[0] = *request_length / 256; + (*request)[1] = *request_length % 256; + + (*request)[4] = (*request_length - 6) / 256; + (*request)[5] = (*request_length - 6) % 256; + + memcpy(&((*request)[8]), &trans_id, 4); + + return GRST_RET_OK; +} + +int GRSThtcpTSTresponseMake(char **message, int *message_length, + unsigned int trans_id, + char *resp_hdrs, char *entity_hdrs, + char *cache_hdrs) +/* + Make a complete HTCP TST response for a found file and return a pointer + to malloc'd memory pointing to it. +*/ +{ + if ((resp_hdrs != NULL) && (entity_hdrs != NULL) && (cache_hdrs != NULL)) + /* found file response */ + *message_length = + asprintf(message, + "%c%c" /* place holder for total length */ + "%c%c" /* HTCP version 0.0 */ + "%c%c" /* DATA length place holder */ + "%c%c" /* OPCODE,RESPONSE,RESERVED,F1,RR */ + "%c%c%c%c" /* TRANS-ID place holder */ + "%c%c%s" /* OP-DATA: RESP-HDRS */ + "%c%c%s" /* OP-DATA: ENTITY-HDRS */ + "%c%c%s" /* OP-DATA: CACHE-HDRS */ + "%c%c", /* AUTH (LENGTH=2 means no AUTH) */ + 0, 0, + 0, 0, + 0, 0, + GRSThtcpTSTop * 16, 1, /* RR=1, MO=0, RESPONSE=0 (ie found) */ + 0, 0, 0, 0, + strlen(resp_hdrs) / 256, strlen(resp_hdrs) % 256, resp_hdrs, + strlen(entity_hdrs) / 256, strlen(entity_hdrs) % 256, entity_hdrs, + strlen(cache_hdrs) / 256, strlen(cache_hdrs) % 256, cache_hdrs, + 0, 2); + else if (cache_hdrs != NULL) + /* not found file response, just cache_hdrs given */ + *message_length = + asprintf(message, + "%c%c" /* place holder for total length */ + "%c%c" /* HTCP version 0.0 */ + "%c%c" /* DATA length place holder */ + "%c%c" /* OPCODE,RESPONSE,RESERVED,F1,RR */ + "%c%c%c%c" /* TRANS-ID */ + "%c%c%s" /* OP-DATA: CACHE-HDRS */ + "%c%c", /* AUTH (LENGTH=2 means no AUTH) */ + 0, 0, + 0, 0, + 0, 0, + GRSThtcpTSTop * 16 + 1, 1, /* RR=1, MO=0, RESPONSE=1 (missing) */ + 0, 0, 0, 0, + strlen(cache_hdrs) / 256, strlen(cache_hdrs) % 256, cache_hdrs, + 0, 2); + else return GRST_RET_FAILED; + + if (*message_length < 0) return GRST_RET_FAILED; + + (*message)[0] = *message_length / 256; + (*message)[1] = *message_length % 256; + + (*message)[4] = (*message_length - 6) / 256; + (*message)[5] = (*message_length - 6) % 256; + + memcpy(&((*message)[8]), &trans_id, 4); + + return GRST_RET_OK; +} + +int GRSThtcpMessageParse(GRSThtcpMessage *parsed, char *raw, int length) +{ + GRSThtcpCountstr *s; + + bzero(parsed, sizeof(GRSThtcpMessage)); + + if (length < (void *) &(parsed->method) + - (void *) &(parsed->total_length_msb) + 2) + return GRST_RET_FAILED; + + memcpy(parsed, raw, (void *) &(parsed->method) + - (void *) &(parsed->total_length_msb)); + + if (parsed->opcode == GRSThtcpNOPop) return GRST_RET_OK; + + if ((parsed->opcode == GRSThtcpTSTop) && (parsed->rr == 0)) + { + /* point to start of data/auth in raw */ + s = (GRSThtcpCountstr *) &(((GRSThtcpMessage *) raw)->method); + + /* METHOD string */ + + if ((void *) s + 2 + GRSThtcpCountstrLen(s) > (void *) raw + length) + return GRST_RET_FAILED; + parsed->method = s; + s = (GRSThtcpCountstr *) ((void *) s + 2 + GRSThtcpCountstrLen(s)); + + /* URI string */ + + if ((void *) s + 2 + GRSThtcpCountstrLen(s) > (void *) raw + length) + return GRST_RET_FAILED; + parsed->uri = s; + s = (GRSThtcpCountstr *) ((void *) s + 2 + GRSThtcpCountstrLen(s)); + + /* VERSION string */ + + if ((void *) s + 2 + GRSThtcpCountstrLen(s) > (void *) raw + length) + return GRST_RET_FAILED; + parsed->version = s; + s = (GRSThtcpCountstr *) ((void *) s + 2 + GRSThtcpCountstrLen(s)); + + /* REQ-HDRS string */ + + if ((void *) s + 2 + GRSThtcpCountstrLen(s) > (void *) raw + length) + return GRST_RET_FAILED; + parsed->req_hdrs = s; + s = (GRSThtcpCountstr *) ((void *) s + 2 + GRSThtcpCountstrLen(s)); + + return GRST_RET_OK; + } + + if ((parsed->opcode == GRSThtcpTSTop) && (parsed->rr == 1)) + { + /* point to start of data/auth in raw */ + s = (GRSThtcpCountstr *) &(((GRSThtcpMessage *) raw)->method); + + /* RESP-HDRS string */ + + if ((void *) s + 2 + GRSThtcpCountstrLen(s) > (void *) raw + length) + return GRST_RET_FAILED; + parsed->resp_hdrs = s; + s = (GRSThtcpCountstr *) ((void *) s + 2 + GRSThtcpCountstrLen(s)); + + /* ENTITY-HDRS string */ + + if ((void *) s + 2 + GRSThtcpCountstrLen(s) > (void *) raw + length) + return GRST_RET_FAILED; + parsed->entity_hdrs = s; + s = (GRSThtcpCountstr *) ((void *) s + 2 + GRSThtcpCountstrLen(s)); + + /* CACHE-HDRS string */ + + if ((void *) s + 2 + GRSThtcpCountstrLen(s) > (void *) raw + length) + return GRST_RET_FAILED; + parsed->cache_hdrs = s; + s = (GRSThtcpCountstr *) ((void *) s + 2 + GRSThtcpCountstrLen(s)); + + return GRST_RET_OK; + } + + return GRST_RET_FAILED; +} diff --git a/org.gridsite.core/src/htcp b/org.gridsite.core/src/htcp index a71a2c5..96935f7 100644 Binary files a/org.gridsite.core/src/htcp and b/org.gridsite.core/src/htcp differ diff --git a/org.gridsite.core/src/mod_gridsite.c b/org.gridsite.core/src/mod_gridsite.c index b81d7b2..a64d155 100644 --- a/org.gridsite.core/src/mod_gridsite.c +++ b/org.gridsite.core/src/mod_gridsite.c @@ -42,6 +42,7 @@ #endif #include +#include #include #include @@ -56,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +65,11 @@ #include #include +#include +#include +#include +#include + #include #include @@ -77,10 +84,24 @@ module AP_MODULE_DECLARE_DATA gridsite_module; -typedef struct -{ - char *onetimesdir; -} mod_gridsite_srv_cfg; /* per-server config choices */ +#define GRST_SITECAST_GROUPS 32 + +struct sitecast_group + { int socket; int quad1; int quad2; int quad3; int quad4; int port; }; + +#define GRST_SITECAST_ALIASES 32 + +struct sitecast_alias + { const char *sitecast_url; const char *local_path; server_rec *server; }; + +/* Globals, defined by main server directives in httpd.conf + These are assigned default values in create_gridsite_srv_config() */ + +int gridhttpport = 0; +char *onetimesdir = NULL; +char *sitecastdnlists = NULL; +struct sitecast_group sitecastgroups[GRST_SITECAST_GROUPS+1]; +struct sitecast_alias sitecastaliases[GRST_SITECAST_ALIASES]; typedef struct { @@ -890,9 +911,7 @@ int http_gridhttp(request_rec *r, mod_gridsite_dir_cfg *conf) filetemplate = apr_psprintf(r->pool, "%s/%016llxXXXXXX", ap_server_root_relative(r->pool, - ((mod_gridsite_srv_cfg *) - ap_get_module_config(r->server->module_config, - &gridsite_module))->onetimesdir), + onetimesdir), gridauthcookie); if (apr_file_mktemp(&fp, @@ -946,9 +965,13 @@ int http_gridhttp(request_rec *r, mod_gridsite_dir_cfg *conf) "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); + + if (gridhttpport != DEFAULT_HTTP_PORT) + httpurl = apr_psprintf(r->pool, "http://%s:%d%s", r->hostname, + gridhttpport, ap_escape_uri(r->pool, r->uri)); + else 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; @@ -1495,24 +1518,37 @@ static int mod_gridsite_dnlistsuri_handler(request_rec *r, static void *create_gridsite_srv_config(apr_pool_t *p, server_rec *s) { - mod_gridsite_srv_cfg *srv_conf = apr_palloc(p, sizeof(*srv_conf)); + int i; - srv_conf->onetimesdir = apr_pstrdup(p, "/var/www/onetimes"); - /* GridSiteOnetimesDir dir-path */ - return srv_conf; -} + if (!(s->is_virtual)) + { + gridhttpport = GRST_HTTP_PORT; + + onetimesdir = apr_pstrdup(p, "/var/www/onetimes"); + /* GridSiteOnetimesDir dir-path */ -static void *merge_gridsite_srv_config(apr_pool_t *p, void *srvroot, - void *vhost) -/* merge virtual host with server-wide configs */ -{ - mod_gridsite_srv_cfg *conf;; + sitecastdnlists = NULL; - conf = apr_palloc(p, sizeof(*conf)); + sitecastgroups[0].quad1 = 0; + sitecastgroups[0].quad2 = 0; + sitecastgroups[0].quad3 = 0; + sitecastgroups[0].quad4 = 0; + sitecastgroups[0].port = GRST_HTCP_PORT; + /* GridSiteCastUniPort udp-port */ - conf->onetimesdir = ((mod_gridsite_srv_cfg *) srvroot)->onetimesdir; - - return conf; + for (i=1; i <= GRST_SITECAST_GROUPS; ++i) + sitecastgroups[i].port = 0; + /* GridSiteCastGroup mcast-list */ + + for (i=1; i <= GRST_SITECAST_ALIASES; ++i) + { + sitecastaliases[i].sitecast_url = NULL; + sitecastaliases[i].local_path = NULL; + sitecastaliases[i].server = NULL; + } /* GridSiteCastAlias url path */ + } + + return NULL; } static void *create_gridsite_dir_config(apr_pool_t *p, char *path) @@ -1547,7 +1583,7 @@ static void *create_gridsite_dir_config(apr_pool_t *p, char *path) conf->footfile = apr_pstrdup(p, GRST_FOOTFILE); /* GridSiteHeadFile and GridSiteFootFile file name */ - conf->gridhttp = 0; /* GridSiteGridHTTP on/off */ + conf->gridhttp = 0; /* GridSiteGridHTTP on/off */ conf->soap2cgi = 0; /* GridSiteSoap2cgi on/off */ conf->aclformat = apr_pstrdup(p, "GACL"); /* GridSiteACLFormat gacl/xacml */ @@ -1690,18 +1726,60 @@ static void *merge_gridsite_dir_config(apr_pool_t *p, void *vserver, static const char *mod_gridsite_take1_cmds(cmd_parms *a, void *cfg, const char *parm) { - int n; + int n, i; char *p; - mod_gridsite_srv_cfg *srv_cfg = - (mod_gridsite_srv_cfg *) ap_get_module_config(a->server->module_config, - &gridsite_module); if (strcasecmp(a->cmd->name, "GridSiteOnetimesDir") == 0) { if (a->server->is_virtual) return "GridSiteOnetimesDir cannot be used inside a virtual server"; - srv_cfg->onetimesdir = apr_pstrdup(a->pool, parm); + onetimesdir = apr_pstrdup(a->pool, parm); + } + else if (strcasecmp(a->cmd->name, "GridSiteGridHTTPport") == 0) + { + gridhttpport = atoi(parm); + } + else if (strcasecmp(a->cmd->name, "GridSiteCastDNlists") == 0) + { + if (a->server->is_virtual) + return "GridSiteDNlists cannot be used inside a virtual server"; + + sitecastdnlists = apr_pstrdup(a->pool, parm); + } + else if (strcasecmp(a->cmd->name, "GridSiteCastUniPort") == 0) + { + if (a->server->is_virtual) + return "GridSiteCastUniPort cannot be used inside a virtual server"; + + if (sscanf(parm, "%d", &(sitecastgroups[0].port)) != 1) + return "Failed parsing GridSiteCastUniPort numeric value"; + } + else if (strcasecmp(a->cmd->name, "GridSiteCastGroup") == 0) + { + if (a->server->is_virtual) + return "GridSiteCastGroup cannot be used inside a virtual server"; + + for (i=1; i <= GRST_SITECAST_GROUPS; ++i) + { + if (sitecastgroups[i].port == 0) /* a free slot */ + { + sitecastgroups[i].port = GRST_HTCP_PORT; + + if (sscanf(parm, "%d.%d.%d.%d:%d", + &(sitecastgroups[i].quad1), + &(sitecastgroups[i].quad2), + &(sitecastgroups[i].quad3), + &(sitecastgroups[i].quad4), + &(sitecastgroups[i].port)) < 4) + return "Failed parsing GridSiteCastGroup nnn.nnn.nnn.nnn[:port]"; + + break; + } + } + + if (i > GRST_SITECAST_GROUPS) + return "Maximum GridSiteCastGroup groups reached"; } else if (strcasecmp(a->cmd->name, "GridSiteAdminFile") == 0) { @@ -1827,6 +1905,8 @@ static const char *mod_gridsite_take1_cmds(cmd_parms *a, void *cfg, static const char *mod_gridsite_take2_cmds(cmd_parms *a, void *cfg, const char *parm1, const char *parm2) { + int i; + if (strcasecmp(a->cmd->name, "GridSiteUserGroup") == 0) { if (!(unixd_config.suexec_enabled)) @@ -1859,6 +1939,27 @@ static const char *mod_gridsite_take2_cmds(cmd_parms *a, void *cfg, | ((APR_GREAD | APR_GWRITE) * (strcasecmp(parm1, "GroupWrite") == 0)) | ((APR_GREAD | APR_WREAD) * (strcasecmp(parm2, "WorldRead") == 0)); } + else if (strcasecmp(a->cmd->name, "GridSiteCastAlias") == 0) + { + for (i=0; i < GRST_SITECAST_ALIASES; ++i) /* look for free slot */ + { + if ( +// srv_cfg-> + sitecastaliases[i].sitecast_url == NULL) + { +/* + srv_cfg->sitecastaliases[i].sitecast_url = parm1; + srv_cfg->sitecastaliases[i].local_path = parm2; + srv_cfg->sitecastaliases[i].server = a->server; +*/ + sitecastaliases[i].sitecast_url = parm1; + sitecastaliases[i].local_path = parm2; + sitecastaliases[i].server = a->server; + + break; + } + } + } return NULL; } @@ -1945,9 +2046,20 @@ static const command_rec mod_gridsite_cmds[] = AP_INIT_FLAG("GridSiteGridHTTP", mod_gridsite_flag_cmds, NULL, OR_FILEINFO, "on or off"), + AP_INIT_TAKE1("GridSiteGridHTTPport", mod_gridsite_take1_cmds, + NULL, RSRC_CONF, "GridHTTP port"), AP_INIT_TAKE1("GridSiteOnetimesDir", mod_gridsite_take1_cmds, NULL, RSRC_CONF, "directory with GridHTTP onetime passcodes"), - + + AP_INIT_TAKE1("GridSiteCastDNlists", mod_gridsite_take1_cmds, + NULL, RSRC_CONF, "DN Lists directories search path for SiteCast"), + AP_INIT_TAKE1("GridSiteCastUniPort", mod_gridsite_take1_cmds, + NULL, RSRC_CONF, "UDP port for unicast/replies"), + AP_INIT_TAKE1("GridSiteCastGroup", mod_gridsite_take1_cmds, + NULL, RSRC_CONF, "multicast group[:port] to listen for HTCP on"), + AP_INIT_TAKE2("GridSiteCastAlias", mod_gridsite_take2_cmds, + NULL, RSRC_CONF, "URL and local path mapping"), + AP_INIT_FLAG("GridSiteSoap2cgi", mod_gridsite_flag_cmds, NULL, OR_FILEINFO, "on or off"), @@ -2196,9 +2308,7 @@ static int mod_gridsite_perm_handler(request_rec *r) { cookiefile = apr_psprintf(r->pool, "%s/%s", ap_server_root_relative(r->pool, - ((mod_gridsite_srv_cfg *) - ap_get_module_config(r->server->module_config, - &gridsite_module))->onetimesdir), + onetimesdir), &gridauthonetime[18]); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, @@ -2551,12 +2661,390 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx) return returned_ok; } +void sitecast_handle_NOP_request(server_rec *main_server, + GRSThtcpMessage *htcp_mesg, int igroup, + struct sockaddr_in *client_addr_ptr) +{ + int outbuf_len; + char *outbuf; + + if (GRSThtcpNOPresponseMake(&outbuf, &outbuf_len, + htcp_mesg->trans_id) == GRST_RET_OK) + { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server, + "SiteCast sends NOP response from port %d to %s:%d", + sitecastgroups[0].port, inet_ntoa(client_addr_ptr->sin_addr), + ntohs(client_addr_ptr->sin_port)); + + sendto(sitecastgroups[0].socket, outbuf, outbuf_len, 0, + client_addr_ptr, sizeof(struct sockaddr_in)); + + free(outbuf); + } +} + +void sitecast_handle_TST_GET(server_rec *main_server, + GRSThtcpMessage *htcp_mesg, int igroup, + struct sockaddr_in *client_addr_ptr) +{ + int i, outbuf_len, ialias, port; + char *filename, *outbuf, *location, *local_uri = NULL; + struct stat statbuf; + SSLSrvConfigRec *ssl_srv; + + /* check sanity of requested uri */ + + if (strncmp(htcp_mesg->uri->text, "http://", 7) == 0) + { + for (i=7; i < GRSThtcpCountstrLen(htcp_mesg->uri); ++i) + if (htcp_mesg->uri->text[i] == '/') + { + local_uri = &(htcp_mesg->uri->text[i]); + break; + } + } + else if (strncmp(htcp_mesg->uri->text, "https://", 8) == 0) + { + for (i=8; i < GRSThtcpCountstrLen(htcp_mesg->uri); ++i) + if (htcp_mesg->uri->text[i] == '/') + { + local_uri = &(htcp_mesg->uri->text[i]); + break; + } + } + + if (local_uri == NULL) + { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server, + "SiteCast responder only handles http(s):// (%*s requested by %s:%d)", + GRSThtcpCountstrLen(htcp_mesg->uri), + htcp_mesg->uri->text, + inet_ntoa(client_addr_ptr->sin_addr), + ntohs(client_addr_ptr->sin_port)); + return; + } + + /* find if any GridSiteCastAlias lines match */ + + for (ialias=0; ialias < GRST_SITECAST_ALIASES ; ++ialias) + { + if (sitecastaliases[ialias].sitecast_url == NULL) return; /* no match */ + + if ((strlen(sitecastaliases[ialias].sitecast_url) + <= GRSThtcpCountstrLen(htcp_mesg->uri)) && + (strncmp(sitecastaliases[ialias].sitecast_url, + htcp_mesg->uri->text, + strlen(sitecastaliases[ialias].sitecast_url))==0)) break; + } + + if (ialias == GRST_SITECAST_ALIASES) + { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server, + "SiteCast responder does not handle %*s requested by %s:%d", + GRSThtcpCountstrLen(htcp_mesg->uri), + htcp_mesg->uri->text, + inet_ntoa(client_addr_ptr->sin_addr), + ntohs(client_addr_ptr->sin_port)); + + return; /* no match */ + } + + /* convert URL to filename, using alias mapping */ + + asprintf(&filename, "%s%*s", + sitecastaliases[ialias].local_path, + GRSThtcpCountstrLen(htcp_mesg->uri) + - strlen(sitecastaliases[ialias].sitecast_url), + &(htcp_mesg->uri->text[strlen(sitecastaliases[ialias].sitecast_url)]) ); + + if (stat(filename, &statbuf) == 0) /* found file */ + { + ssl_srv = (SSLSrvConfigRec *) + ap_get_module_config(sitecastaliases[ialias].server->module_config, + &ssl_module); + + port = sitecastaliases[ialias].server->addrs->host_port; + if (port == 0) port = ((ssl_srv != NULL) && (ssl_srv->enabled)) + ? GRST_HTTPS_PORT : GRST_HTTP_PORT; + + asprintf(&location, "Location: http%s://%s:%d%s\r\n", + ((ssl_srv != NULL) && (ssl_srv->enabled)) ? "s" : "", + sitecastaliases[ialias].server->server_hostname, port, + local_uri); + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server, + "SiteCast finds %*s at %s, redirects with %s", + GRSThtcpCountstrLen(htcp_mesg->uri), + htcp_mesg->uri->text, filename, location); + + if (GRSThtcpTSTresponseMake(&outbuf, &outbuf_len, + htcp_mesg->trans_id, + location, "", "") == GRST_RET_OK) + { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server, + "SiteCast sends TST response from port %d to %s:%d", + sitecastgroups[0].port, inet_ntoa(client_addr_ptr->sin_addr), + ntohs(client_addr_ptr->sin_port)); + + sendto(sitecastgroups[0].socket, outbuf, outbuf_len, 0, + client_addr_ptr, sizeof(struct sockaddr_in)); + + free(outbuf); + } + + free(location); + } + + free(filename); +} + +void sitecast_handle_request(server_rec *main_server, + char *reqbuf, int reqbuf_len, int igroup, + struct sockaddr_in *client_addr_ptr) +{ + GRSThtcpMessage htcp_mesg; + + if (GRSThtcpMessageParse(&htcp_mesg,reqbuf,reqbuf_len) != GRST_RET_OK) + { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, main_server, + "SiteCast responder rejects format of UDP message from %s:%d", + inet_ntoa(client_addr_ptr->sin_addr), + ntohs(client_addr_ptr->sin_port)); + return; + } + + if (htcp_mesg.rr != 0) /* ignore HTCP responses: we just do requests */ + { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server, + "SiteCast responder ignores HTCP response from %s:%d", + inet_ntoa(client_addr_ptr->sin_addr), + ntohs(client_addr_ptr->sin_port)); + return; + } + + if (htcp_mesg.opcode == GRSThtcpNOPop) + { + sitecast_handle_NOP_request(main_server, &htcp_mesg, + igroup, client_addr_ptr); + return; + } + + if (htcp_mesg.opcode == GRSThtcpTSTop) + { + if (((GRSThtcpCountstrLen(htcp_mesg.method) == 3) && + (strncmp(htcp_mesg.method->text, "GET", 3) == 0)) || + ((GRSThtcpCountstrLen(htcp_mesg.method) == 4) && + (strncmp(htcp_mesg.method->text, "HEAD", 4) == 0))) + { + sitecast_handle_TST_GET(main_server, &htcp_mesg, + igroup, client_addr_ptr); + return; + } + + ap_log_error(APLOG_MARK, APLOG_ERR, 0, main_server, + "SiteCast responder rejects method %*s in TST message from %s:%d", + GRSThtcpCountstrLen(htcp_mesg.method), htcp_mesg.method->text, + inet_ntoa(client_addr_ptr->sin_addr), + ntohs(client_addr_ptr->sin_port)); + return; + } + + ap_log_error(APLOG_MARK, APLOG_ERR, 0, main_server, + "SiteCast does not implement HTCP op-code %d in message from %s:%d", + htcp_mesg.opcode, + inet_ntoa(client_addr_ptr->sin_addr), + ntohs(client_addr_ptr->sin_port)); +} + +void sitecast_responder(server_rec *main_server) +{ +#define GRST_SITECAST_MAXBUF 8192 + char reqbuf[GRST_SITECAST_MAXBUF], *p; + int n, reqbuf_len, i, j, igroup, + quad1, quad2, quad3, quad4, port, retval, client_addr_len; + struct sockaddr_in srv, client_addr; + struct ip_mreq mreq; + fd_set readsckts; + struct hostent *server_hostent; + + strcpy((char *) main_server->process->argv[0], "GridSiteCast UDP responder"); + + /* initialise unicast/replies socket first */ + + bzero(&srv, sizeof(srv)); + srv.sin_family = AF_INET; + srv.sin_port = htons(sitecastgroups[0].port); + + if ((server_hostent = gethostbyname(main_server->server_hostname)) == NULL) + { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, main_server, + "SiteCast UDP Responder fails to look up servername %s", + main_server->server_hostname); + return; + } + + srv.sin_addr.s_addr = (u_int32_t) (server_hostent->h_addr_list[0][0]); + + if (((sitecastgroups[0].socket + = socket(AF_INET, SOCK_DGRAM, 0)) < 0) || + (bind(sitecastgroups[0].socket, + (struct sockaddr *) &srv, sizeof(srv)) < 0)) + { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, main_server, + "mod_gridsite: sitecast responder fails on unicast bind (%s)", + strerror(errno)); + return; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server, + "SiteCast UDP unicast/replies on %d.%d.%d.%d:%d", + server_hostent->h_addr_list[0][0], + server_hostent->h_addr_list[0][1], + server_hostent->h_addr_list[0][2], + server_hostent->h_addr_list[0][3], + sitecastgroups[0].port); + + /* initialise multicast listener sockets next */ + + for (i=1; (i <= GRST_SITECAST_GROUPS) && + (sitecastgroups[i].port != 0); ++i) + { + bzero(&srv, sizeof(srv)); + srv.sin_family = AF_INET; + srv.sin_port = htons(sitecastgroups[i].port); + srv.sin_addr.s_addr = htonl(sitecastgroups[i].quad1*0x1000000 + + sitecastgroups[i].quad2*0x10000 + + sitecastgroups[i].quad3*0x100 + + sitecastgroups[i].quad4); + + if (((sitecastgroups[i].socket + = socket(AF_INET, SOCK_DGRAM, 0)) < 0) || + (bind(sitecastgroups[i].socket, + (struct sockaddr *) &srv, sizeof(srv)) < 0)) + { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, main_server, + "SiteCast UDP Responder fails on multicast bind (%s)", + strerror(errno)); + return; + } + + bzero(&mreq, sizeof(mreq)); + mreq.imr_multiaddr.s_addr = srv.sin_addr.s_addr; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + + if (setsockopt(sitecastgroups[i].socket, IPPROTO_IP, + IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) + { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, main_server, + "SiteCast UDP Responder fails on setting multicast"); + return; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server, + "SiteCast UDP Responder listening on %d.%d.%d.%d:%d", + sitecastgroups[i].quad1, sitecastgroups[i].quad2, + sitecastgroups[i].quad3, sitecastgroups[i].quad4, sitecastgroups[i].port); + } + + while (1) /* **** main listening loop **** */ + { + /* set up bitmasks for select */ + + FD_ZERO(&readsckts); + + n = 0; + for (i=0; (i <= GRST_SITECAST_GROUPS) && + (sitecastgroups[i].port != 0); ++i) /* reset bitmask */ + { + FD_SET(sitecastgroups[i].socket, &readsckts); + if (sitecastgroups[i].socket > n) n = sitecastgroups[i].socket; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server, + "SiteCast UDP Responder waiting for requests"); + + if ((retval = select(n + 1, &readsckts, NULL, NULL, NULL)) < 1) + continue; /* < 1 on timeout or error */ + + for (igroup=0; (igroup <= GRST_SITECAST_GROUPS) && + (sitecastgroups[igroup].port != 0); ++igroup) + { + if (FD_ISSET(sitecastgroups[igroup].socket, &readsckts)) + { + client_addr_len = sizeof(client_addr); + + if ((reqbuf_len = recvfrom(sitecastgroups[igroup].socket, + reqbuf, GRST_SITECAST_MAXBUF, 0, + (struct sockaddr *) &client_addr, &client_addr_len)) >= 0) + { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server, + "SiteCast receives UDP message from %s:%d " + "to %d.%d.%d.%d:%d", + inet_ntoa(client_addr.sin_addr), + ntohs(client_addr.sin_port), + sitecastgroups[igroup].quad1, + sitecastgroups[igroup].quad2, + sitecastgroups[igroup].quad3, + sitecastgroups[igroup].quad4, + sitecastgroups[igroup].port); + + sitecast_handle_request(main_server, reqbuf, + reqbuf_len, igroup, + &client_addr); + } + } + } + + } /* **** end of main listening loop **** */ +} + static int mod_gridsite_server_post_config(apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *main_server) { SSL_CTX *ctx; SSLSrvConfigRec *sc; server_rec *this_server; + apr_proc_t *procnew = NULL; + apr_status_t status; + const char *userdata_key = "sitecast_init"; + + apr_pool_userdata_get((void **) &procnew, userdata_key, + main_server->process->pool); + + /* we only fork responder if one not already forked and we have at + least one GridSiteCastAlias defined. This means it is possible + to run a responder with no groups - listening on unicast only! */ + + if ((procnew == NULL) && + (sitecastaliases[0].sitecast_url != NULL)) + { + /* UDP multicast responder required but not yet started */ + + procnew = apr_pcalloc(main_server->process->pool, sizeof(*procnew)); + apr_pool_userdata_set((const void *) procnew, userdata_key, + apr_pool_cleanup_null, main_server->process->pool); + + status = apr_proc_fork(procnew, pPool); + + if (status < 0) + { + ap_log_error(APLOG_MARK, APLOG_CRIT, status, main_server, + "mod_gridsite: Failed to spawn SiteCast responder process"); + return HTTP_INTERNAL_SERVER_ERROR; + } + else if (status == APR_INCHILD) + { + ap_log_error(APLOG_MARK, APLOG_NOTICE, status, main_server, + "mod_gridsite: Spawning SiteCast responder process"); + sitecast_responder(main_server); + exit(-1); + } + + apr_pool_note_subprocess(main_server->process->pool, + procnew, APR_KILL_AFTER_TIMEOUT); + } + + /* continue with normal HTTP/HTTPS servers */ ap_add_version_component(pPool, apr_psprintf(pPool, "mod_gridsite/%s", VERSION)); @@ -2565,6 +3053,8 @@ static int mod_gridsite_server_post_config(apr_pool_t *pPool, this_server != NULL; this_server = this_server->next) { + /* we do some GridSite OpenSSL magic for HTTPS servers */ + sc = ap_get_module_config(this_server->module_config, &ssl_module); if ((sc != NULL) && @@ -2676,7 +3166,7 @@ module AP_MODULE_DECLARE_DATA gridsite_module = create_gridsite_dir_config, /* dir config creater */ merge_gridsite_dir_config, /* dir merger */ create_gridsite_srv_config, /* create server config */ - merge_gridsite_srv_config, /* merge server config */ + NULL, /* merge server config */ mod_gridsite_cmds, /* command apr_table_t */ register_hooks /* register hooks */ };