UNIXworkcode

/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2026 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "sab.h" #include "../../util/util.h" #include "../../util/pblock.h" int rq_match(pblock *pb, const pb_key *param, Request *rq, const char *match, const char *notmatch, int *error) { if(error) { *error = 0; } if(!match && !notmatch) { return 1; } char *str = pblock_findkeyval(param, rq->reqpb); if(!str) { str = ""; } int ret = 0; if(match) { regex_t regex; if(regcomp(&regex, match, REG_EXTENDED)) { log_ereport(LOG_MISCONFIG, "sab: cannot compile regex pattern %s", match); if(error) { *error = 1; } return 0; } regmatch_t rm; if(regexec(&regex, str, 1, &rm, 0) == 0) { ret = 1; } regfree(&regex); } else { ret = 1; } if(notmatch) { regex_t regex; if(regcomp(&regex, notmatch, REG_EXTENDED)) { log_ereport(LOG_MISCONFIG, "sab: cannot compile regex pattern %s", match); if(error) { *error = 1; } return 0; } regmatch_t rm; if(regexec(&regex, str, 1, &rm, 0) == 0) { ret = 0; } regfree(&regex); } return ret; } int sab_url_match(pblock *pb, Request *rq, int *error) { char *match = pblock_findval("match", pb); char *notmatch = pblock_findval("notmatch", pb); return rq_match(pb, pb_key_uri, rq, match, notmatch, error); } int sab_query_match(pblock *pb, Request *rq, int *error) { char *match = pblock_findval("query_match", pb); char *notmatch = pblock_findval("query_notmatch", pb); return rq_match(pb, pb_key_query, rq, match, notmatch, error); } // Simple detection based on a dumb cookie. If not it adds // is-bot to rq->vars. // // Args: // cookie: cookie name // value: cookie value (optional) // match: only apply this check if the request url matches this regex // notmatch: the url should also not match this pattern // query_match: only apply this check if the request query matches this regex // query_notmatch: the query should also not match this pattern // int sab_has_cookie(pblock *pb, Session *sn, Request *rq) { int error; int match = sab_url_match(pb, rq, &error); if(!match) { return error ? REQ_ABORTED : REQ_NOACTION; } match = sab_query_match(pb, rq, &error); if(!match) { return error ? REQ_ABORTED : REQ_NOACTION; } char *cookie_name = pblock_findval("cookie", pb); char *cookie_value = pblock_findval("value", pb); if(!cookie_name) { log_ereport(LOG_MISCONFIG, "sab-has-cookie: no cookie specified"); return REQ_ABORTED; } WSBool has_cookie = FALSE; char *cookie = pblock_findkeyval(pb_key_cookie, rq->headers); if(cookie) { char *value = util_cookie_find(cookie, cookie_name); if(value) { if(cookie_value) { has_cookie = !strcmp(cookie_value, value); } else { has_cookie = TRUE; } } } if(!has_cookie) { pblock_nvinsert("is-bot", "1", rq->vars); } return REQ_NOACTION; }