Annotation of embedaddon/lighttpd/src/mod_access.c, revision 1.1.1.3

1.1.1.3 ! misho       1: #include "first.h"
        !             2: 
1.1       misho       3: #include "base.h"
                      4: #include "log.h"
                      5: #include "buffer.h"
                      6: 
                      7: #include "plugin.h"
                      8: 
                      9: #include <ctype.h>
                     10: #include <stdlib.h>
                     11: #include <string.h>
                     12: 
                     13: typedef struct {
1.1.1.3 ! misho      14:        array *access_allow;
1.1       misho      15:        array *access_deny;
                     16: } plugin_config;
                     17: 
                     18: typedef struct {
                     19:        PLUGIN_DATA;
                     20: 
                     21:        plugin_config **config_storage;
                     22: 
                     23:        plugin_config conf;
                     24: } plugin_data;
                     25: 
                     26: INIT_FUNC(mod_access_init) {
                     27:        plugin_data *p;
                     28: 
                     29:        p = calloc(1, sizeof(*p));
                     30: 
                     31:        return p;
                     32: }
                     33: 
                     34: FREE_FUNC(mod_access_free) {
                     35:        plugin_data *p = p_d;
                     36: 
                     37:        UNUSED(srv);
                     38: 
                     39:        if (!p) return HANDLER_GO_ON;
                     40: 
                     41:        if (p->config_storage) {
                     42:                size_t i;
                     43:                for (i = 0; i < srv->config_context->used; i++) {
                     44:                        plugin_config *s = p->config_storage[i];
                     45: 
1.1.1.3 ! misho      46:                        if (NULL == s) continue;
        !            47: 
        !            48:                        array_free(s->access_allow);
1.1       misho      49:                        array_free(s->access_deny);
                     50: 
                     51:                        free(s);
                     52:                }
                     53:                free(p->config_storage);
                     54:        }
                     55: 
                     56:        free(p);
                     57: 
                     58:        return HANDLER_GO_ON;
                     59: }
                     60: 
                     61: SETDEFAULTS_FUNC(mod_access_set_defaults) {
                     62:        plugin_data *p = p_d;
                     63:        size_t i = 0;
                     64: 
                     65:        config_values_t cv[] = {
                     66:                { "url.access-deny",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
1.1.1.3 ! misho      67:                { "url.access-allow",            NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
1.1       misho      68:                { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
                     69:        };
                     70: 
1.1.1.2   misho      71:        p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
1.1       misho      72: 
                     73:        for (i = 0; i < srv->config_context->used; i++) {
1.1.1.3 ! misho      74:                data_config const* config = (data_config const*)srv->config_context->data[i];
1.1       misho      75:                plugin_config *s;
                     76: 
                     77:                s = calloc(1, sizeof(plugin_config));
                     78:                s->access_deny    = array_init();
1.1.1.3 ! misho      79:                s->access_allow   = array_init();
1.1       misho      80: 
                     81:                cv[0].destination = s->access_deny;
1.1.1.3 ! misho      82:                cv[1].destination = s->access_allow;
1.1       misho      83: 
                     84:                p->config_storage[i] = s;
                     85: 
1.1.1.3 ! misho      86:                if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
1.1       misho      87:                        return HANDLER_ERROR;
                     88:                }
                     89:        }
                     90: 
                     91:        return HANDLER_GO_ON;
                     92: }
                     93: 
                     94: #define PATCH(x) \
                     95:        p->conf.x = s->x;
                     96: static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
                     97:        size_t i, j;
                     98:        plugin_config *s = p->config_storage[0];
                     99: 
1.1.1.3 ! misho     100:        PATCH(access_allow);
1.1       misho     101:        PATCH(access_deny);
                    102: 
                    103:        /* skip the first, the global context */
                    104:        for (i = 1; i < srv->config_context->used; i++) {
                    105:                data_config *dc = (data_config *)srv->config_context->data[i];
                    106:                s = p->config_storage[i];
                    107: 
                    108:                /* condition didn't match */
                    109:                if (!config_check_cond(srv, con, dc)) continue;
                    110: 
                    111:                /* merge config */
                    112:                for (j = 0; j < dc->value->used; j++) {
                    113:                        data_unset *du = dc->value->data[j];
                    114: 
                    115:                        if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
                    116:                                PATCH(access_deny);
1.1.1.3 ! misho     117:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-allow"))) {
        !           118:                                PATCH(access_allow);
1.1       misho     119:                        }
                    120:                }
                    121:        }
                    122: 
                    123:        return 0;
                    124: }
                    125: #undef PATCH
                    126: 
                    127: /**
                    128:  * URI handler
                    129:  *
                    130:  * we will get called twice:
                    131:  * - after the clean up of the URL and 
                    132:  * - after the pathinfo checks are done
                    133:  *
                    134:  * this handles the issue of trailing slashes
                    135:  */
                    136: URIHANDLER_FUNC(mod_access_uri_handler) {
                    137:        plugin_data *p = p_d;
                    138:        int s_len;
                    139:        size_t k;
                    140: 
1.1.1.3 ! misho     141:        if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON;
1.1       misho     142: 
                    143:        mod_access_patch_connection(srv, con, p);
                    144: 
1.1.1.3 ! misho     145:        s_len = buffer_string_length(con->uri.path);
1.1       misho     146: 
                    147:        if (con->conf.log_request_handling) {
1.1.1.3 ! misho     148:                log_error_write(srv, __FILE__, __LINE__, "s",
1.1       misho     149:                                "-- mod_access_uri_handler called");
                    150:        }
                    151: 
1.1.1.3 ! misho     152:        for (k = 0; k < p->conf.access_allow->used; ++k) {
        !           153:                data_string *ds = (data_string *)p->conf.access_allow->data[k];
        !           154:                int ct_len = buffer_string_length(ds->value);
        !           155:                int allowed = 0;
        !           156: 
        !           157:                if (ct_len > s_len) continue;
        !           158:                if (buffer_is_empty(ds->value)) continue;
        !           159: 
        !           160:                /* if we have a case-insensitive FS we have to lower-case the URI here too */
        !           161: 
        !           162:                if (con->conf.force_lowercase_filenames) {
        !           163:                        if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
        !           164:                                allowed = 1;
        !           165:                        }
        !           166:                } else {
        !           167:                        if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
        !           168:                                allowed = 1;
        !           169:                        }
        !           170:                }
        !           171: 
        !           172:                if (allowed) {
        !           173:                        return HANDLER_GO_ON;
        !           174:                }
        !           175:        }
        !           176: 
        !           177:        if (k > 0) { /* have access_allow but none matched */
        !           178:                con->http_status = 403;
        !           179:                con->mode = DIRECT;
        !           180: 
        !           181:                if (con->conf.log_request_handling) {
        !           182:                        log_error_write(srv, __FILE__, __LINE__, "sb",
        !           183:                                "url denied as failed to match any from access_allow", con->uri.path);
        !           184:                }
        !           185: 
        !           186:                return HANDLER_FINISHED;
        !           187:        }
        !           188: 
