php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
fpm_php.c
Go to the documentation of this file.
1 /* (c) 2007,2008 Andrei Nigmatulin */
2
3#include "fpm_config.h"
4
5#include <stdlib.h>
6#include <string.h>
7#include <stdio.h>
8
9#include "php.h"
10#include "php_main.h"
11#include "php_ini.h"
12#include "ext/standard/dl.h"
13
14#include "fastcgi.h"
15
16#include "fpm.h"
17#include "fpm_php.h"
18#include "fpm_cleanup.h"
19#include "fpm_worker_pool.h"
20#include "zlog.h"
21
22static char **limit_extensions = NULL;
23
24static int fpm_php_zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int mode, int stage) /* {{{ */
25{
26 zend_ini_entry *ini_entry;
27 zend_string *duplicate;
28
29 if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length)) == NULL) {
30 return FAILURE;
31 }
32
33 duplicate = zend_string_init(new_value, new_value_length, 1);
34
35 if (!ini_entry->on_modify
36 || ini_entry->on_modify(ini_entry, duplicate,
37 ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) {
38 ini_entry->value = duplicate;
39 /* when mode == ZEND_INI_USER keep unchanged to allow ZEND_INI_PERDIR (.user.ini) */
40 if (mode == ZEND_INI_SYSTEM) {
41 ini_entry->modifiable = mode;
42 }
43 } else {
44 zend_string_release_ex(duplicate, 1);
45 }
46
47 return SUCCESS;
48}
49/* }}} */
50
51static void fpm_php_disable(char *value, int (*zend_disable)(const char *, size_t)) /* {{{ */
52{
53 char *s = 0, *e = value;
54
55 while (*e) {
56 switch (*e) {
57 case ' ':
58 case ',':
59 if (s) {
60 *e = '\0';
61 zend_disable(s, e - s);
62 s = 0;
63 }
64 break;
65 default:
66 if (!s) {
67 s = e;
68 }
69 break;
70 }
71 e++;
72 }
73
74 if (s) {
75 zend_disable(s, e - s);
76 }
77}
78/* }}} */
79
80#define FPM_PHP_INI_ALTERING_ERROR -1
81#define FPM_PHP_INI_APPLIED 1
82#define FPM_PHP_INI_EXTENSION_FAILED 0
83#define FPM_PHP_INI_EXTENSION_LOADED 2
84
85int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */
86{
87
88 char *name = kv->key;
89 char *value = kv->value;
90 int name_len = strlen(name);
91 int value_len = strlen(value);
92
93 if (!strcmp(name, "extension") && *value) {
94 zval zv;
96
97#if ZEND_RC_DEBUG
98 bool orig_rc_debug = zend_rc_debug;
99 /* Loading extensions after php_module_startup() breaks some invariants.
100 * For instance, it will update the refcount of persistent strings,
101 * which is normally not allowed at this stage. */
102 zend_rc_debug = false;
103#endif
104
106
107#if ZEND_RC_DEBUG
108 zend_rc_debug = orig_rc_debug;
109#endif
110
113 }
114
115 if (fpm_php_zend_ini_alter_master(name, name_len, value, value_len, mode, PHP_INI_STAGE_ACTIVATE) == FAILURE) {
117 }
118
119 if (!strcmp(name, "disable_functions") && *value) {
121 return FPM_PHP_INI_APPLIED;
122 }
123
124 if (!strcmp(name, "disable_classes") && *value) {
125 char *v = strdup(value);
126 PG(disable_classes) = v;
127 fpm_php_disable(v, zend_disable_class);
128 return FPM_PHP_INI_APPLIED;
129 }
130
131 return FPM_PHP_INI_APPLIED;
132}
133/* }}} */
134
135static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp) /* {{{ */
136{
137 struct key_value_s *kv;
138 int apply_result;
139 bool extension_loaded = false;
140
141 for (kv = wp->config->php_values; kv; kv = kv->next) {
142 apply_result = fpm_php_apply_defines_ex(kv, ZEND_INI_USER);
143 if (apply_result == FPM_PHP_INI_ALTERING_ERROR) {
144 zlog(ZLOG_ERROR, "Unable to set php_value '%s'", kv->key);
145 } else if (apply_result == FPM_PHP_INI_EXTENSION_LOADED) {
146 extension_loaded = true;
147 }
148 }
149
150 for (kv = wp->config->php_admin_values; kv; kv = kv->next) {
151 apply_result = fpm_php_apply_defines_ex(kv, ZEND_INI_SYSTEM);
152 if (apply_result == FPM_PHP_INI_ALTERING_ERROR) {
153 zlog(ZLOG_ERROR, "Unable to set php_admin_value '%s'", kv->key);
154 } else if (apply_result == FPM_PHP_INI_EXTENSION_LOADED) {
155 extension_loaded = true;
156 }
157 }
158
159 if (extension_loaded) {
161 }
162
163 return 0;
164}
165/* }}} */
166
167static int fpm_php_set_allowed_clients(struct fpm_worker_pool_s *wp) /* {{{ */
168{
171 }
172 return 0;
173}
174/* }}} */
175
176#if 0 /* Comment out this non used function. It could be used later. */
177static int fpm_php_set_fcgi_mgmt_vars(struct fpm_worker_pool_s *wp) /* {{{ */
178{
179 char max_workers[10 + 1]; /* 4294967295 */
180 int len;
181
182 len = snprintf(max_workers, sizeof(max_workers), "%u", (unsigned int) wp->config->pm_max_children);
183
184 fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, max_workers, len);
185 fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, max_workers, len);
186 return 0;
187}
188/* }}} */
189#endif
190
192{
193 return SG(request_info).path_translated;
194}
195
197{
198 return (char *) SG(request_info).request_uri;
199}
200
202{
203 return (char *) SG(request_info).request_method;
204}
205
207{
208 return SG(request_info).query_string;
209}
210
212{
213 return SG(request_info).auth_user;
214}
215
217{
218 return SG(request_info).content_length;
219}
220
221static void fpm_php_cleanup(int which, void *arg) /* {{{ */
222{
225 if (limit_extensions) {
227 }
228}
229/* }}} */
230
232{
234}
235
237{
238 if (0 > fpm_cleanup_add(FPM_CLEANUP_PARENT, fpm_php_cleanup, 0)) {
239 return -1;
240 }
241 return 0;
242}
243
244int fpm_php_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
245{
246 if (0 > fpm_php_apply_defines(wp) ||
247 0 > fpm_php_set_allowed_clients(wp)) {
248 return -1;
249 }
250
251 if (wp->limit_extensions) {
252 /* Take ownership of limit_extensions. */
253 limit_extensions = wp->limit_extensions;
255 }
256 return 0;
257}
258/* }}} */
259
260int fpm_php_limit_extensions(char *path) /* {{{ */
261{
262 char **p;
263 size_t path_len;
264
265 if (!path || !limit_extensions) {
266 return 0; /* allowed by default */
267 }
268
269 p = limit_extensions;
270 path_len = strlen(path);
271 while (p && *p) {
272 size_t ext_len = strlen(*p);
273 if (path_len > ext_len) {
274 char *path_ext = path + path_len - ext_len;
275 if (strcmp(*p, path_ext) == 0) {
276 return 0; /* allow as the extension has been found */
277 }
278 }
279 p++;
280 }
281
282
283 zlog(ZLOG_NOTICE, "Access to the script '%s' has been denied (see security.limit_extensions)", path);
284 return 1; /* extension not found: not allowed */
285}
286/* }}} */
287
288bool fpm_php_is_key_in_table(zend_string *table, const char *key, size_t key_len) /* {{{ */
289{
290 zval *data;
291 zend_string *str;
292
293 ZEND_ASSERT(table);
295
296 /* inspired from ext/standard/info.c */
297
298 zend_is_auto_global(table);
299
300 /* find the table and ensure it's an array */
301 data = zend_hash_find(&EG(symbol_table), table);
302 if (!data || Z_TYPE_P(data) != IS_ARRAY) {
303 return NULL;
304 }
305
307 if (str && zend_string_equals_cstr(str, key, key_len)) {
308 return true;
309 }
311
312 return false;
313}
314/* }}} */
SAPI_API void sapi_shutdown(void)
Definition SAPI.c:89
#define SG(v)
Definition SAPI.h:160
size_t len
Definition apprentice.c:174
char s[4]
Definition cdf.c:77
uint32_t v
Definition cdf.c:1237
PHPAPI void php_dl(const char *file, int type, zval *return_value, int start_now)
Definition dl.c:281
void fcgi_set_mgmt_var(const char *name, size_t name_len, const char *value, size_t value_len)
Definition fastcgi.c:1727
void fcgi_terminate(void)
Definition fastcgi.c:456
void fcgi_set_allowed_clients(char *ip)
Definition fastcgi.c:821
zval * zv
Definition ffi.c:3975
zval * arg
Definition ffi.c:3975
int fpm_cleanup_add(int type, void(*cleanup)(int, void *), void *arg)
Definition fpm_cleanup.c:18
@ FPM_CLEANUP_PARENT
Definition fpm_cleanup.h:14
#define FPM_PHP_INI_EXTENSION_FAILED
Definition fpm_php.c:82
char * fpm_php_script_filename(void)
Definition fpm_php.c:191
size_t fpm_php_content_length(void)
Definition fpm_php.c:216
char * fpm_php_request_method(void)
Definition fpm_php.c:201
char * fpm_php_query_string(void)
Definition fpm_php.c:206
int fpm_php_limit_extensions(char *path)
Definition fpm_php.c:260
char * fpm_php_request_uri(void)
Definition fpm_php.c:196
#define FPM_PHP_INI_ALTERING_ERROR
Definition fpm_php.c:80
int fpm_php_init_main(void)
Definition fpm_php.c:236
#define FPM_PHP_INI_EXTENSION_LOADED
Definition fpm_php.c:83
#define FPM_PHP_INI_APPLIED
Definition fpm_php.c:81
char * fpm_php_auth_user(void)
Definition fpm_php.c:211
bool fpm_php_is_key_in_table(zend_string *table, const char *key, size_t key_len)
Definition fpm_php.c:288
void fpm_php_soft_quit(void)
Definition fpm_php.c:231
int fpm_php_init_child(struct fpm_worker_pool_s *wp)
Definition fpm_php.c:244
int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode)
Definition fpm_php.c:85
void fpm_worker_pool_free_limit_extensions(char **limit_extensions)
@ FPM_AF_INET
char * mode
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
void php_module_shutdown(void)
Definition main.c:2424
#define PG(v)
Definition php_globals.h:31
#define PHP_INI_STAGE_ACTIVATE
Definition php_ini.h:73
unsigned char key[REFLECTION_KEY_LEN]
zend_constant * data
p
Definition session.c:1105
zend_string * value
Definition zend_ini.h:53
uint8_t modifiable
Definition zend_ini.h:59
void * mh_arg3
Definition zend_ini.h:52
void * mh_arg2
Definition zend_ini.h:51
void * mh_arg1
Definition zend_ini.h:50
struct key_value_s * php_admin_values
Definition fpm_conf.h:97
struct key_value_s * php_values
Definition fpm_conf.h:98
struct fpm_worker_pool_config_s * config
enum fpm_address_domain listen_address_domain
char * key
Definition fpm_conf.h:17
struct key_value_s * next
Definition fpm_conf.h:16
char * value
Definition fpm_conf.h:18
ZEND_API void zend_collect_module_handlers(void)
Definition zend_API.c:2489
ZEND_API zend_result zend_disable_class(const char *class_name, size_t class_name_length)
Definition zend_API.c:3707
ZEND_API void zend_disable_functions(const char *function_list)
Definition zend_API.c:3641
struct _zval_struct zval
strlen(string $string)
extension_loaded(string $extension)
strcmp(string $string1, string $string2)
zend_string_release_ex(func->internal_function.function_name, 0)
ZEND_API bool zend_is_auto_global(zend_string *name)
#define snprintf
struct _zend_ini_entry zend_ini_entry
#define EG(v)
ZEND_API zval *ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
Definition zend_hash.c:2668
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
#define ZEND_HASH_FOREACH_STR_KEY(ht, _key)
Definition zend_hash.h:1138
#define ZEND_INI_SYSTEM
Definition zend_ini.h:26
#define ZEND_INI_USER
Definition zend_ini.h:24
struct _zend_string zend_string
#define MODULE_PERSISTENT
#define ZEND_ASSERT(c)
ZEND_API void zend_interned_strings_switch_storage(bool request)
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define IS_ARRAY
Definition zend_types.h:607
@ FAILURE
Definition zend_types.h:61
#define Z_TYPE(zval)
Definition zend_types.h:659
zend_string * name
value
@ ZLOG_ERROR
Definition zlog.h:45
@ ZLOG_NOTICE
Definition zlog.h:43
#define zlog(flags,...)
Definition zlog.h:9