
                                mod_epp
                                =======

OVERVIEW
--------

This Apache 2.0 module implements the EPP over TCP protocol as defined
in draft-ietf-provreg-epp-tcp-05.txt and the session management parts of
draft-ietf-provreg-epp-0(6|7).txt.

This is *not* a full implementation of EPP, this module just makes it
possible to write an EPP server as a set of CGI scripts.



RATIONALE
---------

EPP is an XML-based protocol, but it does not utilise one of the common
XML based transaction protocols like SOAP, XML-RPC or HTTP. Writing
an EPP server does not only involve programming the registry logic,
as all the server infrastructure (authentication, logging, security,
build-system, portability, ...) cannot be based on a well established
framework. In our opinion, this is the main reason why there is no open
source implementation of server-side EPP.

Fortunately, the Apache 2.0 HTTP server is versatile and flexible enough
to accommodate other protocols than HTTP through the "Module" extension
mechanism. As part of Apache's support for DAV, a basic set of XML
parsing and handling is already included in the Apache framework.



IMPLEMENTATION
--------------

mod_epp implements an Apache 2.0 "connection handler" which reads EPP
frames (as encapsulated according to the EPP/TCP spec), does some
rudimentary XML parsing and converts the data to a normal Apache request
object which can be handled by the e.g. a CGI script.

The actual EPP command (as XML text) is passed to the handler encoded as
HTTP form-encoded data, which makes it accessible to normal HTML form
processing environments.

On the output side, mod_epp installs an "output filter" which will
encapsulate the output of the actual EPP processor (e.g. the CGI-script)
in an EPP/TCP frame.

As of the current version, mod_epp does not validate incoming
EPP requests according to the EPP XML schema. It only checks
for XML-wellformedness and some rudimentary constraints
on the XML structure insofar as needed to

* generate suitable URLs to call the right scripts
* handle EPP <login> and <logout> commands
* extract authentication information from the request



INSTALLATION
------------

You should have a recent Apache 2.0, compiled and installed (including
header files!).

Unpack the distribution and run:

apxs -a -c -i mod_epp.c

The -a should put something like

LoadModule epp_module         modules/mod_epp.so

into your httpd.conf file to load the module.

See the man page of apxs (part of the Apache 2.0 httpd distribution)
or http://www.onlamp.com/topics/apache/apache_modules for further
information on compiling and installing Apache modules.

The mod_epp module does not replace the HTTP functionality
of Apache 2.0, the server can still be used to serve web pages
on a different port.

There has been a change in the Apache internal filter API recently;
this module was developed for 2.0.43. Version 2.0.39 is definitely
too old.

If you turn on StdEnvVars, you might run into a core dump. Please
have a look at http://nagoya.apache.org/bugzilla/show_bug.cgi?id=15057
for a possible workaround.

mod_epp triggers a bug in mod_epp. See 
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=18339
for more information including a patch.


CONFIGURATION
-------------

All configuration is done inside the main Apache config
file "httpd.conf". See also the comments in the example
file which is included in the mod_epp distribution.

First of all, we need to tell Apache to listen on the EPP port:

# from: http://www.iana.org/assignments/port-numbers
# epp-temp        3121/tcp   Extensible Provisioning Protocol
Listen  3121

To activate mod_epp for this port we use:

<VirtualHost *:3121>
EPPEngine On
</VirtualHost>

Inside the <VirtualHost> context you can specify further 
parameters concerning mod_epp (listed here with the defaults):

EPPCommandRoot          /epp/command
EPPSessionRoot          /epp/session
EPPErrorRoot            /epp/error
EPPAuthURI              /epp/auth/login
EPPVersion		7


Detailed description:

EPPCommandRoot defines how mod_epp will build the path to the script
	handling any command. If the EPP message contained e.g.
	<epp> <command> <foobar/> </command> </epp>
	then it will use "$EPPCommandRoot/foobar".

	This is URL-Space! If you want to map to static files,
	use a path relativ to DocumentRoot. If you want to
	point to CGI scripts, you need a "ScriptAlias" directive
	to map that URL-space directory to a file-system directory
	containing the actual scripts.

