Ticket #322: fastcgi-authorizer-fixes.diff

File fastcgi-authorizer-fixes.diff, 6.6 kB (added by maherb, 2 years ago)

All fastcgi mode=authorizer fixes (Variable- env works, proper re-dispatching, and assert failure fix when auth is running in front of cgi).

  • src/mod_fastcgi.c

     
    13861386 
    13871387                                                host->min_procs = 1; 
    13881388                                                host->max_procs = 1; 
    13891389                                        } 
    13901390 
    13911391                                        if (!buffer_is_empty(fcgi_mode)) { 
    13921392                                                if (strcmp(fcgi_mode->ptr, "responder") == 0) { 
    13931393                                                        host->mode = FCGI_RESPONDER; 
    13941394                                                } else if (strcmp(fcgi_mode->ptr, "authorizer") == 0) { 
    13951395                                                        host->mode = FCGI_AUTHORIZER; 
    1396                                                         if (buffer_is_empty(host->docroot)) { 
    1397                                                                 log_error_write(srv, __FILE__, __LINE__, "s", 
    1398                                                                                 "ERROR: docroot is required for authorizer mode."); 
    1399                                                                 return HANDLER_ERROR; 
    1400                                                         } 
    14011396                                                } else { 
    14021397                                                        log_error_write(srv, __FILE__, __LINE__, "sbs", 
    14031398                                                                        "WARNING: unknown fastcgi mode:", 
    14041399                                                                        fcgi_mode, "(ignored, mode set to responder)"); 
    14051400                                                } 
    14061401                                        } 
    14071402 
    14081403                                        /* if extension already exists, take it */ 
    14091404                                        fastcgi_extension_insert(s->exts, da_ext->key, host); 
    14101405                                } 
     
    20372032        fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0); 
    20382033        buffer_append_memory(b, (const char *)&header, sizeof(header)); 
    20392034        buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used); 
    20402035 
    20412036        fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0); 
    20422037        buffer_append_memory(b, (const char *)&header, sizeof(header)); 
    20432038 
    20442039        b->used++; /* add virtual \0 */ 
    20452040        hctx->wb->bytes_in += b->used - 1; 
    20462041 
    2047         if (con->request.content_length) { 
     2042        if (con->request.content_length && host->mode != FCGI_AUTHORIZER) { 
    20482043                chunkqueue *req_cq = con->request_content_queue; 
    20492044                chunk *req_c; 
    20502045                off_t offset; 
    20512046 
    20522047                /* something to send ? */ 
    20532048                for (offset = 0, req_c = req_cq->first; offset != req_cq->bytes_in; ) { 
    20542049                        off_t weWant = req_cq->bytes_in - offset > FCGI_MAX_LENGTH ? FCGI_MAX_LENGTH : req_cq->bytes_in - offset; 
    20552050                        off_t written = 0; 
    20562051                        off_t weHave = 0; 
    20572052 
     
    22672262                        if (0 == strncasecmp(key, "Content-Length", key_len)) { 
    22682263                                con->response.content_length = strtol(value, NULL, 10); 
    22692264                                con->parsed_response |= HTTP_CONTENT_LENGTH; 
    22702265 
    22712266                                if (con->response.content_length < 0) con->response.content_length = 0; 
    22722267                        } 
    22732268                        break; 
    22742269                default: 
    22752270                        break; 
    22762271                } 
     2272                if ( host->mode == FCGI_AUTHORIZER && 
     2273                     key_len > 9 && 
     2274                     0 == strncasecmp(key, CONST_STR_LEN("Variable-")) ) 
     2275                { 
     2276                        if ( key_len == 20 && 0 == strncasecmp(key, CONST_STR_LEN("Variable-REMOTE_USER")) ) { 
     2277                                buffer_copy_string(con->authed_user, value); 
     2278                        } else { 
     2279                                if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { 
     2280                                        ds = data_response_init(); 
     2281                                } 
     2282                                buffer_copy_string_len(ds->key, key + 9, key_len - 9); 
     2283                                buffer_copy_string(ds->value, value); 
     2284 
     2285                                array_insert_unique(con->environment, (data_unset *)ds); 
     2286                        } 
     2287                } 
    22772288        } 
    22782289 
    22792290        /* CGI/1.1 rev 03 - 7.2.1.2 */ 
    22802291        if ((con->parsed_response & HTTP_LOCATION) && 
    22812292            !(con->parsed_response & HTTP_STATUS)) { 
    22822293                con->http_status = 302; 
    22832294        } 
    22842295 
    22852296        return 0; 
    22862297} 
     
    31303141 
    31313142                        if (host->mode == FCGI_AUTHORIZER && 
    31323143                            (con->http_status == 200 || 
    31333144                             con->http_status == 0)) { 
    31343145                                /* 
    31353146                                 * If we are here in AUTHORIZER mode then a request for autorizer 
    31363147                                 * was proceeded already, and status 200 has been returned. We need 
    31373148                                 * now to handle autorized request. 
    31383149                                 */ 
    31393150 
    3140                                 buffer_copy_string_buffer(con->physical.doc_root, host->docroot); 
     3151                                if ( ! buffer_is_empty(host->docroot) ) { 
     3152                                        /* 
     3153                                         * Serve local file if they specified 
     3154                                         * a docroot 
     3155                                         */ 
     3156                                        buffer_copy_string_buffer(con->physical.doc_root, host->docroot); 
     3157 
     3158                                        buffer_copy_string_buffer(con->physical.path, host->docroot); 
     3159                                        buffer_append_string_buffer(con->physical.path, con->uri.path); 
     3160                                        fcgi_connection_close(srv, hctx); 
    31413161 
    3142                                 buffer_copy_string_buffer(con->physical.path, host->docroot); 
    3143                                 buffer_append_string_buffer(con->physical.path, con->uri.path); 
    3144                                 fcgi_connection_close(srv, hctx); 
     3162                                        con->mode = DIRECT; 
     3163                                        con->file_started = 1; /* fcgi_extension won't touch the request afterwards */ 
     3164                                } else { 
     3165                                        if ( buffer_is_empty(con->authed_user) ) { 
     3166                                                /* 
     3167                                                 * Currently we depend on a 
     3168                                                 * non-empty authed_user in order to 
     3169                                                 * determine if a user has been 
     3170                                                 * authed, this should probably change 
     3171                                                 * in the future: 
     3172                                                 */ 
     3173                                                buffer_copy_string(con->authed_user, "-"); 
     3174                                        } 
    31453175 
    3146                                 con->mode = DIRECT; 
    3147                                 con->file_started = 1; /* fcgi_extension won't touch the request afterwards */ 
     3176                                        fcgi_connection_close(srv, hctx); 
     3177                                        con->mode = DIRECT; 
     3178                                        con->file_started = 0; 
     3179                                        con->file_finished = 0; 
     3180                                        buffer_reset(con->physical.path); 
     3181                                } 
    31483182                        } else { 
    31493183                                /* we are done */ 
    31503184                                fcgi_connection_close(srv, hctx); 
    31513185                        } 
    31523186 
    31533187                        joblist_append(srv, con); 
    31543188                        return HANDLER_FINISHED; 
    31553189                case -1: 
    31563190                        if (proc->pid && proc->state != PROC_STATE_DIED) { 
    31573191                                int status; 
     
    33913425 
    33923426                                if (buffer_is_equal(ds->value, extension->key)) { 
    33933427                                        break; 
    33943428                                } 
    33953429                        } 
    33963430 
    33973431                        if (k == p->conf.exts->used) { 
    33983432                                /* found nothign */ 
    33993433                                extension = NULL; 
    34003434                        } 
     3435 
     3436                        if ( extension != NULL && 
     3437                             ! buffer_is_empty(con->authed_user) && 
     3438                             extension->used > 0 && 
     3439                             extension->hosts[0]->mode == FCGI_AUTHORIZER ) 
     3440                        { 
     3441                                extension = NULL; 
     3442                        } 
    34013443                        break; 
    34023444                } 
    34033445        } 
    34043446 
    34053447        if (extension == NULL) { 
    34063448                /* check if extension matches */ 
    34073449                for (k = 0; k < p->conf.exts->used; k++) { 
    34083450                        size_t ct_len; /* length of the config entry */ 
    34093451 
    34103452                        extension = p->conf.exts->exts[k]; 
    34113453 
     3454                        if ( ! buffer_is_empty(con->authed_user) && 
     3455                             extension->used > 0 && 
     3456                             extension->hosts[0]->mode == FCGI_AUTHORIZER ) 
     3457                        { 
     3458                                continue; 
     3459                        } 
     3460 
    34123461                        if (extension->key->used == 0) continue; 
    34133462 
    34143463                        ct_len = extension->key->used - 1; 
    34153464 
    34163465                        if (s_len < ct_len) continue; 
    34173466 
    34183467                        /* check extension in the form "/fcgi_pattern" */ 
    34193468                        if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) { 
    34203469                                break; 
    34213470                        } else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) { 
     
    35113560                         * 
    35123561                         * /fcgi-bin/foo/bar 
    35133562                         * 
    35143563                         * SCRIPT_NAME = /fcgi-bin/foo 
    35153564                         * PATH_INFO   = /bar 
    35163565                         * 
    35173566                         */ 
    35183567 
    35193568                        /* the rewrite is only done for /prefix/? matches */ 
    35203569                        if (extension->key->ptr[0] == '/' && 
     3570                            extension->key->used > 2 && 
    35213571                            con->uri.path->used > extension->key->used && 
    35223572                            NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) { 
    35233573                                /* rewrite uri.path and pathinfo */ 
    35243574 
    35253575                                buffer_copy_string(con->request.pathinfo, pathinfo); 
    35263576 
    35273577                                con->uri.path->used -= con->request.pathinfo->used - 1; 
    35283578                                con->uri.path->ptr[con->uri.path->used - 1] = '\0'; 
    35293579                        } 
    35303580                }