static ngx_int_t
ngx_http_data_dome_auth_handler(ngx_http_request_t *r)
{
    ngx_buf_t                       *b;
    ngx_int_t                        rc;
    ngx_str_t                        val;
    ngx_str_t                        x_datadome_response;
    ngx_uint_t                       i;
    ngx_chain_t                      out;
    ngx_list_part_t                 *part;
    ngx_table_elt_t                 *header;
    ngx_table_elt_t                 *location;
    ngx_http_data_dome_auth_ctx_t   *ctx;
    ngx_http_data_dome_auth_conf_t  *acf;

    // you can dissable this module in location or if level
    acf = ngx_http_get_module_loc_conf(r, ngx_http_data_dome_auth_module);

    if (acf->uri_lengths == NULL) {
  return NGX_DECLINED;
    }

    if (r->internal && acf->pass_internal_redirect) {
  return NGX_DECLINED;
    }

    // but module use main request context to keep the status
    // to prevent duplicated query to API server
    ctx = ngx_http_get_module_ctx(r->main, ngx_http_data_dome_auth_module);

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->main->connection->log, 0,
		   "Data Dome auth request handler, ctx: %p", ctx);

    if (ctx != NULL) {
    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->main->connection->log, 0,
		   "Data Dome auth request handler ctx: declined %d, processing: %d, done: %d",
		    ctx->declined, ctx->processing, ctx->done);

	if (ctx->declined) {
	    return NGX_DECLINED;
	}

	if (ctx->processing) {
	    return NGX_OK;
	}

	if (!ctx->done) {
	    return NGX_AGAIN;
	}

    if (ngx_http_data_dome_auth_set_variables(r, acf, ctx) != NGX_OK) {
        return NGX_ERROR;
    }

	if (acf->learning) {
	    return NGX_OK;
	}

    if (ctx->subrequest_rc < NGX_OK) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    x_datadome_response.len = 0;

    part = &ctx->subrequest->headers_out.headers.part;
    header = part->elts;

    for (i = 0; /* void */ ; i++) {

        if (i >= part->nelts) {
            if (part->next == NULL) {
                break;
            }

            part = part->next;
            header = part->elts;
            i = 0;
        }

        if (header[i].hash == 0) {
            continue;
        }

        if (header[i].key.len != sizeof("X-DataDomeResponse") - 1) {
            continue;
        }

        if (ngx_strncmp(header[i].key.data, "X-DataDomeResponse", header[i].key.len) != 0) {
            continue;
        }

        x_datadome_response = header[i].value;

        break;
    }

    if (x_datadome_response.len == 0) {
	    ngx_log_error(NGX_LOG_ERR, r->main->connection->log, 0, "API server response hasn't got X-DataDomeResponse");
	    return NGX_DECLINED;
    }

    if ((ngx_uint_t)ngx_atoi(x_datadome_response.data, x_datadome_response.len) != ctx->subrequest->headers_out.status) {
	    ngx_log_error(NGX_LOG_ERR, r->main->connection->log, 0, "API server response's X-DataDomeResponse (%V) != status (%d)",
	        &x_datadome_response, ctx->subrequest->headers_out.status);
	    return NGX_DECLINED;
    }

	if (ngx_http_data_dome_auth_execute_x_datadome_headers(r->main->pool, "X-DataDome-headers",
	                                                       &ctx->subrequest->headers_out.headers,
	                                                       &r->main->headers_out.headers) == NGX_ERROR) {
	    return NGX_ERROR;
	}

	if (ngx_http_data_dome_auth_execute_x_datadome_headers(r->main->pool, "X-DataDome-request-headers",
	                                                       &ctx->subrequest->headers_out.headers,
	                                                       &r->main->headers_in.headers) == NGX_ERROR) {
	    return NGX_ERROR;
	}

	switch (ctx->subrequest->headers_out.status) {
	case NGX_HTTP_MOVED_PERMANENTLY:
	case NGX_HTTP_MOVED_TEMPORARILY:
	case NGX_HTTP_UNAUTHORIZED:
	case NGX_HTTP_FORBIDDEN:

        part = &ctx->subrequest->headers_out.headers.part;
        header = part->elts;

        for (i = 0; /* void */ ; i++) {

            if (i >= part->nelts) {
                if (part->next == NULL) {
                  break;
                }

                part = part->next;
                header = part->elts;
                i = 0;
            }

            if (header[i].hash == 0) {
                continue;
            }

            if (header[i].key.len != sizeof("Location") - 1) {
                continue;
            }

            if (ngx_strncmp(header[i].key.data, "Location", header[i].key.len) != 0) {
                continue;
            }

            location = ngx_list_push(&r->main->headers_out.headers);
            if (location == NULL) {
              return NGX_HTTP_INTERNAL_SERVER_ERROR;
            }

            location->hash = 1;
            location->key = header[i].key;
            location->lowcase_key = header[i].lowcase_key;
            location->value = header[i].value;

            break;
        }

	    // nginx reset upstream buffer length, so, use body lenght from header ;)
	    val.len = ctx->subrequest->headers_out.content_length_n;
	    val.data = ctx->subrequest->upstream->buffer.pos;

	    // if response hasn't Content-Length and body the length was -1, fix it
	    if (ctx->subrequest->headers_out.content_length_n < 0) {
	      val.len = 0;
	    }

	    if (val.len == 0) {
    	    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
	    		   "Data Dome auth send response without body: s: %d",
		    	   ctx->subrequest->headers_out.status);
            return ctx->subrequest->headers_out.status;
	    }

	    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
			   "Data Dome auth send response: s: %d, c: %V, b: %V",
			   ctx->subrequest->headers_out.status, &ctx->subrequest->headers_out.content_type, &val);

        r->headers_out.status = ctx->subrequest->headers_out.status;

        r->headers_out.content_length_n = val.len;

        if (ctx->subrequest->headers_out.content_type.len) {
            r->headers_out.content_type_len = ctx->subrequest->headers_out.content_type.len;
            r->headers_out.content_type = ctx->subrequest->headers_out.content_type;
        } else {
            if (ngx_http_set_content_type(r) != NGX_OK) {
                return NGX_HTTP_INTERNAL_SERVER_ERROR;
            }
        }

        if (r->method == NGX_HTTP_HEAD || val.len == 0) {
            rc = ngx_http_send_header(r);
            if (rc != NGX_OK) {
                return rc;
            }

            return NGX_DONE;
        }

        b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
        if (b == NULL) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
        b->pos = val.data;
        b->last = val.data + val.len;
        b->memory = val.len ? 1 : 0;
        b->last_buf = (r == r->main) ? 1 : 0;
        b->last_in_chain = 1;

        out.buf = b;
        out.next = NULL;

        rc = ngx_http_send_header(r);

        if (rc == NGX_ERROR || rc > NGX_OK) {
            return rc;
        }

        if (r->header_only) {
            ngx_http_finalize_request(r, NGX_DONE);
            return NGX_DONE;
        }

        rc = ngx_http_output_filter(r, &out);
	    if (rc != NGX_OK) {
	      return rc;
	    }

        ngx_http_finalize_request(r, NGX_DONE);
	    return NGX_DONE;

	case NGX_HTTP_OK:

	    return NGX_OK;

	default:

	    ngx_log_error(NGX_LOG_ERR, r->main->connection->log, 0,
			  "Data Dome auth request unexpected status: %d, pass", ctx->subrequest->headers_out.status);

	    return NGX_OK;
	}
    }

    ctx = ngx_pcalloc(r->main->pool, sizeof(ngx_http_data_dome_auth_ctx_t));
    if (ctx == NULL) {
	return NGX_ERROR;
    }

    if (ngx_http_script_run(r, &ctx->uri, acf->uri_lengths->elts, 0, acf->uri_values->elts)
        == NULL)
    {
        return NGX_ERROR;
    }

    if (ngx_strncmp(ctx->uri.data, "off", ctx->uri.len) == 0) {
	    return NGX_DECLINED;
    }

    ngx_http_set_ctx(r->main, ctx, ngx_http_data_dome_auth_module);