1.1       misho     189:        for (k = 0; k < p->conf.access_deny->used; k++) {
                    190:                data_string *ds = (data_string *)p->conf.access_deny->data[k];
1.1.1.3 ! misho     191:                int ct_len = buffer_string_length(ds->value);
1.1       misho     192:                int denied = 0;
                    193: 
                    194: 
                    195:                if (ct_len > s_len) continue;
1.1.1.3 ! misho     196:                if (buffer_is_empty(ds->value)) continue;
1.1       misho     197: 
                    198:                /* if we have a case-insensitive FS we have to lower-case the URI here too */
                    199: 
                    200:                if (con->conf.force_lowercase_filenames) {
                    201:                        if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
                    202:                                denied = 1;
                    203:                        }
                    204:                } else {
                    205:                        if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
                    206:                                denied = 1;
                    207:                        }
                    208:                }
                    209: 
                    210:                if (denied) {
                    211:                        con->http_status = 403;
                    212:                        con->mode = DIRECT;
                    213: 
                    214:                        if (con->conf.log_request_handling) {
                    215:                                log_error_write(srv, __FILE__, __LINE__, "sb", 
                    216:                                        "url denied as we match:", ds->value);
                    217:                        }
                    218: 
                    219:                        return HANDLER_FINISHED;
                    220:                }
                    221:        }
                    222: 
                    223:        /* not found */
                    224:        return HANDLER_GO_ON;
                    225: }
                    226: 
                    227: 
                    228: int mod_access_plugin_init(plugin *p);
                    229: int mod_access_plugin_init(plugin *p) {
                    230:        p->version     = LIGHTTPD_VERSION_ID;
                    231:        p->name        = buffer_init_string("access");
                    232: 
                    233:        p->init        = mod_access_init;
                    234:        p->set_defaults = mod_access_set_defaults;
                    235:        p->handle_uri_clean = mod_access_uri_handler;
                    236:        p->handle_subrequest_start  = mod_access_uri_handler;
                    237:        p->cleanup     = mod_access_free;
                    238: 
                    239:        p->data        = NULL;
                    240: 
                    241:        return 0;
                    242: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>