X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=pop.c;h=02caf5ab601f5a1c1e6d1466bdb57d2ad34a4522;hb=ad000200cbe6a9528da52812b53979038de24169;hp=8de50f4914b2a698daf882ad3abf51b3fe5a3f15;hpb=d6458b986f8ef99d0ced02798a82d0c14ca0cf4a;p=cascardo%2Frnetproxy.git diff --git a/pop.c b/pop.c index 8de50f4..02caf5a 100644 --- a/pop.c +++ b/pop.c @@ -18,47 +18,167 @@ ** */ -#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) +{ + char * end; + size_t len; + if (pop->buffer->len == 0) + return -1; + end = memchr (pop->buffer->str, '\n', pop->buffer->len); + if (end == NULL) + return -1; + len = end - pop->buffer->str + 1; + g_string_truncate (pop->line, 0); + g_string_append_len (pop->line, pop->buffer->str, len); + g_string_erase (pop->buffer, 0, len); + return 0; +} + static void -pop_read (net_hook_t *hook, gchar *buffer, size_t len) +pop_watch (HCConn *conn, HCEvent event, gpointer data) { - pop_t *pop = hook->data; - hook->data = pop->orig_data; - pop->orig_read (hook, buffer, len); - hook->data = pop; + 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; + } } -net_hook_t * -pop_hook_new (net_hook_t *layer) +static ssize_t +pop_read (gpointer data, gchar *buffer, size_t len) { - 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); - layer->read = pop_read; - layer->data = pop; - return layer; + 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; } -void -pop_destroy (net_hook_t *hook) +static ssize_t +pop_write (gpointer data, gchar *buffer, size_t len) { - pop_t *pop = hook->data; - g_string_free (pop->buffer, TRUE); - hook->read = pop->orig_read; - hook->data = pop->orig_data; - g_slice_free (net_hook_t, (gpointer) pop); + pop_t *pop = data; + hc_conn_write (pop->lowconn, buffer, len); + return len; +} + +static void +pop_close (gpointer data) +{ + pop_t *pop = data; + hc_conn_close (pop->lowconn); + pop_destroy (pop); +} + +int +hc_conn_set_driver_pop (HCConn *conn, HCConn *lowconn) +{ + pop_t *pop; + pop = g_slice_new (pop_t); + pop->buffer = g_string_sized_new (4096); + pop->line = g_string_sized_new (4096); + 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; }