EPPSessionRoot defines how mod_epp will build the path to the script
	handling any session handling events. This includes
	"hello", "login", and "logout".

EPPErrorRoot is the base path for all error handler calls. These
	can be cgi-scripts which can make use of the following parameters:

		code	EPP error code (decimal number)
		clTRID	Client Transaction ID (if available)
		msg	Human readable error message

	Currently, mod_epp will call the following scripts unter
	EPPErrorRoot:

		parse		XML parsing error.
		schema		If a violation of the EPP schema is detected.
				(i.e.  mod_epp cannot make sense of the XML 
				tree.)
		protocol	Wrong sequence of EPP frames detected.
				This concerns primarily EPP state-machine 
				problems.)
		authrequired	Authentication required, but not supplied.
		internal	mod_epp internal error.

EPPAuthURI is accessed during the EPP <login> command. You should protect
	that URI with whatever access control mechanism you want
	to apply to the whole setup.

	All further requests in this EPP session will inherit this
	authentication information. 

	Example config (within the EPP VirtualHost):

	<Location /epp/auth>
		AuthType Basic
		AuthName "EPP"
		AuthUserFile <some-path>/htpasswd
		require valid-user
	</Location>

	The rationale for this setup is the following: As the
	authentication procedure could be expensive, we decided
	not to require apache authentication on the normal EPP
	commands. By issuing a pseudo-request on login, the
	expensive checks can be performed just once for all commands.

	mod_epp will insert a REMOTE_USER header in all subsequent
	requests from the same connection even if no apache-side
	authentication is done for requests after the initial 
	login procedure.

	In such a setup you have to make sure that the EPP command
	scripts are *not* callable via a normal HTTP port.

EPPVersion specifies which draft version of the protocol this
	module is supposed to follow. Valid values are the numbers
	"6" and "7". The only difference is the handling of the
	<login> command.

	For version 6, this is a valid EPP frame (name-spaces & co omitted)

		<epp>
		 <command>
		  <creds>
		   <clID>someregistrar</clID>
		   <pw>somepassword</pw>
		  </creds>
		  <login/>
		  <clTRID>tag-01</clTRID>
		 </command>
		</epp>

	Version 7 (which is the current draft as of 2003/01/07) defines
	<login> something like this:

		<epp>
		 <command>
		  <login>
		   <clID>someregistrar</clID>
		   <pw>somepassword</pw>
		  </login>
		  <clTRID>tag-02</clTRID>
		 </command>
		</epp>

	You can run different EPP versions on different ports on the same
	server.



SSL SUPPORT
-----------

EPP can be layered on Apache 2.0 mod_ssl. The configuration should look
something like this:


	Listen  3121
	<VirtualHost *:3121>
	SSLEngine on
	SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
	SSLCertificateFile /.../server.crt
	SSLCertificateKeyFile /.../server.key

	SSLCACertificateFile /.../cacert.pem
	SSLVerifyClient optional_no_ca

	<Directory "/.../cgi-bin">
    		SSLOptions +StdEnvVars +ExportCertData
	</Directory>

	CustomLog logs/epp_ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

	EPPEngine On

	[and other EPP directives; see above.]

	</VirtualHost>

Bug Alert: The client CERT does not show up in the first
(fake) hello request.

Bug Alert 2: If there are any SSL negotiation or configuration
problems, the Apache process might dump core. Please have a look at 
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=18339 where I 
propose the following patch to Apache 2.0.44:

--- httpd-2.0.44/modules/ssl/ssl_engine_io.c.old    Mon Jan 13 18:35:22 2003
+++ httpd-2.0.44/modules/ssl/ssl_engine_io.c        Tue Mar 25 21:07:47 2003
@@ -997,6 +997,7 @@
     SSL_free(ssl);
     sslconn->ssl = NULL;
     filter_ctx->pssl = NULL; /* so filters know we've been shutdown */
