diff options
Diffstat (limited to 'school/node_modules/node-forge/mod_fsp/mod_fsp.c')
-rw-r--r-- | school/node_modules/node-forge/mod_fsp/mod_fsp.c | 415 |
1 files changed, 0 insertions, 415 deletions
diff --git a/school/node_modules/node-forge/mod_fsp/mod_fsp.c b/school/node_modules/node-forge/mod_fsp/mod_fsp.c deleted file mode 100644 index 8beb824..0000000 --- a/school/node_modules/node-forge/mod_fsp/mod_fsp.c +++ /dev/null @@ -1,415 +0,0 @@ -/** - * 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 */ -}; |