X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=client-tags.c;h=5cb873d449402b37cdd9d88b1ff8f0c1d5d21d1e;hp=54c4704895be9efa6eddf1460a45eb396b73581f;hb=32ba28b1225c54c850c48814b018e7afcffbd0a5;hpb=80f60832adc944984150109d3260455ab9a16e49 diff --git a/client-tags.c b/client-tags.c index 54c47048..5cb873d4 100644 --- a/client-tags.c +++ b/client-tags.c @@ -4,7 +4,7 @@ * * Purpose : Functions related to client-specific tags. * - * Copyright : Copyright (C) 2016 Fabian Keil + * Copyright : Copyright (C) 2016-2017 Fabian Keil * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General @@ -42,6 +42,7 @@ #include "jcc.h" #include "miscutil.h" #include "errlog.h" +#include "parsers.h" struct client_specific_tag { @@ -232,8 +233,8 @@ void get_tag_list_for_client(struct list *tag_list, if (enabled_tags->end_of_life && (enabled_tags->end_of_life < now)) { struct client_specific_tag *next_tag = enabled_tags->next; - log_error(LOG_LEVEL_INFO, - "Tag '%s' for client %s expired %u seconds ago. Deleting it.", + log_error(LOG_LEVEL_TAGGING, + "Tag '%s' for client %s expired %ld seconds ago. Deleting it.", enabled_tags->name, client_address, (now - enabled_tags->end_of_life)); remove_tag_for_client(client_address, enabled_tags->name); @@ -242,6 +243,8 @@ void get_tag_list_for_client(struct list *tag_list, } else { + log_error(LOG_LEVEL_TAGGING, "Enlisting tag '%s' for client %s", + enabled_tags->name, client_address); enlist(tag_list, enabled_tags->name); } enabled_tags = enabled_tags->next; @@ -251,6 +254,84 @@ void get_tag_list_for_client(struct list *tag_list, } +/********************************************************************* + * + * Function : get_next_tag_timeout_for_client + * + * Description : Figures out when the next temporarily enabled tag + * for the client will have timed out. + * + * Parameters : + * 1 : client_address = Address of the client + * + * Returns : Lowest timeout in seconds + * + *********************************************************************/ +time_t get_next_tag_timeout_for_client(const char *client_address) +{ + struct client_specific_tag *enabled_tags; + time_t next_timeout = 0; + const time_t now = time(NULL); + + privoxy_mutex_lock(&client_tags_mutex); + + enabled_tags = get_tags_for_client(client_address); + while (enabled_tags != NULL) + { + log_error(LOG_LEVEL_TAGGING, + "Evaluating tag '%s' for client %s. End of life %ld", + enabled_tags->name, client_address, enabled_tags->end_of_life); + if (enabled_tags->end_of_life) + { + time_t time_left = enabled_tags->end_of_life - now; + /* Add a second to make sure the tag will have expired */ + time_left++; + log_error(LOG_LEVEL_CGI, "%ld > %ld?", next_timeout, time_left); + if (next_timeout == 0 || next_timeout > time_left) + { + next_timeout = time_left; + } + } + enabled_tags = enabled_tags->next; + } + + privoxy_mutex_unlock(&client_tags_mutex); + + log_error(LOG_LEVEL_CGI, "Next timeout in %ld seconds", next_timeout); + + return next_timeout; + +} + + +/********************************************************************* + * + * Function : create_client_specific_tag + * + * Description : Allocates memory for a client specific tag + * and populates it. + * + * Parameters : + * 1 : name = The name of the tag to create. + * 2 : time_to_live = 0, or the number of seconds + * the tag remains activated. + * + * Returns : Pointer to populated tag + * + *********************************************************************/ +static struct client_specific_tag *create_client_specific_tag(const char *name, + const time_t time_to_live) +{ + struct client_specific_tag *tag; + + tag = zalloc_or_die(sizeof(struct client_specific_tag)); + tag->name = strdup_or_die(name); + tag->end_of_life = time_to_live ? (time(NULL) + time_to_live) : 0; + + return tag; + +} + /********************************************************************* * * Function : add_tag_for_client @@ -279,10 +360,7 @@ static void add_tag_for_client(const char *client_address, /* XXX: Code duplication. */ requested_tags = zalloc_or_die(sizeof(struct requested_tags)); requested_tags->client = strdup_or_die(client_address); - requested_tags->tags = zalloc_or_die(sizeof(struct client_specific_tag)); - requested_tags->tags->name = strdup_or_die(tag); - requested_tags->tags->end_of_life = time_to_live ? - (time(NULL) + time_to_live) : 0; + requested_tags->tags = create_client_specific_tag(tag, time_to_live); validate_requested_tags(); return; @@ -305,10 +383,7 @@ static void add_tag_for_client(const char *client_address, clients_with_tags->next->prev = clients_with_tags; clients_with_tags = clients_with_tags->next; clients_with_tags->client = strdup_or_die(client_address); - clients_with_tags->tags = zalloc_or_die(sizeof(struct client_specific_tag)); - clients_with_tags->tags->name = strdup_or_die(tag); - clients_with_tags->tags->end_of_life = time_to_live ? - (time(NULL) + time_to_live) : 0; + clients_with_tags->tags = create_client_specific_tag(tag, time_to_live); validate_requested_tags(); @@ -321,10 +396,7 @@ static void add_tag_for_client(const char *client_address, { if (enabled_tags->next == NULL) { - enabled_tags->next = zalloc_or_die(sizeof(struct client_specific_tag)); - enabled_tags->next->name = strdup_or_die(tag); - clients_with_tags->tags->end_of_life = time_to_live ? - (time(NULL) + time_to_live) : 0; + enabled_tags->next = create_client_specific_tag(tag, time_to_live); enabled_tags->next->prev = enabled_tags; break; } @@ -365,6 +437,13 @@ static void remove_tag_for_client(const char *client_address, const char *tag) clients_with_tags = clients_with_tags->next; } + assert(clients_with_tags != NULL); + if (clients_with_tags == NULL) + { + log_error(LOG_LEVEL_ERROR, + "Tried to remove tag %s for tag-less client %s", + tag, client_address); + } enabled_tags = clients_with_tags->tags; while (enabled_tags != NULL) { @@ -397,17 +476,16 @@ static void remove_tag_for_client(const char *client_address, const char *tag) /* Client has preceding client */ clients_with_tags->prev->next = clients_with_tags->next; } - freez(clients_with_tags->client); if (clients_with_tags == requested_tags) { - /* Removing last tag */ - freez(requested_tags); - clients_with_tags = requested_tags; - } - else - { - freez(clients_with_tags); + /* + * We're in the process of removing the last tag, + * mark the global list as empty. + */ + requested_tags = NULL; } + freez(clients_with_tags->client); + freez(clients_with_tags); } freez(enabled_tags->name); freez(enabled_tags); @@ -484,17 +562,17 @@ jb_err enable_client_specific_tag(struct client_state *csp, return JB_ERR_PARSE; } - if (client_has_requested_tag(csp->ip_addr_str, tag_name)) + if (client_has_requested_tag(csp->client_address, tag_name)) { - log_error(LOG_LEVEL_ERROR, - "Tag '%s' already enabled for client '%s'", tag->name, csp->ip_addr_str); + log_error(LOG_LEVEL_TAGGING, + "Tag '%s' already enabled for client '%s'", tag->name, csp->client_address); } else { - add_tag_for_client(csp->ip_addr_str, tag_name, time_to_live); - log_error(LOG_LEVEL_INFO, - "Tag '%s' enabled for client '%s'. TTL: %d.", - tag->name, csp->ip_addr_str, time_to_live); + add_tag_for_client(csp->client_address, tag_name, time_to_live); + log_error(LOG_LEVEL_TAGGING, + "Tag '%s' enabled for client '%s'. TTL: %ld.", + tag->name, csp->client_address, time_to_live); } privoxy_mutex_unlock(&client_tags_mutex); @@ -529,17 +607,17 @@ jb_err disable_client_specific_tag(struct client_state *csp, const char *tag_nam return JB_ERR_PARSE; } - if (client_has_requested_tag(csp->ip_addr_str, tag_name)) + if (client_has_requested_tag(csp->client_address, tag_name)) { - remove_tag_for_client(csp->ip_addr_str, tag_name); - log_error(LOG_LEVEL_INFO, - "Tag '%s' disabled for client '%s'", tag->name, csp->ip_addr_str); + remove_tag_for_client(csp->client_address, tag_name); + log_error(LOG_LEVEL_TAGGING, + "Tag '%s' disabled for client '%s'", tag->name, csp->client_address); } else { - log_error(LOG_LEVEL_ERROR, + log_error(LOG_LEVEL_TAGGING, "Tag '%s' currently not set for client '%s'", - tag->name, csp->ip_addr_str); + tag->name, csp->client_address); } privoxy_mutex_unlock(&client_tags_mutex); @@ -581,6 +659,7 @@ int client_tag_match(const struct pattern_spec *pattern, { if (0 == regexec(pattern->pattern.tag_regex, tag->str, 0, NULL, 0)) { + log_error(LOG_LEVEL_TAGGING, "Client tag '%s' matches", tag->str); return 1; } } @@ -588,6 +667,44 @@ int client_tag_match(const struct pattern_spec *pattern, return 0; } + + +/********************************************************************* + * + * Function : set_client_address + * + * Description : Sets the client address that will be used to enable, + * disable, or apply client tags. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : headers = Client headers + * + * Returns : void. + * + *********************************************************************/ +void set_client_address(struct client_state *csp, const struct list *headers) +{ + if (csp->config->trust_x_forwarded_for) + { + const char *client_address; + + client_address = get_header_value(headers, "X-Forwarded-For:"); + if (client_address != NULL) + { + csp->client_address = strdup_or_die(client_address); + log_error(LOG_LEVEL_HEADER, + "Got client address %s from X-Forwarded-For header", + csp->client_address); + } + } + + if (csp->client_address == NULL) + { + csp->client_address = strdup_or_die(csp->ip_addr_str); + } +} + #else #error Compiling client-tags.c without FEATURE_CLIENT_TAGS #endif /* def FEATURE_CLIENT_TAGS */