コード例 #1
0
ファイル: web_agent.c プロジェクト: dromero91/openam
int send_data(const char *msg, Session *sn, Request *rq) {
    int len = msg != NULL?strlen(msg):0;
    int retVal = REQ_ABORTED;

    if(len > 0) {
        char buf[50];
        buf[0] = '\0';
        sprintf(buf, "%d", len);
        protocol_status(sn, rq, PROTOCOL_OK, NULL); 
        param_free(pblock_remove("content-type", rq->srvhdrs));
        pblock_nvinsert("content-type", "text/html", rq->srvhdrs); 
        pblock_nvinsert("content-length", buf, rq->srvhdrs); 
    
        /* Send the headers to the client*/
        protocol_start_response(sn, rq);
    
        /* Write the output using net_write*/
        if (IO_ERROR == net_write(sn->csd, (char *)msg, len)) {
            retVal = REQ_EXIT; 
        } else {
            retVal = net_flush(sn->csd);
        }

    }
    return retVal; 
}
コード例 #2
0
ファイル: WebObjects.c プロジェクト: LaurentDavery/wonder
static int sendResponse(Session *sn, Request *rq, HTTPResponse *resp)
{
   pb_param *pb_entry;

   /*
    *	collect up the headers
    */
   pb_entry = pblock_remove(CONTENT_TYPE,rq->srvhdrs);			/* remove default */
   param_free(pb_entry);			/* aB. Need to free parameters we remove from pblocks !!! */
   st_perform(resp->headers,gethdr,rq);

   /*
    *	ensure a content length
    */
   if (pblock_findval(CONTENT_LENGTH, rq->srvhdrs) == NULL) {
      char length[64];
      util_itoa(resp->content_length,length);
      pblock_nvinsert(CONTENT_LENGTH,length, rq->srvhdrs);
   }

   protocol_status(sn, rq, resp->status, resp->statusMsg);

   if (protocol_start_response(sn, rq) == REQ_NOACTION) {
      WOLog(WO_ERR,"protocol_start_response() returned REQ_NOACTION (!?)");
      return REQ_PROCEED;
   }

   if (resp->content_length)
      if (net_write(sn->csd, resp->content, resp->content_length) == IO_ERROR) {
         WOLog(WO_ERR,"Failed to send content to client");
         return REQ_EXIT;
      }

         return REQ_PROCEED;
}
コード例 #3
0
ファイル: web_agent.c プロジェクト: dromero91/openam
static int process_new_notification(pblock *param,
                                    Session *sn,
                                    Request *rq,
                                    void* agent_config)
{
    handle_notification(sn, rq, agent_config);

    /* Use the protocol_status function to set the status of the
     * response before calling protocol_start_response.
     */
    protocol_status(sn, rq, PROTOCOL_OK, NULL);

    /* Although we would expect the ObjectType stage to
     * set the content-type, set it here just to be
     * completely sure that it gets set to text/html.
     */
    param_free(pblock_remove("content-type", rq->srvhdrs));
    pblock_nvinsert("content-type", "text/html", rq->srvhdrs);

    pblock_nvinsert("content-length", "2", rq->srvhdrs);

    /* Send the headers to the client*/
    protocol_start_response(sn, rq);

    /* Write the output using net_write*/
    if (IO_ERROR == net_write(sn->csd, "OK", 2)) {
        return REQ_EXIT;
    }
    return REQ_PROCEED;
}
コード例 #4
0
ファイル: web_agent.c プロジェクト: dromero91/openam
static int do_deny(Session *sn, Request *rq, am_status_t status) {
    int retVal = REQ_ABORTED;
    /* Set the return code 403 Forbidden */
    protocol_status(sn, rq, PROTOCOL_FORBIDDEN, NULL);
    am_web_log_info("do_redirect() Status code= %s.",
                     am_status_to_string(status));
    return retVal;
}
コード例 #5
0
int 
htaccess_evaluate(pblock *pb, Session *sn, Request *rq)
{
    char *p = pblock_findval("path", rq->vars);
    struct stat *finfo = request_stat_path(p, rq);
    int isdir = finfo && S_ISDIR(finfo->st_mode);

    /* some java servlets that are set in rules.properties don't set this */
    if(!pblock_findval("ntrans-base", rq->vars))
        return REQ_NOACTION;

    char *methstr = pblock_findval("method", rq->reqpb);
    int methnum;
    HttpMethodRegistry& registry = HttpMethodRegistry::GetRegistry();

    /* treat HEAD as a GET */
    if (!strcasecmp(methstr, "HEAD"))
        methnum = registry.HttpMethodRegistry::GetMethodIndex("GET");
    else
        methnum = registry.HttpMethodRegistry::GetMethodIndex(methstr);

    /* if it isn't a method we support, don't allow access */
    if (methnum == -1)
    {
        protocol_status(sn, rq, PROTOCOL_FORBIDDEN, NULL);
        return REQ_ABORTED;
    }

    switch(htaccess_evaluate_access(p, isdir, methnum, pb, sn, rq)) {
      case ACCESS_OK:
        return REQ_PROCEED;

      case ACCESS_FORBIDDEN:
      default:
        protocol_status(sn, rq, PROTOCOL_FORBIDDEN, NULL);
        log_error(LOG_SECURITY, "htaccess-find", sn, rq, 
                  "access of %s denied by server configuration.", p);
        /* fallthrough */

      case ACCESS_AUTHFAIL:
        /* the data structures will be set up by http_auth.c */
        return REQ_ABORTED;
    }
}
コード例 #6
0
ファイル: web_agent.c プロジェクト: dromero91/openam
/**
 * This function is used for sending a 302 redirect in the browser.
 */
