summaryrefslogtreecommitdiff
path: root/libmailutils/base
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-10-24 14:26:08 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-10-24 14:46:19 +0300
commitbe1380d7aa53c031a237b5e993187733eab3fa40 (patch)
treed51add3f754cd73e37c9c8c345ba04d94b838152 /libmailutils/base
parentd992b1b4f5d731a3e11a5caaffd22cfd068e5477 (diff)
downloadmailutils-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.c87
-rw-r--r--libmailutils/base/wicket.c89
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;

Return to:

Send suggestions and report system problems to the System administrator.