summaryrefslogtreecommitdiffstats
path: root/base/tps/src/modules/tps/mod_tps.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'base/tps/src/modules/tps/mod_tps.cpp')
-rw-r--r--base/tps/src/modules/tps/mod_tps.cpp732
1 files changed, 732 insertions, 0 deletions
diff --git a/base/tps/src/modules/tps/mod_tps.cpp b/base/tps/src/modules/tps/mod_tps.cpp
new file mode 100644
index 000000000..dc6cc95f9
--- /dev/null
+++ b/base/tps/src/modules/tps/mod_tps.cpp
@@ -0,0 +1,732 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation;
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301 USA
+//
+// Copyright (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef XP_WIN32
+#define TPS_PUBLIC __declspec(dllexport)
+#else /* !XP_WIN32 */
+#define TPS_PUBLIC
+#endif /* !XP_WIN32 */
+
+
+
+/* _________________________________________________________________
+**
+** TPS Module Headers
+** _________________________________________________________________
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include "nspr.h"
+
+#include "httpd/httpd.h"
+#include "httpd/http_config.h"
+#include "httpd/http_log.h"
+#include "httpd/http_protocol.h"
+#include "httpd/http_main.h"
+
+#include "apr_strings.h"
+
+#include "engine/RA.h"
+#include "main/Memory.h"
+#include "main/RA_Msg.h"
+#include "main/RA_Session.h"
+#include "modules/tps/AP_Context.h"
+#include "modules/tps/AP_Session.h"
+#include "msg/RA_Begin_Op_Msg.h"
+#include "msg/RA_End_Op_Msg.h"
+#include "processor/RA_Enroll_Processor.h"
+#include "processor/RA_Format_Processor.h"
+#include "processor/RA_Pin_Reset_Processor.h"
+#include "processor/RA_Renew_Processor.h"
+#include "processor/RA_Unblock_Processor.h"
+#include "ssl.h"
+
+#define MOD_TPS_KEY_NAME "mod_tps"
+
+/* _________________________________________________________________
+**
+** TPS Module Request Data
+** _________________________________________________________________
+*/
+
+/**
+ * Processors for different operations.
+ */
+static RA_Enroll_Processor m_enroll_processor;
+static RA_Unblock_Processor m_unblock_processor;
+static RA_Pin_Reset_Processor m_pin_reset_processor;
+static RA_Renew_Processor m_renew_processor;
+static RA_Format_Processor m_format_processor;
+
+
+/* _________________________________________________________________
+**
+** TPS Module Command Data
+** _________________________________________________________________
+*/
+
+static const char MOD_TPS_CONFIGURATION_FILE_PARAMETER[] = "TPSConfigPathFile";
+
+static const char MOD_TPS_CONFIGURATION_FILE_USAGE[] =
+"TPS Configuration Filename prefixed by a complete path, or\n"
+"a path that is relative to the Apache server root.";
+
+/* per-process config structure */
+typedef struct {
+ int nInitCount;
+ int nSignedAuditInitCount;
+} mod_tps_global_config;
+
+
+/* _________________________________________________________________
+**
+** TPS Module Server Configuration Creation Data
+** _________________________________________________________________
+*/
+
+typedef struct {
+ char *TPS_Configuration_File;
+ AP_Context *context;
+ mod_tps_global_config *gconfig; /* pointer to per-process config */
+} mod_tps_server_configuration;
+
+
+
+/* _________________________________________________________________
+**
+** TPS Module Registration Data
+** _________________________________________________________________
+*/
+
+#define MOD_TPS_CONFIG_KEY tps_module
+
+static const char MOD_TPS_CONFIG_KEY_NAME[] = "tps_module";
+
+extern module TPS_PUBLIC MOD_TPS_CONFIG_KEY;
+
+
+
+/* _________________________________________________________________
+**
+** TPS Module Helper Functions
+** _________________________________________________________________
+*/
+
+mod_tps_global_config *mod_tps_config_global_create(server_rec *s)
+{
+ apr_pool_t *pool = s->process->pool;
+ mod_tps_global_config *globalc = NULL;
+ void *vglobalc = NULL;
+
+ apr_pool_userdata_get(&vglobalc, MOD_TPS_KEY_NAME, pool);
+ if (vglobalc) {
+ return (mod_tps_global_config *) vglobalc; /* reused for lifetime of the server */
+ }
+
+ /*
+ * allocate an own subpool which survives server restarts
+ */
+ globalc = (mod_tps_global_config *)apr_palloc(pool, sizeof(*globalc));
+
+ /*
+ * initialize per-module configuration
+ */
+ globalc->nInitCount = 0;
+ globalc->nSignedAuditInitCount = 0;
+
+ apr_pool_userdata_set(globalc, MOD_TPS_KEY_NAME,
+ apr_pool_cleanup_null,
+ pool);
+
+ return globalc;
+}
+
+/**
+ * Terminate Apache
+ */
+void tps_die( void )
+{
+ /*
+ * This is used for fatal errors and here
+ * it is common module practice to really
+ * exit from the complete program.
+ */
+ exit( 1 );
+}
+
+
+/**
+ * Creates an RA_Session from the RA framework.
+ *
+ * Centralize the allocation of the session object here so that
+ * we can provide our own session management here in the future.
+ */
+static RA_Session *
+mod_tps_create_session( request_rec *rq )
+{
+ return new AP_Session( rq );
+} /* mod_tps_create_session */
+
+
+/**
+ * Returns RA_Session to the RA framework.
+ */
+static void
+mod_tps_destroy_session( RA_Session *session )
+{
+ if( session != NULL ) {
+ delete session;
+ session = NULL;
+ }
+} /* mod_tps_destroy_session */
+
+
+
+/* _________________________________________________________________
+**
+** TPS Module Request Phase
+** _________________________________________________________________
+*/
+
+/**
+ * Terminate the TPS module
+ */
+static apr_status_t
+mod_tps_terminate( void *data )
+{
+ /* This routine is ONLY called when this server's */
+ /* pool has been cleared or destroyed. */
+
+ /* Log TPS module debug information. */
+ RA::Debug( "mod_tps::mod_tps_terminate",
+ "The TPS module has been terminated!" );
+
+ /* Free TPS resources. */
+ RA::Shutdown();
+
+ /* Since all members of mod_tps_server_configuration are allocated */
+ /* from a pool, there is no need to unset any of these members. */
+
+#ifdef MEM_PROFILING
+ /* If memory profiling is enabled, turn off memory profiling. */
+ MEM_shutdown();
+#endif
+
+ SSL_ClearSessionCache();
+ /* Shutdown all APR library routines. */
+ /* NOTE: This automatically destroys all memory pools. */
+ /* Allow the NSS Module to perform this task. */
+ /* apr_terminate(); */
+
+
+ /* Terminate the entire Apache server */
+ /* NOTE: Allow the NSS Module to perform this task. */
+ /* tps_die(); */
+
+ return OK;
+}
+
+static apr_status_t
+mod_tps_child_terminate (void *data)
+{
+ RA::Debug("mod_tps::mod_tps_child_terminate",
+ "The TPS module has been terminated!" );
+
+ /* Free TPS resources. */
+ RA::Child_Shutdown();
+
+ return OK;
+}
+
+static int
+mod_tps_initialize( apr_pool_t *p,
+ apr_pool_t *plog,
+ apr_pool_t *ptemp,
+ server_rec *sv )
+{
+ mod_tps_server_configuration *sc = NULL;
+ char *cfg_path_file = NULL;
+ int status;
+
+ /* Retrieve the TPS module. */
+ sc = ( ( mod_tps_server_configuration * )
+ ap_get_module_config( sv->module_config,
+ &MOD_TPS_CONFIG_KEY ) );
+
+ /* Check to see if the TPS module has been loaded. */
+ if( sc->context != NULL ) {
+ return OK;
+ }
+
+ sc->gconfig->nInitCount++;
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, sv,
+ "Entering mod_tps_initialize - init count is [%d]",
+ sc->gconfig->nInitCount);
+
+ /* Load the TPS module. */
+
+#ifdef MEM_PROFILING
+ /* If memory profiling is enabled, turn on memory profiling. */
+ MEM_init( MEM_AUDIT_FILE, MEM_DUMP_FILE );
+#endif
+
+ /* Retrieve the path to where the configuration files are located, */
+ /* and insure that the TPS module configuration file is located here. */
+ if( sc->TPS_Configuration_File != NULL ) {
+ /* provide TPS Config File from <apache_server_root>/conf/httpd.conf */
+ if( sc->TPS_Configuration_File[0] == '/' ) {
+ /* Complete path to TPS Config File is denoted */
+ cfg_path_file = apr_psprintf( p,
+ "%s",
+ ( char * )
+ sc->TPS_Configuration_File );
+ } else {
+ /* TPS Config File is located relative to the Apache server root */
+ cfg_path_file = apr_psprintf( p,
+ "%s/%s",
+ ( char * ) ap_server_root,
+ ( char * )
+ sc->TPS_Configuration_File );
+ }
+ } else {
+ /* Log information regarding this failure. */
+ ap_log_error( "mod_tps_initialize",
+ __LINE__, APLOG_ERR, 0, sv,
+ "The tps module was installed incorrectly since the "
+ "parameter named '%s' is missing from the Apache "
+ "Configuration file!",
+ ( char * ) MOD_TPS_CONFIGURATION_FILE_PARAMETER );
+
+ /* Display information on the screen regarding this failure. */
+ printf( "\nUnable to start Apache:\n"
+ " The tps module is missing the required parameter named\n"
+ " '%s' in the Apache Configuration file!\n",
+ ( char * ) MOD_TPS_CONFIGURATION_FILE_PARAMETER );
+
+ goto loser;
+ }
+
+ /* Initialize the "server" member of mod_tps_server_configuration. */
+ sc->context = new AP_Context( sv );
+
+ status = RA::Initialize( cfg_path_file, sc->context );
+ if( status != RA_INITIALIZATION_SUCCESS ) {
+ /* Log information regarding this failure. */
+ ap_log_error( "mod_tps_initialize",
+ __LINE__, APLOG_ERR, 0, sv,
+ "The tps module was installed incorrectly "
+ "since the file named '%s' does not exist!",
+ cfg_path_file );
+
+ /* Display information on the screen regarding this failure. */
+ printf( "\nUnable to start Apache:\n"
+ " The tps module configuration file called\n"
+ " '%s' does not exist!\n",
+ cfg_path_file );
+
+ /* Since all members of mod_tps_server_configuration are allocated */
+ /* from a pool, there is no need to unset any of these members. */
+
+ goto loser;
+ }
+
+ if (sc->gconfig->nInitCount < 2 ) {
+ sc->gconfig->nSignedAuditInitCount++;
+ status = RA::InitializeInChild( sc->context,
+ sc->gconfig->nSignedAuditInitCount);
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, sv,
+ "mod_tps_initialize - pid is [%d] - post config already done once -"
+ " additional config will be done in init_child",
+ getpid());
+ status = RA_INITIALIZATION_SUCCESS;
+ }
+
+ if (status != RA_INITIALIZATION_SUCCESS ) {
+ ap_log_error( "mod_tps_initialize",
+ __LINE__, APLOG_ERR, 0, sv,
+ "The tps module failed to do the initializeInChild tasks. ");
+ printf( "\nUnable to start Apache:\n"
+ " The tps module failed to do the initializeInChild tasks. ");
+ goto loser;
+ }
+
+ /* Register a server termination routine. */
+ apr_pool_cleanup_register( p,
+ sv,
+ mod_tps_terminate,
+ apr_pool_cleanup_null );
+
+ /* Log TPS module debug information. */
+ RA::Debug( "mod_tps::mod_tps_initialize",
+ "The TPS module has been successfully loaded!" );
+
+ return OK;
+
+loser:
+ /* Log TPS module debug information. */
+ RA::Debug( "mod_tps::mod_tps_initialize",
+ "Failed loading the TPS module!" );
+
+ if( sc->context != NULL ) {
+ /* Free TPS resources. */
+ RA::Shutdown();
+
+ /* Since all members of mod_tps_server_configuration are allocated */
+ /* from a pool, there is no need to unset any of these members. */
+ }
+
+#ifdef MEM_PROFILING
+ /* If memory profiling is enabled, turn off memory profiling. */
+ MEM_shutdown();
+#endif
+
+ /* Shutdown all APR library routines. */
+ /* NOTE: This automatically destroys all memory pools. */
+ apr_terminate();
+
+ /* Terminate the entire Apache server */
+ tps_die();
+
+ return DECLINED;
+}
+
+/**
+ * mod_tps_handler handles the protocol between the token client
+ * and the RA (Session)
+ */
+static int
+mod_tps_handler( request_rec *rq )
+{
+ char buf[1024];
+ int ret_code = DECLINED;
+ int status = DECLINED;
+ RA_Session *session = NULL;
+ RA_Begin_Op_Msg *begin_op_msg = NULL;
+ NameValueSet *extensions = NULL;
+ const char *tenc = apr_table_get(rq->headers_in, "Transfer-Encoding");
+
+ /* Log TPS module debug information. */
+ RA::Debug( "mod_tps::mod_tps_handler",
+ "mod_tps::mod_tps_handler" );
+
+ RA::Debug( "mod_tps::mod_tps_handler",
+ "uri '%s'", rq->uri);
+
+ /* XXX: We need to change "nk_service" to "tps",
+ and need to update ESC. */
+ if (strcmp(rq->handler,"nk_service") != 0) {
+ RA::Debug( "mod_tps::mod_tps_handler",
+ "DECLINED uri '%s'", rq->uri);
+ return DECLINED;
+ }
+
+ RA::Debug( "mod_tps::mod_tps_handler",
+ "uri '%s' DONE", rq->uri);
+
+ /*
+ * check to see if the http request contains
+ * "transfer-encoding: chunked"
+ */
+ /* XXX: rq->chunked not set to true even in the chunked mode */
+ if(!tenc || PL_strcasecmp(tenc, "chunked") != 0) {
+ /* print the following when browser accesses directly */
+ strcpy( buf, "<HTML>Registration Authority</HTML>" );
+
+ /* write out the data */
+ ( void ) ap_rwrite( ( const void * ) buf, strlen( buf ), rq );
+
+ ret_code = OK;
+
+ return ret_code;
+ }
+
+ /* request contains chunked encoding */
+ session = mod_tps_create_session( rq );
+
+ /* read in the data present on the connection */
+ begin_op_msg = ( RA_Begin_Op_Msg * ) session->ReadMsg();
+ if( begin_op_msg == NULL ) {
+ /* Log TPS module error information. */
+ RA::Error( "mod_tps::mod_tps_handler",
+ "no begin op found" );
+ goto loser;
+ }
+
+ /* retrieve the extensions */
+ extensions = begin_op_msg->GetExtensions();
+
+ /* perform the appropriate processing based upon the type of operation */
+ if( begin_op_msg->GetOpType() == OP_ENROLL ) {
+ status = m_enroll_processor.Process( session, extensions );
+ } else if( begin_op_msg->GetOpType() == OP_UNBLOCK ) {
+ status = m_unblock_processor.Process( session, extensions );
+ } else if( begin_op_msg->GetOpType() == OP_RESET_PIN ) {
+ status = m_pin_reset_processor.Process( session, extensions );
+ } else if( begin_op_msg->GetOpType() == OP_RENEW ) {
+ status = m_renew_processor.Process( session, extensions );
+ } else if( begin_op_msg->GetOpType() == OP_FORMAT ) {
+ status = m_format_processor.Process( session, extensions );
+ } else {
+ /* Log TPS module error information. */
+ RA::Error( "mod_tps::mod_tps_handler",
+ "unknown operation requested (op='%d')",
+ begin_op_msg->GetOpType() );
+ goto loser;
+ } /* if */
+
+ ret_code = OK;
+
+loser:
+ /* determine the results of the operation and report it */
+ if( begin_op_msg != NULL ) {
+ int result;
+
+ if( status == 0 ) {
+ result = RESULT_GOOD;
+ } else {
+ result = RESULT_ERROR;
+ }
+
+ RA_End_Op_Msg *end_op = new RA_End_Op_Msg( begin_op_msg->GetOpType(),
+ result,
+ status );
+
+ session->WriteMsg( end_op );
+
+ if( end_op != NULL ) {
+ delete end_op;
+ end_op = NULL;
+ }
+ }
+
+ /* remove any operational messages */
+ if( begin_op_msg != NULL ) {
+ delete begin_op_msg;
+ begin_op_msg = NULL;
+ }
+
+ /* remove any sessions */
+ if( session != NULL ) {
+ mod_tps_destroy_session( session );
+ session = NULL;
+ }
+
+ return ret_code;
+} /* mod_tps_handler */
+
+
+
+/* _________________________________________________________________
+**
+** TPS Module Command Phase
+** _________________________________________________________________
+*/
+
+static const char *mod_tps_get_config_path_file( cmd_parms *cmd,
+ void *mconfig,
+ const char *tpsconf )
+{
+ if( cmd->path ) {
+ ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL,
+ "The %s config param cannot be specified "
+ "in a Directory section.",
+ cmd->directive->directive );
+ } else {
+ mod_tps_server_configuration *sc = NULL;
+
+ /* Retrieve the TPS module. */
+ sc = ( ( mod_tps_server_configuration * )
+ ap_get_module_config( cmd->server->module_config,
+ &MOD_TPS_CONFIG_KEY ) );
+
+ /* Initialize the "TPS Configuration File" */
+ /* member of mod_tps_server_configuration. */
+ sc->TPS_Configuration_File = apr_pstrdup( cmd->pool, tpsconf );
+ }
+
+ return NULL;
+}
+
+
+static const command_rec mod_tps_config_cmds[] = {
+ AP_INIT_TAKE1( MOD_TPS_CONFIGURATION_FILE_PARAMETER,
+ ( const char*(*)() ) mod_tps_get_config_path_file,
+ NULL,
+ RSRC_CONF,
+ MOD_TPS_CONFIGURATION_FILE_USAGE ),
+ { NULL }
+};
+
+
+
+/* _________________________________________________________________
+**
+** TPS Module Server Configuration Creation Phase
+** _________________________________________________________________
+*/
+
+/**
+ * Create TPS module server configuration
+ */
+static void *
+mod_tps_config_server_create( apr_pool_t *p, server_rec *sv )
+{
+ /* Initialize all APR library routines. */
+ apr_initialize();
+
+ /* Create a memory pool for this server. */
+ mod_tps_server_configuration *sc = ( mod_tps_server_configuration * )
+ apr_pcalloc( p,
+ ( apr_size_t )
+ sizeof( *sc ) );
+
+ /* Initialize all members of mod_tps_server_configuration. */
+ sc->TPS_Configuration_File = NULL;
+ sc->context = NULL;
+ sc->gconfig = mod_tps_config_global_create(sv);
+
+ return sc;
+}
+
+static void mod_tps_init_child(apr_pool_t *p, server_rec *sv)
+{
+ int status = -1;
+ mod_tps_server_configuration *srv_cfg = NULL;
+ srv_cfg = ( ( mod_tps_server_configuration * )
+ ap_get_module_config(sv->module_config, &MOD_TPS_CONFIG_KEY));
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0 /* status */, NULL,
+ "Entering mod_tps_init_child pid [%d] init count is [%d]",
+ getpid(), srv_cfg->gconfig->nInitCount);
+
+ srv_cfg = ( ( mod_tps_server_configuration * )
+ ap_get_module_config(sv->module_config, &MOD_TPS_CONFIG_KEY));
+
+ if (srv_cfg->gconfig->nInitCount > 1) {
+ srv_cfg->gconfig->nSignedAuditInitCount++;
+ status = RA::InitializeInChild(srv_cfg->context,
+ srv_cfg->gconfig->nSignedAuditInitCount);
+
+
+ if (status != RA_INITIALIZATION_SUCCESS) {
+ /* Need to shut down, the child was not initialized properly. */
+ ap_log_error( "mod_tps_init_child",
+ __LINE__, APLOG_ERR, 0, sv,
+ "The tps module failed to do the initializeInChild tasks. ");
+ printf( "\nUnable to start Apache:\n"
+ " The tps module failed to do the initializeInChild tasks. ");
+ goto loser;
+ }
+
+ /* Register a server termination routine. */
+ apr_pool_cleanup_register( p,
+ sv,
+ mod_tps_child_terminate,
+ apr_pool_cleanup_null );
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, sv,
+ "mod_tps_init_child - pid is [%d] - config should be done in regular post config",
+ getpid());
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0 /* status */, NULL,
+ "Leaving mod_tps_init_child");
+ return;
+loser:
+ /* Log TPS module debug information. */
+ RA::Debug( "mod_tps::mod_tps_initialize",
+ "Failed loading the TPS module!" );
+
+ /* Free TPS resources. */
+ /* If we are here, the parent should be up. */
+ RA::Shutdown();
+
+ /* Since all members of mod_tps_server_configuration are allocated */
+ /* from a pool, there is no need to unset any of these members. */
+
+#ifdef MEM_PROFILING
+ /* If memory profiling is enabled, turn off memory profiling. */
+ MEM_shutdown();
+#endif
+
+ /* Shutdown all APR library routines. */
+ /* NOTE: This automatically destroys all memory pools. */
+ apr_terminate();
+
+ /* Terminate the entire Apache server */
+ _exit(APEXIT_CHILDFATAL);
+
+ return;
+
+}
+
+
+
+/* _________________________________________________________________
+**
+** TPS Module Registration Phase
+** _________________________________________________________________
+*/
+
+static void
+mod_tps_register_hooks( apr_pool_t *p )
+{
+ static const char *const mod_tps_preloaded_modules[] = { "mod_nss.c",
+ NULL };
+ static const char *const mod_tps_postloaded_modules[] = { NULL };
+
+ ap_hook_post_config( mod_tps_initialize,
+ mod_tps_preloaded_modules,
+ mod_tps_postloaded_modules,
+ APR_HOOK_MIDDLE );
+
+ ap_hook_child_init(mod_tps_init_child, NULL,NULL, APR_HOOK_MIDDLE);
+
+ ap_hook_handler( mod_tps_handler,
+ mod_tps_preloaded_modules,
+ mod_tps_postloaded_modules,
+ APR_HOOK_MIDDLE );
+}
+
+
+module TPS_PUBLIC MOD_TPS_CONFIG_KEY = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* create per-dir config structures */
+ NULL, /* merge per-dir config structures */
+ mod_tps_config_server_create, /* create per-server config structures */
+ NULL, /* merge per-server config structures */
+ mod_tps_config_cmds, /* table of configuration directives */
+ mod_tps_register_hooks /* register hooks */
+};
+
+
+
+#ifdef __cplusplus
+}
+#endif
+