static void do_url_redirect(Session *sn, Request *rq, char* redirect_url)
{
    /* Set the return code to 302 Redirect */
    protocol_status(sn, rq, PROTOCOL_REDIRECT, NULL);

    /* set the new URL to redirect */
    pblock_nvinsert("escape", "no", rq->vars);

    param_free(pblock_remove("Location", rq->srvhdrs));
    pblock_nvinsert("Location", redirect_url, rq->srvhdrs);
    protocol_start_response(sn, rq);
}
コード例 #7
0
int service_reconfig(pblock *pb, Session *sn, Request *rq)
{
    param_free(pblock_remove("content-type", rq->srvhdrs));
    pblock_nvinsert("content-type", "text/html", rq->srvhdrs);
    protocol_status(sn, rq, PROTOCOL_OK, NULL);
    protocol_start_response(sn, rq);

    PR_fprintf(sn->csd, "<html><head><title>"
                        "Dynamic Reconfiguration"
                        "</title></head><body>\n"
                        "<H2>Dynamic Reconfiguration</H2>\n"
                        "<p>pid: %d</p>\n", getpid());

    // Asynchronous reconfiguration
    WebServer::RequestReconfiguration();

    PR_fprintf(sn->csd, "</body></html>");

    return REQ_PROCEED;
}
コード例 #8
0
int service_dumpstats(pblock *pb, Session *sn, Request *rq)
{
    char *refresh, *refresh_val = NULL;

    /* See if client asked for automatic refresh in query string */
    if ((refresh = pblock_findval("query", rq->reqpb)) != NULL ) {
        if (!strncmp("refresh", refresh, 7)) {
             refresh_val = strchr(refresh, '=');
             if (refresh_val)
                 refresh_val++;
        }
    }

    param_free(pblock_remove("content-type", rq->srvhdrs));
    pblock_nvinsert("content-type", "text/plain", rq->srvhdrs);
    if (refresh_val)
        pblock_nvinsert("refresh", refresh_val, rq->srvhdrs);
    httpfilter_buffer_output(sn, rq, PR_TRUE);
    protocol_status(sn, rq, PROTOCOL_OK, NULL);
    protocol_start_response(sn,rq);

    PR_fprintf(sn->csd, PRODUCT_DAEMON_BIN" pid: %d\n", getpid());

    StatsHeaderNode *hdr = StatsManager::getHeader();

    if (!hdr) {
        PR_fprintf(sn->csd, "\nStatistics disabled\n");
        return REQ_PROCEED;
    }
    int rv = REQ_PROCEED;
#ifdef XP_WIN32
    rv = write_stats_dump(sn->csd, hdr);
#else
    if (hdr && (hdr->hdrStats.maxProcs == 1)) {
        rv = write_stats_dump(sn->csd, hdr);
    } else {
        StatsManager::serviceDumpStats(sn->csd, NULL);
    }
#endif
    return rv;
}
コード例 #9
0
ファイル: web_agent.c プロジェクト: dromero91/openam
static int do_redirect(Session *sn, Request *rq, am_status_t status,
        am_policy_result_t *policy_result,
        const char *original_url, const char* method,
        void* agent_config) {
    int retVal = REQ_ABORTED;
    char *redirect_url = NULL;
    const am_map_t advice_map = policy_result->advice_map;
    am_status_t ret = AM_SUCCESS;

    ret = am_web_get_url_to_redirect(status, advice_map,
            original_url, method,
            AM_RESERVED, &redirect_url, agent_config);

    if (ret == AM_SUCCESS && redirect_url != NULL) {
        char *advice_txt = NULL;
        if (B_FALSE == am_web_use_redirect_for_advice(agent_config) && policy_result->advice_string != NULL) {
            // Composite advice is sent as a POST
            ret = am_web_build_advice_response(policy_result, redirect_url,
                    &advice_txt);
            am_web_log_debug("do_redirect(): policy status=%s,",
                    "response[%s]", am_status_to_string(status),
                    advice_txt);
            if (ret == AM_SUCCESS) {
                retVal = send_data(advice_txt, sn, rq);
            } else {
                am_web_log_error("do_redirect(): Error while building "
                        "advice response body:%s",
                        am_status_to_string(ret));
                retVal = REQ_EXIT;
            }
        } else {
            // No composite advice or composite advice is redirected
            am_web_log_debug("do_redirect() policy status = %s, ",
                    "redirection URL is %s",
                    am_status_to_string(status), redirect_url);

            // we need to modify the redirect_url with the policy advice
            if (B_TRUE == am_web_use_redirect_for_advice(agent_config) &&
                    policy_result->advice_string != NULL) {
                char *redirect_url_with_advice = NULL;
                ret = am_web_build_advice_redirect_url(policy_result,
                        redirect_url, &redirect_url_with_advice);
                if (ret == AM_SUCCESS) {
                    redirect_url = redirect_url_with_advice;
                    am_web_log_debug("do_redirect(): policy status=%s, "
                            "redirect url with advice [%s]",
                            am_status_to_string(status),
                            redirect_url);
                } else {
                    am_web_log_error("do_redirect(): Error while building "
                            "the redirect url with advice:%s",
                            am_status_to_string(ret));
                }
            }

            /* redirection is enabled by the PathCheck directive */
            /* Set the return code to 302 Redirect */
            protocol_status(sn, rq, PROTOCOL_REDIRECT, NULL);

            /* set the new URL to redirect */
            //pblock_nvinsert("url", redirect_url, rq->vars);
            pblock_nvinsert("escape", "no", rq->vars);

            param_free(pblock_remove("Location", rq->srvhdrs));
            pblock_nvinsert("Location", redirect_url, rq->srvhdrs);
            protocol_start_response(sn, rq);

            am_web_free_memory(redirect_url);
        }
    } else if (ret == AM_NO_MEMORY) {
        /* Set the return code 500 Internal Server Error. */
        protocol_status(sn, rq, PROTOCOL_SERVER_ERROR, NULL);
        am_web_log_error("do_redirect() Status code= %s.",
                am_status_to_string(status));
    } else {
        /* Set the return code 403 Forbidden */
        protocol_status(sn, rq, PROTOCOL_FORBIDDEN, NULL);
        am_web_log_info("do_redirect() Status code= %s.",
                am_status_to_string(status));
    }

    return retVal;
}
コード例 #10
0
PRStatus FcgiParser::parseAuthHeaders(pblock *pb) {
    Request *rq = request->getOrigRequest();
    authHeaderPrefixLen = strlen(AUTH_HEADER_PREFIX);
    char *s;

    if(pb) {
        if((s = pblock_findval("status", pb))) {
            if((strlen(s) < 3) ||
               (!isdigit(s[0]) || (!isdigit(s[1])) || (!isdigit(s[2])))) {
                s = NULL;
            }
            else {
              char ch = s[3];
              s[3] = '\0';
              int statusNum = atoi(s);
              s[3] = ch;

              rq->status_num = statusNum;
              if(statusNum == 200)
                authorized = PR_TRUE;
            }
        }

        if(!authorized) {
            protocol_status(request->getOrigSession(), request->getOrigRequest(), PROTOCOL_UNAUTHORIZED, NULL);
        } else {
            //retain only the headers starting with "Varaiable-"
            for (int i = 0; i < pb->hsize; i++) {
                pb_entry *p = pb->ht[i];
                while (p) {
                    const char *name = PL_strdup(p->param->name);
                    const char *value = PL_strdup(p->param->value);

                    if (*name == 'v' && (!PL_strcmp(name, "variable-"))) {
                        pb_param *pparam = pblock_fr((char *)name, pb, PR_TRUE);
                        param_free(pparam);
                        name += authHeaderPrefixLen;   // remove the prefix from name
                        if(*name == 'r' && (!PL_strcmp(name, "remote_user"))) {
                            pblock_nvinsert("auth-user", value, rq->vars);
                        }
            if(*name == 'a' && (!PL_strcmp(name, "auth_type"))) {
                            pblock_nvinsert("auth-type", value, rq->vars);
                        }

                        pblock_nvinsert(name, value, rq->headers);
                    }

                   PL_strfree((char *)name);
                   PL_strfree((char *)value);

                   p = p->next;
                } //while
            } //for
        } //if

    } else {
        lastError = INVALID_HTTP_HEADER;
        request->log(LOG_FAILURE, GetString(DBT_invalid_response));
        return PR_FAILURE;
    }

    return PR_SUCCESS;
}
コード例 #11
0
PRStatus FcgiParser::parseHttpHeader(CircularBuffer& to) {
    if(!waitingForDataParse)
        return PR_SUCCESS;

    const char *data = httpHeader.data();
    int len = httpHeader.length();
    PRUint8 flag = 0;
    while(len-- && flag < 2) {
        switch(*data) {
            case '\r':
                break;
            case '\n':
                flag++;
                break;
            default:
                flag = 0;
                break;
        }

        data++;
    }

    /*
     * Return (to be called later when we have more data)
     */

    if(flag < 2)
        return PR_SUCCESS;

    waitingForDataParse = PR_FALSE;
    Request *rq = request->getOrigRequest();

    pblock *authpb = NULL;
    if(fcgiRole == FCGI_AUTHORIZER) {
        authpb = pblock_create(rq->srvhdrs->hsize);
    }

    register int x ,y;
    register char c;
    int nh;
    char t[REQ_MAX_LINE];
    PRBool headerEnd = PR_FALSE;
    char* statusHeader = pblock_findval("status", rq->srvhdrs);
    char *next = const_cast<char *>(httpHeader.data());

    nh = 0;
    x = 0; y = -1;
 
    for(; !headerEnd;) {
        c = *(next++);
        switch(c) {
        case CR:
            // Silently ignore CRs
            break;

        case LF:
            if (x == 0) {
                headerEnd = PR_TRUE;
                break; 
            }

            t[x] = '\0';
            if(y == -1) {
                request->log(LOG_FAILURE,  "name without value: got line \"%s\"", t);
                return PR_FAILURE;
            }
            while(t[y] && isspace(t[y])) ++y;

            // Do not change the status header to 200 if it was already set
            // This would happen only if it were a cgi error handler
            // and so the status had been already set on the request
            // originally
            if (!statusHeader || // If we don't already have a Status: header
                PL_strcmp(t, "status") || // or this isn't a Status: header
                PL_strncmp(&t[y], "200", 3)) // or this isn't "Status: 200"
            {
                if(!PL_strcmp(t, "content-type")) {
                    pb_param* pParam = pblock_remove ( "content-type", rq->srvhdrs );
                    if ( pParam ) param_free ( pParam );
                }
                if(fcgiRole == FCGI_AUTHORIZER) {
                    pblock_nvinsert(t, &t[y], authpb);
                } else {
                    pblock_nvinsert(t, &t[y], rq->srvhdrs);
                } // !FCGI_AUTHORIZER
            }

            x = 0;
            y = -1;
            ++nh;
            break;

        case ':':
            if(y == -1) {
                y = x+1;
                c = '\0';
            }

        default:
            t[x++] = ((y == -1) && isupper(c) ? tolower(c) : c);

        }
    } // for

    if(fcgiRole == FCGI_AUTHORIZER) {
        if(parseAuthHeaders(authpb) != PR_SUCCESS) {
            pblock_free(authpb);
            return PR_FAILURE;
        }

        pblock_copy(authpb, rq->srvhdrs);
        pblock_free(authpb);

    } else {

        /*
         * We're done scanning the FCGI script's header output.  Now
         * we have to write to the client:  status, FCGI header, and
         * any over-read FCGI output.
         */
        char *s;
        char *l = pblock_findval("location", rq->srvhdrs);

        if((s = pblock_findval("status", rq->srvhdrs))) {
            if((strlen(s) < 3) ||
               (!isdigit(s[0]) || (!isdigit(s[1])) || (!isdigit(s[2])))) {
                s = NULL;
            }
            else {
              char ch = s[3];
              s[3] = '\0';
              int statusNum = atoi(s);
              s[3] = ch;

              rq->status_num = statusNum;
            }
        }

        if(!s) {
            if (l)
                pblock_nvinsert("url", l, rq->vars);
            protocol_status(request->getOrigSession(), request->getOrigRequest(), (l ? PROTOCOL_REDIRECT : PROTOCOL_OK), NULL);
        }
    }

    len = next - httpHeader.data();
    len = httpHeader.length() - len;

    if(len < 0)
        return PR_FAILURE;

    /*
     * Only send the body for methods other than HEAD.
     */
    if(!request->isHead()) {
        if(len > 0) {
            if(to.addData(next, len) != len)
                return PR_FAILURE;
        }
    }

    next = NULL;
    return PR_SUCCESS;
}
コード例 #12
0
ファイル: end_request.hpp プロジェクト: TomaseLiu/mosh-fcgi
		End_request(uint32_t _app_status_, Protocol_status _proto_status_) {
			app_status() = _app_status_;
			protocol_status() = _proto_status_;
		}
