LCOV - code coverage report
Current view: top level - fuzz - client-tags.c (source / functions) Hit Total Coverage
Test: trace.lcov_info_final Lines: 156 186 83.9 %
Date: 2021-02-22 04:51:02 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /*********************************************************************
       2             :  *
       3             :  * File        :  $Source: /cvsroot/ijbswa/current/client-tags.c,v $
       4             :  *
       5             :  * Purpose     :  Functions related to client-specific tags.
       6             :  *
       7             :  * Copyright   :  Copyright (C) 2016-2017 Fabian Keil <fk@fabiankeil.de>
       8             :  *
       9             :  *                This program is free software; you can redistribute it
      10             :  *                and/or modify it under the terms of the GNU General
      11             :  *                Public License as published by the Free Software
      12             :  *                Foundation; either version 2 of the License, or (at
      13             :  *                your option) any later version.
      14             :  *
      15             :  *                This program is distributed in the hope that it will
      16             :  *                be useful, but WITHOUT ANY WARRANTY; without even the
      17             :  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
      18             :  *                PARTICULAR PURPOSE.  See the GNU General Public
      19             :  *                License for more details.
      20             :  *
      21             :  *                The GNU General Public License should be included with
      22             :  *                this file.  If not, you can view it at
      23             :  *                http://www.gnu.org/copyleft/gpl.html
      24             :  *                or write to the Free Software Foundation, Inc., 59
      25             :  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
      26             :  *
      27             :  **********************************************************************/
      28             : 
      29             : #include "config.h"
      30             : 
      31             : #ifdef FEATURE_CLIENT_TAGS
      32             : 
      33             : #include <stdio.h>
      34             : #include <sys/types.h>
      35             : #include <stdlib.h>
      36             : #include <ctype.h>
      37             : #include <string.h>
      38             : #include <assert.h>
      39             : 
      40             : #include "project.h"
      41             : #include "list.h"
      42             : #include "jcc.h"
      43             : #include "miscutil.h"
      44             : #include "errlog.h"
      45             : #include "parsers.h"
      46             : 
      47             : struct client_specific_tag
      48             : {
      49             :    char *name;
      50             : 
      51             :    time_t end_of_life;
      52             : 
      53             :    struct client_specific_tag *next;
      54             :    struct client_specific_tag *prev;
      55             : };
      56             : 
      57             : /**
      58             :  * This struct represents tags that have been requested by clients
      59             :  */
      60             : struct requested_tags
      61             : {
      62             :    char *client; /**< The IP address of the client that requested the tag */
      63             : 
      64             :    /**< List of tags the client requested .... */
      65             :    struct client_specific_tag *tags;
      66             : 
      67             :    struct requested_tags *next;
      68             :    struct requested_tags *prev;
      69             : };
      70             : 
      71             : struct requested_tags *requested_tags;
      72             : static void remove_tag_for_client(const char *client_address, const char *tag);
      73             : 
      74             : /*********************************************************************
      75             :  *
      76             :  * Function    :  validate_tag_list
      77             :  *
      78             :  * Description :  Validates the given tag list
      79             :  *
      80             :  * Parameters  :
      81             :  *          1  :  enabled_tags = The tags to validate
      82             :  *
      83             :  * Returns     :  void
      84             :  *
      85             :  *********************************************************************/
      86        1969 : static void validate_tag_list(struct client_specific_tag *enabled_tags)
      87             : {
      88        3938 :    while (enabled_tags != NULL)
      89             :    {
      90        1969 :       if (enabled_tags->name == NULL)
      91             :       {
      92           0 :          assert(enabled_tags->name != NULL);
      93           0 :          log_error(LOG_LEVEL_FATAL, "validate_tag_list(): Tag without name detected");
      94             :       }
      95        1969 :       if (enabled_tags->next != NULL)
      96             :       {
      97           0 :          if (enabled_tags->next->prev != enabled_tags)
      98             :          {
      99           0 :             assert(enabled_tags->next->prev == enabled_tags);
     100           0 :             log_error(LOG_LEVEL_FATAL, "validate_tag_list(): Invalid backlink detected");
     101             :          }
     102             :       }
     103        1969 :       enabled_tags = enabled_tags->next;
     104             :    }
     105        1969 : }
     106             : 
     107             : /*********************************************************************
     108             :  *
     109             :  * Function    :  validate_requested_tags
     110             :  *
     111             :  * Description :  Validates the requested_tags list
     112             :  *
     113             :  * Parameters  : N/A
     114             :  *
     115             :  * Returns     :  void
     116             :  *
     117             :  *********************************************************************/
     118         832 : static jb_err validate_requested_tags()
     119             : {
     120             :    struct requested_tags *requested_tag;
     121             : 
     122        2801 :    for (requested_tag = requested_tags; requested_tag != NULL;
     123        1969 :         requested_tag = requested_tag->next)
     124             :    {
     125        1969 :       if (requested_tag->client == NULL)
     126             :       {
     127           0 :          assert(requested_tag->client != NULL);
     128           0 :          log_error(LOG_LEVEL_FATAL, "validate_tag_list(): Client not registered");
     129             :       }
     130        1969 :       validate_tag_list(requested_tag->tags);
     131        1969 :       if (requested_tag->next != NULL)
     132             :       {
     133        1314 :          if (requested_tag->next->prev != requested_tag)
     134             :          {
     135           0 :             assert(requested_tag->next->prev == requested_tag);
     136           0 :             log_error(LOG_LEVEL_FATAL, "validate_requested_tags(): Invalid backlink detected");
     137             :          }
     138             :       }
     139             :    }
     140             : 
     141         832 :    return TRUE;
     142             : }
     143             : 
     144             : 
     145             : /*********************************************************************
     146             :  *
     147             :  * Function    :  get_client_specific_tag
     148             :  *
     149             :  * Description :  Returns the data for a client-specific-tag specified
     150             :  *                by name.
     151             :  *
     152             :  * Parameters  :
     153             :  *          1  :  tag_list = The tag list to check
     154             :  *          2  :  name =     The tag name to look up
     155             :  *
     156             :  * Returns     :  Pointer to tag structure or NULL on error.
     157             :  *
     158             :  *********************************************************************/
     159         805 : static struct client_tag_spec *get_client_specific_tag(
     160             :    struct client_tag_spec *tag_list, const char *name)
     161             : {
     162             :    struct client_tag_spec *tag;
     163             : 
     164        1796 :    for (tag = tag_list; tag != NULL; tag = tag->next)
     165             :    {
     166        1734 :       if (tag->name != NULL && !strcmp(tag->name, name))
     167             :       {
     168         743 :          return tag;
     169             :       }
     170             :    }
     171             : 
     172          62 :    log_error(LOG_LEVEL_ERROR, "No such tag: '%s'", name);
     173             : 
     174          62 :    return NULL;
     175             : 
     176             : }
     177             : 
     178             : 
     179             : /*********************************************************************
     180             :  *
     181             :  * Function    :  get_tags_for_client
     182             :  *
     183             :  * Description :  Returns the list of tags the client opted-in.
     184             :  *
     185             :  * Parameters  :
     186             :  *          1  :  client_address = Address of the client
     187             :  *
     188             :  * Returns     :  Pointer to tag structure or NULL on error.
     189             :  *
     190             :  *********************************************************************/
     191       34918 : static struct client_specific_tag *get_tags_for_client(const char *client_address)
     192             : {
     193             :    struct requested_tags *requested_tag;
     194             : 
     195       38224 :    for (requested_tag = requested_tags; requested_tag != NULL;
     196        3306 :         requested_tag = requested_tag->next)
     197             :    {
     198        4850 :       if (!strcmp(requested_tag->client, client_address))
     199             :       {
     200        1544 :          return requested_tag->tags;
     201             :       }
     202             :    }
     203             : 
     204       33374 :    return NULL;
     205             : }
     206             : 
     207             : 
     208             : /*********************************************************************
     209             :  *
     210             :  * Function    :  get_tag_list_for_client
     211             :  *
     212             :  * Description :  Provides a list of tag names the client opted-in.
     213             :  *                Other tag attributes are not part of the list.
     214             :  *
     215             :  * Parameters  :
     216             :  *          1  :  tag_list = The list to fill in.
     217             :  *          2  :  client_address = Address of the client
     218             :  *
     219             :  * Returns     :  Pointer to tag list.
     220             :  *
     221             :  *********************************************************************/
     222       33010 : void get_tag_list_for_client(struct list *tag_list,
     223             :                              const char *client_address)
     224             : {
     225             :    struct client_specific_tag *enabled_tags;
     226       33010 :    const time_t now = time(NULL);
     227             : 
     228       33010 :    privoxy_mutex_lock(&client_tags_mutex);
     229             : 
     230       33010 :    enabled_tags = get_tags_for_client(client_address);
     231       33799 :    while (enabled_tags != NULL)
     232             :    {
     233         789 :       if (enabled_tags->end_of_life && (enabled_tags->end_of_life < now))
     234             :       {
     235           0 :          struct client_specific_tag *next_tag = enabled_tags->next;
     236           0 :          log_error(LOG_LEVEL_TAGGING,
     237             :             "Tag '%s' for client %s expired %ld seconds ago. Deleting it.",
     238             :             enabled_tags->name, client_address,
     239           0 :             (now - enabled_tags->end_of_life));
     240           0 :          remove_tag_for_client(client_address, enabled_tags->name);
     241           0 :          enabled_tags = next_tag;
     242           0 :          continue;
     243             :       }
     244             :       else
     245             :       {
     246         789 :          log_error(LOG_LEVEL_TAGGING, "Enlisting tag '%s' for client %s.",
     247             :             enabled_tags->name, client_address);
     248         789 :          enlist(tag_list, enabled_tags->name);
     249             :       }
     250         789 :       enabled_tags = enabled_tags->next;
     251             :    }
     252             : 
     253       33010 :    privoxy_mutex_unlock(&client_tags_mutex);
     254       33010 : }
     255             : 
     256             : 
     257             : /*********************************************************************
     258             :  *
     259             :  * Function    :  get_next_tag_timeout_for_client
     260             :  *
     261             :  * Description :  Figures out when the next temporarily enabled tag
     262             :  *                for the client will have timed out.
     263             :  *
     264             :  * Parameters  :
     265             :  *          1  :  client_address = Address of the client
     266             :  *
     267             :  * Returns     :  Lowest timeout in seconds
     268             :  *
     269             :  *********************************************************************/
     270         233 : time_t get_next_tag_timeout_for_client(const char *client_address)
     271             : {
     272             :    struct client_specific_tag *enabled_tags;
     273         233 :    time_t next_timeout = 0;
     274         233 :    const time_t now = time(NULL);
     275             : 
     276         233 :    privoxy_mutex_lock(&client_tags_mutex);
     277             : 
     278         233 :    enabled_tags = get_tags_for_client(client_address);
     279         316 :    while (enabled_tags != NULL)
     280             :    {
     281          83 :       log_error(LOG_LEVEL_TAGGING,
     282             :          "Evaluating tag '%s' for client %s. End of life %ld.",
     283             :          enabled_tags->name, client_address, enabled_tags->end_of_life);
     284          83 :       if (enabled_tags->end_of_life)
     285             :       {
     286          47 :           time_t time_left = enabled_tags->end_of_life - now;
     287             :           /* Add a second to make sure the tag will have expired */
     288          47 :           time_left++;
     289          47 :           log_error(LOG_LEVEL_CGI, "%ld > %ld?", next_timeout, time_left);
     290          47 :           if (next_timeout == 0 || next_timeout > time_left)
     291             :           {
     292          47 :              next_timeout = time_left;
     293             :           }
     294             :        }
     295          83 :        enabled_tags = enabled_tags->next;
     296             :    }
     297             : 
     298         233 :    privoxy_mutex_unlock(&client_tags_mutex);
     299             : 
     300         233 :    log_error(LOG_LEVEL_CGI, "Next timeout in %ld seconds", next_timeout);
     301             : 
     302         233 :    return next_timeout;
     303             : 
     304             : }
     305             : 
     306             : 
     307             : /*********************************************************************
     308             :  *
     309             :  * Function    :  create_client_specific_tag
     310             :  *
     311             :  * Description :  Allocates memory for a client specific tag
     312             :  *                and populates it.
     313             :  *
     314             :  * Parameters  :
     315             :  *          1  :  name = The name of the tag to create.
     316             :  *          2  :  time_to_live = 0, or the number of seconds
     317             :  *                               the tag remains activated.
     318             :  *
     319             :  * Returns     :  Pointer to populated tag
     320             :  *
     321             :  *********************************************************************/
     322         284 : static struct client_specific_tag *create_client_specific_tag(const char *name,
     323             :    const time_t time_to_live)
     324             : {
     325             :    struct client_specific_tag *tag;
     326             : 
     327         284 :    tag = zalloc_or_die(sizeof(struct client_specific_tag));
     328         284 :    tag->name = strdup_or_die(name);
     329         284 :    tag->end_of_life = time_to_live ? (time(NULL) + time_to_live) : 0;
     330             : 
     331         284 :    return tag;
     332             : 
     333             : }
     334             : 
     335             : /*********************************************************************
     336             :  *
     337             :  * Function    :  add_tag_for_client
     338             :  *
     339             :  * Description :  Adds the tag for the client.
     340             :  *
     341             :  * Parameters  :
     342             :  *          1  :  client_address = Address of the client
     343             :  *          2  :  tag = The tag to add.
     344             :  *          3  :  time_to_live = 0, or the number of seconds
     345             :  *                               the tag remains activated.
     346             :  *
     347             :  * Returns     :  void
     348             :  *
     349             :  *********************************************************************/
     350         284 : static void add_tag_for_client(const char *client_address,
     351             :    const char *tag, const time_t time_to_live)
     352             : {
     353             :    struct requested_tags *clients_with_tags;
     354             :    struct client_specific_tag *enabled_tags;
     355             : 
     356         284 :    validate_requested_tags();
     357             : 
     358         284 :    if (requested_tags == NULL)
     359             :    {
     360             :       /* XXX: Code duplication. */
     361         119 :       requested_tags = zalloc_or_die(sizeof(struct requested_tags));
     362         119 :       requested_tags->client = strdup_or_die(client_address);
     363         119 :       requested_tags->tags = create_client_specific_tag(tag, time_to_live);
     364             : 
     365         119 :       validate_requested_tags();
     366         119 :       return;
     367             :    }
     368             :    else
     369             :    {
     370         165 :       clients_with_tags = requested_tags;
     371         482 :       while (clients_with_tags->next != NULL)
     372             :       {
     373         317 :          if (!strcmp(clients_with_tags->client, client_address))
     374             :          {
     375           0 :             break;
     376             :          }
     377         317 :          clients_with_tags = clients_with_tags->next;
     378             :       }
     379         165 :       if (strcmp(clients_with_tags->client, client_address))
     380             :       {
     381             :          /* Client does not have tags yet, add new structure */
     382         165 :          clients_with_tags->next = zalloc_or_die(sizeof(struct requested_tags));
     383         165 :          clients_with_tags->next->prev = clients_with_tags;
     384         165 :          clients_with_tags = clients_with_tags->next;
     385         165 :          clients_with_tags->client = strdup_or_die(client_address);
     386         165 :          clients_with_tags->tags = create_client_specific_tag(tag, time_to_live);
     387             : 
     388         165 :          validate_requested_tags();
     389             : 
     390         165 :          return;
     391             :       }
     392             :    }
     393             : 
     394           0 :    enabled_tags = clients_with_tags->tags;
     395           0 :    while (enabled_tags != NULL)
     396             :    {
     397           0 :       if (enabled_tags->next == NULL)
     398             :       {
     399           0 :          enabled_tags->next = create_client_specific_tag(tag, time_to_live);
     400           0 :          enabled_tags->next->prev = enabled_tags;
     401           0 :          break;
     402             :       }
     403           0 :       enabled_tags = enabled_tags->next;
     404             :    }
     405             : 
     406           0 :    validate_requested_tags();
     407             : }
     408             : 
     409             : 
     410             : /*********************************************************************
     411             :  *
     412             :  * Function    :  remove_tag_for_client
     413             :  *
     414             :  * Description :  Removes the tag for the client.
     415             :  *
     416             :  * Parameters  :
     417             :  *          1  :  client_address = Address of the client
     418             :  *          2  :  tag = The tag to remove.
     419             :  *
     420             :  * Returns     :  void
     421             :  *
     422             :  *********************************************************************/
     423         132 : static void remove_tag_for_client(const char *client_address, const char *tag)
     424             : {
     425             :    struct requested_tags *clients_with_tags;
     426             :    struct client_specific_tag *enabled_tags;
     427             : 
     428         132 :    validate_requested_tags();
     429             : 
     430         132 :    clients_with_tags = requested_tags;
     431         393 :    while (clients_with_tags != NULL && clients_with_tags->client != NULL)
     432             :    {
     433         393 :       if (!strcmp(clients_with_tags->client, client_address))
     434             :       {
     435         132 :          break;
     436             :       }
     437         261 :       clients_with_tags = clients_with_tags->next;
     438             :    }
     439             : 
     440         132 :    assert(clients_with_tags != NULL);
     441         132 :    if (clients_with_tags == NULL)
     442             :    {
     443           0 :       log_error(LOG_LEVEL_ERROR,
     444             :          "Tried to remove tag %s for tag-less client %s",
     445             :          tag, client_address);
     446             :    }
     447         132 :    enabled_tags = clients_with_tags->tags;
     448         132 :    while (enabled_tags != NULL)
     449             :    {
     450         132 :       if (!strcmp(enabled_tags->name, tag))
     451             :       {
     452         132 :          if (enabled_tags->next != NULL)
     453             :          {
     454           0 :             enabled_tags->next->prev = enabled_tags->prev;
     455           0 :             if (enabled_tags == clients_with_tags->tags)
     456             :             {
     457             :                /* Tag is first in line */
     458           0 :                clients_with_tags->tags = enabled_tags->next;
     459             :             }
     460             :          }
     461         132 :          if (enabled_tags->prev != NULL)
     462             :          {
     463             :             /* Tag has preceding tag */
     464           0 :             enabled_tags->prev->next = enabled_tags->next;
     465             :          }
     466         132 :          if (enabled_tags->prev == NULL && enabled_tags->next == NULL)
     467             :          {
     468             :             /* Tag is the only one */
     469         132 :             if (clients_with_tags->next != NULL)
     470             :             {
     471             :                /* Client has following client */
     472          35 :                clients_with_tags->next->prev = clients_with_tags->prev;
     473             :             }
     474         132 :             if (clients_with_tags->prev != NULL)
     475             :             {
     476             :                /* Client has preceding client */
     477          74 :                clients_with_tags->prev->next = clients_with_tags->next;
     478             :             }
     479         132 :             if (clients_with_tags == requested_tags)
     480             :             {
     481             :                /*
     482             :                 * We're in the process of removing the last tag,
     483             :                 * mark the global list as empty.
     484             :                 */
     485          58 :                requested_tags = NULL;
     486             :             }
     487         132 :             freez(clients_with_tags->client);
     488         132 :             freez(clients_with_tags);
     489             :          }
     490         132 :          freez(enabled_tags->name);
     491         132 :          freez(enabled_tags);
     492         132 :          break;
     493             :       }
     494             : 
     495           0 :       enabled_tags = enabled_tags->next;
     496             :    }
     497             : 
     498         132 :    validate_requested_tags();
     499             : 
     500         132 : }
     501             : 
     502             : 
     503             : /*********************************************************************
     504             :  *
     505             :  * Function    :  client_has_requested_tag
     506             :  *
     507             :  * Description :  Checks whether or not the given client requested
     508             :  *                the tag.
     509             :  *
     510             :  * Parameters  :
     511             :  *          1  :  client_address = Address of the client
     512             :  *          2  :  tag = Tag to check.
     513             :  *
     514             :  * Returns     :  TRUE or FALSE.
     515             :  *
     516             :  *********************************************************************/
     517        1675 : int client_has_requested_tag(const char *client_address, const char *tag)
     518             : {
     519             :    struct client_specific_tag *enabled_tags;
     520             : 
     521        1675 :    enabled_tags = get_tags_for_client(client_address);
     522             : 
     523        1924 :    while (enabled_tags != NULL)
     524             :    {
     525         672 :       if (!strcmp(enabled_tags->name, tag))
     526             :       {
     527         423 :          return TRUE;
     528             :       }
     529         249 :       enabled_tags = enabled_tags->next;
     530             :    }
     531             : 
     532        1252 :    return FALSE;
     533             : 
     534             : }
     535             : 
     536             : /*********************************************************************
     537             :  *
     538             :  * Function    :  enable_client_specific_tag
     539             :  *
     540             :  * Description :  Enables a client-specific-tag for the client
     541             :  *
     542             :  * Parameters  :
     543             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     544             :  *          2  :  tag_name = The name of the tag to enable
     545             :  *          3  :  time_to_live = If not 0, the number of seconds the
     546             :  *                               tag should stay enabled.
     547             :  *
     548             :  * Returns     :  JB_ERR_OK on success, JB_ERR_MEMORY or JB_ERR_PARSE.
     549             :  *
     550             :  *********************************************************************/
     551         511 : jb_err enable_client_specific_tag(struct client_state *csp,
     552             :    const char *tag_name, const time_t time_to_live)
     553             : {
     554             :    struct client_tag_spec *tag;
     555             : 
     556         511 :    privoxy_mutex_lock(&client_tags_mutex);
     557             : 
     558         511 :    tag = get_client_specific_tag(csp->config->client_tags, tag_name);
     559         511 :    if (tag == NULL)
     560             :    {
     561          19 :       privoxy_mutex_unlock(&client_tags_mutex);
     562          19 :       return JB_ERR_PARSE;
     563             :    }
     564             : 
     565         492 :    if (client_has_requested_tag(csp->client_address, tag_name))
     566             :    {
     567         208 :       log_error(LOG_LEVEL_TAGGING,
     568             :          "Tag '%s' already enabled for client '%s'.",
     569             :          tag->name, csp->client_address);
     570             :    }
     571             :    else
     572             :    {
     573         284 :       add_tag_for_client(csp->client_address, tag_name, time_to_live);
     574         284 :       log_error(LOG_LEVEL_TAGGING,
     575             :          "Tag '%s' enabled for client '%s'. TTL: %ld.",
     576             :          tag->name, csp->client_address, time_to_live);
     577             :    }
     578             : 
     579         492 :    privoxy_mutex_unlock(&client_tags_mutex);
     580             : 
     581         492 :    return JB_ERR_OK;
     582             : 
     583             : }
     584             : 
     585             : /*********************************************************************
     586             :  *
     587             :  * Function    :  disable_client_specific_tag
     588             :  *
     589             :  * Description :  Disables a client-specific-tag for the client
     590             :  *
     591             :  * Parameters  :
     592             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     593             :  *          2  :  tag_name = The name of the tag to disable
     594             :  *
     595             :  * Returns     :  JB_ERR_OK on success, JB_ERR_MEMORY or JB_ERR_PARSE.
     596             :  *
     597             :  *********************************************************************/
     598         294 : jb_err disable_client_specific_tag(struct client_state *csp, const char *tag_name)
     599             : {
     600             :    struct client_tag_spec *tag;
     601             : 
     602         294 :    privoxy_mutex_lock(&client_tags_mutex);
     603             : 
     604         294 :    tag = get_client_specific_tag(csp->config->client_tags, tag_name);
     605         294 :    if (tag == NULL)
     606             :    {
     607          43 :       privoxy_mutex_unlock(&client_tags_mutex);
     608          43 :       return JB_ERR_PARSE;
     609             :    }
     610             : 
     611         251 :    if (client_has_requested_tag(csp->client_address, tag_name))
     612             :    {
     613         132 :       remove_tag_for_client(csp->client_address, tag_name);
     614         132 :       log_error(LOG_LEVEL_TAGGING,
     615             :          "Tag '%s' disabled for client '%s'.", tag->name, csp->client_address);
     616             :    }
     617             :    else
     618             :    {
     619         119 :       log_error(LOG_LEVEL_TAGGING,
     620             :          "Tag '%s' currently not set for client '%s'.",
     621             :          tag->name, csp->client_address);
     622             :    }
     623             : 
     624         251 :    privoxy_mutex_unlock(&client_tags_mutex);
     625         251 :    return JB_ERR_OK;
     626             : 
     627             : }
     628             : 
     629             : 
     630             : /*********************************************************************
     631             :  *
     632             :  * Function    :  client_tag_match
     633             :  *
     634             :  * Description :  Compare a client tag against a client tag pattern.
     635             :  *
     636             :  * Parameters  :
     637             :  *          1  :  pattern = a TAG pattern
     638             :  *          2  :  tag = Client tag to match
     639             :  *
     640             :  * Returns     :  Nonzero if the tag matches the pattern, else 0.
     641             :  *
     642             :  *********************************************************************/
     643      700980 : int client_tag_match(const struct pattern_spec *pattern,
     644             :                      const struct list *tags)
     645             : {
     646             :    struct list_entry *tag;
     647             : 
     648      700980 :    if (!(pattern->flags & PATTERN_SPEC_CLIENT_TAG_PATTERN))
     649             :    {
     650             :       /*
     651             :        * It's not a client pattern and thus shouldn't
     652             :        * be matched against client tags.
     653             :        */
     654      567460 :       return 0;
     655             :    }
     656             : 
     657      133520 :    assert(tags);
     658             : 
     659      135896 :    for (tag = tags->first; tag != NULL; tag = tag->next)
     660             :    {
     661        3168 :       if (0 == regexec(pattern->pattern.tag_regex, tag->str, 0, NULL, 0))
     662             :       {
     663         792 :          log_error(LOG_LEVEL_TAGGING, "Client tag '%s' matches.", tag->str);
     664         792 :          return 1;
     665             :       }
     666             :    }
     667             : 
     668      132728 :    return 0;
     669             : 
     670             : }
     671             : 
     672             : 
     673             : /*********************************************************************
     674             :  *
     675             :  * Function    :  set_client_address
     676             :  *
     677             :  * Description :  Sets the client address that will be used to enable,
     678             :  *                disable, or apply client tags.
     679             :  *
     680             :  * Parameters  :
     681             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     682             :  *          2  :  headers = Client headers
     683             :  *
     684             :  * Returns     :  void.
     685             :  *
     686             :  *********************************************************************/
     687       33010 : void set_client_address(struct client_state *csp, const struct list *headers)
     688             : {
     689       33010 :    if (csp->config->trust_x_forwarded_for)
     690             :    {
     691             :       const char *client_address;
     692             : 
     693       33010 :       client_address = get_header_value(headers, "X-Forwarded-For:");
     694       33010 :       if (client_address != NULL)
     695             :       {
     696        2053 :          csp->client_address = strdup_or_die(client_address);
     697        2053 :          log_error(LOG_LEVEL_HEADER,
     698             :             "Got client address %s from X-Forwarded-For header",
     699             :             csp->client_address);
     700             :       }
     701             :    }
     702             : 
     703       33010 :    if (csp->client_address == NULL)
     704             :    {
     705       30957 :       csp->client_address = strdup_or_die(csp->ip_addr_str);
     706             :    }
     707       33010 : }
     708             : 
     709             : #else
     710             : #error Compiling client-tags.c without FEATURE_CLIENT_TAGS
     711             : #endif /* def FEATURE_CLIENT_TAGS */

Generated by: LCOV version 1.14