#if (NGX_PCRE)

    if (acf->uri_regex_exclusion) {
        if (ngx_regex_exec(acf->uri_regex_exclusion, &r->main->uri, NULL, 0) != NGX_REGEX_NO_MATCHED) {

            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->main->connection->log, 0,
                  "Data Dome auth URI regex exclusion: \"%V\" match with URI: %V",
                   &acf->uri_regex_exclusion_raw, &r->main->uri);

            ctx->declined = 1;
            return NGX_DECLINED;
        }
    }

    if (acf->uri_regex) {

	if (ngx_regex_exec(acf->uri_regex, &r->main->uri, NULL, 0) != NGX_REGEX_NO_MATCHED) {

	    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->main->connection->log, 0,
			  "Data Dome auth URI regex: \"%V\" match with URI: %V",
			   &acf->uri_regex_raw, &r->main->uri);

	    goto validate;
	}

	ctx->declined = 1;
	return NGX_DECLINED;
    }

 validate:

#endif

    ctx->processing = 1;

    // keep original read and write event handler because read client body may override it
    ctx->read_event_handler = r->main->read_event_handler;
    ctx->write_event_handler = r->main->write_event_handler;

    return ngx_http_data_dome_subrequest(r);
}
ngx_int_t
ngx_http_echo_eval_cmd_args(ngx_http_request_t *r,
        ngx_http_echo_cmd_t *cmd, ngx_array_t *computed_args,
        ngx_array_t *opts)
{
    ngx_uint_t                       i;
    ngx_array_t                     *args = cmd->args;
    ngx_str_t                       *arg, *raw, *opt;
    ngx_http_echo_arg_template_t    *value;
    ngx_flag_t                       expecting_opts = 1;


    value = args->elts;

    for (i = 0; i < args->nelts; i++) {
        raw = &value[i].raw_value;

        if (value[i].lengths == NULL && raw->len > 0) {
            if (expecting_opts) {
                if (raw->len == 1 || raw->data[0] != '-') {
                    expecting_opts = 0;

                } else if (raw->data[1] == '-') {
                    expecting_opts = 0;
                    continue;

                } else {
                    opt = ngx_array_push(opts);
                    if (opt == NULL) {
                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
                    }

                    opt->len = raw->len - 1;
                    opt->data = raw->data + 1;

                    continue;
                }
            }
        }

        arg = ngx_array_push(computed_args);
        if (arg == NULL) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        if (value[i].lengths == NULL) { /* does not contain vars */
            dd("Using raw value \"%.*s\"", (int) raw->len, raw->data);
            *arg = *raw;

        } else {
            if (ngx_http_script_run(r, arg, value[i].lengths->elts,
                        0, value[i].values->elts) == NULL)
            {
                return NGX_HTTP_INTERNAL_SERVER_ERROR;
            }
        }
    }

    return NGX_OK;
}
ngx_int_t 
ngx_http_qrcode_eval_cmd_args(ngx_http_request_t *r,
		ngx_http_qrcode_cmd_t *cmd, ngx_array_t *compiled_args)
{
	ngx_http_qrcode_arg_template_t *value;
	ngx_str_t *arg;
	ngx_uint_t i;

	value = cmd->args->elts;

	for (i = 0; i < cmd->args->nelts; i++) 
	{
		arg = ngx_array_push(compiled_args);

		if (arg == NULL) {
			return NGX_HTTP_INTERNAL_SERVER_ERROR;
		}

		if (value[i].lengths == NULL) { /* does not contain vars */
			*arg = value[i].raw_value;
		}
	   	else {
			if (ngx_http_script_run(r, arg, value[i].lengths->elts,
						0, value[i].values->elts) == NULL) {
				return NGX_HTTP_INTERNAL_SERVER_ERROR;
			}
		}
	}

	return NGX_OK;
}
static ngx_int_t
ngx_http_upstream_init_hash_peer(ngx_http_request_t *r,
    ngx_http_upstream_srv_conf_t *us)
{
    ngx_http_upstream_hash_peer_data_t     *uhpd;

    ngx_str_t val;

    if (ngx_http_script_run(r, &val, us->lengths, 0, us->values) == NULL) {
        return NGX_ERROR;
    }

    uhpd = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_hash_peer_data_t)
            + sizeof(uintptr_t) *
                ((ngx_http_upstream_hash_peers_t *)us->peer.data)->number /
                    (8 * sizeof(uintptr_t)));
    if (uhpd == NULL) {
        return NGX_ERROR;
    }

    r->upstream->peer.data = uhpd;

    uhpd->peers = us->peer.data;

    r->upstream->peer.free = ngx_http_upstream_free_hash_peer;
    r->upstream->peer.get = ngx_http_upstream_get_hash_peer;
    r->upstream->peer.tries = us->retries + 1;
#if (NGX_HTTP_SSL)
    r->upstream->peer.set_session = ngx_http_upstream_set_hash_peer_session;
    r->upstream->peer.save_session = ngx_http_upstream_save_hash_peer_session;