コード例 #13
0
/** **************************************************************************
 * check-request-limits SAF
 *
 * See top of this file for the pb parameters this SAF can consume and the
 * defaults for each.
 *
 * This SAF counts requests per interval for the given monitor/bucket. If
 * the request/sec in an interval exceeds the max-rps given then it returns
 * REQ_ABORTED for this and all subsequent matching requests in the current
 * interval. After the next interval request rate recomputation the request
 * limiting may be discontinued if the conditions of 'continue' are met.
 *
 * Separately, concurrent requests for the same bucket may be limited to
 * the given number if max-connections is given.
 *
 * On the next request after purge_timeout, a purge sweep of the buckets is
 * done, deleting any entries which have not seen any recomputes in the 
 * purge interval (unless timeout disabled by setting it to zero).
 *
 * For more information, refer to the WS7.0 security functional spec at:
 * http://sac.eng/arc/WSARC/2004/076/
 *
 * For params: http://docs.sun.com/source/817-1835-10/npgmysaf.html#wp14889
 * For returns: http://docs.sun.com/source/817-1835-10/npgmysaf.html#wp14969
 *
 * This returns:
 *      REQ_NOACTION: If the request can go on.
 *      REQ_ABORTED: If the request has hit limits and is not to be processed.
 *          Return code is set to 'error' param (default 503).
 *
 */
