Back to index

php5  5.3.10
fpm_php.c
Go to the documentation of this file.
00001 
00002        /* $Id: fpm_php.c,v 1.22.2.4 2008/12/13 03:21:18 anight Exp $ */
00003        /* (c) 2007,2008 Andrei Nigmatulin */
00004 
00005 #include "fpm_config.h"
00006 
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <stdio.h>
00010 
00011 #include "php.h"
00012 #include "php_main.h"
00013 #include "php_ini.h"
00014 #include "ext/standard/dl.h"
00015 
00016 #include "fastcgi.h"
00017 
00018 #include "fpm.h"
00019 #include "fpm_php.h"
00020 #include "fpm_cleanup.h"
00021 #include "fpm_worker_pool.h"
00022 #include "zlog.h"
00023 
00024 static char **limit_extensions = NULL;
00025 
00026 static int fpm_php_zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int mode, int stage TSRMLS_DC) /* {{{ */
00027 {
00028        zend_ini_entry *ini_entry;
00029        char *duplicate;
00030 
00031        if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == FAILURE) {
00032               return FAILURE;
00033        }
00034 
00035        duplicate = strdup(new_value);
00036 
00037        if (!ini_entry->on_modify
00038                      || ini_entry->on_modify(ini_entry, duplicate, new_value_length,
00039                             ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC) == SUCCESS) {
00040               ini_entry->value = duplicate;
00041               ini_entry->value_length = new_value_length;
00042               ini_entry->modifiable = mode;
00043        } else {
00044               free(duplicate);
00045        }
00046 
00047        return SUCCESS;
00048 }
00049 /* }}} */
00050 
00051 static void fpm_php_disable(char *value, int (*zend_disable)(char *, uint TSRMLS_DC) TSRMLS_DC) /* {{{ */
00052 {
00053        char *s = 0, *e = value;
00054 
00055        while (*e) {
00056               switch (*e) {
00057                      case ' ':
00058                      case ',':
00059                             if (s) {
00060                                    *e = '\0';
00061                                    zend_disable(s, e - s TSRMLS_CC);
00062                                    s = 0;
00063                             }
00064                             break;
00065                      default:
00066                             if (!s) {
00067                                    s = e;
00068                             }
00069                             break;
00070               }
00071               e++;
00072        }
00073 
00074        if (s) {
00075               zend_disable(s, e - s TSRMLS_CC);
00076        }
00077 }
00078 /* }}} */
00079 
00080 int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */
00081 {
00082        TSRMLS_FETCH();
00083 
00084        char *name = kv->key;
00085        char *value = kv->value;
00086        int name_len = strlen(name);
00087        int value_len = strlen(value);
00088 
00089        if (!strcmp(name, "extension") && *value) {
00090               zval zv;
00091               php_dl(value, MODULE_PERSISTENT, &zv, 1 TSRMLS_CC);
00092               return Z_BVAL(zv) ? 1 : -1;
00093        }
00094 
00095        if (fpm_php_zend_ini_alter_master(name, name_len+1, value, value_len, mode, PHP_INI_STAGE_ACTIVATE TSRMLS_CC) == FAILURE) {
00096               return -1;
00097        }
00098 
00099        if (!strcmp(name, "disable_functions") && *value) {
00100               char *v = strdup(value);
00101               PG(disable_functions) = v;
00102               fpm_php_disable(v, zend_disable_function TSRMLS_CC);
00103               return 1;
00104        }
00105 
00106        if (!strcmp(name, "disable_classes") && *value) {
00107               char *v = strdup(value);
00108               PG(disable_classes) = v;
00109               fpm_php_disable(v, zend_disable_class TSRMLS_CC);
00110               return 1;
00111        }
00112 
00113        return 1;
00114 }
00115 /* }}} */
00116 
00117 static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp) /* {{{ */
00118 {
00119        struct key_value_s *kv;
00120 
00121        for (kv = wp->config->php_values; kv; kv = kv->next) {
00122               if (fpm_php_apply_defines_ex(kv, ZEND_INI_USER) == -1) {
00123                      zlog(ZLOG_ERROR, "Unable to set php_value '%s'", kv->key);
00124               }
00125        }
00126 
00127        for (kv = wp->config->php_admin_values; kv; kv = kv->next) {
00128               if (fpm_php_apply_defines_ex(kv, ZEND_INI_SYSTEM) == -1) {
00129                      zlog(ZLOG_ERROR, "Unable to set php_admin_value '%s'", kv->key);
00130               }
00131        }
00132 
00133        return 0;
00134 }
00135 
00136 static int fpm_php_set_allowed_clients(struct fpm_worker_pool_s *wp) /* {{{ */
00137 {
00138        if (wp->listen_address_domain == FPM_AF_INET) {
00139               fcgi_set_allowed_clients(wp->config->listen_allowed_clients);
00140        }
00141        return 0;
00142 }
00143 /* }}} */
00144 
00145 #if 0 /* Comment out this non used function. It could be used later. */
00146 static int fpm_php_set_fcgi_mgmt_vars(struct fpm_worker_pool_s *wp) /* {{{ */
00147 {
00148        char max_workers[10 + 1]; /* 4294967295 */
00149        int len;
00150 
00151        len = sprintf(max_workers, "%u", (unsigned int) wp->config->pm_max_children);
00152 
00153        fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, max_workers, len);
00154        fcgi_set_mgmt_var("FCGI_MAX_REQS",  sizeof("FCGI_MAX_REQS")-1,  max_workers, len);
00155        return 0;
00156 }
00157 /* }}} */
00158 #endif
00159 
00160 char *fpm_php_script_filename(TSRMLS_D) /* {{{ */
00161 {
00162        return SG(request_info).path_translated;
00163 }
00164 /* }}} */
00165 
00166 char *fpm_php_request_uri(TSRMLS_D) /* {{{ */
00167 {
00168        return (char *) SG(request_info).request_uri;
00169 }
00170 /* }}} */
00171 
00172 char *fpm_php_request_method(TSRMLS_D) /* {{{ */
00173 {
00174        return (char *) SG(request_info).request_method;
00175 }
00176 /* }}} */
00177 
00178 char *fpm_php_query_string(TSRMLS_D) /* {{{ */
00179 {
00180        return SG(request_info).query_string;
00181 }
00182 /* }}} */
00183 
00184 char *fpm_php_auth_user(TSRMLS_D) /* {{{ */
00185 {
00186        return SG(request_info).auth_user;
00187 }
00188 /* }}} */
00189 
00190 size_t fpm_php_content_length(TSRMLS_D) /* {{{ */
00191 {
00192        return SG(request_info).content_length;
00193 }
00194 /* }}} */
00195 
00196 static void fpm_php_cleanup(int which, void *arg) /* {{{ */
00197 {
00198        TSRMLS_FETCH();
00199        php_module_shutdown(TSRMLS_C);
00200        sapi_shutdown();
00201 }
00202 /* }}} */
00203 
00204 void fpm_php_soft_quit() /* {{{ */
00205 {
00206        fcgi_set_in_shutdown(1);
00207 }
00208 /* }}} */
00209 
00210 int fpm_php_init_main() /* {{{ */
00211 {
00212        if (0 > fpm_cleanup_add(FPM_CLEANUP_PARENT, fpm_php_cleanup, 0)) {
00213               return -1;
00214        }
00215        return 0;
00216 }
00217 /* }}} */
00218 
00219 int fpm_php_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
00220 {
00221        if (0 > fpm_php_apply_defines(wp) ||
00222               0 > fpm_php_set_allowed_clients(wp)) {
00223               return -1;
00224        }
00225 
00226        if (wp->limit_extensions) {
00227               limit_extensions = wp->limit_extensions;
00228        }
00229        return 0;
00230 }
00231 /* }}} */
00232 
00233 int fpm_php_limit_extensions(char *path) /* {{{ */
00234 {
00235        char **p;
00236        size_t path_len;
00237 
00238        if (!path || !limit_extensions) {
00239               return 0; /* allowed by default */
00240        }
00241 
00242        p = limit_extensions;
00243        path_len = strlen(path);
00244        while (p && *p) {
00245               size_t ext_len = strlen(*p);
00246               if (path_len > ext_len) {
00247                      char *path_ext = path + path_len - ext_len;
00248                      if (strcmp(*p, path_ext) == 0) {
00249                             return 0; /* allow as the extension has been found */
00250                      }
00251               }
00252               p++;
00253        }
00254 
00255 
00256        zlog(ZLOG_NOTICE, "Access to the script '%s' has been denied (see security.limit_extensions)", path);
00257        return 1; /* extension not found: not allowed  */
00258 }
00259 /* }}} */