(4) ap_process_request_internal
多数のフック関数が実行されている、この関数の中を覗いてみる。handlerフック関数の実行処理 に書いたap_process_async_request()で実行されている関数だ。
ちなみに2.4.9と2.4.10の間では、server/request.cに相違点はないようだった。
従って、ap_process_request_internal関数にも違いはない。
(httpd-2.4.9/server/request.c)
126 AP_DECLARE(int) ap_process_request_internal(request_rec *r)
127 {
128 int file_req = (r->main && r->filename);
request_recのmain変数は、リクエストのサブリクエストから見た親リクエストを指す。
mainに値があるということは処理中のrequest_recはサブリクエストということだ。
サブリクエストというのは、リクエスト処理中に副次的に発生した処理すべきパスに対してリクエスト処理と一定の例外を除いて同様の操作を行う仕掛けだ。
サブリクエストが直接レスポンスを返すことはないが、リソースのファイルシステム上のパスの判定や、あるいは、アクセスチェックなどは行われる必要があったりする。
そうした処理のために用いられる。
(見たところ、ap_sub_req_method_uri()や、ap_sub_req_lookup_dirent()、ap_sub_req_lookup_file()といった 関数から処理が行われている)
リソースのファイルシステム上のパスは、request_recのfilenameに収められる。
URLパスから生成されるサブリクエストの場合はfilenameはnulと考えられる。
129 int access_status;
130 core_dir_config *d;
131
132 /* Ignore embedded %2F's in path for proxy requests */
コメントによれば、proxyへのリクエストのパスに含まれている "%2F"(エンコードされたスラッシュ)は 無視するとある。
proxyへのリクエストでなければ、無視しないという意味なんだろう。
133 if (!r->proxyreq && r->parsed_uri.path) {
request_recのproxyreq変数は、このリクエストがproxyサーバへのリクエストの場合に種別が記録される。
proxyの設定が行われていて、proxyモジュールが受け取ったリクエストを処理対象と判断した場合に値が入る。
このif文はその否定なので、proxyへのリクエストではないリクエストが処理対象となる。
かつ、parsed_uri.path にも値が入っている場合だ。
134 d = ap_get_core_module_config(r->per_dir_config);
これはcoreモジュールの設定情報のアドレスを取得するマクロだ。
r->per_dir_configにモジュールの設定情報が入っている。
この中のcoreモジュールの設定情報の 場所を返してくれる。
135 if (d->allow_encoded_slashes) {
これは、AllowEncodedSlashes ディレクティブの設定情報だ。
こちらのif文は Onか、NoDecodeの場合だ。
136 access_status = ap_unescape_url_keep2f(r->parsed_uri.path, d->decode_encoded_slashes);
この場合、%2Fがパスに含まれていてもエラーとはしない。
Onの場合はデコードする。
NoDecodeの場合はそのまま残す。
137 }
138 else {
こちらのelseは Offの場合だ。
139 access_status = ap_unescape_url(r->parsed_uri.path);
その場合、エンコードされているURLパスをデコードし、不正なエンコードがされていたり 禁止文字(通常は"/")がエンコードされていた場合にエラーとしている。
禁止文字がスラッシュ(%2F)だ。
禁止文字があったら 404(not found)を返している。
On/Offいずれであっても、エンコード自体が誤っていればデコードできないので、エラーとなる。
その場合は 400(bad request)が返ってくる。
140 }
141 if (access_status) {
ここは、AllowEncodedSlashes Offで%2Fが見つかるか、エンコードそのものが 誤りの場合。
142 if (access_status == HTTP_NOT_FOUND) {
143 if (! d->allow_encoded_slashes) {
144 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00026)
145 "found %%2f (encoded '/') in URI "
146 "(decoded='%s'), returning 404",
147 r->parsed_uri.path);
148 }
149 }
150 return access_status;
151 }
152 }
153
154 ap_getparents(r->uri); /* OK --- shrinking transformations... */
ap_getparent()は、urlから . や .. の相対パス指定を除去する。
. の場合は単に除去し、
.. の場合は前のパスセグメントごと除去する("xx/.."のまとまりで除去する)。
155
156 /* All file subrequests are a huge pain... they cannot bubble through the
157 * next several steps. Only file subrequests are allowed an empty uri,
158 * otherwise let translate_name kill the request.
159 */
160 if (!file_req) {
ここはサブリクエストではないか、サブリクエストでもfilename(リソースのローカルパス)が未詳のリクエストが処理対象となる。
161 if ((access_status = ap_location_walk(r))) {
ここでは、<Location><LocationMatch>
162 return access_status;
163 }
164 if ((access_status = ap_if_walk(r))) {
ここでは、<If><IfElse><Else>
165 return access_status;
166 }
167
168 d = ap_get_core_module_config(r->per_dir_config);
169 if (d->log) {
170 r->log = d->log;
171 }
172
173 if ((access_status = ap_run_translate_name(r))) {
174 return decl_die(access_status, "translate", r);
175 }
176 }
177
178 /* Reset to the server default config prior to running map_to_storage
179 */
180 r->per_dir_config = r->server->lookup_defaults;
181
182 if ((access_status = ap_run_map_to_storage(r))) {
183 /* This request wasn't in storage (e.g. TRACE) */
184 return access_status;
185 }
186
187 /* Rerun the location walk, which overrides any map_to_storage config.
188 */
189 if ((access_status = ap_location_walk(r))) {
190 return access_status;
191 }
192 if ((access_status = ap_if_walk(r))) {
193 return access_status;
194 }
195
196 d = ap_get_core_module_config(r->per_dir_config);
197 if (d->log) {
198 r->log = d->log;
199 }
200
201 if ((access_status = ap_run_post_perdir_config(r))) {
202 return access_status;
203 }
204
205 /* Only on the main request! */
206 if (r->main == NULL) {
207 if ((access_status = ap_run_header_parser(r))) {
208 return access_status;
209 }
210 }
211
212 /* Skip authn/authz if the parent or prior request passed the authn/authz,
213 * and that configuration didn't change (this requires optimized _walk()
214 * functions in map_to_storage that use the same merge results given
215 * identical input.) If the config changes, we must re-auth.
216 */
217 if (r->prev && (r->prev->per_dir_config == r->per_dir_config)) {
218 r->user = r->prev->user;
219 r->ap_auth_type = r->prev->ap_auth_type;
220 }
221 else if (r->main && (r->main->per_dir_config == r->per_dir_config)) {
222 r->user = r->main->user;
223 r->ap_auth_type = r->main->ap_auth_type;
224 }
225 else {
mod_access_compatを使用している場合は、ap_satisfies()がSatisfyディレクティブの指定を返す。
226 switch (ap_satisfies(r)) { 227 case SATISFY_ALL: 228 case SATISFY_NOSPEC:
229 if ((access_status = ap_run_access_checker(r)) != OK) {
230 return decl_die(access_status,
231 "check access (with Satisfy All)", r);
232 }
233
234 access_status = ap_run_access_checker_ex(r);
access_cheker_exフック関数は 2.2系には存在していない。
ap_hook_access_checker_ex()関数を呼び出しているのは、ap_hook_check_access_ex()だけで、
ap_hook_check_access_ex()を経由してフック関数を登録するようになっている。
見たところ、ここでは、Require ipなどのユーザに依存しない認可処理を行っている。
235 if (access_status == OK) {
236 ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
237 "request authorized without authentication by "
238 "access_checker_ex hook: %s", r->uri);
239 }
240 else if (access_status != DECLINED) {
241 return decl_die(access_status, "check access", r);
242 }
243 else {
244 if ((access_status = ap_run_check_user_id(r)) != OK) {
245 return decl_die(access_status, "check user", r);
246 }
247 if (r->user == NULL) {
248 /* don't let buggy authn module crash us in authz */
249 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00027)
250 "No authentication done but request not "
251 "allowed without authentication for %s. "
252 "Authentication not configured?",
253 r->uri);
254 access_status = HTTP_INTERNAL_SERVER_ERROR;
255 return decl_die(access_status, "check user", r);
256 }
257 if ((access_status = ap_run_auth_checker(r)) != OK) {
258 return decl_die(access_status, "check authorization", r);
259 }
260 }
261 break;
262 case SATISFY_ANY:
263 if ((access_status = ap_run_access_checker(r)) == OK) {
264 ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
265 "request authorized without authentication by "
266 "access_checker hook and 'Satisfy any': %s",
267 r->uri);
268 break;
269 }
270
271 access_status = ap_run_access_checker_ex(r);
272 if (access_status == OK) {
273 ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
274 "request authorized without authentication by "
275 "access_checker_ex hook: %s", r->uri);
276 }
277 else if (access_status != DECLINED) {
278 return decl_die(access_status, "check access", r);
279 }
280 else {
281 if ((access_status = ap_run_check_user_id(r)) != OK) {
282 return decl_die(access_status, "check user", r);
283 }
284 if (r->user == NULL) {
285 /* don't let buggy authn module crash us in authz */
286 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00028)
287 "No authentication done but request not "
288 "allowed without authentication for %s. "
289 "Authentication not configured?",
290 r->uri);
291 access_status = HTTP_INTERNAL_SERVER_ERROR;
292 return decl_die(access_status, "check user", r);
293 }
294 if ((access_status = ap_run_auth_checker(r)) != OK) {
295 return decl_die(access_status, "check authorization", r);
296 }
297 }
298 break;
299 }
300 }
301 /* XXX Must make certain the ap_run_type_checker short circuits mime
302 * in mod-proxy for r->proxyreq && r->parsed_uri.scheme
303 * && !strcmp(r->parsed_uri.scheme, "http")
304 */
305 if ((access_status = ap_run_type_checker(r)) != OK) {
306 return decl_die(access_status, "find types", r);
307 }
308
309 if ((access_status = ap_run_fixups(r)) != OK) {
310 ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r, "fixups hook gave %d: %s",
311 access_status, r->uri);
312 return access_status;
313 }
314
315 return OK;
316 }
これで、ap_process_request_internalは終わる。
0 件のコメント:
コメントを投稿