diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-10-24 14:26:08 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-10-24 14:46:19 +0300 |
commit | be1380d7aa53c031a237b5e993187733eab3fa40 (patch) | |
tree | d51add3f754cd73e37c9c8c345ba04d94b838152 /libmailutils/base | |
parent | d992b1b4f5d731a3e11a5caaffd22cfd068e5477 (diff) | |
download | mailutils-be1380d7aa53c031a237b5e993187733eab3fa40.tar.gz mailutils-be1380d7aa53c031a237b5e993187733eab3fa40.tar.bz2 |
Improve the algorithm for URL look up in wickets.
The new algorithm always returns the best match, i.e. the
one with the smallest number of wildcard comparisons.
* include/mailutils/auth.h (mu_wicket_stream_match_url)
(mu_wicket_file_match_url): New protos.
Remove unnecessary 'extern' qualifiers.
* include/mailutils/url.h (mu_url_is_ticket): Remove.
(mu_url_matches_ticket): New proto.
* libmailutils/base/url.c (mu_url_parse): Fix name corruption during
password obfuscation.
(defined): Remove static function.
(mu_url_is_ticket): Remove function.
(mu_url_matches_ticket): New function.
* libmailutils/base/wicket.c (get_ticket_url): Remove.
(mu_wicket_stream_match_url)
(mu_wicket_file_match_url): New functions.
(file_ticket_get_cred): Use mu_wicket_file_match_url.
* libmailutils/tests/wicket.c: New file.
* libmailutils/tests/Wicketfile: New file.
* libmailutils/tests/wicket.at: New file.
* libmailutils/tests/Makefile.am (noinst_PROGRAMS): Add wicket.
(EXTRA_DIST): Add Wicketfile
(TESTSUITE_AT): Add wicket.at
* libmailutils/tests/testsuite.at: Include wicket.at
* libmailutils/tests/.gitignore: Update.
Diffstat (limited to 'libmailutils/base')
-rw-r--r-- | libmailutils/base/url.c | 87 | ||||
-rw-r--r-- | libmailutils/base/wicket.c | 89 |
2 files changed, 108 insertions, 68 deletions
diff --git a/libmailutils/base/url.c b/libmailutils/base/url.c index 9b4e102c6..49aab4b18 100644 --- a/libmailutils/base/url.c +++ b/libmailutils/base/url.c @@ -316,13 +316,18 @@ mu_url_parse (mu_url_t url) char *newname; memset (url->name + pstart, 0, plen); - newname = realloc (url->name, len); - if (!newname) - goto CLEANUP; + if (len > nlen + 1) + { + newname = realloc (url->name, len); + if (!newname) + goto CLEANUP; + url->name = newname; + } + else + newname = url->name; memmove (newname + pstart + PASS_REPL_LEN, newname + pstart + plen, nlen - (pstart + plen) + 1); memcpy (newname + pstart, PASS_REPL, PASS_REPL_LEN); - url->name = newname; } /* Dup the strings we found. We wouldn't have to do this @@ -959,44 +964,68 @@ mu_url_decode (const char *s) return mu_url_decode_len (s, strlen (s)); } -static int -defined (const char *s) -{ - if (s && strcmp ("*", s) != 0) - return 1; - return 0; -} +#define is_wildcard(s) ((s)[0] == '*' && s[1] == 0) int -mu_url_is_ticket (mu_url_t ticket, mu_url_t url) +mu_url_matches_ticket (mu_url_t ticket, mu_url_t url, int *pwc) { - if (!ticket || !url) + int wcnt = 0; + + if (is_wildcard (ticket->scheme)) + wcnt++; + else if (mu_c_strcasecmp (ticket->scheme, url->scheme)) return 0; - /* If ticket has a scheme, host, port, or path, then the queries - equivalent must be defined and match. */ - if (defined (ticket->scheme)) + if (ticket->flags & MU_URL_HOST) { - if (!url->scheme || mu_c_strcasecmp (ticket->scheme, url->scheme) != 0) + if (is_wildcard (ticket->host)) + wcnt++; + else if (url->flags & MU_URL_HOST) + { + if (mu_c_strcasecmp (ticket->host, url->host)) + /* FIXME: Compare IP addresses */ + return 0; + } + else return 0; } - if (defined (ticket->host)) + else + wcnt++; + + if (ticket->flags & MU_URL_PORT) { - if (!url->host || mu_c_strcasecmp (ticket->host, url->host) != 0) - return 0; + /* FIXME: No way to put a wildcard in the ticket file */ + if (url->port & MU_URL_PORT) + { + if (ticket->port != url->port) + return 0; + else + wcnt++; + } } - if (ticket->port && ticket->port != url->port) - return 0; - /* If ticket has a user or pass, but url doesn't, that's OK, we were - urling for this info. But if url does have a user/pass, it - must match the ticket. */ - if (url->user) + else + wcnt++; + + if (ticket->flags & MU_URL_USER) { - if (defined (ticket->user) && strcmp (ticket->user, url->user) != 0) - return 0; + if (is_wildcard (ticket->user)) + wcnt += 2; + + /* If ticket has a user or pass, but url doesn't, that's OK, we were + looking for this info. But if url does have a user/pass, it + must match the ticket. */ + else if (url->flags & MU_URL_USER) + { + if (strcmp (ticket->user, url->user)) + return 0; + } } - + else + wcnt++; + /* Guess it matches. */ + if (pwc) + *pwc = wcnt; return 1; } diff --git a/libmailutils/base/wicket.c b/libmailutils/base/wicket.c index 705e69a69..4d79c2ce4 100644 --- a/libmailutils/base/wicket.c +++ b/libmailutils/base/wicket.c @@ -34,6 +34,9 @@ #include <mailutils/util.h> #include <mailutils/mu_auth.h> #include <mailutils/stream.h> +#include <mailutils/cstr.h> +#include <mailutils/nls.h> +#include <mailutils/errno.h> #include <mailutils/sys/auth.h> #include <mailutils/sys/url.h> @@ -50,7 +53,8 @@ mu_wicket_create (mu_wicket_t *pwicket) } int -mu_wicket_get_ticket (mu_wicket_t wicket, const char *user, mu_ticket_t *pticket) +mu_wicket_get_ticket (mu_wicket_t wicket, const char *user, + mu_ticket_t *pticket) { if (!wicket) return EINVAL; @@ -168,8 +172,6 @@ file_ticket_destroy (mu_ticket_t ticket) } } -static int get_ticket_url (mu_ticket_t ticket, mu_url_t url, mu_url_t *pticket_url); - int file_ticket_get_cred (mu_ticket_t ticket, mu_url_t url, const char *challenge, char **pplain, mu_secret_t *psec) @@ -178,7 +180,7 @@ file_ticket_get_cred (mu_ticket_t ticket, mu_url_t url, const char *challenge, if (!ft->tickurl) { - int rc = get_ticket_url (ticket, url, &ft->tickurl); + int rc = mu_wicket_file_match_url (ft->filename, url, &ft->tickurl); if (rc) return rc; } @@ -241,37 +243,28 @@ _file_wicket_get_ticket (mu_wicket_t wicket, void *data, return 0; } -static int -get_ticket_url (mu_ticket_t ticket, mu_url_t url, mu_url_t *pticket_url) +int +mu_wicket_stream_match_url (mu_stream_t stream, struct mu_debug_locus *loc, + mu_url_t url, mu_url_t *pticket_url) { - mu_stream_t stream; - struct file_ticket *ft = mu_ticket_get_data (ticket); int rc; mu_url_t u = NULL; char *buf = NULL; size_t bufsize = 0; size_t len; - - rc = mu_file_stream_create (&stream, ft->filename, MU_STREAM_READ); - if (rc) - return rc; + mu_url_t pret = NULL; + int weight = 0; + int line = loc->line; while ((rc = mu_stream_getline (stream, &buf, &bufsize, &len)) == 0 && len > 0) { char *p; int err; + int n; - /* Truncate a trailing newline. */ - if (len && buf[len - 1] == '\n') - buf[--len] = 0; - - /* Skip leading spaces */ - for (p = buf; *p == ' ' || *p == '\t'; p++) - ; - /* Skip trailing spaces */ - for (; len > 0 && (p[len-1] == ' ' || p[len-1] == '\t'); ) - p[--len] = 0; + loc->line++; + p = mu_str_stripws (buf); /* Skip empty lines and comments. */ if (*p == 0 || *p == '#') @@ -280,43 +273,42 @@ get_ticket_url (mu_ticket_t ticket, mu_url_t url, mu_url_t *pticket_url) if ((err = mu_url_create (&u, p)) != 0) { /* Skip erroneous entry */ - /* FIXME: Error message */ + mu_error (_("%s:%u: cannot create URL: %s"), + loc->file, loc->line, mu_strerror (err)); continue; } if ((err = mu_url_parse (u)) != 0) { - /* FIXME: See above */ + mu_error (_("%s:%u: cannot parse URL: %s"), + loc->file, loc->line, mu_strerror (err)); mu_url_destroy (&u); continue; } - if (!mu_url_is_ticket (u, url)) + if (!mu_url_matches_ticket (u, url, &n)) { mu_url_destroy (&u); continue; } - if (ft->user) + if (!pret || n < weight) { - if (u->name && strcmp (u->name, "*") != 0 - && strcmp (ft->user, u->name) != 0) - { - mu_url_destroy (&u); - continue; - } + pret = u; + weight = n; + line = loc->line; + if (weight == 0) + break; } - - break; } - mu_stream_close (stream); free (buf); - mu_stream_destroy (&stream); - if (rc == 0) { - if (u) - *pticket_url = u; + if (pret) + { + *pticket_url = pret; + loc->line = line; + } else rc = MU_ERR_NOENT; } @@ -325,6 +317,25 @@ get_ticket_url (mu_ticket_t ticket, mu_url_t url, mu_url_t *pticket_url) } int +mu_wicket_file_match_url (const char *name, mu_url_t url, + mu_url_t *pticket_url) +{ + mu_stream_t stream; + int rc; + struct mu_debug_locus loc; + + rc = mu_file_stream_create (&stream, name, MU_STREAM_READ); + if (rc) + return rc; + loc.file = name; + loc.line = 0; + rc = mu_wicket_stream_match_url (stream, &loc, url, pticket_url); + mu_stream_close (stream); + mu_stream_destroy (&stream); + return rc; +} + +int mu_file_wicket_create (mu_wicket_t *pwicket, const char *filename) { mu_wicket_t wicket; |