#endif

    /* must be big enough for the retry keys */
    if ((uhpd->current_key.data = ngx_pcalloc(r->pool, NGX_ATOMIC_T_LEN + val.len)) == NULL) {
        return NGX_ERROR;
    }

    ngx_memcpy(uhpd->current_key.data, val.data, val.len);
    uhpd->current_key.len = val.len;
    uhpd->original_key = val;
    uhpd->hash = ngx_http_upstream_hash_crc32(uhpd->current_key.data, uhpd->current_key.len);
    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "upstream_hash: hashed \"%V\" to %ui", &uhpd->current_key,
                   ngx_http_upstream_get_hash_peer_index(uhpd));
    uhpd->try_i = 0;

    /* In case this one is marked down */
    ngx_http_upstream_hash_next_peer(uhpd, &r->upstream->peer.tries, r->connection->log);
    if ((ngx_int_t)r->upstream->peer.tries == -1) {
        return NGX_ERROR;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "upstream_hash: Starting with %ui",
                   ngx_http_upstream_get_hash_peer_index(uhpd));


    return NGX_OK;
}
static ngx_int_t
ngx_http_scgi_eval(ngx_http_request_t *r, ngx_http_scgi_loc_conf_t * scf)
{
    ngx_url_t             url;
    ngx_http_upstream_t  *u;

    ngx_memzero(&url, sizeof(ngx_url_t));

    if (ngx_http_script_run(r, &url.url, scf->scgi_lengths->elts, 0,
                            scf->scgi_values->elts)
        == NULL)
    {
        return NGX_ERROR;
    }

    url.no_resolve = 1;

    if (ngx_parse_url(r->pool, &url) != NGX_OK) {
        if (url.err) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                          "%s in upstream \"%V\"", url.err, &url.url);
        }

        return NGX_ERROR;
    }

    if (url.no_port) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "no port in upstream \"%V\"", &url.url);
        return NGX_ERROR;
    }

    u = r->upstream;

    u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
    if (u->resolved == NULL) {
        return NGX_ERROR;
    }

    if (url.addrs && url.addrs[0].sockaddr) {
        u->resolved->sockaddr = url.addrs[0].sockaddr;
        u->resolved->socklen = url.addrs[0].socklen;
        u->resolved->naddrs = 1;
        u->resolved->host = url.addrs[0].name;

    } else {
        u->resolved->host = url.host;
        u->resolved->port = url.port;
    }

    return NGX_OK;
}
static ngx_int_t
ngx_http_headers_filter(ngx_http_request_t *r)
{
    ngx_str_t                 value;
    ngx_uint_t                i;
    ngx_http_header_val_t    *h;
    ngx_http_headers_conf_t  *conf;

    conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);

    if ((conf->expires == NGX_HTTP_EXPIRES_OFF && conf->headers == NULL)
        || r != r->main
        || (r->headers_out.status != NGX_HTTP_OK
            && r->headers_out.status != NGX_HTTP_NO_CONTENT
            && r->headers_out.status != NGX_HTTP_MOVED_PERMANENTLY
            && r->headers_out.status != NGX_HTTP_MOVED_TEMPORARILY
            && r->headers_out.status != NGX_HTTP_NOT_MODIFIED))
    {
        return ngx_http_next_header_filter(r);
    }

    if (conf->expires != NGX_HTTP_EXPIRES_OFF) {
        if (ngx_http_set_expires(r, conf) != NGX_OK) {
            return NGX_ERROR;
        }
    }

    if (conf->headers) {
        h = conf->headers->elts;
        for (i = 0; i < conf->headers->nelts; i++) {

            if (h[i].lengths == NULL) {
                value = h[i].value.value;

            } else {
                if (ngx_http_script_run(r, &value, h[i].lengths->elts, 0,
                                        h[i].values->elts)
                    == NULL)
                {
                    return NGX_ERROR;
                }
            }

            if (h[i].handler(r, &h[i], &value) != NGX_OK) {
                return NGX_ERROR;
            }
        }
    }

    return ngx_http_next_header_filter(r);
}
Example #7
0
static ngx_int_t
ngx_http_variable_realpath_root(ngx_http_request_t *r,
    ngx_http_variable_value_t *v, uintptr_t data)
{
    size_t                     len;
    ngx_str_t                  path;
    ngx_http_core_loc_conf_t  *clcf;
    u_char                     real[NGX_MAX_PATH];

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    if (clcf->root_lengths == NULL) {
        path = clcf->root;

    } else {
        if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1,
                                clcf->root_values->elts)
            == NULL)
        {
            return NGX_ERROR;
        }

        path.data[path.len - 1] = '\0';

        if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
            return NGX_ERROR;
        }
    }

    if (ngx_realpath(path.data, real) == NULL) {
        ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                      ngx_realpath_n " \"%s\" failed", path.data);
        return NGX_ERROR;
    }

    len = ngx_strlen(real);

    v->data = ngx_pnalloc(r->pool, len);
    if (v->data == NULL) {
        return NGX_ERROR;
    }

    v->len = len;
    v->valid = 1;
    v->no_cacheable = 0;
    v->not_found = 0;

    ngx_memcpy(v->data, real, len);

    return NGX_OK;
}
u_char *
ngx_http_map_filename_to_path(ngx_http_request_t *r, ngx_str_t *filename,
    ngx_str_t *path)
{
    u_char                    *last;
    ngx_http_core_loc_conf_t  *clcf;

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    if (clcf->alias) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      "At present \"alias\" not supported in static delete "
                      "module");
        return NULL;
    }

    if (clcf->root_lengths == NULL) {
        path->len = clcf->root.len + filename->len + 2;
        path->data = ngx_pnalloc(r->pool, path->len);
        if (path->data == NULL) {
            return NULL;
        }

        last = ngx_copy(path->data, clcf->root.data, clcf->root.len);
    } else {

        if (ngx_http_script_run(r, path, clcf->root_lengths->elts,
                                filename->len + 2, clcf->root_values->elts)
            == NULL)
        {
            return NULL;
        }

        if (ngx_conf_full_name((ngx_cycle_t *)ngx_cycle, path, 0) != NGX_OK) {
            return NULL;
        }

        last = path->data + (path->len - filename->len - 2);
    }

    if (filename->data[0] != '/') {
        *last++ = '/';
    }
    last = ngx_cpystrn(last, filename->data, filename->len + 1);
    return last;
}
static ngx_int_t ngx_http_upstream_init_q_chash_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us)
{
    ngx_int_t                                       rc;
    ngx_http_upstream_q_chash_srv_conf_t            *uchscf;
    ngx_http_upstream_q_chash_peer_data_t           *qchp;
    ngx_http_upstream_q_chash_ring                  *q_chash_ring;
    ngx_str_t                                       evaluated_key_to_hash;

    uchscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_q_chash_module);
    if (uchscf == NULL) {
        return NGX_ERROR;
    }

    q_chash_ring = uchscf->q_chash_ring;

    qchp = ngx_pcalloc(r->pool, sizeof(*qchp));
    if(qchp == NULL)
        return NGX_ERROR;
    r->upstream->peer.data = &qchp->rrp;

    qchp->q_chash_ring = q_chash_ring;
    qchp->get_rr_peer = ngx_http_upstream_get_round_robin_peer;
    qchp->tries = 0;
    qchp->ignore = 0;
    qchp->rr_mode = 0;

    rc = ngx_http_upstream_init_round_robin_peer(r, us);
    if(rc != NGX_OK)
        return NGX_ERROR;

    r->upstream->peer.get = ngx_http_upstream_get_q_chash_peer;

    // calculate the vnode_index
    if(q_chash_ring->nr_valid_peers > 1) {
        if (ngx_http_script_run(r, &evaluated_key_to_hash, uchscf->lengths->elts, 0, uchscf->values->elts) == NULL)
            return NGX_ERROR;

        qchp->point = (uint32_t)ngx_crc32_long(evaluated_key_to_hash.data, evaluated_key_to_hash.len);
        qchp->vnode_index = q_chash_find(q_chash_ring, qchp->point);

        ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "q_chash key %V, point %uD, vnode_index %ui", &evaluated_key_to_hash, qchp->point, qchp->vnode_index);
    }

    return NGX_OK;
}
static ngx_int_t
ngx_http_upstream_init_consistent_hash_peer(ngx_http_request_t *r,
        ngx_http_upstream_srv_conf_t *us)
{
    ngx_str_t                                          evaluated_key_to_hash;
    ngx_http_upstream_consistent_hash_srv_conf_t      *uchscf;
    ngx_http_upstream_consistent_hash_peer_data_t     *uchpd;

    uchscf = ngx_http_conf_upstream_srv_conf(us,
            ngx_http_upstream_consistent_hash_module);
    if (uchscf == NULL) {
        return NGX_ERROR;
    }

    uchpd = ngx_pcalloc(r->pool, 
            sizeof(ngx_http_upstream_consistent_hash_peer_data_t));
    if (uchpd == NULL) {
        return NGX_ERROR;
    }

    r->upstream->peer.data = &uchpd->rrp;

    if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) {
        return NGX_ERROR;
    }

    r->upstream->peer.get = ngx_http_upstream_get_consistent_hash_peer;

    uchpd->buckets = uchscf->data;
    uchpd->tries = 0;

    if (ngx_http_script_run(r, &evaluated_key_to_hash, 
                uchscf->lengths->elts, 0, uchscf->values->elts) == NULL)
    {
        return NGX_ERROR;
    }

    uchpd->point = 
        ngx_crc32_long(evaluated_key_to_hash.data, evaluated_key_to_hash.len);

    uchpd->get_rr_peer = ngx_http_upstream_get_round_robin_peer;

    return NGX_OK;
}
static ngx_int_t
ngx_http_upstream_init_chash_peer(ngx_http_request_t *r,
    ngx_http_upstream_srv_conf_t *us)
{
    ngx_str_t                            hash_value;
    ngx_http_upstream_chash_srv_conf_t  *ucscf;
    ngx_http_upstream_chash_peer_data_t *uchpd;

    ucscf = ngx_http_conf_upstream_srv_conf(us,
                                     ngx_http_upstream_consistent_hash_module);
    if (ucscf == NULL) {
        return NGX_ERROR;
    }

    uchpd = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_chash_peer_data_t));
    if (uchpd == NULL) {
        return NGX_ERROR;
    }

    uchpd->ucscf = ucscf;
    if (ngx_http_script_run(r, &hash_value,
                ucscf->lengths->elts, 0, ucscf->values->elts) == NULL) {
        return NGX_ERROR;
    }

    uchpd->hash = ngx_murmur_hash2(hash_value.data, hash_value.len);

    r->upstream->peer.get = ngx_http_upstream_get_chash_peer;
    r->upstream->peer.free = ngx_http_upstream_free_chash_peer;
    r->upstream->peer.data = uchpd;

