root/sapi/fpm/fpm/fpm_php.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fpm_php_zend_ini_alter_master
  2. fpm_php_disable
  3. fpm_php_apply_defines_ex
  4. fpm_php_apply_defines
  5. fpm_php_set_allowed_clients
  6. fpm_php_set_fcgi_mgmt_vars
  7. fpm_php_script_filename
  8. fpm_php_request_uri
  9. fpm_php_request_method
  10. fpm_php_query_string
  11. fpm_php_auth_user
  12. fpm_php_content_length
  13. fpm_php_cleanup
  14. fpm_php_soft_quit
  15. fpm_php_init_main
  16. fpm_php_init_child
  17. fpm_php_limit_extensions
  18. fpm_php_get_string_from_table

   1 
   2         /* $Id: fpm_php.c,v 1.22.2.4 2008/12/13 03:21:18 anight Exp $ */
   3         /* (c) 2007,2008 Andrei Nigmatulin */
   4 
   5 #include "fpm_config.h"
   6 
   7 #include <stdlib.h>
   8 #include <string.h>
   9 #include <stdio.h>
  10 
  11 #include "php.h"
  12 #include "php_main.h"
  13 #include "php_ini.h"
  14 #include "ext/standard/dl.h"
  15 
  16 #include "fastcgi.h"
  17 
  18 #include "fpm.h"
  19 #include "fpm_php.h"
  20 #include "fpm_cleanup.h"
  21 #include "fpm_worker_pool.h"
  22 #include "zlog.h"
  23 
  24 static char **limit_extensions = NULL;
  25 
  26 static int fpm_php_zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int mode, int stage) /* {{{ */
  27 {
  28         zend_ini_entry *ini_entry;
  29         zend_string *duplicate;
  30 
  31         if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length)) == NULL) {
  32                 return FAILURE;
  33         }
  34 
  35         duplicate = zend_string_init(new_value, new_value_length, 1);
  36 
  37         if (!ini_entry->on_modify
  38                         || ini_entry->on_modify(ini_entry, duplicate,
  39                                 ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) {
  40                 ini_entry->value = duplicate;
  41                 ini_entry->modifiable = mode;
  42         } else {
  43                 zend_string_release(duplicate);
  44         }
  45 
  46         return SUCCESS;
  47 }
  48 /* }}} */
  49 
  50 static void fpm_php_disable(char *value, int (*zend_disable)(char *, size_t)) /* {{{ */
  51 {
  52         char *s = 0, *e = value;
  53 
  54         while (*e) {
  55                 switch (*e) {
  56                         case ' ':
  57                         case ',':
  58                                 if (s) {
  59                                         *e = '\0';
  60                                         zend_disable(s, e - s);
  61                                         s = 0;
  62                                 }
  63                                 break;
  64                         default:
  65                                 if (!s) {
  66                                         s = e;
  67                                 }
  68                                 break;
  69                 }
  70                 e++;
  71         }
  72 
  73         if (s) {
  74                 zend_disable(s, e - s);
  75         }
  76 }
  77 /* }}} */
  78 
  79 int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */
  80 {
  81 
  82         char *name = kv->key;
  83         char *value = kv->value;
  84         int name_len = strlen(name);
  85         int value_len = strlen(value);
  86 
  87         if (!strcmp(name, "extension") && *value) {
  88                 zval zv;
  89                 php_dl(value, MODULE_PERSISTENT, &zv, 1);
  90                 return Z_TYPE(zv) == IS_TRUE;
  91         }
  92 
  93         if (fpm_php_zend_ini_alter_master(name, name_len, value, value_len, mode, PHP_INI_STAGE_ACTIVATE) == FAILURE) {
  94                 return -1;
  95         }
  96 
  97         if (!strcmp(name, "disable_functions") && *value) {
  98                 char *v = strdup(value);
  99                 PG(disable_functions) = v;
 100                 fpm_php_disable(v, zend_disable_function);
 101                 return 1;
 102         }
 103 
 104         if (!strcmp(name, "disable_classes") && *value) {
 105                 char *v = strdup(value);
 106                 PG(disable_classes) = v;
 107                 fpm_php_disable(v, zend_disable_class);
 108                 return 1;
 109         }
 110 
 111         return 1;
 112 }
 113 /* }}} */
 114 
 115 static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp) /* {{{ */
 116 {
 117         struct key_value_s *kv;
 118 
 119         for (kv = wp->config->php_values; kv; kv = kv->next) {
 120                 if (fpm_php_apply_defines_ex(kv, ZEND_INI_USER) == -1) {
 121                         zlog(ZLOG_ERROR, "Unable to set php_value '%s'", kv->key);
 122                 }
 123         }
 124 
 125         for (kv = wp->config->php_admin_values; kv; kv = kv->next) {
 126                 if (fpm_php_apply_defines_ex(kv, ZEND_INI_SYSTEM) == -1) {
 127                         zlog(ZLOG_ERROR, "Unable to set php_admin_value '%s'", kv->key);
 128                 }
 129         }
 130 
 131         return 0;
 132 }
 133 /* }}} */
 134 
 135 static int fpm_php_set_allowed_clients(struct fpm_worker_pool_s *wp) /* {{{ */
 136 {
 137         if (wp->listen_address_domain == FPM_AF_INET) {
 138                 fcgi_set_allowed_clients(wp->config->listen_allowed_clients);
 139         }
 140         return 0;
 141 }
 142 /* }}} */
 143 
 144 #if 0 /* Comment out this non used function. It could be used later. */
 145 static int fpm_php_set_fcgi_mgmt_vars(struct fpm_worker_pool_s *wp) /* {{{ */
 146 {
 147         char max_workers[10 + 1]; /* 4294967295 */
 148         int len;
 149 
 150         len = sprintf(max_workers, "%u", (unsigned int) wp->config->pm_max_children);
 151 
 152         fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, max_workers, len);
 153         fcgi_set_mgmt_var("FCGI_MAX_REQS",  sizeof("FCGI_MAX_REQS")-1,  max_workers, len);
 154         return 0;
 155 }
 156 /* }}} */
 157 #endif
 158 
 159 char *fpm_php_script_filename(void) /* {{{ */
 160 {
 161         return SG(request_info).path_translated;
 162 }
 163 /* }}} */
 164 
 165 char *fpm_php_request_uri(void) /* {{{ */
 166 {
 167         return (char *) SG(request_info).request_uri;
 168 }
 169 /* }}} */
 170 
 171 char *fpm_php_request_method(void) /* {{{ */
 172 {
 173         return (char *) SG(request_info).request_method;
 174 }
 175 /* }}} */
 176 
 177 char *fpm_php_query_string(void) /* {{{ */
 178 {
 179         return SG(request_info).query_string;
 180 }
 181 /* }}} */
 182 
 183 char *fpm_php_auth_user(void) /* {{{ */
 184 {
 185         return SG(request_info).auth_user;
 186 }
 187 /* }}} */
 188 
 189 size_t fpm_php_content_length(void) /* {{{ */
 190 {
 191         return SG(request_info).content_length;
 192 }
 193 /* }}} */
 194 
 195 static void fpm_php_cleanup(int which, void *arg) /* {{{ */
 196 {
 197         php_module_shutdown();
 198         sapi_shutdown();
 199 }
 200 /* }}} */
 201 
 202 void fpm_php_soft_quit() /* {{{ */
 203 {
 204         fcgi_terminate();
 205 }
 206 /* }}} */
 207 
 208 int fpm_php_init_main() /* {{{ */
 209 {
 210         if (0 > fpm_cleanup_add(FPM_CLEANUP_PARENT, fpm_php_cleanup, 0)) {
 211                 return -1;
 212         }
 213         return 0;
 214 }
 215 /* }}} */
 216 
 217 int fpm_php_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
 218 {
 219         if (0 > fpm_php_apply_defines(wp) ||
 220                 0 > fpm_php_set_allowed_clients(wp)) {
 221                 return -1;
 222         }
 223 
 224         if (wp->limit_extensions) {
 225                 limit_extensions = wp->limit_extensions;
 226         }
 227         return 0;
 228 }
 229 /* }}} */
 230 
 231 int fpm_php_limit_extensions(char *path) /* {{{ */
 232 {
 233         char **p;
 234         size_t path_len;
 235 
 236         if (!path || !limit_extensions) {
 237                 return 0; /* allowed by default */
 238         }
 239 
 240         p = limit_extensions;
 241         path_len = strlen(path);
 242         while (p && *p) {
 243                 size_t ext_len = strlen(*p);
 244                 if (path_len > ext_len) {
 245                         char *path_ext = path + path_len - ext_len;
 246                         if (strcmp(*p, path_ext) == 0) {
 247                                 return 0; /* allow as the extension has been found */
 248                         }
 249                 }
 250                 p++;
 251         }
 252 
 253 
 254         zlog(ZLOG_NOTICE, "Access to the script '%s' has been denied (see security.limit_extensions)", path);
 255         return 1; /* extension not found: not allowed  */
 256 }
 257 /* }}} */
 258 
 259 char* fpm_php_get_string_from_table(zend_string *table, char *key) /* {{{ */
 260 {
 261         zval *data, *tmp;
 262         zend_string *str;
 263         if (!table || !key) {
 264                 return NULL;
 265         }
 266 
 267         /* inspired from ext/standard/info.c */
 268 
 269         zend_is_auto_global(table);
 270 
 271         /* find the table and ensure it's an array */
 272         data = zend_hash_find(&EG(symbol_table), table);
 273         if (!data || Z_TYPE_P(data) != IS_ARRAY) {
 274                 return NULL;
 275         }
 276 
 277         ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(data), str, tmp) {
 278                 if (str && !strncmp(ZSTR_VAL(str), key, ZSTR_LEN(str))) {
 279                         return Z_STRVAL_P(tmp);
 280                 }
 281         } ZEND_HASH_FOREACH_END();
 282 
 283         return NULL;
 284 }
 285 /* }}} */
 286 

/* [<][>][^][v][top][bottom][index][help] */