/* Copyright (c) 2004-2018 Dovecot authors, see the included COPYING file */
#include "auth-common.h"
#include "lib-signals.h"
#include "hash.h"
#include "str.h"
#include "strescape.h"
#include "var-expand.h"
#include "auth-request.h"
#include "auth-cache.h"
#include <time.h>
struct auth_cache {
};
static bool
unsigned int *idx_r)
{
unsigned int i;
if (size == 1) {
*idx_r = i;
return TRUE;
}
*idx_r = i;
return TRUE;
}
}
}
return FALSE;
}
static void
{
if (len == 1)
else {
}
}
{
else {
}
}
{
const char *extra_vars;
for (; *query != '\0'; ) {
if (*query != '%') {
query++;
continue;
}
if (size == 0) {
/* broken %variable ending too early */
break;
}
/* just add the key. it would be nice to prevent
duplicates here as well, but that's just too
much trouble and probably very rare. */
} else {
}
}
/* %n and %d both used -> replace with %u */
}
/* we rely on these being at the beginning */
str_truncate(str, 0);
for (i = 0; i < N_ELEMENTS(key_seen); i++) {
if (key_seen[i])
}
if (*extra_vars != '\0') {
}
}
static void
{
else {
/* unlinking tail */
}
else {
/* unlinking head */
}
}
static void
struct auth_cache_node *node)
{
else
}
static void
{
}
{
i_info("SIGHUP received, %u cache entries flushed",
}
{
unsigned int total_count;
i_info("Authentication cache hits %u/%u (%u%%)",
i_info("Authentication cache inserts: "
"positive: %u entries %llu bytes, "
"negative: %u entries %llu bytes",
i_info("Authentication cache current size: "
/* reset counters */
}
unsigned int neg_ttl_secs
)
{
return cache;
}
{
}
{
return ret;
}
const char *username)
{
"+" master user, "\t" and then usually followed by the username.
It's too much trouble to keep track of all the cache keys, so we'll
just match it as if it was the username. If e.g. '%n' is used in the
cache key instead of '%u', it means that cache entries can be
removed only when @domain isn't in the username parameter. */
return FALSE;
data++;
data++;
if (*data == '+') {
/* skip over +master_user */
data++;
}
if (*data != '\t')
return FALSE;
data++;
}
const char *const *usernames)
{
unsigned int i;
return TRUE;
}
return FALSE;
}
const char *const *usernames)
{
unsigned int ret = 0;
ret++;
}
}
return ret;
}
static const char *
{
/* cache key %variables are separated by tabs, make sure that there
are no tabs in the string */
return str_tabescape(string);
}
static const char *
const char *key)
{
/* It's fine to have unknown %variables in the cache key.
For example db-ldap can have pass_attrs containing
%{ldap:fields} which are used for output, not as part of
the input needed for cache_key. Those could in theory be
filtered out early in the cache_key, but that gets more
problematic when it needs to support also filtering out
e.g. %{sha256:ldap:fields}. */
error_logged = TRUE;
}
return value;
}
const char *
bool *expired_r, bool *neg_expired_r)
{
const char *value;
unsigned int ttl_secs;
*neg_expired_r = FALSE;
cache->miss_count++;
return NULL;
}
/* TTL expired */
cache->miss_count++;
} else {
/* move to head */
}
}
*neg_expired_r = TRUE;
return value;
}
{
/* we're not caching negative entries */
return;
}
/* store into cache using the translated username, except if we're doing
a master user login */
alloc_size = sizeof(struct auth_cache_node) -
/* make sure we have enough space */
/* key is already in cache (probably expired), remove it */
}
/* @UNSAFE */
if (*value != '\0') {
cache->pos_entries++;
} else {
cache->neg_entries++;
}
}
{
return;
}