X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=pop.c;h=02caf5ab601f5a1c1e6d1466bdb57d2ad34a4522;hb=442dc01c2b410071ff214a22f31adb25a62890b2;hp=6c33235f05f6a9b831de641f1d9cc2e09d2ce369;hpb=2b10227932141f86d8bb5f0706bfe87b4c0a8bcf;p=cascardo%2Frnetproxy.git diff --git a/pop.c b/pop.c index 6c33235..02caf5a 100644 --- a/pop.c +++ b/pop.c @@ -18,20 +18,59 @@ ** */ -#include #include #include -#include "nethook.h" +#include "hcconn_internal.h" #include "pop.h" +#include "usermap.h" typedef struct { - net_read orig_read; - gpointer orig_data; GString *buffer; GString *line; + GString *push; + gchar *user; + HCConn *lowconn; } pop_t; +void +pop_destroy (pop_t *pop) +{ + g_string_free (pop->buffer, TRUE); + g_string_free (pop->line, TRUE); + g_string_free (pop->push, TRUE); + if (pop->user) + g_free (pop->user); + g_slice_free (pop_t, (gpointer) pop); +} + +static int +pop_check_user (pop_t *pop) +{ + gchar *end; + gchar *s; + end = pop->line->str + pop->line->len; + s = pop->line->str; + while (s < end && *s == ' ') s++; + if (end - s < 5) + return -1; + if (g_ascii_strncasecmp (s, "USER ", 5) != 0) + return -1; + s += 5; + while (s < end && *s == ' ') s++; + if (s == end) + return -1; + end--; + while (end >= s && (*end == '\n' || *end == '\r')) end--; + if (end < s) + return -1; + if (pop->user) + g_free (pop->user); + pop->user = g_strndup (s, end - s + 2); + pop->user[end - s + 1] = 0; + return 0; +} + static int pop_getline (pop_t *pop) { @@ -50,37 +89,96 @@ pop_getline (pop_t *pop) } static void -pop_read (net_hook_t *hook, gchar *buffer, size_t len) +pop_watch (HCConn *conn, HCEvent event, gpointer data) +{ + char buffer[4096]; + int r; + HCConn *pop_conn = data; + pop_t *pop = pop_conn->layer; + switch (event) + { + case HC_EVENT_READ: + while ((r = hc_conn_read (conn, buffer, sizeof (buffer))) > 0) + { + g_string_append_len (pop->buffer, buffer, r); + while (pop_getline (pop) == 0) + { + if (pop_check_user (pop) == 0) + { + g_message ("User is trying to authenticate as %s.", + pop->user); + if (usermap_perm (pop->user) == ACCESS_DENY) + { + g_message ("Denying access to user %s.", pop->user); + if (pop_conn->func) + pop_conn->func (pop_conn, HC_EVENT_CLOSE, + pop_conn->data); + return; + } + } + g_string_append_len (pop->push, pop->line->str, pop->line->len); + if (pop_conn->func) + pop_conn->func (pop_conn, HC_EVENT_READ, pop_conn->data); + } + } + break; + case HC_EVENT_CLOSE: + if (pop_conn->func) + pop_conn->func (pop_conn, event, pop_conn->data); + break; + } +} + +static ssize_t +pop_read (gpointer data, gchar *buffer, size_t len) +{ + pop_t *pop = data; + int r; + if (len > pop->push->len) + { + r = pop->push->len; + memcpy (buffer, pop->push->str, r); + g_string_truncate (pop->push, 0); + } + else + { + r = len; + memcpy (buffer, pop->push->str, r); + g_string_erase (pop->push, 0, r); + } + return r; +} + +static ssize_t +pop_write (gpointer data, gchar *buffer, size_t len) +{ + pop_t *pop = data; + hc_conn_write (pop->lowconn, buffer, len); + return len; +} + +static void +pop_close (gpointer data) { - pop_t *pop = hook->data; - g_string_append_len (pop->buffer, buffer, len); - hook->data = pop->orig_data; - while (pop_getline (pop) == 0) - pop->orig_read (hook, pop->line->str, pop->line->len); - hook->data = pop; + pop_t *pop = data; + hc_conn_close (pop->lowconn); + pop_destroy (pop); } -net_hook_t * -pop_hook_new (net_hook_t *layer) +int +hc_conn_set_driver_pop (HCConn *conn, HCConn *lowconn) { pop_t *pop; pop = g_slice_new (pop_t); - pop->orig_read = layer->read; - pop->orig_data = layer->data; pop->buffer = g_string_sized_new (4096); pop->line = g_string_sized_new (4096); - layer->read = pop_read; - layer->data = pop; - return layer; -} - -void -pop_destroy (net_hook_t *hook) -{ - pop_t *pop = hook->data; - g_string_free (pop->buffer, TRUE); - g_string_free (pop->line, TRUE); - hook->read = pop->orig_read; - hook->data = pop->orig_data; - g_slice_free (net_hook_t, (gpointer) pop); + pop->push = g_string_sized_new (4096); + pop->user = NULL; + pop->lowconn = lowconn; + conn->read = pop_read; + conn->write = pop_write; + conn->close = pop_close; + conn->layer = pop; + hc_conn_set_callback (lowconn, pop_watch, conn); + return 0; }