int check_request_limits(pblock *pb, Session *sn, Request *rq)
{
    const char * param;
    int response = REQ_NOACTION;

    if (rq->rq_attr.req_restarted) {
        // Do not count restarted requests as new requests for the
        // purpose of reqlimit accounting as it is just one client
        // request.  (This is particularly important for
        // max-connections since processing restarts would cause the
        // conc counter to increase more than once for a given request
        // but only decrease once at the end).
        return response;
    }

    time_t time_now = rq->req_start;
    assert (time_now != NULL);

    // Get max-rps
    
    int max_rps = 0;
    param = pblock_findval(MAXRPS_PARAM, pb);
    if (param) {
        max_rps = atoi(param);
    }

    // Get max-connections

    int conc = 0;
    param = pblock_findval(CONC_PARAM, pb);
    if (param) {
        conc = atoi(param);
    }

    // We must have at least max-rps or max-connections, otherwise can't
    // do anything meaningful here

    if (!max_rps && !conc) {
        log_error(LOG_MISCONFIG, "check-request-limits", sn, rq,
                  XP_GetAdminStr(DBT_reqlimitCantWork));
        return response;
    }

    // Decide bucket name; if none, we use the anonymous bucket anon_bucket

    bucket_info * bucket = NULL;
    const char * bucket_name = pblock_findval(MONITOR_PARAM, pb);
    if (!bucket_name) {
        bucket = &anon_bucket;
    }

    // interval (in seconds), or use default

    int interval = DEFAULT_INTERVAL;
    param = pblock_findval(INTERVAL_PARAM, pb);
    if (param) {
        interval = atoi(param);
    }

    // Check continue, or use default
    int cont = DEFAULT_CONTINUE;
    param = pblock_findval(CONTINUE_PARAM, pb);
    if (param) {
        if (!strcmp(CONT_THRESHOLD_VAL, param)) { cont = CONT_THRESHOLD; }
        else if (!strcmp(CONT_SILENCE_VAL, param)) { cont = CONT_SILENCE; }
        else {
            // Log config error but continue since we have default
            log_error(LOG_MISCONFIG, "check-request-limits", sn, rq,
                      XP_GetAdminStr(DBT_reqlimitBadContinue));
        }
    }

    //----- START_CRIT ------------------------------

    crit_enter(reqlimit_crit);

    if (purge_timeout && (time_now > next_timeout)) { // run purge if needed
        handle_purge_timeout(time_now);
    }

    // If using anon bucket we already have reference to it, otherwise need
    // to go find it in hashtable (and if not found, create one)

    if (!bucket) {

        bucket = (bucket_info *)PL_HashTableLookup(hashtable, bucket_name);

        if (!bucket) {
            // Need to create new entry for this one
            log_error(LOG_VERBOSE, "check-request-limits", sn, rq,
                      "creating new entry for [%s]", bucket_name);
            bucket = (bucket_info *)PERM_MALLOC(sizeof(bucket_info));
            bucket->count = 1;
            bucket->time = time_now + interval;
            bucket->state = REQ_NOACTION;
            bucket->conc = 0;   // handle conc case on initial?
            PL_HashTableAdd(hashtable, 
                            (const void *)PERM_STRDUP(bucket_name), 
                            (void *)bucket);
            // Since it is the first request, no need to check more
            crit_exit(reqlimit_crit);
            return response;
        }
    }

    // If we are doing max-rps limiting then handle it otherwise don't bother

    if (max_rps) {

        bucket->count++;

        if (time_now > bucket->time) { 
            // Interval or more has passed, time to recompute and recheck

            int time_interval = time_now - bucket->time + interval;
            int rps = bucket->count / time_interval;

            log_error(LOG_VERBOSE, "check-request-limits", sn, rq,
                      "bucket [%s] %d req/s (%d req in %d sec)",
                      bucket_name ? bucket_name: "", 
                      rps, bucket->count, time_interval);

            if (rps > max_rps) {
                // Start limiting
                bucket->state = REQ_ABORTED;
                log_error(LOG_WARN,  "check-request-limits", sn, rq,
                          XP_GetAdminStr(DBT_reqlimitAboveMaxRPS),
                          rps, max_rps,
                          bucket_name ? bucket_name: "");

            } else {
                // Reset state if we're under threshhold or if this is first 
                // hit (which means an interval with zero hits has already 
                // passed)
                if ((cont == CONT_THRESHOLD) || (bucket->count == 1)) {
                    bucket->state = REQ_NOACTION;
                }
            }

            // Prepare for next interval by resetting count and recompute time
            bucket->count = 0;
            bucket->time = time_now + interval;
        }

        response = bucket->state;
    }

    // If decision to reject already done, no need to check or increase conc
    // since this is not getting processed anyway. Otherwise, do it if needed.
 
    if (conc && response != REQ_ABORTED) {

        if (bucket->conc >= conc) {
            // Note that this reject is based on conditions at this instant
            // instead of over an interval, so is independent of bucket->state
            response = REQ_ABORTED;

        } else {
            bucket->conc++;
            // This queues up a call to fn associated with req_cleanup
            // (here, reqlimit_conc_done) to be called after request is done
            request_set_data(rq, req_cleanup, bucket);
        }
    }

    crit_exit(reqlimit_crit);

    //----- END_CRIT ------------------------------

    if (response == REQ_NOACTION) {
        return REQ_NOACTION;
    }

    // abort this request

    int err = DEFAULT_ERROR;
    param = pblock_findval(ERROR_PARAM, pb);
    if (param) {
        err = atoi(param);
    }
    protocol_status(sn, rq, err, NULL);

    log_error(LOG_VERBOSE, "check-request-limits", sn, rq,
              "Rejecting request matching bucket [%s] with status %d",
              bucket_name ? bucket_name: "", err);
              
    return response;
}