static ngx_inline ngx_int_t ngx_http_auth_digest_decode_auth(ngx_http_request_t *r, ngx_str_t *auth_str, char *field_name, ngx_str_t *field_val){ ngx_str_t key; u_char *start, *last; //, *p; key.len = ngx_strlen(field_name) + 2; key.data = ngx_pcalloc(r->pool, key.len); // p = ngx_sprintf(key.data,"%s=", field_name); start = (u_char *) ngx_strstr(auth_str->data, key.data); if (start==NULL){ field_val->len = 1; field_val->data = ngx_pcalloc(r->pool, 1); return 1; } start += key.len-1; if (*start=='"'){ start++; last = (u_char *) ngx_strstr(start+1, "\""); }else{ last = (u_char *) ngx_strstr(start+1, ","); } if (last==NULL) last = auth_str->data + auth_str->len; if (last>start){ field_val->len = last-start + 1; field_val->data = ngx_pcalloc(r->pool, field_val->len); // p = ngx_cpymem(field_val->data, start, last-start); } return 0; }
static ngx_int_t ngx_http_static_delete_handler(ngx_http_request_t *r) { u_char *last; ngx_int_t rc; ngx_str_t filename; ngx_str_t path; size_t root; ngx_http_static_delete_loc_conf_t *sdlcf; sdlcf = ngx_http_get_module_loc_conf(r, ngx_http_static_delete_module); if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK && rc != NGX_AGAIN) { return rc; } rc = ngx_http_complex_value(r, &sdlcf->filename, &filename); if (rc != NGX_OK) { return NGX_ERROR; } if (filename.data[filename.len - 1] == '/') { return NGX_HTTP_NOT_FOUND; } if (ngx_strstr(filename.data, "./")) { return NGX_HTTP_NOT_ALLOWED; } if (ngx_strstr(filename.data, "../")) { return NGX_HTTP_NOT_ALLOWED; } last = ngx_http_map_filename_to_path(r, &filename, &path); if (last == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } path.len = last - path.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http filename: \"%s\"", path.data); if (ngx_delete_file(path.data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_delete_file_n " \"%s\" failed", path.data); return NGX_HTTP_NOT_FOUND; } return ngx_http_static_delete_send_response(r, &path); }
static ngx_int_t ngx_rtmp_play_parse_index(char type, u_char *args) { u_char *p, c; static u_char name[] = "xindex="; name[0] = (u_char) type; for ( ;; ) { p = (u_char *) ngx_strstr(args, name); if (p == NULL) { return 0; } if (p != args) { c = *(p - 1); if (c != '?' && c != '&') { args = p + 1; continue; } } return atoi((char *) p + (sizeof(name) - 1)); } }
static ngx_uint_t ngx_http_access_plus_compute_methods(ngx_str_t *str_methods) { ngx_uint_t m = NGX_HTTP_UNKNOWN; int i = 0; ngx_uint_t methods = 0; if (ngx_strstr(str_methods->data, "*") || ngx_strstr(str_methods->data, "all")) { return ~0; } do { if (ngx_strstr(str_methods->data, ngx_http_access_plus_methods[i])) { methods |= m; } m <<= 1; }while (ngx_http_access_plus_methods[++i]); return methods; }
static void ngx_proc_luashm_backup_thread_cycle(void *data) { ngx_proc_luashm_backup_conf_t *pbcf; ngx_cycle_t *cycle; ngx_shm_zone_t *zone; ngx_str_t *name; ngx_uint_t i; ngx_time_t *tp; int64_t now,settimestamp; cycle = data; pbcf = ngx_proc_get_conf(cycle->conf_ctx, ngx_proc_luashm_backup_module); if(pbcf->settimestamp.data == NULL){ pthread_exit((void *)0); return; } while(pbcf->running){ ngx_time_update(); if(ngx_strstr(pbcf->settimestamp.data,":")==NULL){ settimestamp=ngx_atoi(pbcf->settimestamp.data,pbcf->settimestamp.len); }else{ tp = ngx_timeofday(); now = (int64_t) tp->sec * 1000 + tp->msec; settimestamp=GetTick((char*)pbcf->settimestamp.data)*1000; ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0, "========= now:%lu, settimestamp:%lu =========",now,settimestamp); if(settimestamp<now) settimestamp=(24*60*60*1000)-(now-settimestamp); else settimestamp=settimestamp-now; if(settimestamp==0)settimestamp=1; } ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0, "========= backup time:%s, sleeptime:%lu =========",pbcf->settimestamp.data,settimestamp); ngx_msleep(settimestamp); if(!pbcf->running)break; i = 0; for (; i < pbcf->shdict_names->nelts;i++) { name = ((ngx_str_t*)pbcf->shdict_names->elts) + i; zone = ngx_http_lua_find_zone(name->data,name->len); dd("shm.name:%s,shm.name_len:%ld,shm.size:%ld ", name->data,name->len,zone->shm.size); ngx_proc_luashm_backup_backup(cycle,zone); } ngx_log_error(NGX_LOG_DEBUG, cycle->log, 0, "luashm_backup %V",&ngx_cached_http_time); ngx_sleep(60); if(!pbcf->running)break; } pthread_exit((void *)0); }
static ngx_int_t ngx_streaming_handler(ngx_http_request_t *r) { size_t root; ngx_int_t rc; ngx_uint_t level; ngx_str_t path; ngx_open_file_info_t of; ngx_http_core_loc_conf_t *clcf; if(!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) return NGX_HTTP_NOT_ALLOWED; if(r->uri.data[r->uri.len - 1] == '/') return NGX_DECLINED; rc = ngx_http_discard_request_body(r); if(rc != NGX_OK) return rc; mp4_split_options_t *options = mp4_split_options_init(r); if(r->args.len && !mp4_split_options_set(r, options, (const char *)r->args.data, r->args.len)) { mp4_split_options_exit(r, options); return NGX_DECLINED; } if(!options) return NGX_DECLINED; if(!ngx_http_map_uri_to_path(r, &path, &root, 1)) { mp4_split_options_exit(r, options); return NGX_HTTP_INTERNAL_SERVER_ERROR; } u_int m3u8 = 0; struct bucket_t *bucket = bucket_init(r); int result = 0; { if(ngx_strstr(path.data, "m3u8")) m3u8 = 1; char *ext = strrchr((const char *)path.data, '.'); strcpy(ext, ".mp4"); path.len = ((u_char *)ext - path.data) + 4; // ngx_open_and_stat_file in ngx_open_cached_file expects the name to be zero-terminated. path.data[path.len] = '\0'; } ngx_log_t *nlog = r->connection->log; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, nlog, 0, "http mp4 filename: \"%s\"", path.data); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_memzero(&of, sizeof(ngx_open_file_info_t)); of.read_ahead = clcf->read_ahead; of.directio = NGX_MAX_OFF_T_VALUE; of.valid = clcf->open_file_cache_valid; of.min_uses = clcf->open_file_cache_min_uses; 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) { mp4_split_options_exit(r, options); switch(of.err) { case 0: return NGX_HTTP_INTERNAL_SERVER_ERROR; case NGX_ENOENT: case NGX_ENOTDIR: case NGX_ENAMETOOLONG: level = NGX_LOG_ERR; rc = NGX_HTTP_NOT_FOUND; break; case NGX_EACCES: level = NGX_LOG_ERR; rc = NGX_HTTP_FORBIDDEN; break; default: level = NGX_LOG_CRIT; rc = NGX_HTTP_INTERNAL_SERVER_ERROR; break; } if(rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) { ngx_log_error(level, nlog, of.err, ngx_open_file_n " \"%s\" failed", path.data); } return rc; } if(!of.is_file) { mp4_split_options_exit(r, options); if(ngx_close_file(of.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, nlog, ngx_errno, ngx_close_file_n " \"%s\" failed", path.data); } return NGX_DECLINED; } ngx_file_t *file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); if(file == NULL) { mp4_split_options_exit(r, options); return NGX_HTTP_INTERNAL_SERVER_ERROR; } file->fd = of.fd; file->name = path; file->log = nlog; mp4_context_t *mp4_context = mp4_open(r, file, of.size, MP4_OPEN_MOOV); if(!mp4_context) { mp4_split_options_exit(r, options); ngx_log_error(NGX_LOG_ALERT, nlog, ngx_errno, "mp4_open failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } mp4_context->root = root; if(m3u8) { if((result = mp4_create_m3u8(mp4_context, bucket))) { char action[50]; sprintf(action, "ios_playlist&segments=%d", result); view_count(mp4_context, (char *)path.data, options ? options->hash : NULL, action); } r->allow_ranges = 0; // dirty hack r->headers_out.content_type.data = (u_char *)"application/vnd.apple.mpegurl"; r->headers_out.content_type.len = 29; r->headers_out.content_type_len = r->headers_out.content_type.len; } else { result = output_ts(mp4_context, bucket, options); if(!options || !result) { mp4_close(mp4_context); ngx_log_error(NGX_LOG_ALERT, nlog, ngx_errno, "output_ts failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } char action[50] = "ios_view"; view_count(mp4_context, (char *)path.data, options->hash, action); r->allow_ranges = 1; } mp4_close(mp4_context); mp4_split_options_exit(r, options); result = result == 0 ? 415 : 200; r->root_tested = !r->error_page; if(result && bucket) { nlog->action = "sending mp4 to client"; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, nlog, 0, "content_length: %d", bucket->content_length); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = bucket->content_length; r->headers_out.last_modified_time = of.mtime; if(ngx_http_set_content_type(r) != NGX_OK) return NGX_HTTP_INTERNAL_SERVER_ERROR; if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } //ngx_table_elt_t *h = ngx_list_push(&r->headers_out.headers); //if(h == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR; //h->hash = 1; //h->key.len = sizeof(X_MOD_HLS_KEY) - 1; //h->key.data = (u_char *)X_MOD_HLS_KEY; //h->value.len = sizeof(X_MOD_HLS_VERSION) - 1; //h->value.data = (u_char *)X_MOD_HLS_VERSION; rc = ngx_http_send_header(r); if(rc == NGX_ERROR || rc > NGX_OK || r->header_only) { ngx_log_error(NGX_LOG_ALERT, nlog, ngx_errno, ngx_close_file_n "ngx_http_send_header failed"); return rc; } return ngx_http_output_filter(r, bucket->first); } else return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; }
ngx_int_t ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { int line_break_len; size_t size; u_char *p, *last, *pos; ngx_int_t i, j; ngx_buf_t *b, *first = NULL; unsigned found; ngx_connection_t *c; ngx_http_request_t *mr; ngx_http_connection_t *hc; mr = r->main; hc = r->main->http_connection; c = mr->connection; size = 0; b = c->buffer; if (mr->request_line.data[mr->request_line.len] == CR) { line_break_len = 2; } else { line_break_len = 1; } if (mr->request_line.data >= b->start && mr->request_line.data + mr->request_line.len + line_break_len <= b->pos) { first = b; size += b->pos - mr->request_line.data; } if (hc->nbusy) { b = NULL; for (i = 0; i < hc->nbusy; i++) { b = hc->busy[i]; if (first == NULL) { if (mr->request_line.data >= b->pos || mr->request_line.data + mr->request_line.len + line_break_len <= b->start) { continue; } dd("found first at %d", (int) i); first = b; } size += b->pos - b->start; } } size++; /* plus the null terminator, as required by the later ngx_strstr() call */ v->data = ngx_palloc(r->pool, size); if (v->data == NULL) { return NGX_ERROR; } last = v->data; b = c->buffer; found = 0; if (first == b) { found = 1; pos = b->pos; last = ngx_copy(v->data, mr->request_line.data, pos - mr->request_line.data); if (b != mr->header_in) { /* skip truncated header entries (if any) */ while (last > v->data && last[-1] != LF) { last--; } } i = 0; for (p = v->data; p != last; p++) { if (*p == '\0') { i++; if (p + 1 != last && *(p + 1) == LF) { *p = CR; } else if (i % 2 == 1) { *p = ':'; } else { *p = LF; } } } } if (hc->nbusy) { for (i = 0; i < hc->nbusy; i++) { b = hc->busy[i]; if (!found) { if (b != first) { continue; } dd("found first"); found = 1; } p = last; pos = b->pos; if (b == first) { dd("request line: %.*s", (int) mr->request_line.len, mr->request_line.data); last = ngx_copy(last, mr->request_line.data, pos - mr->request_line.data); } else { last = ngx_copy(last, b->start, pos - b->start); } #if 1 /* skip truncated header entries (if any) */ while (last > p && last[-1] != LF) { last--; } #endif j = 0; for (; p != last; p++) { if (*p == '\0') { j++; if (p + 1 == last) { /* XXX this should not happen */ dd("found string end!!"); } else if (*(p + 1) == LF) { *p = CR; } else if (j % 2 == 1) { *p = ':'; } else { *p = LF; } } } if (b == mr->header_in) { break; } } } *last++ = '\0'; if (last - v->data > (ssize_t) size) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "buffer error when evaluating " "$echo_client__request_headers: \"%V\"", (ngx_int_t) (last - v->data - size)); return NGX_ERROR; } /* strip the leading part (if any) of the request body in our header. * the first part of the request body could slip in because nginx core's * ngx_http_request_body_length_filter and etc can move r->header_in->pos * in case that some of the body data has been preread into r->header_in. */ if ((p = (u_char *) ngx_strstr(v->data, CRLF CRLF)) != NULL) { last = p + sizeof(CRLF CRLF) - 1; } else if ((p = (u_char *) ngx_strstr(v->data, CRLF "\n")) != NULL) { last = p + sizeof(CRLF "\n") - 1; } else if ((p = (u_char *) ngx_strstr(v->data, "\n" CRLF)) != NULL) { last = p + sizeof("\n" CRLF) - 1; } else { for (p = last - 1; p - v->data >= 2; p--) { if (p[0] == LF && p[-1] == CR) { p[-1] = LF; last = p + 1; break; } if (p[0] == LF && p[-1] == LF) { last = p + 1; break; } } } v->len = last - v->data; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; }
static ngx_int_t ngx_rtmp_dash_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) { u_char *p; size_t len; ngx_rtmp_dash_ctx_t *ctx; ngx_rtmp_dash_frag_t *f; ngx_rtmp_dash_app_conf_t *dacf; dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); if (dacf == NULL || !dacf->dash || dacf->path.len == 0) { goto next; } if (s->auto_pushed) { goto next; } ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "dash: publish: name='%s' type='%s'", v->name, v->type); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); if (ctx == NULL) { ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_dash_ctx_t)); if (ctx == NULL) { goto next; } ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_dash_module); } else { if (ctx->opened) { goto next; } f = ctx->frags; ngx_memzero(ctx, sizeof(ngx_rtmp_dash_ctx_t)); ctx->frags = f; } if (ctx->frags == NULL) { ctx->frags = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_dash_frag_t) * (dacf->winfrags * 2 + 1)); if (ctx->frags == NULL) { return NGX_ERROR; } } ctx->id = 0; if (ngx_strstr(v->name, "..")) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "dash: bad stream name: '%s'", v->name); return NGX_ERROR; } ctx->name.len = ngx_strlen(v->name); ctx->name.data = ngx_palloc(s->connection->pool, ctx->name.len + 1); if (ctx->name.data == NULL) { return NGX_ERROR; } *ngx_cpymem(ctx->name.data, v->name, ctx->name.len) = 0; len = dacf->path.len + 1 + ctx->name.len + sizeof(".mpd"); if (dacf->nested) { len += sizeof("/index") - 1; } ctx->playlist.data = ngx_palloc(s->connection->pool, len); p = ngx_cpymem(ctx->playlist.data, dacf->path.data, dacf->path.len); if (p[-1] != '/') { *p++ = '/'; } p = ngx_cpymem(p, ctx->name.data, ctx->name.len); /* * ctx->stream holds initial part of stream file path * however the space for the whole stream path * is allocated */ ctx->stream.len = p - ctx->playlist.data + 1; ctx->stream.data = ngx_palloc(s->connection->pool, ctx->stream.len + NGX_INT32_LEN + sizeof(".m4x")); ngx_memcpy(ctx->stream.data, ctx->playlist.data, ctx->stream.len - 1); ctx->stream.data[ctx->stream.len - 1] = (dacf->nested ? '/' : '-'); if (dacf->nested) { p = ngx_cpymem(p, "/index.mpd", sizeof("/index.mpd") - 1); } else { p = ngx_cpymem(p, ".mpd", sizeof(".mpd") - 1); } ctx->playlist.len = p - ctx->playlist.data; *p = 0; /* playlist bak (new playlist) path */ ctx->playlist_bak.data = ngx_palloc(s->connection->pool, ctx->playlist.len + sizeof(".bak")); p = ngx_cpymem(ctx->playlist_bak.data, ctx->playlist.data, ctx->playlist.len); p = ngx_cpymem(p, ".bak", sizeof(".bak") - 1); ctx->playlist_bak.len = p - ctx->playlist_bak.data; *p = 0; ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "dash: playlist='%V' playlist_bak='%V' stream_pattern='%V'", &ctx->playlist, &ctx->playlist_bak, &ctx->stream); ctx->start_time = *ngx_cached_time; if (ngx_rtmp_dash_ensure_directory(s) != NGX_OK) { return NGX_ERROR; } next: return next_publish(s, v); }
static ngx_int_t ngx_http_upstream_init_consistent(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) { ngx_uint_t i, j, continuum_index, pointer_index, pointer_per_server, pointer_counter, value; ngx_http_upstream_server_t *server; ngx_http_upstream_consistent_peer_t *peers; ngx_http_upstream_consistent_data_t *ucd; ngx_http_upstream_consistent_continuum_item_t *continuum; uint64_t total_weight; us->peer.init = ngx_http_upstream_init_consistent_peer; ucd = us->peer.data; if (!us->servers) { return NGX_ERROR; } server = us->servers->elts; peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_consistent_peer_t) * us->servers->nelts); if (peers == NULL) { return NGX_ERROR; } total_weight = 0; for (i = 0; i < us->servers->nelts; i++) { peers[i].server = &server[i]; total_weight += server[i].weight; } ucd->continuum_count = us->servers->nelts + CONTINUUM_ADDITION; continuum = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_consistent_continuum_item_t) * ucd->continuum_count * POINTS_PER_SERVER); if (continuum == NULL) { return NGX_ERROR; } pointer_counter = continuum_index = 0; for (i = 0; i < us->servers->nelts; ++i) { float pct = (float)peers[i].server->weight / (float)total_weight; pointer_per_server = (ngx_uint_t) ((floorf((float) (pct * POINTS_PER_SERVER / 4 * (float) us->servers->nelts + 0.0000000001))) * 4); // 4 == pointer_per_hash for (pointer_index = 1; pointer_index <= pointer_per_server / 4; pointer_index++) { u_char *sort_host; sort_host = ngx_pcalloc(cf->pool, MAX_HOST_SORT_LENGTH); if (sort_host == NULL) { return NGX_ERROR; } if (ngx_strstr(peers[i].server->addrs->name.data, ":11211") != NULL) { peers[i].server->addrs->name.len -= 6; peers[i].server->addrs->name.data[peers[i].server->addrs->name.len] = '\0'; } ngx_snprintf(sort_host, MAX_HOST_SORT_LENGTH, "%V-%ui%Z", &peers[i].server->addrs->name, pointer_index-1); // 4 == pointer_per_hash for (j = 0; j < 4; j++) { value = ngx_http_upstream_consistent_ketama_hash(sort_host, ngx_strlen(sort_host), j); continuum[continuum_index].index = i; continuum[continuum_index++].value = value; } } pointer_counter += pointer_per_server; } ngx_qsort(continuum, pointer_counter, sizeof(ngx_http_upstream_consistent_continuum_item_t), ngx_http_upstream_consistent_continuum_item_cmp); ucd->peers = peers; ucd->continuum_points_counter = pointer_counter; ucd->continuum = continuum; /* for (i = 0; i < continuum_index; i++) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "upstream_consistent: %i", continuum[i].value); } */ return NGX_OK; }
/* * Function called when the sticky command is parsed on the conf file */ static char *ngx_http_sticky_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_upstream_srv_conf_t *upstream_conf; ngx_http_sticky_srv_conf_t *sticky_conf; ngx_uint_t i; ngx_str_t tmp; ngx_str_t name = ngx_string("route"); ngx_str_t domain = ngx_string(""); ngx_str_t path = ngx_string("/"); ngx_str_t hmac_key = ngx_string(""); time_t expires = NGX_CONF_UNSET; unsigned secure = 0; unsigned httponly = 0; ngx_http_sticky_misc_hash_pt hash = NGX_CONF_UNSET_PTR; ngx_http_sticky_misc_hmac_pt hmac = NULL; ngx_http_sticky_misc_text_pt text = NULL; ngx_uint_t no_fallback = 0; /* parse all elements */ for (i = 1; i < cf->args->nelts; i++) { ngx_str_t *value = cf->args->elts; /* is "name=" is starting the argument ? */ if ((u_char *)ngx_strstr(value[i].data, "name=") == value[i].data) { /* do we have at least one char after "name=" ? */ if (value[i].len <= sizeof("name=") - 1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "a value must be provided to \"name=\""); return NGX_CONF_ERROR; } /* save what's after "name=" */ name.len = value[i].len - ngx_strlen("name="); name.data = (u_char *)(value[i].data + sizeof("name=") - 1); continue; } /* is "domain=" is starting the argument ? */ if ((u_char *)ngx_strstr(value[i].data, "domain=") == value[i].data) { /* do we have at least one char after "domain=" ? */ if (value[i].len <= ngx_strlen("domain=")) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "a value must be provided to \"domain=\""); return NGX_CONF_ERROR; } /* save what's after "domain=" */ domain.len = value[i].len - ngx_strlen("domain="); domain.data = (u_char *)(value[i].data + sizeof("domain=") - 1); continue; } /* is "path=" is starting the argument ? */ if ((u_char *)ngx_strstr(value[i].data, "path=") == value[i].data) { /* do we have at least one char after "path=" ? */ if (value[i].len <= ngx_strlen("path=")) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "a value must be provided to \"path=\""); return NGX_CONF_ERROR; } /* save what's after "domain=" */ path.len = value[i].len - ngx_strlen("path="); path.data = (u_char *)(value[i].data + sizeof("path=") - 1); continue; } /* is "expires=" is starting the argument ? */ if ((u_char *)ngx_strstr(value[i].data, "expires=") == value[i].data) { /* do we have at least one char after "expires=" ? */ if (value[i].len <= sizeof("expires=") - 1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "a value must be provided to \"expires=\""); return NGX_CONF_ERROR; } /* extract value */ tmp.len = value[i].len - ngx_strlen("expires="); tmp.data = (u_char *)(value[i].data + sizeof("expires=") - 1); /* convert to time, save and validate */ expires = ngx_parse_time(&tmp, 1); if (expires == NGX_ERROR || expires < 1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid value for \"expires=\""); return NGX_CONF_ERROR; } continue; } if (ngx_strncmp(value[i].data, "secure", 6) == 0 && value[i].len == 6) { secure = 1; continue; } if (ngx_strncmp(value[i].data, "httponly", 8) == 0 && value[i].len == 8) { httponly = 1; continue; } /* is "text=" is starting the argument ? */ if ((u_char *)ngx_strstr(value[i].data, "text=") == value[i].data) { /* only hash or hmac can be used, not both */ if (hmac || hash != NGX_CONF_UNSET_PTR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "please choose between \"hash=\", \"hmac=\" and \"text\""); return NGX_CONF_ERROR; } /* do we have at least one char after "name=" ? */ if (value[i].len <= sizeof("text=") - 1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "a value must be provided to \"text=\""); return NGX_CONF_ERROR; } /* extract value to temp */ tmp.len = value[i].len - ngx_strlen("text="); tmp.data = (u_char *)(value[i].data + sizeof("text=") - 1); /* is name=raw */ if (ngx_strncmp(tmp.data, "raw", sizeof("raw") - 1) == 0 ) { text = ngx_http_sticky_misc_text_raw; continue; } /* is name=md5 */ if (ngx_strncmp(tmp.data, "md5", sizeof("md5") - 1) == 0 ) { text = ngx_http_sticky_misc_text_md5; continue; } /* is name=sha1 */ if (ngx_strncmp(tmp.data, "sha1", sizeof("sha1") - 1) == 0 ) { text = ngx_http_sticky_misc_text_sha1; continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "wrong value for \"text=\": raw, md5 or sha1"); return NGX_CONF_ERROR; } /* is "hash=" is starting the argument ? */ if ((u_char *)ngx_strstr(value[i].data, "hash=") == value[i].data) { /* only hash or hmac can be used, not both */ if (hmac || text) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "please choose between \"hash=\", \"hmac=\" and \"text=\""); return NGX_CONF_ERROR; } /* do we have at least one char after "hash=" ? */ if (value[i].len <= sizeof("hash=") - 1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "a value must be provided to \"hash=\""); return NGX_CONF_ERROR; } /* extract value to temp */ tmp.len = value[i].len - ngx_strlen("hash="); tmp.data = (u_char *)(value[i].data + sizeof("hash=") - 1); /* is hash=index */ if (ngx_strncmp(tmp.data, "index", sizeof("index") - 1) == 0 ) { hash = NULL; continue; } /* is hash=md5 */ if (ngx_strncmp(tmp.data, "md5", sizeof("md5") - 1) == 0 ) { hash = ngx_http_sticky_misc_md5; continue; } /* is hash=sha1 */ if (ngx_strncmp(tmp.data, "sha1", sizeof("sha1") - 1) == 0 ) { hash = ngx_http_sticky_misc_sha1; continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "wrong value for \"hash=\": index, md5 or sha1"); return NGX_CONF_ERROR; } /* is "hmac=" is starting the argument ? */ if ((u_char *)ngx_strstr(value[i].data, "hmac=") == value[i].data) { /* only hash or hmac can be used, not both */ if (hash != NGX_CONF_UNSET_PTR || text) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "please choose between \"hash=\", \"hmac=\" and \"text\""); return NGX_CONF_ERROR; } /* do we have at least one char after "hmac=" ? */ if (value[i].len <= sizeof("hmac=") - 1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "a value must be provided to \"hmac=\""); return NGX_CONF_ERROR; } /* extract value */ tmp.len = value[i].len - ngx_strlen("hmac="); tmp.data = (u_char *)(value[i].data + sizeof("hmac=") - 1); /* is hmac=md5 ? */ if (ngx_strncmp(tmp.data, "md5", sizeof("md5") - 1) == 0 ) { hmac = ngx_http_sticky_misc_hmac_md5; continue; } /* is hmac=sha1 ? */ if (ngx_strncmp(tmp.data, "sha1", sizeof("sha1") - 1) == 0 ) { hmac = ngx_http_sticky_misc_hmac_sha1; continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "wrong value for \"hmac=\": md5 or sha1"); return NGX_CONF_ERROR; } /* is "hmac_key=" is starting the argument ? */ if ((u_char *)ngx_strstr(value[i].data, "hmac_key=") == value[i].data) { /* do we have at least one char after "hmac_key=" ? */ if (value[i].len <= ngx_strlen("hmac_key=")) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "a value must be provided to \"hmac_key=\""); return NGX_CONF_ERROR; } /* save what's after "hmac_key=" */ hmac_key.len = value[i].len - ngx_strlen("hmac_key="); hmac_key.data = (u_char *)(value[i].data + sizeof("hmac_key=") - 1); continue; } /* is "no_fallback" flag present ? */ if (ngx_strncmp(value[i].data, "no_fallback", sizeof("no_fallback") - 1) == 0 ) { no_fallback = 1; continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid arguement (%V)", &value[i]); return NGX_CONF_ERROR; } /* if has and hmac and name have not been set, default to md5 */ if (hash == NGX_CONF_UNSET_PTR && hmac == NULL && text == NULL) { hash = ngx_http_sticky_misc_md5; } /* don't allow meaning less parameters */ if (hmac_key.len > 0 && hash != NGX_CONF_UNSET_PTR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"hmac_key=\" is meaningless when \"hmac\" is used. Please remove it."); return NGX_CONF_ERROR; } /* ensure we have an hmac key if hmac's been set */ if (hmac_key.len == 0 && hmac != NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "please specify \"hmac_key=\" when using \"hmac\""); return NGX_CONF_ERROR; } /* ensure hash is NULL to avoid conflicts later */ if (hash == NGX_CONF_UNSET_PTR) { hash = NULL; } /* save the sticky parameters */ sticky_conf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_sticky_module); sticky_conf->cookie_name = name; sticky_conf->cookie_domain = domain; sticky_conf->cookie_path = path; sticky_conf->cookie_expires = expires; sticky_conf->cookie_secure = secure; sticky_conf->cookie_httponly = httponly; sticky_conf->hash = hash; sticky_conf->hmac = hmac; sticky_conf->text = text; sticky_conf->hmac_key = hmac_key; sticky_conf->no_fallback = no_fallback; sticky_conf->peers = NULL; /* ensure it's null before running */ upstream_conf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); /* * ensure another upstream module has not been already loaded * peer.init_upstream is set to null and the upstream module use RR if not set * But this check only works when the other module is declared before sticky */ if (upstream_conf->peer.init_upstream) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "You can't use sticky with another upstream module"); return NGX_CONF_ERROR; } /* configure the upstream to get back to this module */ upstream_conf->peer.init_upstream = ngx_http_init_upstream_sticky; upstream_conf->flags = NGX_HTTP_UPSTREAM_CREATE | NGX_HTTP_UPSTREAM_MAX_FAILS | NGX_HTTP_UPSTREAM_FAIL_TIMEOUT | NGX_HTTP_UPSTREAM_DOWN | NGX_HTTP_UPSTREAM_WEIGHT; return NGX_CONF_OK; }
static int ngx_http_lua_ngx_req_raw_header(lua_State *L) { int n, line_break_len; u_char *data, *p, *last, *pos; unsigned no_req_line = 0, found; size_t size; ngx_buf_t *b, *first = NULL; ngx_int_t i, j; ngx_connection_t *c; ngx_http_request_t *r, *mr; ngx_http_connection_t *hc; n = lua_gettop(L); if (n > 0) { no_req_line = lua_toboolean(L, 1); } dd("no req line: %d", (int) no_req_line); r = ngx_http_lua_get_req(L); if (r == NULL) { return luaL_error(L, "no request object found"); } ngx_http_lua_check_fake_request(L, r); mr = r->main; hc = mr->http_connection; c = mr->connection; #if 1 dd("hc->nbusy: %d", (int) hc->nbusy); if (hc->nbusy) { dd("hc->busy: %p %p %p %p", hc->busy[0]->start, hc->busy[0]->pos, hc->busy[0]->last, hc->busy[0]->end); } dd("request line: %p %p", mr->request_line.data, mr->request_line.data + mr->request_line.len); dd("header in: %p %p %p %p", mr->header_in->start, mr->header_in->pos, mr->header_in->last, mr->header_in->end); dd("c->buffer: %p %p %p %p", c->buffer->start, c->buffer->pos, c->buffer->last, c->buffer->end); #endif size = 0; b = c->buffer; if (mr->request_line.data[mr->request_line.len] == CR) { line_break_len = 2; } else { line_break_len = 1; } if (mr->request_line.data >= b->start && mr->request_line.data + mr->request_line.len + line_break_len <= b->pos) { first = b; size += b->pos - mr->request_line.data; } dd("size: %d", (int) size); if (hc->nbusy) { b = NULL; for (i = 0; i < hc->nbusy; i++) { b = hc->busy[i]; dd("busy buf: %d: [%.*s]", (int) i, (int) (b->pos - b->start), b->start); if (first == NULL) { if (mr->request_line.data >= b->pos || mr->request_line.data + mr->request_line.len + line_break_len <= b->start) { continue; } dd("found first at %d", (int) i); first = b; } dd("adding size %d", (int) (b->pos - b->start)); size += b->pos - b->start; } } size++; /* plus the null terminator, as required by the later ngx_strstr() call */ dd("header size: %d", (int) size); data = lua_newuserdata(L, size); last = data; b = c->buffer; found = 0; if (first == b) { found = 1; pos = b->pos; if (no_req_line) { last = ngx_copy(data, mr->request_line.data + mr->request_line.len + line_break_len, pos - mr->request_line.data - mr->request_line.len - line_break_len); } else { last = ngx_copy(data, mr->request_line.data, pos - mr->request_line.data); } if (b != mr->header_in) { /* skip truncated header entries (if any) */ while (last > data && last[-1] != LF) { last--; } } i = 0; for (p = data; p != last; p++) { if (*p == '\0') { i++; if (p + 1 != last && *(p + 1) == LF) { *p = CR; } else if (i % 2 == 1) { *p = ':'; } else { *p = LF; } } } } if (hc->nbusy) { for (i = 0; i < hc->nbusy; i++) { b = hc->busy[i]; if (!found) { if (b != first) { continue; } dd("found first"); found = 1; } p = last; pos = b->pos; if (b == first) { dd("request line: %.*s", (int) mr->request_line.len, mr->request_line.data); if (no_req_line) { last = ngx_copy(last, mr->request_line.data + mr->request_line.len + line_break_len, pos - mr->request_line.data - mr->request_line.len - line_break_len); } else { last = ngx_copy(last, mr->request_line.data, pos - mr->request_line.data); } } else { last = ngx_copy(last, b->start, pos - b->start); } #if 1 /* skip truncated header entries (if any) */ while (last > p && last[-1] != LF) { last--; } #endif j = 0; for (; p != last; p++) { if (*p == '\0') { j++; if (p + 1 == last) { /* XXX this should not happen */ dd("found string end!!"); } else if (*(p + 1) == LF) { *p = CR; } else if (j % 2 == 1) { *p = ':'; } else { *p = LF; } } } if (b == mr->header_in) { break; } } } *last++ = '\0'; if (last - data > (ssize_t) size) { return luaL_error(L, "buffer error: %d", (int) (last - data - size)); } /* strip the leading part (if any) of the request body in our header. * the first part of the request body could slip in because nginx core's * ngx_http_request_body_length_filter and etc can move r->header_in->pos * in case that some of the body data has been preread into r->header_in. */ if ((p = (u_char *) ngx_strstr(data, CRLF CRLF)) != NULL) { last = p + sizeof(CRLF CRLF) - 1; } else if ((p = (u_char *) ngx_strstr(data, CRLF "\n")) != NULL) { last = p + sizeof(CRLF "\n") - 1; } else if ((p = (u_char *) ngx_strstr(data, "\n" CRLF)) != NULL) { last = p + sizeof("\n" CRLF) - 1; } else { for (p = last - 1; p - data >= 2; p--) { if (p[0] == LF && p[-1] == CR) { p[-1] = LF; last = p + 1; break; } if (p[0] == LF && p[-1] == LF) { last = p + 1; break; } } } lua_pushlstring(L, (char *) data, last - data); return 1; }
static void ngx_wirte_tracking_into_mongodb(ngx_http_request_t *r, ngx_http_vesb_aio_log_main_conf_t *valcf,ngx_http_vesb_aio_log_loc_conf_t *vallcf,int timeuse) { mongo conn[1]; char *conn_str; int port,status,insertstatus; time_t timenow; ngx_list_part_t *part = &r->headers_in.headers.part; ngx_table_elt_t *header = part->elts; ngx_uint_t i; if(r->headers_out.status == NGX_HTTP_OK) { conn_str = (char *)valcf->mongodb_conn_str.data; port = (int)valcf->mongodb_conn_port; status = mongo_client( conn, conn_str, port ); if( status == MONGO_OK ) { mongo_set_op_timeout( conn, 10000 );//time oust 10000 ms time ( &timenow ); bson b[1]; bson_init( b ); bson_append_new_oid( b, "_id" ); if( r->headers_in.x_forwarded_for == NULL ) { bson_append_string_n( b, "realclientip" , (char *)r->connection->addr_text.data, r->connection->addr_text.len); } else { bson_append_string_n( b, "realclientip" , (char *)r->headers_in.x_forwarded_for->value.data,r->headers_in.x_forwarded_for->value.len); } bson_append_int( b,"statuscode",r->headers_out.status); bson_append_int( b,"usetime",timeuse); bson_append_long( b,"requestsize",r->request_length); bson_append_long( b,"responsesize",r->headers_out.content_length_n); bson_append_time_t( b,"invoketime",timenow ); if(vallcf->app_name.data != NULL) { bson_append_string_n( b,"appname",(char *)vallcf->app_name.data,vallcf->app_name.len); } else { bson_append_string( b,"appname","undefine"); } /*get method name*/ 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(ngx_strstr(header[i].key.data,"SOAPAction") != NULL) { bson_append_string_n( b,"SOAPAction",(char *)header[i].value.data,header[i].value.len); } else if(ngx_strstr(header[i].key.data,"Content-Type") != NULL) { bson_append_string_n( b,"Content-Type",(char *)header[i].value.data,header[i].value.len); } } bson_finish( b ); insertstatus = mongo_insert( conn,"vesb.tracking", b , NULL ); if( insertstatus != MONGO_OK ) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "insert tracking log in mongodb is failed!(error:%d)",conn[0].err); } bson_destroy( b ); } else { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "mongodb is unconnection!(error:%d)",status); } mongo_destroy( conn ); } }
static ngx_str_t* ngx_http_graphicsmagick_get_command(ngx_http_request_t *r) { u_char *dst, *src; size_t len; u_char *p, *start_p; ngx_uint_t i; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_str_t *ret; part = &r->headers_in.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].key.len == ngx_http_graphicsmagick_command_header.len && ngx_strncmp(header[i].key.data, ngx_http_graphicsmagick_command_header.data, header[i].key.len) == 0) { ret = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); ret->data = header[i].value.data; ret->len = header[i].value.len; return ret; } } /* not found, check as a reaquest arg */ if (r->args.len) { p = (u_char *) ngx_strstr(r->args.data, "X-ImageMagick-Convert"); if (p) { start_p = p += 22; while (p < r->args.data + r->args.len) { if (*p++ != '&') { continue; } } ret = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); ret->data = start_p; ret->len = p - start_p; dst = ret->data; src = ret->data; ngx_unescape_uri(&dst, &src, ret->len, NGX_UNESCAPE_URI); len = (ret->data + ret->len) - src; if (len) { dst = ngx_copy(dst, src, len); } ret->len = dst - ret->data; return ret; } } return NULL; }
static char * ngx_http_naxsi_cr_loc_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_dummy_loc_conf_t *alcf = conf, **bar; ngx_http_dummy_main_conf_t *main_cf; ngx_str_t *value; ngx_http_check_rule_t *rule_c; unsigned int i; u_char *var_end; if (!alcf || !cf) return (NGX_CONF_ERROR); value = cf->args->elts; main_cf = ngx_http_conf_get_module_main_conf(cf, ngx_http_naxsi_module); if (!alcf->pushed) { bar = ngx_array_push(main_cf->locations); if (!bar) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ *bar = alcf; alcf->pushed = 1; } if (ngx_strcmp(value[0].data, TOP_CHECK_RULE_T) && ngx_strcmp(value[0].data, TOP_CHECK_RULE_N)) return (NGX_CONF_ERROR); /* #ifdef _debug_readconf */ /* ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, */ /* "pushing rule %d in check rules", rule.rule_id); */ /* #endif */ i = 0; if (!alcf->check_rules) alcf->check_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_check_rule_t)); if (!alcf->check_rules) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ rule_c = ngx_array_push(alcf->check_rules); if (!rule_c) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memset(rule_c, 0, sizeof(ngx_http_check_rule_t)); /* process the first word : score rule */ if (value[1].data[i] == '$') { var_end = (u_char *) ngx_strchr((value[1].data)+i, ' '); if (!var_end) { /* LCOV_EXCL_START */ ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); /* LCOV_EXCL_STOP */ } rule_c->sc_tag.len = var_end - value[1].data; rule_c->sc_tag.data = ngx_pcalloc(cf->pool, rule_c->sc_tag.len + 1); if (!rule_c->sc_tag.data) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_c->sc_tag.data, value[1].data, rule_c->sc_tag.len); i += rule_c->sc_tag.len + 1; } else { /* LCOV_EXCL_START */ ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); /* LCOV_EXCL_STOP */ } // move to next word while (value[1].data[i] && value[1].data[i] == ' ') i++; // get the comparison type if (value[1].data[i] == '>' && value[1].data[i+1] == '=') rule_c->cmp = SUP_OR_EQUAL; else if (value[1].data[i] == '>' && value[1].data[i+1] != '=') rule_c->cmp = SUP; else if (value[1].data[i] == '<' && value[1].data[i+1] == '=') rule_c->cmp = INF_OR_EQUAL; else if (value[1].data[i] == '<' && value[1].data[i+1] != '=') rule_c->cmp = INF; else { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } // move to next word while (value[1].data[i] && !(value[1].data[i] >= '0' && value[1].data[i] <= '9') && (value[1].data[i] != '-')) i++; NX_LOG_DEBUG(_debug_readconf, NGX_LOG_EMERG, cf, 0, "XX-special score in checkrule:%s from (%d)", value[1].data, atoi((const char *)value[1].data+i)); // get the score rule_c->sc_score = atoi((const char *)(value[1].data+i)); /* process the second word : Action rule */ if (ngx_strstr(value[2].data, "BLOCK")) rule_c->block = 1; else if (ngx_strstr(value[2].data,"ALLOW")) rule_c->allow = 1; else if (ngx_strstr(value[2].data, "LOG")) rule_c->log = 1; else if (ngx_strstr(value[2].data, "DROP")) rule_c->drop = 1; else { /* LCOV_EXCL_START */ ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); /* LCOV_EXCL_STOP */ } return (NGX_CONF_OK); }
static ngx_uint_t ngx_http_browser(ngx_http_request_t *r, ngx_http_browser_conf_t *cf) { size_t len; u_char *name, *ua, *last, c; ngx_str_t *ancient; ngx_uint_t i, version, ver, scale; ngx_http_modern_browser_t *modern; if (r->headers_in.user_agent == NULL) { if (cf->modern_unlisted_browsers) { return NGX_HTTP_MODERN_BROWSER; } return NGX_HTTP_ANCIENT_BROWSER; } ua = r->headers_in.user_agent->value.data; len = r->headers_in.user_agent->value.len; last = ua + len; if (cf->modern_browsers) { modern = cf->modern_browsers->elts; for (i = 0; i < cf->modern_browsers->nelts; i++) { name = ua + modern[i].skip; if (name >= last) { continue; } name = (u_char *) ngx_strstr(name, modern[i].name); if (name == NULL) { continue; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "browser: \"%s\"", name); name += modern[i].add; if (name >= last) { continue; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "version: \"%ui\" \"%s\"", modern[i].version, name); version = 0; ver = 0; scale = 1000000; while (name < last) { c = *name++; if (c >= '0' && c <= '9') { ver = ver * 10 + (c - '0'); continue; } if (c == '.') { version += ver * scale; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "version: \"%ui\" \"%ui\"", modern[i].version, version); if (version > modern[i].version) { return NGX_HTTP_MODERN_BROWSER; } ver = 0; scale /= 100; continue; } break; } version += ver * scale; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "version: \"%ui\" \"%ui\"", modern[i].version, version); if (version >= modern[i].version) { return NGX_HTTP_MODERN_BROWSER; } return NGX_HTTP_ANCIENT_BROWSER; } if (!cf->modern_unlisted_browsers) { return NGX_HTTP_ANCIENT_BROWSER; } } if (cf->netscape4) { if (len > sizeof("Mozilla/4.72 ") - 1 && ngx_strncmp(ua, "Mozilla/", sizeof("Mozilla/") - 1) == 0 && ua[8] > '0' && ua[8] < '5') { return NGX_HTTP_ANCIENT_BROWSER; } } if (cf->ancient_browsers) { ancient = cf->ancient_browsers->elts; for (i = 0; i < cf->ancient_browsers->nelts; i++) { if (len >= ancient[i].len && ngx_strstr(ua, ancient[i].data) != NULL) { return NGX_HTTP_ANCIENT_BROWSER; } } } if (cf->modern_unlisted_browsers) { return NGX_HTTP_MODERN_BROWSER; } return NGX_HTTP_ANCIENT_BROWSER; }
//#define readconf_debug static char * ngx_http_dummy_read_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_dummy_loc_conf_t *alcf = conf, **bar; ngx_http_dummy_main_conf_t *main_cf; ngx_str_t *value; ngx_http_rule_t rule, *rule_r; ngx_http_check_rule_t *rule_c; ngx_http_custom_rule_location_t *location; unsigned int i; u_char *var_end; #ifdef readconf_debug if (cf) { value = cf->args->elts; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "TOP READ CONF %V %V", &(value[0]), &(value[1])); } #endif if (!alcf || !cf) return (NGX_CONF_ERROR); value = cf->args->elts; main_cf = ngx_http_conf_get_module_main_conf(cf, ngx_http_naxsi_module); if (!alcf->pushed) { bar = ngx_array_push(main_cf->locations); if (!bar) return (NGX_CONF_ERROR); *bar = alcf; alcf->pushed = 1; } /* store denied URL for location */ if (!ngx_strcmp(value[0].data, TOP_DENIED_URL_T) && value[1].len) { alcf->denied_url = ngx_pcalloc(cf->pool, sizeof(ngx_str_t)); if (!alcf->denied_url) return (NGX_CONF_ERROR); alcf->denied_url->data = ngx_pcalloc(cf->pool, value[1].len+1); if (!alcf->denied_url->data) return (NGX_CONF_ERROR); memcpy(alcf->denied_url->data, value[1].data, value[1].len); alcf->denied_url->len = value[1].len; return (NGX_CONF_OK); } /* it's a flagrule, just a hack to enable/disable mod */ if (!ngx_strcmp(value[0].data, TOP_ENABLED_FLAG_T)) { alcf->enabled = 1; return (NGX_CONF_OK); } /* it's a flagrule, just a hack to enable/disable mod */ if (!ngx_strcmp(value[0].data, TOP_DISABLED_FLAG_T)) { alcf->force_disabled = 1; return (NGX_CONF_OK); } /* it's a flagrule, currently just a hack to enable/disable learning mode */ if (!ngx_strcmp(value[0].data, TOP_LEARNING_FLAG_T)) { alcf->learning = 1; return (NGX_CONF_OK); } if (!ngx_strcmp(value[0].data, TOP_BASIC_RULE_T)) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "XX-TOP READ CONF %s", value[0].data); #endif memset(&rule, 0, sizeof(ngx_http_rule_t)); if (ngx_http_dummy_cfg_parse_one_rule(cf, value, &rule, cf->args->nelts) != NGX_CONF_OK) { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } /* push in whitelist rules, as it have a whitelist ID array */ if (rule.wl_id) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in whitelist rules", rule.rule_id); #endif if (alcf->whitelist_rules == NULL) { alcf->whitelist_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->whitelist_rules == NULL) { return NGX_CONF_ERROR; } } rule_r = ngx_array_push(alcf->whitelist_rules); if (!rule_r) { return (NGX_CONF_ERROR); } memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* else push in appropriate ruleset */ else { if (rule.br->headers) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in header rules", rule.rule_id); #endif if (alcf->header_rules == NULL) { alcf->header_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->header_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->header_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in body match rules (POST/PUT) */ if (rule.br->body || rule.br->body_var) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in body rules", rule.rule_id); #endif if (alcf->body_rules == NULL) { alcf->body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->body_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->body_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in generic rules, as it's matching the URI */ if (rule.br->url) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in generic rules", rule.rule_id); #endif if (alcf->generic_rules == NULL) { alcf->generic_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->generic_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->generic_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in GET arg rules, but we should push in POST rules too */ if (rule.br->args_var || rule.br->args) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in GET rules", rule.rule_id); #endif if (alcf->get_rules == NULL) { alcf->get_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->get_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->get_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in custom locations. It's a rule matching a VAR_NAME or an EXACT_URI : - GET_VAR, POST_VAR, URI */ if (rule.br->custom_location) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in custom_location rules", rule.rule_id); #endif location = rule.br->custom_locations->elts; for (i = 0; i < rule.br->custom_locations->nelts; i++) { if (location[i].args_var) { if (alcf->get_rules == NULL) { alcf->get_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->get_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->get_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } if (location[i].body_var) { if (alcf->body_rules == NULL) { alcf->body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->body_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->body_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } if (location[i].headers_var) { if (alcf->header_rules == NULL) { alcf->header_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->header_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->header_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } } } } return (NGX_CONF_OK); } /* this should be moved in a function, plus this code is not safe. */ else if (!ngx_strcmp(value[0].data, TOP_CHECK_RULE_T)) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in check rules", rule.rule_id); #endif i = 0; if (!alcf->check_rules) alcf->check_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_check_rule_t)); if (!alcf->check_rules) return (NGX_CONF_ERROR); rule_c = ngx_array_push(alcf->check_rules); if (!rule_c) return (NGX_CONF_ERROR); memset(rule_c, 0, sizeof(ngx_http_check_rule_t)); /* process the first word : score rule */ if (value[1].data[i] == '$') { #ifdef MDBG ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "XX-special score rule !"); #endif var_end = (u_char *) ngx_strchr((value[1].data)+i, ' '); if (!var_end) { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } rule_c->sc_tag.data = ngx_pcalloc(cf->pool, var_end - value[1].data +1); if (!rule_c->sc_tag.data) return (NGX_CONF_ERROR); memcpy(rule_c->sc_tag.data, value[1].data, (var_end - value[1].data)); i += (var_end - value[1].data) + 1; rule_c->sc_tag.len = (var_end - value[1].data); } else { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } // move to next word while (value[1].data[i] && value[1].data[i] == ' ') i++; // get the comparison type if (value[1].data[i] == '>' && value[1].data[i+1] == '=') rule_c->cmp = SUP_OR_EQUAL; else if (value[1].data[i] == '>' && value[1].data[i+1] != '=') rule_c->cmp = SUP; else if (value[1].data[i] == '<' && value[1].data[i+1] == '=') rule_c->cmp = INF_OR_EQUAL; else if (value[1].data[i] == '<' && value[1].data[i+1] != '=') rule_c->cmp = INF; else { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } // move to next word while (value[1].data[i] && !(value[1].data[i] >= '0' && value[1].data[i] <= '9') && (value[1].data[i] != '-')) i++; #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "XX-special score in checkrule:%s from (%d)", value[1].data, atoi((const char *)value[1].data+i)); #endif // get the score rule_c->sc_score = atoi((const char *)(value[1].data+i)); /* process the second word : Action rule */ if (!ngx_strstr(value[2].data, "BLOCK")) rule_c->block = 1; else if (!ngx_strstr(value[2].data, "ALLOW")) rule_c->block = 1; else if (!ngx_strstr(value[2].data, "LOG")) rule_c->block = 1; else { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } return (NGX_CONF_OK); } ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); }
static ngx_int_t ngx_http_data_dome_auth_execute_x_datadome_headers(ngx_pool_t *pool, const char* x_datadome_header, ngx_list_t *src, ngx_list_t *dst) { u_char *end; ngx_str_t x_datadome_headers; ngx_uint_t i, j; ngx_list_part_t *part, *sub_part; ngx_table_elt_t *header, *sub_header, *new_header; ngx_uint_t x_datadome_header_len = strlen(x_datadome_header); part = &src->part; header = part->elts; x_datadome_headers.len = 0; x_datadome_headers.data = NULL; 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 != x_datadome_header_len) { continue; } if (ngx_strncmp(header[i].key.data, x_datadome_header, header[i].key.len) != 0) { continue; } x_datadome_headers.len = header[i].value.len; x_datadome_headers.data = ngx_pcalloc(pool, x_datadome_headers.len + 1); if (x_datadome_headers.data == NULL) { return NGX_ERROR; } (void) ngx_cpymem(x_datadome_headers.data, header[i].value.data, x_datadome_headers.len); break; } while (x_datadome_headers.len > 0) { end = (u_char *) ngx_strstr(x_datadome_headers.data, " "); if (end == NULL) { end = x_datadome_headers.data + x_datadome_headers.len; } part = &src->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 != (size_t) (end - x_datadome_headers.data)) { continue; } if (ngx_strncmp(header[i].key.data, x_datadome_headers.data, header[i].key.len) != 0) { continue; } sub_part = &dst->part; sub_header = sub_part->elts; new_header = NULL; for (j = 0; /* void */ ; j++) { if (j >= sub_part->nelts) { if (sub_part->next == NULL) { break; } sub_part = sub_part->next; sub_header = sub_part->elts; j = 0; } if (sub_header[j].hash == 0) { continue; } if (sub_header[j].key.len != header[i].key.len) { continue; } if (ngx_strncmp(sub_header[j].key.data, header[i].key.data, sub_header[j].key.len) != 0) { continue; } if (sub_header[j].key.len == sizeof("Set-Cookie") - 1 && ngx_strncmp(sub_header[j].key.data, "Set-Cookie", sub_header[j].key.len) == 0) { break; } new_header = &sub_header[j]; break; } if (new_header == NULL) { new_header = ngx_list_push(dst); if (new_header == NULL) { return NGX_ERROR; } } new_header->hash = 1; new_header->key = header[i].key; new_header->value = header[i].value; new_header->lowcase_key = header[i].lowcase_key; break; } x_datadome_headers.len -= end - x_datadome_headers.data; x_datadome_headers.data = end; while (*x_datadome_headers.data == ' ') { x_datadome_headers.data++; x_datadome_headers.len--; } } return NGX_OK; }