Mercurial > dovecot > core-2.2
changeset 14340:a090cbbe3008
auth: Fixed auth cache key generation to support %{long} variables
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 14 Mar 2012 14:55:25 +0200 |
parents | 13d4c4f91622 |
children | 90738a7c7535 |
files | src/auth/Makefile.am src/auth/auth-cache.c src/auth/auth-request.c src/auth/auth-request.h src/auth/test-auth-cache.c |
diffstat | 5 files changed, 162 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/Makefile.am Wed Mar 14 13:42:08 2012 +0200 +++ b/src/auth/Makefile.am Wed Mar 14 14:55:25 2012 +0200 @@ -24,6 +24,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-auth \ + -I$(top_srcdir)/src/lib-test \ -I$(top_srcdir)/src/lib-dns \ -I$(top_srcdir)/src/lib-sql \ -I$(top_srcdir)/src/lib-settings \ @@ -182,3 +183,22 @@ checkpassword_reply_sources = \ checkpassword-reply.c + +test_programs = \ + test-auth-cache + +noinst_PROGRAMS = $(test_programs) + +test_libs = \ + ../lib-test/libtest.la \ + ../lib/liblib.la + +test_auth_cache_SOURCES = test-auth-cache.c +test_auth_cache_LDADD = auth-cache.o $(test_libs) +test_auth_cache_DEPENDENCIES = auth-cache.o $(test_libs) + +check: check-am check-test +check-test: all-am + for bin in $(test_programs); do \ + if ! $(RUN_TEST) ./$$bin; then exit 1; fi; \ + done
--- a/src/auth/auth-cache.c Wed Mar 14 13:42:08 2012 +0200 +++ b/src/auth/auth-cache.c Wed Mar 14 14:55:25 2012 +0200 @@ -23,29 +23,75 @@ unsigned long long pos_size, neg_size; }; +static const struct var_expand_table * +auth_request_var_expand_tab_find(const char *key, unsigned int size) +{ + const struct var_expand_table *tab = auth_request_var_expand_static_tab; + unsigned int i; + + for (i = 0; tab[i].key != '\0' || tab[i].long_key != NULL; i++) { + if (size == 1) { + if (key[0] == tab[i].key) + return &tab[i]; + } else if (tab[i].long_key != NULL) { + if (strncmp(key, tab[i].long_key, size) == 0 && + tab[i].long_key[size] == '\0') + return &tab[i]; + } + } + return NULL; +} + char *auth_cache_parse_key(pool_t pool, const char *query) { + const struct var_expand_table *tab; string_t *str; - char key_seen[256]; - uint8_t key; + bool key_seen[100]; + unsigned int idx, size, tab_idx; + bool add_key; memset(key_seen, 0, sizeof(key_seen)); str = str_new(pool, 32); - for (; *query != '\0'; query++) { - if (*query == '%' && query[1] != '\0') { + for (; *query != '\0'; ) { + if (*query != '%') { query++; - key = var_get_key(query); - if (key != '\0' && key != '%' && !key_seen[key]) { - if (str_len(str) != 0) - str_append_c(str, '\t'); - str_append_c(str, '%'); - str_append_c(str, key); + continue; + } + + var_get_key_range(++query, &idx, &size); + if (size == 0) { + /* broken %variable ending too early */ + break; + } + query += idx; - /* @UNSAFE */ - key_seen[key] = 1; + tab = auth_request_var_expand_tab_find(query, size); + if (tab == NULL) { + /* 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. */ + add_key = TRUE; + } else { + tab_idx = tab - auth_request_var_expand_static_tab; + i_assert(tab_idx < N_ELEMENTS(key_seen)); + /* @UNSAFE */ + add_key = !key_seen[tab_idx]; + key_seen[tab_idx] = TRUE; + } + if (add_key) { + if (str_len(str) != 0) + str_append_c(str, '\t'); + str_append_c(str, '%'); + if (size == 1) + str_append_c(str, query[0]); + else { + str_append_c(str, '{'); + str_append_n(str, query, size); + str_append_c(str, '}'); } } + query += size; } return str_free_without_data(&str); }
--- a/src/auth/auth-request.c Wed Mar 14 13:42:08 2012 +0200 +++ b/src/auth/auth-request.c Wed Mar 14 14:55:25 2012 +0200 @@ -1741,38 +1741,40 @@ return str_escape(string); } +const struct var_expand_table auth_request_var_expand_static_tab[] = { + { 'u', NULL, "user" }, + { 'n', NULL, "username" }, + { 'd', NULL, "domain" }, + { 's', NULL, "service" }, + { 'h', NULL, "home" }, + { 'l', NULL, "lip" }, + { 'r', NULL, "rip" }, + { 'p', NULL, "pid" }, + { 'w', NULL, "password" }, + { '!', NULL, NULL }, + { 'm', NULL, "mech" }, + { 'c', NULL, "secured" }, + { 'a', NULL, "lport" }, + { 'b', NULL, "rport" }, + { 'k', NULL, "cert" }, + { '\0', NULL, "login_user" }, + { '\0', NULL, "login_username" }, + { '\0', NULL, "login_domain" }, + { '\0', NULL, NULL } +}; + const struct var_expand_table * auth_request_get_var_expand_table(const struct auth_request *auth_request, auth_request_escape_func_t *escape_func) { - static struct var_expand_table static_tab[] = { - { 'u', NULL, "user" }, - { 'n', NULL, "username" }, - { 'd', NULL, "domain" }, - { 's', NULL, "service" }, - { 'h', NULL, "home" }, - { 'l', NULL, "lip" }, - { 'r', NULL, "rip" }, - { 'p', NULL, "pid" }, - { 'w', NULL, "password" }, - { '!', NULL, NULL }, - { 'm', NULL, "mech" }, - { 'c', NULL, "secured" }, - { 'a', NULL, "lport" }, - { 'b', NULL, "rport" }, - { 'k', NULL, "cert" }, - { '\0', NULL, "login_user" }, - { '\0', NULL, "login_username" }, - { '\0', NULL, "login_domain" }, - { '\0', NULL, NULL } - }; struct var_expand_table *tab; if (escape_func == NULL) escape_func = escape_none; - tab = t_malloc(sizeof(static_tab)); - memcpy(tab, static_tab, sizeof(static_tab)); + tab = t_malloc(sizeof(auth_request_var_expand_static_tab)); + memcpy(tab, auth_request_var_expand_static_tab, + sizeof(auth_request_var_expand_static_tab)); tab[0].value = escape_func(auth_request->user, auth_request); tab[1].value = escape_func(t_strcut(auth_request->user, '@'),
--- a/src/auth/auth-request.h Wed Mar 14 13:42:08 2012 +0200 +++ b/src/auth/auth-request.h Wed Mar 14 14:55:25 2012 +0200 @@ -2,6 +2,7 @@ #define AUTH_REQUEST_H #include "network.h" +#include "var-expand.h" #include "mech.h" #include "userdb.h" #include "passdb.h" @@ -122,6 +123,7 @@ typedef void auth_request_proxy_cb_t(bool success, struct auth_request *); extern unsigned int auth_request_state_count[AUTH_REQUEST_STATE_MAX]; +extern const struct var_expand_table auth_request_var_expand_static_tab[]; struct auth_request * auth_request_new(const struct mech_module *mech);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/test-auth-cache.c Wed Mar 14 14:55:25 2012 +0200 @@ -0,0 +1,57 @@ +/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "auth-request.h" +#include "auth-cache.h" +#include "test-common.h" + +const struct var_expand_table auth_request_var_expand_static_tab[] = { + { 'a', NULL, NULL }, + { '\0', NULL, "longb" }, + { 'c', NULL, "longc" }, + { '\0', NULL, NULL } +}; + +const struct var_expand_table * +auth_request_get_var_expand_table(const struct auth_request *auth_request ATTR_UNUSED, + auth_request_escape_func_t *escape_func ATTR_UNUSED) +{ + return auth_request_var_expand_static_tab; +} + +static void test_auth_cache_parse_key(void) +{ + struct { + const char *in, *out; + } tests[] = { + { "foo%5.5Mabar", "%a" }, + { "foo%5.5M{longb}bar", "%{longb}" }, + { "foo%5.5Mcbar", "%c" }, + { "foo%5.5M{longc}bar", "%{longc}" }, + { "%a%b", "%a\t%b" }, + { "%a%{longb}%a", "%a\t%{longb}" }, + { "%{longc}%c", "%{longc}" }, + { "%c%a%{longc}%c", "%c\t%a" }, + { "%a%{env:foo}%{env:foo}%a", "%a\t%{env:foo}\t%{env:foo}" } + }; + const char *cache_key; + unsigned int i; + + test_begin("auth cache parse key"); + + for (i = 0; i < N_ELEMENTS(tests); i++) { + cache_key = auth_cache_parse_key(pool_datastack_create(), + tests[i].in); + test_assert(strcmp(cache_key, tests[i].out) == 0); + } + test_end(); +} + +int main(void) +{ + static void (*test_functions[])(void) = { + test_auth_cache_parse_key, + NULL + }; + return test_run(test_functions); +}