+    c->aborted = 1;

     return APR_SUCCESS;
 }


REQUEST/SCRIPT INTERFACE
------------------------

As explained above, mod_epp translates EPP commands into HTTP-like
requests, where all parameters and arguments are passed like they are
for HTML FORMs. It is thus possible to use any normal CGI library to
parse the requests and extract the arguments. While it is certainly
possible to handle the requests in various fashion, I will concentrate
on the CGI case here.

The script output must conform to the CGI spec, thus it has to
generate a "Content-Type:" header. Currently, mod_epp does not
care what you specify there, it will simply pass the body
to the client.

If the script wants to tear down the connection to the client,
it has to include "Connection: close" in the header of the
answer. This convention was selected in analogy to HTTP 1.1.

mod_epp generates a random string for each EPP connection and passes 
this to the backend as a Cookie with the name "session".
This can be used for session tracking.

Command Interface:
- - - - - - - - -
	
	EPP commands are translated to HTTP POST commands, using
	"Content-Type: multipart/form-data" to encapsulate the
	arguments. (Exception: the pseudo <hello> request on
	connection open is done as HTTP GET with URL-encoded
	arguments.) The following two parameters will be passed:

	"frame": This contains the XML of the EPP command received
		from the client. This is *not* the original XML text
		as received from the client; it is a serialisation of
		the XML tree built from the client's message.

		Thus this is guaranteed to be valid XML.

!  		Although mod_epp does some _very_ basic tests on the 
!		XML structure, mod_epp does *NOT* do schema verification.

	"clTRID": If mod_epp succeeds in extracting the "client
		transaction ID" of the request, it will pass it
		along to the scripts as the clTRID parameter.
		(Can be empty.)

		The rationale behind this feature is, that if
		the CGI cannot parse the XML due to schema violations
		it still can formulate an error reply tagged
		with the correct clTRID.

	
	Session commands use the same interface.


Error Interface:
- -  - - - - - -
	
	If mod_epp detects an error (e.g. invalid XML, failed
	login, problems with CGIs), it first tries to call an
	external error handler (using a GET request), before 
	falling back to an internally generated error message.

	These error handles receive the following parameters.

	"code"		4-digit error code as defined in the RFC
	"clTRID"	Client transaction ID (can be empty)
	"msg"		Human readable error message


EXAMPLE SCRIPTS
---------------

The directory "examples" contains some static responses as well
as some scripts which generate simple answers to some common EPP
queries. They are *not* useful for a real EPP server, they just
serve as script interface examples.

A sample implementation of a real EPP server is outside the scope of
mod_epp; please see http://sourceforge.net/projects/aepps/ for such
scripts.


REVERSE PROXY SETUP
-------------------

It is possible to run a mod_epp enabled Apache 2.0 as
proxy between the world of EPP and HTTP. This is the
ideal setup if your favorite scripting engine is not
supported inside Apache 2.0. For example, you can proxy
to an Apache 1.3.x with PHP or mod_perl, or even an
IIS running ASP scripts. 

Here is an example where access control and error generation
is local, but all command and session scripts are proxied
to a different server:

	Listen  3121
	<VirtualHost *:3121>
	EPPEngine On

	EPPCommandRoot          /proxy/command
	EPPSessionRoot          /proxy/session
	ProxyPass /proxy/ http://localhost:8000/epp/

	# requests will go to e.g.
	# http://localhost:8000/epp/command/transfer

	EPPErrorRoot            /cgi-bin/epp/error
	EPPAuthURI              /epp/auth/login
	<Location /epp/auth>
	   Auth ...
	</Location>
	</VirtualHost>

Authentication information will be passed using an
"Authorization: Basic" header. The connection close mechanism does not
seem to work in this setup. I'm investigating an alternative.

AUTHOR
------

This module is currently developed by Otmar Lendl under contract
from NIC.at. You can reach the author at lendl@nic.at.



LICENCE
-------

We intend to release this module under the Apache licence.  The
formalities have not been worked out yet, so please consider this to be
a preliminary release in both code and licence. ;-)


