Skip to content

Commit

Permalink
PHP: Implement better error handling.
Browse files Browse the repository at this point in the history
Previously the PHP module would produce one of four status codes

  200 OK
  301 Moved Permanently
  500 Internal Server Error
  503 Service Unavailable

200 for successful requests, 301 for cases where the url was a directory
without a trailing '/', 500 for bad PHP or non-existing PHP file and 503
for all other errors.

With this commit we now handle missing files and directories, returning
404 Not Found and files and directories that don't allow access,
returning 403 Forbidden.

We do these checks in two places, when we check if we should do a
directory redirect (bar -> bar/) and in the nxt_php_execute() function.

One snag with the latter is that the php_execute_script() function only
returns success/failure (no reason). However while it took a
zend_file_handle structure with the filename of the script to run, we
can instead pass through an already opened file-pointer (FILE *) via
that structure. So we can try opening the script ourselves and do the
required checks before calling php_execute_script().

We also make use of the zend_stream_init_fp() function that initialises
the zend_file_handle structure if it's available otherwise we use our
own version. This is good because the zend_file_handle structure has
changed over time and the zend_stream_init_fp() function should change
with it.

Closes: <#767>
Reviewed-by: Alejandro Colomar <[email protected]>
Cc: Andrei Zeliankou <[email protected]>
Signed-off-by: Andrew Clayton <[email protected]>
  • Loading branch information
ac000 committed Jan 31, 2023
1 parent 83d8b85 commit 5f186d5
Showing 1 changed file with 40 additions and 5 deletions.
45 changes: 40 additions & 5 deletions src/nxt_php_sapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,13 @@ static void nxt_php_str_trim_lead(nxt_str_t *str, u_char t);
nxt_inline u_char *nxt_realpath(const void *c);

static nxt_int_t nxt_php_do_301(nxt_unit_request_info_t *req);
static nxt_int_t nxt_php_handle_fs_err(nxt_unit_request_info_t *req);

static void nxt_php_request_handler(nxt_unit_request_info_t *req);
static void nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx,
nxt_unit_request_t *r);
#if (PHP_VERSION_ID < 70400)
static void nxt_zend_stream_init_filename(zend_file_handle *handle,
static void nxt_zend_stream_init_fp(zend_file_handle *handle, FILE *fp,
const char *filename);
#endif
static void nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r);
Expand Down Expand Up @@ -984,6 +985,24 @@ nxt_php_do_301(nxt_unit_request_info_t *req)
}


static nxt_int_t
nxt_php_handle_fs_err(nxt_unit_request_info_t *req)
{
switch (nxt_errno) {
case ELOOP:
case EACCES:
case ENFILE:
return nxt_unit_response_init(req, NXT_HTTP_FORBIDDEN, 0, 0);
case ENOENT:
case ENOTDIR:
case ENAMETOOLONG:
return nxt_unit_response_init(req, NXT_HTTP_NOT_FOUND, 0, 0);
}

return NXT_UNIT_ERROR;
}


static void
nxt_php_request_handler(nxt_unit_request_info_t *req)
{
Expand Down Expand Up @@ -1062,6 +1081,8 @@ nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r)
ret = stat(tpath, &sb);
if (ret == 0 && S_ISDIR(sb.st_mode)) {
ec = nxt_php_do_301(ctx->req);
} else if (ret == -1) {
ec = nxt_php_handle_fs_err(ctx->req);
}

nxt_unit_request_done(ctx->req, ec);
Expand Down Expand Up @@ -1115,20 +1136,23 @@ nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r)

#if (PHP_VERSION_ID < 70400)
static void
nxt_zend_stream_init_filename(zend_file_handle *handle, const char *filename)
nxt_zend_stream_init_fp(zend_file_handle *handle, FILE *fp,
const char *filename)
{
nxt_memzero(handle, sizeof(zend_file_handle));
handle->type = ZEND_HANDLE_FILENAME;
handle->type = ZEND_HANDLE_FP;
handle->handle.fp = fp;
handle->filename = filename;
}
#else
#define nxt_zend_stream_init_filename zend_stream_init_filename
#define nxt_zend_stream_init_fp zend_stream_init_fp
#endif


static void
nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r)
{
FILE *fp;
#if (PHP_VERSION_ID < 50600)
void *read_post;
#endif
Expand All @@ -1140,6 +1164,17 @@ nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r)

nxt_unit_req_debug(ctx->req, "PHP execute script %s", filename);

fp = fopen(filename, "re");
if (fp == NULL) {
nxt_int_t ec;

nxt_unit_req_debug(ctx->req, "PHP fopen(\"%s\") failed", filename);

ec = nxt_php_handle_fs_err(ctx->req);
nxt_unit_request_done(ctx->req, ec);
return;
}

SG(server_context) = ctx;
SG(options) |= SAPI_OPTION_NO_CHDIR;
SG(request_info).request_uri = nxt_unit_sptr_get(&r->target);
Expand Down Expand Up @@ -1198,7 +1233,7 @@ nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r)
nxt_php_vcwd_chdir(ctx->req, ctx->script_dirname.start);
}

nxt_zend_stream_init_filename(&file_handle, filename);
nxt_zend_stream_init_fp(&file_handle, fp, filename);

php_execute_script(&file_handle TSRMLS_CC);

Expand Down

0 comments on commit 5f186d5

Please sign in to comment.