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); }
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; }
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; }
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", ×tamp) != 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; }
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; }