#if (NGX_HTTP_SSL)
    r->upstream->peer.set_session = ngx_http_upstream_chash_set_peer_session;
    r->upstream->peer.save_session = ngx_http_upstream_chash_save_peer_session;
#endif

    return NGX_OK;
}
static ngx_int_t
ngx_http_upstream_init_consistent_hash_peer(ngx_http_request_t *r,
        ngx_http_upstream_srv_conf_t *us)
{
    ngx_str_t                                          evaluated_key_to_hash;
    ngx_http_upstream_consistent_hash_srv_conf_t      *uchscf;
    ngx_http_upstream_consistent_hash_peer_data_t     *uchpd;

    uchscf = ngx_http_conf_upstream_srv_conf(us,
                                          ngx_http_upstream_consistent_hash_module);
    if (uchscf == NULL) {
        return NGX_ERROR;
    }

    uchpd = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_consistent_hash_peer_data_t));
    if (uchpd == NULL) {
        return NGX_ERROR;
    }

    r->upstream->peer.data = uchpd->peers;
    uchpd->peers = us->peer.data;

    if (ngx_http_script_run(r, &evaluated_key_to_hash, 
                uchscf->lengths->elts, 0, uchscf->values->elts) == NULL)
    {
        return NGX_ERROR;
    }

    uchpd->point = 
        ngx_crc32_long(evaluated_key_to_hash.data, evaluated_key_to_hash.len);

    r->upstream->peer.free = ngx_http_upstream_free_consistent_hash_peer;
    r->upstream->peer.get = ngx_http_upstream_get_consistent_hash_peer;
    r->upstream->peer.data = uchpd;

    return NGX_OK;
}
Example #13
0
static ngx_int_t
ngx_http_variable_document_root(ngx_http_request_t *r,
    ngx_http_variable_value_t *v, uintptr_t data)
{
    ngx_str_t                  path;
    ngx_http_core_loc_conf_t  *clcf;

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    if (clcf->root_lengths == NULL) {
        v->len = clcf->root.len;
        v->valid = 1;
        v->no_cacheable = 0;
        v->not_found = 0;
        v->data = clcf->root.data;

    } else {
        if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0,
                                clcf->root_values->elts)
            == NULL)
        {
            return NGX_ERROR;
        }

        if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
            return NGX_ERROR;
        }

        v->len = path.len;
        v->valid = 1;
        v->no_cacheable = 0;
        v->not_found = 0;
        v->data = path.data;
    }

    return NGX_OK;
}
static ngx_int_t
ngx_http_mogilefs_eval_tracker(ngx_http_request_t *r, ngx_http_mogilefs_loc_conf_t *mgcf)
{
    ngx_str_t             tracker;
    ngx_http_upstream_t  *u;
    ngx_http_mogilefs_ctx_t *ctx;

    ctx = ngx_http_get_module_ctx(r, ngx_http_mogilefs_module);

    if (ngx_http_script_run(r, &tracker, mgcf->tracker_lengths->elts, 0,
                            mgcf->tracker_values->elts)
        == NULL)
    {
        return NGX_ERROR;
    }

    u = r->upstream;

    u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
    if (u->resolved == NULL) {
        return NGX_ERROR;
    }

    if(ctx->peer_addr == NULL) {
        u->resolved->host = tracker;
        u->resolved->no_port = 1;
    }
    else {
        u->resolved->sockaddr = ctx->peer_addr;
        u->resolved->socklen = ctx->peer_addr_len;
        u->resolved->naddrs = 1;
        u->resolved->host = tracker;
    }

    return NGX_OK;
}
/*
 * Do the substitutions from ctx->line_in
 * and output the chain buffers to ctx->out
 * */
static ngx_int_t
ngx_http_subs_match(ngx_http_request_t *r, ngx_http_subs_ctx_t *ctx)
{
    ngx_buf_t   *src, *dst, *temp;
    ngx_log_t   *log;
    ngx_int_t    count, match_count;
    sub_pair_t  *pairs, *pair;
    ngx_uint_t   i;

    count = 0;
    match_count = 0;

    log = r->connection->log;

    src = ctx->line_in;
    dst = ctx->line_dst;

    pairs = (sub_pair_t *) ctx->sub_pairs->elts;
    for (i = 0; i < ctx->sub_pairs->nelts; i++) {

        pair = &pairs[i];

        if (!pair->has_captured) {
            if (pair->sub.data == NULL) {
                if (ngx_http_script_run(r, &pair->sub, pair->sub_lengths->elts,
                                        0, pair->sub_values->elts) == NULL)
                {
                    goto failed;
                }
            }

        } else {
            pair->sub.data = NULL;
            pair->sub.len = 0;
        }

        /* exchange the src and dst buffer */
        if (dst->pos != dst->last) {

            temp = src;
            src = dst;
            dst = temp;

            ngx_buffer_init(dst);
        }

        if ((!pair->regex)
             && ((ngx_uint_t)(src->last - src->pos) < pair->match.len)) {
            continue;
        }

        if (pair->once && pair->matched) {
            continue;
        }

        if (pair->sub.data == NULL && !pair->has_captured) {

            if (ngx_http_script_run(r, &pair->sub, pair->sub_lengths->elts, 0,
                                    pair->sub_values->elts) == NULL)
            {
                goto failed;
            }
        }

        /* regex substitution */
        if (pair->regex || pair->insensitive) {
            count = ngx_http_subs_match_regex_substituion(r, pair, src, dst);
            if (count == NGX_ERROR) {
                goto failed;
            }

        } else {
            /* fixed string substituion */
            count = ngx_http_subs_match_fix_substituion(r, pair, src, dst);
            if (count == NGX_ERROR) {
                goto failed;
            }
        }

        /* no match. */
        if (count == 0){
            continue;
        }

        if (src->pos < src->last) {

            if (buffer_append_string(dst, src->pos, src->last - src->pos,
                                     r->pool) == NULL) {
                goto failed;
            }

            src->pos = src->last;
        }

        /* match */
        match_count += count;
    }

    /* no match last time */
    if (dst->pos == dst->last){
        dst = src;
    }

    if (ngx_http_subs_out_chain_append(r, ctx, dst) != NGX_OK) {
        goto failed;
    }

    ngx_buffer_init(ctx->line_in);
    ngx_buffer_init(ctx->line_dst);

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "match counts: %i", match_count);

    return match_count;

