summaryrefslogtreecommitdiff
path: root/school/node_modules/node-forge/mod_fsp
diff options
context:
space:
mode:
Diffstat (limited to 'school/node_modules/node-forge/mod_fsp')
-rw-r--r--school/node_modules/node-forge/mod_fsp/README135
-rw-r--r--school/node_modules/node-forge/mod_fsp/mod_fsp.c415
2 files changed, 550 insertions, 0 deletions
diff --git a/school/node_modules/node-forge/mod_fsp/README b/school/node_modules/node-forge/mod_fsp/README
new file mode 100644
index 0000000..0331e01
--- /dev/null
+++ b/school/node_modules/node-forge/mod_fsp/README
@@ -0,0 +1,135 @@
+=======
+mod_fsp
+=======
+
+mod_fsp is an Apache2 module for providing a Flash Socket Policy on the
+same port that HTTP is served. The cross-domain policy that is served is
+specified via a configuration option 'FSPPolicyFile'.
+
+If a flash application sends a policy file request to an Apache server
+that has enabled and configured the mod_fsp module over its HTTP port,
+then the configured cross-domain policy will be returned as the response.
+
+========
+Building
+========
+
+To build the mod_fsp source code you can use Apache2's module
+build and installation tool: 'apxs2' which is, at the time of
+this writing, available on debian in the package:
+
+apache2-threaded-dev
+
+To compile mod_fsp you would run the following command:
+
+apxs2 -c mod_fsp.c
+
+============
+Installation
+============
+
+To install mod_fsp you the following command as root:
+
+apxs2 -c -i -a mod_fsp.c
+
+You must then restart your apache2 process, typically like so:
+
+/etc/init.d/apache2 restart
+
+===================
+Manual Installation
+===================
+
+To manually enable mod_dsp on your Apache2 server, you must copy the
+module file to the appropriate directory and create a load file.
+
+The module file:
+
+fsp.so (The library extension may vary if you are not using linux).
+
+Must be copied to Apache's module installation directory which is
+typically located (on a debian system):
+
+/usr/lib/apache2/modules
+
+The load file:
+
+fsp.load
+
+Must be created in Apache2's 'mods-available' directory, typically
+located (on a debian system):
+
+/etc/apache2/mods-available
+
+The load file should contain:
+
+LoadModule fsp_module /usr/lib/apache2/modules/mod_fsp.so
+
+If your Apache module installation directory is different from
+the one listed above, you will need to set the correct one in the
+fsp.load file.
+
+To actually enable the module you must create a symbolic link in
+Apache's 'mods-enabled' directory, typically located (on debian):
+
+/etc/apache2/mods-enabled
+
+By typing (from that directory):
+
+ln -s ../mods-available/fsp.load fsp.load
+
+=============
+Configuration
+=============
+
+Once mod_fsp is installed, it must be configured. There is currently
+only one configuration option for mod_fsp: 'FSPPolicyFile'. This
+configuration option will set the file that mod_fsp will look in
+on apache startup for the cross-domain policy to serve. This option
+can be provided on a per-port basis. Each port can use a different
+one, but VirtualServers on a single port will use the same one. This
+is a limitation of the design by Adobe.
+
+Note: The cross-domain policy may fail to be served if the configuration
+option isn't added in the first VirtualHost entry (for a given port) read
+by Apache.
+
+An example of this configuration in use:
+
+<VirtualHost *:80>
+ ServerName example.com
+ DocumentRoot /var/www/example.com
+ ErrorLog /var/log/apache2/example.com-error.log
+ CustomLog /var/log/apache2/example.com-access.log vhost_combined
+
+ # mod_fsp config option
+ FSPPolicyFile /etc/apache2/crossdomain/crossdomain.xml
+
+ <Directory /var/www/example.com>
+ Options Indexes FollowSymLinks MultiViews
+ AllowOverride All
+ Order allow,deny
+ allow from all
+ </Directory>
+
+</VirtualHost>
+
+And example of the most permissive cross-domain policy file for flash:
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE cross-domain-policy SYSTEM
+"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
+<cross-domain-policy>
+<site-control permitted-cross-domain-policies="all"/>
+<allow-access-from domain="*" to-ports="*"/>
+<allow-http-request-headers-from domain="*" headers="*"/>
+</cross-domain-policy>
+
+==================
+Note about SSL/TLS
+==================
+
+Flash currently has no built-in SSL/TLS support so there is no
+reason to specify an 'FSPPolicyFile' option for SSL servers. The
+Flash player cannot directly communicate with them when doing
+internal look ups of policy files.
diff --git a/school/node_modules/node-forge/mod_fsp/mod_fsp.c b/school/node_modules/node-forge/mod_fsp/mod_fsp.c
new file mode 100644
index 0000000..8beb824
--- /dev/null
+++ b/school/node_modules/node-forge/mod_fsp/mod_fsp.c
@@ -0,0 +1,415 @@
+/**
+ * Flash Socket Policy Apache Module.
+ *
+ * This module provides a flash socket policy file on the same port that
+ * serves HTTP on Apache. This can help simplify setting up a server that
+ * supports cross-domain communication with flash.
+ *
+ * Quick note about Apache memory handling: Data is allocated from pools and
+ * is not manually returned to those pools. The pools are typically considered
+ * short-lived and will be cleaned up automatically by Apache.
+ *
+ * @author Dave Longley
+ *
+ * Copyright (c) 2010 Digital Bazaar, Inc. All rights reserved.
+ */
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+
+#include "ap_compat.h"
+
+#include <string.h>
+
+// length of a policy file request
+#define PFR_LENGTH 23
+
+// declare main module
+module AP_MODULE_DECLARE_DATA fsp_module;
+
+// configuration for the module
+typedef struct fsp_config
+{
+ // the cross-domain policy to serve
+ char* policy;
+ apr_size_t policy_length;
+} fsp_config;
+
+// filter state for keeping track of detected policy file requests
+typedef struct filter_state
+{
+ fsp_config* cfg;
+ int checked;
+ int found;
+} filter_state;
+
+// for registering hooks, filters, etc.
+static void fsp_register_hooks(apr_pool_t *p);
+static int fsp_pre_connection(conn_rec *c, void *csd);
+
+// filter handler declarations
+static apr_status_t fsp_input_filter(
+ ap_filter_t* f, apr_bucket_brigade* bb,
+ ap_input_mode_t mode, apr_read_type_e block, apr_off_t nbytes);
+static int fsp_output_filter(ap_filter_t* f, apr_bucket_brigade* bb);
+
+/**
+ * Registers the hooks for this module.
+ *
+ * @param p the pool to allocate from, if necessary.
+ */
+static void fsp_register_hooks(apr_pool_t* p)
+{
+ // registers the pre-connection hook to handle adding filters
+ ap_hook_pre_connection(
+ fsp_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
+
+ // will parse a policy file request, to be added in pre_connection
+ ap_register_input_filter(
+ "fsp_request", fsp_input_filter,
+ NULL, AP_FTYPE_CONNECTION);
+
+ // will emit a cross-domain policy response to be added in pre_connection
+ ap_register_output_filter(
+ "fsp_response", fsp_output_filter,
+ NULL, AP_FTYPE_CONNECTION);
+}
+
+/**
+ * A hook that is called before a connection is handled. This function will
+ * get the module configuration and add the flash socket policy filters if
+ * a cross-domain policy has been specified in the configuration.
+ *
+ * @param c the connection.
+ * @param csd the connection socket descriptor.
+ *
+ * @return OK on success.
+ */
+static int fsp_pre_connection(conn_rec* c, void* csd)
+{
+ // only install filters if a policy was specified in the module config
+ fsp_config* cfg = ap_get_module_config(
+ c->base_server->module_config, &fsp_module);
+ if(cfg->policy != NULL)
+ {
+ // allocate filter state
+ filter_state* state = apr_palloc(c->pool, sizeof(filter_state));
+ if(state != NULL)
+ {
+ // initialize state
+ state->cfg = cfg;
+ state->checked = state->found = 0;
+
+ // add filters
+ ap_add_input_filter("fsp_request", state, NULL, c);
+ ap_add_output_filter("fsp_response", state, NULL, c);
+ }
+ }
+
+ return OK;
+}
+
+/**
+ * Searches the input request for a flash socket policy request. This request,
+ * unfortunately, does not follow the HTTP protocol and cannot be handled
+ * via a special HTTP handler. Instead, it is a short xml string followed by
+ * a null character:
+ *
+ * '<policy-file-request/>\0'
+ *
+ * A peek into the incoming data checks the first character of the stream to
+ * see if it is '<' (as opposed to typically something else for HTTP). If it
+ * is not, then this function returns and HTTP input is read normally. If it
+ * is, then the remaining bytes in the policy-file-request are read and
+ * checked. If a match is found, then the filter state will be updated to
+ * inform the output filter to send a cross-domain policy as a response. If
+ * no match is found, HTTP traffic will proceed as usual.
+ *
+ * @param f the input filter.
+ * @param state the filter state.
+ *
+ * @return APR_SUCCESS on success, some other status on failure.
+ */
+static apr_status_t find_policy_file_request(
+ ap_filter_t* f, filter_state* state)
+{
+ apr_status_t rval = APR_SUCCESS;
+
+ // create a temp buffer for speculative reads
+ apr_bucket_brigade* tmp = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
+
+ // FIXME: not sure how blocking mode works ... can it return fewer than
+ // the number of specified bytes?
+
+ // peek at the first PFR_LENGTH bytes
+ rval = ap_get_brigade(
+ f->next, tmp, AP_MODE_SPECULATIVE, APR_BLOCK_READ, PFR_LENGTH);
+ if(rval == APR_SUCCESS)
+ {
+ // quickly check the first bucket for the beginning of a pfr
+ const char* data;
+ apr_size_t length;
+ apr_bucket* b = APR_BRIGADE_FIRST(tmp);
+ rval = apr_bucket_read(b, &data, &length, APR_BLOCK_READ);
+ if(rval == APR_SUCCESS && length > 0 && data[0] == '<')
+ {
+ // possible policy file request, fill local buffer
+ char pfr[PFR_LENGTH];
+ char* ptr = pfr;
+ memcpy(ptr, data, length);
+ ptr += length;
+ memset(ptr, '\0', PFR_LENGTH - length);
+ b = APR_BUCKET_NEXT(b);
+ while(rval == APR_SUCCESS && b != APR_BRIGADE_SENTINEL(tmp))
+ {
+ rval = apr_bucket_read(b, &data, &length, APR_BLOCK_READ);
+ if(rval == APR_SUCCESS)
+ {
+ memcpy(ptr, data, length);
+ ptr += length;
+ b = APR_BUCKET_NEXT(b);
+ }
+ }
+
+ if(rval == APR_SUCCESS)
+ {
+ // see if pfr is a policy file request: '<policy-file-request/>\0'
+ if((ptr - pfr == PFR_LENGTH) && (pfr[PFR_LENGTH - 1] == '\0') &&
+ (strncmp(pfr, "<policy-file-request/>", PFR_LENGTH -1) == 0))
+ {
+ // pfr found
+ state->found = 1;
+ }
+ }
+ }
+ }
+
+ return rval;
+}
+
+/**
+ * Handles incoming data. If an attempt has not yet been made to look for
+ * a policy request (it is the beginning of the connection), then one is
+ * made. Otherwise this filter does nothing.
+ *
+ * If an attempt is made to find a policy request and one is not found, then
+ * reads proceed as normal. If one is found, then the filter state is modified
+ * to inform the output filter to send a policy request and the return value
+ * of this filter is EOF indicating that the connection should close after
+ * sending the cross-domain policy.
+ *
+ * @param f the input filter.
+ * @param bb the brigate to fill with input from the next filters in the chain
+ * and then process (look for a policy file request).
+ * @param mode the type of read requested (ie: AP_MODE_GETLINE means read until
+ * a CRLF is found, AP_MODE_GETBYTES means 'nbytes' of data, etc).
+ * @param block APR_BLOCK_READ or APR_NONBLOCK_READ, indicates the type of
+ * blocking to do when trying to read.
+ * @param nbytes used if the read mode is appropriate to specify the number of
+ * bytes to read (set to 0 for AP_MODE_GETLINE).
+ *
+ * @return the status of the input (ie: APR_SUCCESS for read success, APR_EOF
+ * for end of stream, APR_EAGAIN to read again when non-blocking).
+ */
+static apr_status_t fsp_input_filter(
+ ap_filter_t* f, apr_bucket_brigade* bb,
+ ap_input_mode_t mode, apr_read_type_e block, apr_off_t nbytes)
+{
+ apr_status_t rval = APR_SUCCESS;
+
+ filter_state* state = f->ctx;
+ if(state->checked == 1)
+ {
+ // already checked for policy file request, just read from other filters
+ rval = ap_get_brigade(f->next, bb, mode, block, nbytes);
+ }
+ else
+ {
+ // try to find a policy file request
+ rval = find_policy_file_request(f, state);
+ state->checked = 1;
+
+ if(rval == APR_SUCCESS)
+ {
+ if(state->found)
+ {
+ // do read of PFR_LENGTH bytes, consider end of stream
+ rval = ap_get_brigade(
+ f->next, bb, AP_MODE_READBYTES, APR_BLOCK_READ, PFR_LENGTH);
+ rval = APR_EOF;
+ }
+ else
+ {
+ // do normal read
+ rval = ap_get_brigade(f->next, bb, mode, block, nbytes);
+ }
+ }
+ }
+
+ return rval;
+}
+
+/**
+ * Handles outgoing data. If the filter state indicates that a cross-domain
+ * policy should be sent then it is added to the outgoing brigade of data. If
+ * a policy request was not detected, then this filter makes no changes to
+ * the outgoing data.
+ *
+ * @param f the output filter.
+ * @param bb the outgoing brigade of data.
+ *
+ * @return APR_SUCCESS on success, some other status on error.
+ */
+static int fsp_output_filter(ap_filter_t* f, apr_bucket_brigade* bb)
+{
+ apr_status_t rval = APR_SUCCESS;
+
+ filter_state* state = f->ctx;
+ if(state->found)
+ {
+ // found policy-file-request, add response bucket
+ // bucket is immortal because the data is stored in the configuration
+ // and doesn't need to be copied
+ apr_bucket* head = apr_bucket_immortal_create(
+ state->cfg->policy, state->cfg->policy_length, bb->bucket_alloc);
+ APR_BRIGADE_INSERT_HEAD(bb, head);
+ }
+
+ if(rval == APR_SUCCESS)
+ {
+ // pass brigade to next filter
+ rval = ap_pass_brigade(f->next, bb);
+ }
+
+ return rval;
+}
+
+/**
+ * Creates the configuration for this module.
+ *
+ * @param p the pool to allocate from.
+ * @param s the server the configuration is for.
+ *
+ * @return the configuration data.
+ */
+static void* fsp_create_config(apr_pool_t* p, server_rec* s)
+{
+ // allocate config
+ fsp_config* cfg = apr_palloc(p, sizeof(fsp_config));
+
+ // no default policy
+ cfg->policy = NULL;
+ cfg->policy_length = 0;
+ return cfg;
+}
+
+/**
+ * Sets the policy file to use from the configuration.
+ *
+ * @param parms the command directive parameters.
+ * @param userdata NULL, not used.
+ * @param arg the string argument to the command directive (the file with
+ * the cross-domain policy to serve as content).
+ *
+ * @return NULL on success, otherwise an error string to display.
+ */
+static const char* fsp_set_policy_file(
+ cmd_parms* parms, void* userdata, const char* arg)
+{
+ const char* rval = NULL;
+
+ apr_pool_t* pool = (apr_pool_t*)parms->pool;
+ fsp_config* cfg = ap_get_module_config(
+ parms->server->module_config, &fsp_module);
+
+ // ensure command is in the correct context
+ rval = ap_check_cmd_context(parms, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if(rval == NULL)
+ {
+ // get canonical file name
+ char* fname = ap_server_root_relative(pool, arg);
+ if(fname == NULL)
+ {
+ rval = (const char*)apr_psprintf(
+ pool, "%s: Invalid policy file '%s'",
+ parms->cmd->name, arg);
+ }
+ else
+ {
+ // try to open the file
+ apr_status_t rv;
+ apr_file_t* fd;
+ apr_finfo_t finfo;
+ rv = apr_file_open(&fd, fname, APR_READ, APR_OS_DEFAULT, pool);
+ if(rv == APR_SUCCESS)
+ {
+ // stat file
+ rv = apr_file_info_get(&finfo, APR_FINFO_NORM, fd);
+ if(rv == APR_SUCCESS)
+ {
+ // ensure file is not empty
+ apr_size_t length = (apr_size_t)finfo.size;
+ if(length <= 0)
+ {
+ rval = (const char*)apr_psprintf(
+ pool, "%s: policy file '%s' is empty",
+ parms->cmd->name, fname);
+ }
+ // read file
+ else
+ {
+ char* buf = (char*)apr_palloc(pool, length + 1);
+ buf[length] = '\0';
+ rv = apr_file_read_full(fd, buf, length, NULL);
+ if(rv == APR_SUCCESS)
+ {
+ // TODO: validate file
+ // save policy string
+ cfg->policy = buf;
+ cfg->policy_length = length + 1;
+ }
+ }
+
+ // close the file
+ apr_file_close(fd);
+ }
+ }
+
+ // handle error case
+ if(rv != APR_SUCCESS)
+ {
+ char errmsg[120];
+ rval = (const char*)apr_psprintf(
+ pool, "%s: Invalid policy file '%s' (%s)",
+ parms->cmd->name, fname,
+ apr_strerror(rv, errmsg, sizeof(errmsg)));
+ }
+ }
+ }
+
+ return rval;
+}
+
+// table of configuration directives
+static const command_rec fsp_cmds[] =
+{
+ AP_INIT_TAKE1(
+ "FSPPolicyFile", /* the directive */
+ fsp_set_policy_file, /* function to call when directive is found */
+ NULL, /* user data to pass to function, not used */
+ RSRC_CONF, /* indicates the directive appears outside of <Location> */
+ "FSPPolicyFile (string) The cross-domain policy file to use"), /* docs */
+ {NULL}
+};
+
+// module setup
+module AP_MODULE_DECLARE_DATA fsp_module =
+{
+ STANDARD20_MODULE_STUFF, /* stuff declared in every 2.0 mod */
+ NULL, /* create per-directory config structure */
+ NULL, /* merge per-directory config structures */
+ fsp_create_config, /* create per-server config structure */
+ NULL, /* merge per-server config structures */
+ fsp_cmds, /* command apr_table_t */
+ fsp_register_hooks /* register hooks */
+};