failed:

    ngx_log_error(NGX_LOG_ERR, log, 0,
                  "[subs_filter] ngx_http_subs_match error.");

    return -1;
}
Example #16
0
static ssize_t
ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
    u_char **name, u_char *buf, size_t len)
{
    size_t                     root;
    ssize_t                    n;
    ngx_str_t                  log, path;
    ngx_open_file_info_t       of;
    ngx_http_log_loc_conf_t   *llcf;
    ngx_http_core_loc_conf_t  *clcf;

    if (!r->root_tested) {

        /* test root directory existance */

        if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
            /* simulate successfull logging */
            return len;
        }

        path.data[root] = '\0';

        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

        ngx_memzero(&of, sizeof(ngx_open_file_info_t));

        of.valid = clcf->open_file_cache_valid;
        of.min_uses = clcf->open_file_cache_min_uses;
        of.test_dir = 1;
        of.test_only = 1;
        of.errors = clcf->open_file_cache_errors;
        of.events = clcf->open_file_cache_events;

        if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
            != NGX_OK)
        {
            if (of.err == 0) {
                /* simulate successfull logging */
                return len;
            }

            ngx_log_error(NGX_LOG_ERR, r->connection->log, of.err,
                          "testing \"%s\" existence failed", path.data);

            /* simulate successfull logging */
            return len;
        }

        if (!of.is_dir) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ENOTDIR,
                          "testing \"%s\" existence failed", path.data);

            /* simulate successfull logging */
            return len;
        }
    }

    if (ngx_http_script_run(r, &log, script->lengths->elts, 1,
                            script->values->elts)
        == NULL)
    {
        /* simulate successfull logging */
        return len;
    }

    log.data[log.len - 1] = '\0';
    *name = log.data;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http log \"%s\"", log.data);

    llcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);

    ngx_memzero(&of, sizeof(ngx_open_file_info_t));

    of.log = 1;
    of.valid = llcf->open_file_cache_valid;
    of.min_uses = llcf->open_file_cache_min_uses;
    of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;

    if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool)
        != NGX_OK)
    {
        ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                      "%s \"%s\" failed", of.failed, log.data);
        /* simulate successfull logging */
        return len;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http log #%d", of.fd);

    n = ngx_write_fd(of.fd, buf, len);

    return n;
}
static ngx_int_t
ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
{
    u_char                     ch, *p, *last;
    ngx_str_t                 *uri, *args, u, a;
    ngx_table_elt_t           *location;
    ngx_http_core_loc_conf_t  *clcf;

    r->err_status = err_page->overwrite;

    r->method = NGX_HTTP_GET;
    r->method_name = ngx_http_get_name;

    r->zero_in_uri = 0;

    args = NULL;

    if (err_page->uri_lengths) {
        if (ngx_http_script_run(r, &u, err_page->uri_lengths->elts, 0,
                                err_page->uri_values->elts)
            == NULL)
        {
            return NGX_ERROR;
        }

        p = u.data;
        uri = &u;

        if (*p == '/') {

            last = p + uri->len;

            while (p < last) {

                ch = *p++;

                if (ch == '?') {
                    a.len = last - p;
                    a.data = p;
                    args = &a;

                    u.len = p - 1 - u.data;

                    while (p < last) {
                        if (*p++ == '\0') {
                            r->zero_in_uri = 1;
                            break;
                        }
                    }

                    break;
                }

                if (ch == '\0') {
                    r->zero_in_uri = 1;
                    continue;
                }
            }
        }

    } else {
        uri = &err_page->uri;
    }

    if (uri->data[0] == '/') {
        return ngx_http_internal_redirect(r, uri, args);
    }

    if (uri->data[0] == '@') {
        return ngx_http_named_location(r, uri);
    }

    location = ngx_list_push(&r->headers_out.headers);

    if (location == NULL) {
        return NGX_ERROR;
    }

    r->err_status = NGX_HTTP_MOVED_TEMPORARILY;

    location->hash = 1;
    location->key.len = sizeof("Location") - 1;
    location->key.data = (u_char *) "Location";
    location->value = *uri;

    r->headers_out.location = location;

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    if (clcf->msie_refresh && r->headers_in.msie) {
        return ngx_http_send_refresh(r);
    }

    return ngx_http_send_special_response(r, clcf, NGX_HTTP_MOVED_TEMPORARILY
                                                   - NGX_HTTP_MOVED_PERMANENTLY
                                                   + NGX_HTTP_LEVEL_200);
}
/**
 * @brief nginx module's handler for logger phase
 *
 * This function is responsable to handle the request and log
 * the data we want to the log_zmq via zmq proccess.
 * It's important to note that if this function fails it should
 * not kill the nginx normal running. After all, this is the log
 * phase.
 *
 * @param r A ngx_http_request_t that represents the current request
 * @return A ngx_int_t which can be NGX_ERROR | NGX_OK
 * @note If NGX_DEBUG is setted than we print some messages to the debug log
 */
ngx_int_t
ngx_http_log_zmq_handler(ngx_http_request_t *r)
{
    ngx_http_log_zmq_loc_conf_t         *lccf;
    ngx_http_log_zmq_element_conf_t     *clecf;
    ngx_http_log_zmq_loc_element_conf_t *lelcf, *clelcf;
    ngx_uint_t                          i;
    ngx_str_t                           data;
    ngx_str_t                           zmq_data;
    ngx_str_t                           endpoint;
    ngx_pool_t                          *pool = r->connection->pool;
    ngx_log_t                           *log = r->connection->log;
    ngx_int_t (*serializer)(ngx_pool_t*, ngx_str_t*, ngx_str_t*, ngx_str_t*) = NULL;
    zmq_msg_t query;
    int rc;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler()");

    /* get current location configuration */
    lccf = ngx_http_get_module_loc_conf(r, ngx_http_log_zmq_module);

    /* simply return NGX_OK if location logs are off */
    if (lccf->off == 1) {
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): all logs off");
        return NGX_OK;
    }

    /* location configuration has an ngx_array of log elements, we should iterate
     * by each one
     */
    lelcf = lccf->logs->elts; /* point to the initial position > element 0 */

    /* we use "continue" for each error in the cycle because we do not want the stop
     * the iteration, but continue to the next log */
    for (i = 0; i < lccf->logs->nelts; i++) {

        clelcf = lelcf + i;

        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): %V, off=%d",
                       clelcf->element->name, clelcf->off);

        if (clelcf->off == 1) {
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): element off");
            continue;
        }

        clecf = clelcf->element; /* get the i element of the log array */

        /* worst case? we get a null element ?! */
        if (NULL == clecf) {
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): no element config");
            continue;
        }

        /* we only proceed if all the variables were setted: endpoint, server, format */
        if (clecf->eset == 0 || clecf->fset == 0 || clecf->sset == 0) {
            ngx_log_debug3(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): eset=%d, fset=%d, sset=%d",
                                                       clecf->eset, clecf->fset, clecf->sset);
            continue;
        }

        /* our configuration doesn't has a name? some error ocorred */
        if (NULL == clecf->name || 0 == clecf->name->len) {
            ngx_log_error(NGX_LOG_ERR, log, 0, "log_zmq: handler(): no element name");
            continue;
        } else {
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): setting up \"%V\"", clecf->name);
        }

        /* we set the server variable... but we can use it? */
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): checking server to log");
        if (NULL == clecf->server) {
            ngx_log_error(NGX_LOG_ERR, log, 0, "log_zmq: handler(): no server to log");
            continue;
        } else {
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): server connection \"%V\"", clecf->server->connection);
        }

        /* we set the data format... but we don't have any content to sent? */
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): checking format to log");
        if (NULL == clecf->data_lengths) {
            ngx_log_error(NGX_LOG_ERR, log, 0, "log_zmq: handler(): no format to log");
            continue;
        }

        /* we set the endpoint... but we don't have any valid endpoint? */
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): checking endpoint to log");
        if (NULL == clecf->endpoint_lengths) {
            ngx_log_error(NGX_LOG_ERR, log, 0, "log_zmq: handler(): no endpoint to log");
            continue;
        }

        /* process all data variables and write them back to the data values */
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): script data");
        if (NULL == ngx_http_script_run(r, &data, clecf->data_lengths->elts, 0, clecf->data_values->elts)) {
            ngx_log_error(NGX_LOG_ERR, log, 0, "log_zmq: handler(): error script data");
            continue;
        }

        /* process all endpoint variables and write them back the the endpoint values */
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): script endpoint");
        if (NULL == ngx_http_script_run(r, &endpoint, clecf->endpoint_lengths->elts, 0, clecf->endpoint_values->elts)) {
            ngx_log_error(NGX_LOG_ERR, log, 0, "log_zmq: handler(): error script endpoint");
            continue;
        }

        /* yes, we must go on */
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): logging to server");

        /* no data */
        if (0 == data.len) {
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): no message to log");
            continue;
        }

        /* serialize to the final message format */
        serializer = &log_zmq_serialize;

        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): serializing message");
        if (NGX_ERROR == (*serializer)(pool, &endpoint, &data, &zmq_data)) {
            ngx_log_error(NGX_LOG_ERR, log, 0, "log_zmq: handler(): error serializing message");
            ngx_pfree(pool, zmq_data.data);
            continue;
        }

        /* no context? we dont create any */
        if (NULL == clecf->ctx) {
            ngx_log_error(NGX_LOG_ERR, log, 0, "log_zmq: handler(): no context");
            continue;
        }

        clecf->ctx->log = log;

        rc = 1; /* we should have a rc = 0 after this call */

        /* create zmq context if needed */
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): verify ZMQ context");
        if ((NULL == clecf->ctx->zmq_context) && (0 == clecf->ctx->ccreated)) {
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): creating context");
            rc = zmq_create_ctx(clecf);
            if (rc != 0) {
                ngx_log_error(NGX_LOG_INFO, log, 0, "log_zmq: handler(): error creating context");
                continue;
            }
        }

        /* open zmq socket if needed */
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): verify ZMQ socket");
        if (NULL == clecf->ctx->zmq_socket && 0 == clecf->ctx->screated) {
            ngx_log_debug0(NGX_LOG_INFO, log, 0, "log_zmq: handler(): creating socket");
            rc = zmq_create_socket(pool, clecf);
            if (rc != 0) {
                ngx_log_error(NGX_LOG_INFO, log, 0, "log_zmq: handler(): error creating socket");
                continue;
            }
        }

        /* initialize zmq message */
        zmq_msg_init_size(&query, zmq_data.len);

        ngx_memcpy(zmq_msg_data(&query), zmq_data.data, zmq_data.len);

        if (zmq_msg_send(&query, clecf->ctx->zmq_socket, 0) >= 0) {
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): message sent: %V", &zmq_data);
        } else {
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "log_zmq: handler(): message not sent: %V", &zmq_data);
        }

        /* free all for the next iteration */
        zmq_msg_close(&query);

        ngx_pfree(pool, zmq_data.data);
    }

    return NGX_OK;
}
static ngx_int_t ngx_http_alog_handler(ngx_http_request_t *r)
{
        u_char *line, *p;
        ngx_str_t *computed_log;

        ngx_uint_t l, log_msg_len;
        ngx_http_alog_t *log;

        ngx_http_alog_main_conf_t *lmcf;
        ngx_http_alog_loc_conf_t *llcf;

        lmcf = ngx_http_get_module_main_conf(r, ngx_http_alog_module);
        llcf = ngx_http_get_module_loc_conf(r, ngx_http_alog_module);

        if (lmcf->log_level == NGX_CONF_UNSET || llcf->logs == NULL) {
                return NGX_OK;
        }

        log = llcf->logs->elts;

        for (l = 0; l < llcf->logs->nelts; l++) {

                /* if current log level less than log_level setting, just skip.
                 * actually, low level logs should already have been skipped befroe */
                if (log[l].level < lmcf->log_level) {
                        continue;
                }

                computed_log = NULL;

                if (log[l].script->lengths == NULL) {
                        computed_log = &(log[l].script->raw_value);
                } else {
                        computed_log = ngx_pcalloc(r->pool, sizeof(ngx_str_t));

                        if (computed_log == NULL) {
                                return NGX_HTTP_INTERNAL_SERVER_ERROR;
                        }

                        if (ngx_http_script_run(r, computed_log, log[l].script->lengths->elts, 0, log[l].script->values->elts) == NULL) {
                                return NGX_HTTP_INTERNAL_SERVER_ERROR;
                        } 
                }

                if (computed_log == NULL) {
                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
                }

                log_msg_len = computed_log->len;
                log_msg_len += NGX_LINEFEED_SIZE;

                line = ngx_pcalloc(r->pool, log_msg_len);

                if (line == NULL) {
                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
                }

                p = line;
                p = ngx_cpymem(line, computed_log->data, computed_log->len);
                ngx_linefeed(p);

                if (ngx_http_alog_write(r, line, log_msg_len, log[l].flush) != (ngx_int_t)log_msg_len) {
                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
                }
        }

        return NGX_OK;
}
static ngx_int_t ngx_http_secure_download_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) {
  unsigned timestamp;
  unsigned remaining_time = 0;
  ngx_http_secure_download_loc_conf_t *sdc;
  ngx_http_secure_download_split_uri_t sdsu;
  ngx_str_t secret;
  int value = 0;

  sdc = ngx_http_get_module_loc_conf(r, ngx_http_secure_download_module);
  if (sdc->enable != 1)
  {
      ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
          "securedownload: module not enabled");
      value = -3;
      goto finish;
  }

  if (!sdc->secret_lengths || !sdc->secret_values) {
      ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
          "securedownload: module enabled, but secret key not configured!");
      value = -3;
      goto finish;
  }

  if (ngx_http_secure_download_split_uri(r, &sdsu) == NGX_ERROR)
  {
    ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "securedownload: received an error from ngx_http_secure_download_split_uri", 0);
    value = -3;
    goto finish;
  }

  if (sscanf(sdsu.timestamp, "%08X", &timestamp) != 1)
  {
    ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "securedownload: error in timestamp hex-dec conversion", 0);
    value = -3;
    goto finish;
  }

  remaining_time = timestamp - (unsigned) time(NULL);
  if ((int)remaining_time <= 0)
  {
    ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "securedownload: expired timestamp", 0);
    value = -1;
    goto finish;
  }

  if (ngx_http_script_run(r, &secret, sdc->secret_lengths->elts, 0, sdc->secret_values->elts) == NULL) {
      ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
          "securedownload: evaluation failed");
      value = -3;
      goto finish;
  }

  ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
    "securedownload: evaluated value of secret: \"%V\"", &secret);

  if (ngx_http_secure_download_check_hash(r, &sdsu, &secret) != NGX_OK)
  {
    ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "securedownload: bad hash", 0);
    value = -2;
    goto finish;
  }

  finish:

  v->not_found = 0;
  v->valid = 1;
  v->no_cacheable = 0;
  v->not_found = 0;
  if (value == 0)
  {
    v->data = ngx_pcalloc(r->pool, sizeof(char) * 12);
    if (v->data == NULL) {
        return NGX_ERROR;
    }
    v->len = (int) sprintf((char *)v->data, "%i", remaining_time);
    //printf("valid, %i\n", remaining_time);
  } else {
    v->data = ngx_pcalloc(r->pool, sizeof(char) * 3);
    if (v->data == NULL) {
        return NGX_ERROR;
    }
    v->len = (int) sprintf((char*)v->data, "%i", value);
    //printf("problem %i\n", value);
  }

  return NGX_OK;
}
static ngx_int_t
ngx_http_subs_match_regex_substituion(ngx_http_request_t *r, sub_pair_t *pair,
                                      ngx_buf_t *b, ngx_buf_t *dst)
{
    ngx_str_t  line;
    ngx_log_t *log;
    ngx_int_t  rc, count = 0;

    log = r->connection->log;

    if (pair->captures == NULL || pair->ncaptures == 0) {
        pair->ncaptures = (NGX_HTTP_MAX_CAPTURES + 1) * 3;
        pair->captures = ngx_palloc(r->pool, pair->ncaptures * sizeof(int));
        if (pair->captures == NULL) {
            return NGX_ERROR;
        }
    }

    while (b->pos < b->last) {

        if (pair->once && pair->matched) {
            break;
        }

        line.data = b->pos;
        line.len = b->last - b->pos;

        rc = ngx_regex_exec(pair->match_regex, &line,
                            (int *) pair->captures, pair->ncaptures);

        if (rc == NGX_REGEX_NO_MATCHED) {
            break;

        } else if(rc < 0) {
            ngx_log_error(NGX_LOG_ERR, log, 0,
                          ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
                          rc, &line, &pair->match);

            return NGX_ERROR;
        }

        pair->matched++;
        count++;

        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, log, 0,
                       "regex match:%i, start:%d, end:%d ",
                       rc, pair->captures[0], pair->captures[1]);

        if (pair->has_captured) {
            r->captures = pair->captures;
            r->ncaptures = pair->ncaptures;
            r->captures_data = line.data;

            if (ngx_http_script_run(r, &pair->sub, pair->sub_lengths->elts, 0,
                                    pair->sub_values->elts) == NULL)
            {
                ngx_log_error(NGX_LOG_ALERT, log, 0,
                              "[subs_filter] ngx_http_script_run error.");
                return NGX_ERROR;
            }
        }

        if (buffer_append_string(dst, b->pos, pair->captures[0],
                                 r->pool) == NULL) {
            return NGX_ERROR;
        }

        if (buffer_append_string(dst, pair->sub.data, pair->sub.len,
                                 r->pool) == NULL) {
            return NGX_ERROR;
        }

        b->pos =  b->pos + pair->captures[1];
    }

    return count;
}
Example #22
0
ngx_int_t
ngx_http_fluentd_handler(ngx_http_request_t *r)
{
    u_char                   *line, *p;
    size_t                    len;
    ngx_uint_t                i, l;
    ngx_str_t                 tag;
    ngx_http_fluentd_t        *log;
    ngx_http_log_op_t        *op;
    ngx_http_fluentd_conf_t   *ulcf;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http fluentd handler");

    ulcf = ngx_http_get_module_loc_conf(r, ngx_http_fluentd_module);

    if(ulcf->off) {
        return NGX_OK;
    }

    if(ulcf->tag != NULL)
    {
        if(ulcf->tag->lengths == NULL) {
            tag = ulcf->tag->value;
        }
        else {
            if (ngx_http_script_run(r, &tag, ulcf->tag->lengths->elts, 0, ulcf->tag->values->elts)
                    == NULL)
            {
                return NGX_ERROR;
            }
        }
    }
    else {
        tag.data = (u_char*)"nginx";
        tag.len = sizeof("nginx") - 1;
    }

    log = ulcf->logs->elts;

    for (l = 0; l < ulcf->logs->nelts; l++) {

#if defined nginx_version && nginx_version >= 7018
        ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes);
#endif

        len = 1;
        op = log[l].format->ops->elts;
        for (i = 0; i < log[l].format->ops->nelts; i++) {
            if (op[i].len == 0) {
                len += op[i].getlen(r, op[i].data);

            } else {
                len += op[i].len;
            }
        }

        len += 1 + sizeof("\"tag\":") + 1 + 1 + tag.len + 1 + 1 + 1; /* '{tag: "value", ' */

#if defined nginx_version && nginx_version >= 7003
        line = ngx_pnalloc(r->pool, len);
#else
        line = ngx_palloc(r->pool, len);
#endif
        if (line == NULL) {
            return NGX_ERROR;
        }

        /*
         * JSON Style message
         */
        p = ngx_sprintf(line, "{\"tag\":\"%V\", ", &tag);

        for (i = 0; i < log[l].format->ops->nelts; i++) {
            p = op[i].run(r, p, &op[i]);
        }

        *p++ = '}';

        ngx_http_fluentd_send(log[l].endpoint, line, p - line);
    }

    return NGX_OK;
}
static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t *ctx,
        ngx_str_t *passwd, ngx_http_auth_ldap_loc_conf_t *conf) {

    LDAP *ld;
    LDAPMessage *searchResult;
    LDAPURLDesc *ludpp = conf->ludpp;
    int version = LDAP_VERSION3;
    struct berval bvalue;
    struct timeval timeOut = { 10, 0 };
    int reqcert = LDAP_OPT_X_TLS_ALLOW;

    int rc;
    ngx_uint_t i;
    ngx_ldap_require_t *value;
    ngx_ldap_userinfo *uinfo;

    ngx_flag_t pass = NGX_CONF_UNSET;

    char *dn;
    u_char *p, *filter;

    if (conf->ludpp == NULL) {
	return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    uinfo = ngx_http_auth_ldap_get_user_info(r);
    if (uinfo == NULL) {
	return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

	if (uinfo->password.len == 0)
	{
		return ngx_http_auth_ldap_set_realm(r, &conf->realm);
	}

    /// Set LDAP version to 3 and set connection timeout.
    ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &version);
    ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &timeOut);

    rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &reqcert);
    if (rc != LDAP_OPT_SUCCESS) {
	ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "LDAP: unable to set require cert option: %s",
	        ldap_err2string(rc));
	return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: URL: %s", conf->url.data);

    rc = ldap_initialize(&ld, (const char*) conf->url.data);
    if (rc != LDAP_SUCCESS) {
	ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "LDAP: Session initializing failed: %d, %s, (%s)", rc,
	        ldap_err2string(rc), (const char*) conf->url.data);
	return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: Session initialized", NULL);

    /// Bind to the server
    rc = ldap_simple_bind_s(ld, (const char *) conf->bind_dn.data, (const char *) conf->bind_dn_passwd.data);
    if (rc != LDAP_SUCCESS) {
	ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "LDAP: ldap_simple_bind_s error: %d, %s", rc,
	        ldap_err2string(rc));
	ldap_unbind_s(ld);
	return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: Bind successful", NULL);

    /// Create filter for search users by uid
    filter = ngx_pcalloc(
	    r->pool,
	    (ludpp->lud_filter != NULL ? ngx_strlen(ludpp->lud_filter) : ngx_strlen("(objectClass=*)")) + ngx_strlen("(&(=))")  + ngx_strlen(ludpp->lud_attrs[0])
               + uinfo->username.len + 1);
    p = ngx_sprintf(filter, "(&%s(%s=%s))", ludpp->lud_filter != NULL ? ludpp->lud_filter : "(objectClass=*)", ludpp->lud_attrs[0], uinfo->username.data);
    *p = 0;
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: filter %s", (const char*) filter);

    /// Search the directory
    rc = ldap_search_ext_s(ld, ludpp->lud_dn, ludpp->lud_scope, (const char*) filter, NULL, 0, NULL, NULL, &timeOut, 0,
	    &searchResult);

    if (rc != LDAP_SUCCESS) {
	ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "LDAP: ldap_search_ext_s: %d, %s", rc, ldap_err2string(rc));
	ldap_msgfree(searchResult);
	ldap_unbind_s(ld);
	return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    if (ldap_count_entries(ld, searchResult) > 0) {
	dn = ldap_get_dn(ld, searchResult);
	if (dn != NULL) {
	    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: result DN %s", dn);

	    /// Check require user
	    if (conf->require_user != NULL) {
		value = conf->require_user->elts;
		for (i = 0; i < conf->require_user->nelts; i++) {
		    ngx_str_t val;
		    if (value[i].lengths == NULL)
		    {
			val = value[i].value;
		    }
		    else
		    {
			if (ngx_http_script_run(r, &val, value[i].lengths->elts, 0,
				value[i].values->elts) == NULL)
			{
			    ldap_memfree(dn);
			    ldap_msgfree(searchResult);
			    ldap_unbind_s(ld);
			    return NGX_HTTP_INTERNAL_SERVER_ERROR;
			}
			val.data[val.len] = '\0';
		    }

		    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: compare with: %s", val.data);
		    if (ngx_strncmp(val.data, dn, val.len) == 0) {
			pass = 1;
			if (conf->satisfy_all == 0) {
			    break;
			}
		    } else {
			if (conf->satisfy_all == 1) {
			    ldap_memfree(dn);
			    ldap_msgfree(searchResult);
			    ldap_unbind_s(ld);
			    return ngx_http_auth_ldap_set_realm(r, &conf->realm);
			}
		    }
		}
	    }

	    /// Check require group
	    if (conf->require_group != NULL) {
		if (conf->group_attribute_dn == 1) {
		    bvalue.bv_val = dn;
		    bvalue.bv_len = ngx_strlen(dn);
		} else {
		    bvalue.bv_val = (char*) uinfo->username.data;
		    bvalue.bv_len = uinfo->username.len;
		}

		value = conf->require_group->elts;

		for (i = 0; i < conf->require_group->nelts; i++) {
		    ngx_str_t val;
		    if (value[i].lengths == NULL)
		    {
			val = value[i].value;
		    }
		    else
		    {
			if (ngx_http_script_run(r, &val, value[i].lengths->elts, 0,
				value[i].values->elts) == NULL)
			{
			    ldap_memfree(dn);
			    ldap_msgfree(searchResult);
			    ldap_unbind_s(ld);
			    return NGX_HTTP_INTERNAL_SERVER_ERROR;
			}
			val.data[val.len] = '\0';
		    }

		    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: group compare with: %s", val.data);

		    rc = ldap_compare_ext_s(ld, (const char*) val.data, (const char*) conf->group_attribute.data,
			    &bvalue, NULL, NULL);

		    /*if (rc != LDAP_COMPARE_TRUE && rc != LDAP_COMPARE_FALSE && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
			ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "LDAP: ldap_search_ext_s: %d, %s", rc,
			        ldap_err2string(rc));
			ldap_memfree(dn);
			ldap_msgfree(searchResult);
			ldap_unbind_s(ld);
			return NGX_HTTP_INTERNAL_SERVER_ERROR;
		    }*/

		    if (rc == LDAP_COMPARE_TRUE) {
			pass = 1;
			if (conf->satisfy_all == 0) {
			    break;
			}
		    } else {
			if (conf->satisfy_all == 1) {
			    pass = 0;
			    break;
			}
		    }
		}
	    }

	    /// Check valid user
	    if ( pass != 0 || (conf->require_valid_user == 1 && conf->satisfy_all == 0 && pass == 0)) {
		/// Bind user to the server
		rc = ldap_simple_bind_s(ld, dn, (const char *) uinfo->password.data);
		if (rc != LDAP_SUCCESS) {
		    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "LDAP: ldap_simple_bind_s error: %d, %s", rc,
			    ldap_err2string(rc));
		    pass = 0;
		} else {
		    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: User bind successful", NULL);
		    if (conf->require_valid_user == 1)
			pass = 1;
		}
	    }

	}
	ldap_memfree(dn);
    }

    ldap_msgfree(searchResult);
    ldap_unbind_s(ld);

    if (pass == 1) {
	return NGX_OK;
    }

    return ngx_http_auth_ldap_set_realm(r, &conf->realm);
}
static ngx_int_t
ngx_http_accesskey_handler(ngx_http_request_t *r)
{
    ngx_uint_t   i;
    ngx_uint_t   hashlength,bhashlength;
    ngx_http_accesskey_loc_conf_t  *alcf;

    alcf = ngx_http_get_module_loc_conf(r, ngx_http_accesskey_module);

    if (!alcf->enable) {
        return NGX_OK;
    }

    if (!alcf->signature_lengths || !alcf->signature_values) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "accesskey enabled, but signature not configured!");
        return NGX_HTTP_FORBIDDEN;
    }

    switch(alcf->hashmethod) {
    case NGX_ACCESSKEY_SHA1:
        bhashlength=20;
        break;

    case NGX_ACCESSKEY_MD5:
        bhashlength=16;
        break;

    default:
        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                      "accesskey: hash not supported");
        return NGX_HTTP_FORBIDDEN;
    }
    hashlength=bhashlength*2;

    ngx_str_t args = r->args;
    ngx_str_t look = alcf->arg;

    ngx_uint_t j=0,k=0,l=0;

    for (i = 0; i <= args.len; i++) {
        if ( ( i == args.len) || (args.data[i] == '&') ) {
            if (j > 1) {
                k = j;
                l = i;
            }
            j = 0;
        } else if ( (j == 0) && (i<args.len-look.len) ) {
            if ( (ngx_strncmp(args.data+i, look.data, look.len) == 0)
                    && (args.data[i+look.len] == '=') ) {
                j=i+look.len+1;
                i=j-1;
            } else j=1;
        }
    }

    if (l-k!=hashlength) {
        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                      "accesskey: length %d of \"%V\" argument is not equal %d",
                      l-k, &look, hashlength);
        return NGX_HTTP_FORBIDDEN;
    }

    ngx_str_t val;
    if (ngx_http_script_run(r, &val, alcf->signature_lengths->elts, 0, alcf->signature_values->elts) == NULL) {
        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                      "accesskey: evaluation failed");
        return NGX_ERROR;
    }

    ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                  "accesskey: evaluated value of signature: \"%V\"", &val);

    u_char hashb[64], hasht[128];

    MD5_CTX md5;
    SHA_CTX sha;

    switch(alcf->hashmethod) {
    case NGX_ACCESSKEY_MD5:
        MD5Init(&md5);
        MD5Update(&md5,val.data,val.len);
        MD5Final(hashb, &md5);
        break;
    case NGX_ACCESSKEY_SHA1:
        SHA1_Init(&sha);
        SHA1_Update(&sha,val.data,val.len);
        SHA1_Final(hashb,&sha);
        break;
    };

    static u_char hex[] = "0123456789abcdef";
    u_char *text = hasht;

    for (i = 0; i < bhashlength; i++) {
        *text++ = hex[hashb[i] >> 4];
        *text++ = hex[hashb[i] & 0xf];
    }

    *text = '\0';

    ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                  "accesskey: hash value \"%s\"", hasht);

    if (ngx_strncmp(hasht,args.data+k,hashlength)!=0)
        return NGX_HTTP_FORBIDDEN;

    return NGX_OK;
}
static ngx_int_t
ngx_http_internal_redirect_handler(ngx_http_request_t *r)
{
    u_char                                  *p;
    ngx_uint_t                               i;
    ngx_str_t                                uri, args;
    ngx_http_script_code_pt                  code;
    ngx_http_script_engine_t                 e;
    ngx_http_variable_value_t                stack[10];
    ngx_http_internal_redirect_entry_t      *redirects;
    ngx_http_internal_redirect_main_conf_t  *imcf;
    ngx_http_internal_redirect_loc_conf_t   *ilcf;
    ngx_http_core_main_conf_t               *cmcf;
    ngx_http_phase_handler_t                *ph, *cur_ph, *last_ph, tmp;

    imcf = ngx_http_get_module_main_conf(r, ngx_http_internal_redirect_module);

    if (!imcf->postponed) {

        imcf->postponed = 1;

        cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

        ph = cmcf->phase_engine.handlers;
        cur_ph = &ph[r->phase_handler];
        last_ph = &ph[cur_ph->next - 1];

        if (cur_ph < last_ph) {
            tmp = *cur_ph;

            ngx_memmove(cur_ph, cur_ph + 1,
                        (last_ph - cur_ph) * sizeof(ngx_http_phase_handler_t));

            *last_ph = tmp;
            r->phase_handler--; /* redo the current ph */

            return NGX_DECLINED;
        }
    }

    ilcf = ngx_http_get_module_loc_conf(r, ngx_http_internal_redirect_module);

    if (ilcf->redirects == NULL) {
        return NGX_DECLINED;
    }

    redirects = ilcf->redirects->elts;
    for (i = 0; i < ilcf->redirects->nelts; i++) {
        ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
        ngx_memzero(&stack, sizeof(stack));

        e.sp = stack;
        e.ip = redirects[i].codes->elts;
        e.request = r;
        e.quote = 1;
        e.log = 1;
        e.status = NGX_DECLINED;

        while (*(uintptr_t *) e.ip) {
            code = *(ngx_http_script_code_pt *) e.ip;
            code(&e);
        }

        e.sp--;

        if (e.sp->len && (e.sp->len != 1 || e.sp->data[0] != '0')) {
            break;
        }
    }

    if (i == ilcf->redirects->nelts) {
        return NGX_DECLINED;
    }

    if (redirects[i].code) {
        return redirects[i].code;
    }

    if (redirects[i].lengths) {

        if (ngx_http_script_run(r, &uri, redirects[i].lengths->elts, 0, 
                                redirects->values->elts)
            == NULL)
        {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

    } else {
        uri = redirects[i].name;
    }

    if (uri.data[0] == '@') {

        (void) ngx_http_named_location(r, &uri);

    } else {

        if (uri.data[0] != '/') {
            p = ngx_pcalloc(r->pool, uri.len + 1);
            if (p == NULL) {
                return NGX_HTTP_INTERNAL_SERVER_ERROR;
            }

            uri.len++;
            *p = '/';
            ngx_memcpy(p + 1, uri.data, uri.len);
            uri.data = p;
        }

        ngx_http_split_args(r, &uri, &args);

        (void) ngx_http_internal_redirect(r, &uri, &args);
    }

    ngx_http_finalize_request(r, NGX_DONE);

    return NGX_DONE;
}