summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-09-03 12:49:33 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-09-03 12:59:44 +0300
commit607f57384987efc9f08a1febff4c6ab00e61e2ab (patch)
tree54df99489423c38460ab61ce9c0277ff65d5e782
parent64c8eabf83ec6f1a7b1050a1929b4387f78b7ccc (diff)
downloadmailutils-607f57384987efc9f08a1febff4c6ab00e61e2ab.tar.gz
mailutils-607f57384987efc9f08a1febff4c6ab00e61e2ab.tar.bz2
Re-implement GSASL support.
* libmu_auth/lbuf.c: Removed. * libmu_auth/lbuf.h: Removed. * libmu_auth/Makefile.am : Remove lbuf stuff. * include/mailutils/sys/gsasl-stream.h: New file. * include/mailutils/sys/Makefile.am: Add gsasl-stream.h. * include/mailutils/gsasl.h (mu_gsasl_stream_create): Remove. (gsasl_encoder_stream, gsasl_decoder_stream): New prototypes. * libmu_auth/gsasl.c: Rewrite. * imap4d/authenticate.c (auth_data): Remove. Use struct imap4d_auth instead. (_auth_try): Use new authentication API. (imap4d_authenticate): Likewise. * imap4d/imap4d.h (util_register_event, util_event_remove) (util_run_events): Remove. (imap4d_auth_handler_fp): Change prototype. (imap4d_auth): New struct. (imap4d_auth_result): New enum. * imap4d/io.c (io_format_completion_response) (io_stream_completion_response): New functions. (io_completion_response): Rewrite using io_format_completion_response. * imap4d/util.c (sc2string): Remove leftover prototype. (util_register_event, util_event_remove) (util_run_events): Remove. * imap4d/auth_gsasl.c: Revamp using new streams and the new authentication interface. * imap4d/auth_gss.c: Likewise (though yet untested). * mailbox/xscript-stream.c (_xscript_ctl): Remove unused variables.
-rw-r--r--imap4d/auth_gsasl.c141
-rw-r--r--imap4d/auth_gss.c58
-rw-r--r--imap4d/authenticate.c65
-rw-r--r--imap4d/imap4d.h31
-rw-r--r--imap4d/io.c46
-rw-r--r--imap4d/util.c69
-rw-r--r--include/mailutils/gsasl.h6
-rw-r--r--include/mailutils/sys/Makefile.am1
-rw-r--r--include/mailutils/sys/gsasl-stream.h38
-rw-r--r--libmu_auth/Makefile.am2
-rw-r--r--libmu_auth/gsasl.c316
-rw-r--r--libmu_auth/lbuf.c167
-rw-r--r--libmu_auth/lbuf.h37
-rw-r--r--mailbox/xscript-stream.c1
14 files changed, 376 insertions, 602 deletions
diff --git a/imap4d/auth_gsasl.c b/imap4d/auth_gsasl.c
index 036063db4..b16cd380f 100644
--- a/imap4d/auth_gsasl.c
+++ b/imap4d/auth_gsasl.c
@@ -29,43 +29,6 @@ static Gsasl_session *sess_ctx;
static void auth_gsasl_capa_init (int disable);
-static int
-create_gsasl_stream (mu_stream_t *newstr, mu_stream_t transport, int flags)
-{
- int rc;
-
- rc = mu_gsasl_stream_create (newstr, transport, sess_ctx, flags);
- if (rc)
- {
- mu_diag_output (MU_DIAG_ERROR, _("cannot create SASL stream: %s"),
- mu_strerror (rc));
- return RESP_NO;
- }
-
- if ((rc = mu_stream_open (*newstr)) != 0)
- {
- mu_diag_output (MU_DIAG_ERROR,
- _("cannot open SASL input stream: %s"),
- mu_stream_strerror (*newstr, rc));
- return RESP_NO;
- }
-
- return RESP_OK;
-}
-
-int
-gsasl_replace_streams (void *self, void *data)
-{
- mu_stream_t *s = data;
-
- util_set_input (s[0]);
- util_set_output (s[1]);
- free (s);
- util_event_remove (self);
- free (self);
- return 0;
-}
-
static void
finish_session (void)
{
@@ -73,7 +36,21 @@ finish_session (void)
}
static int
-auth_gsasl (struct imap4d_command *command, char *auth_type, char **username)
+restore_and_return (struct imap4d_auth *ap, mu_stream_t *str, int resp)
+{
+ int rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, str);
+ if (rc)
+ {
+ mu_error (_("%s failed when it should not: %s"), "MU_IOCTL_SWAP_STREAM",
+ mu_stream_strerror (iostream, rc));
+ abort ();
+ }
+ ap->response = resp;
+ return imap4d_auth_resp;
+}
+
+static enum imap4d_auth_result
+auth_gsasl (struct imap4d_auth *ap)
{
char *input_str = NULL;
size_t input_size = 0;
@@ -81,15 +58,15 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username)
char *output;
int rc;
- rc = gsasl_server_start (ctx, auth_type, &sess_ctx);
+ rc = gsasl_server_start (ctx, ap->auth_type, &sess_ctx);
if (rc != GSASL_OK)
{
mu_diag_output (MU_DIAG_NOTICE, _("SASL gsasl_server_start: %s"),
gsasl_strerror (rc));
- return 0;
+ return imap4d_auth_fail;
}
- gsasl_callback_hook_set (ctx, username);
+ gsasl_callback_hook_set (ctx, &ap->username);
output = NULL;
while ((rc = gsasl_step64 (sess_ctx, input_str, &output))
@@ -105,7 +82,8 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username)
gsasl_strerror (rc));
free (input_str);
free (output);
- return RESP_NO;
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
/* Some SASL mechanisms output additional data when GSASL_OK is
@@ -119,44 +97,81 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username)
mu_diag_output (MU_DIAG_NOTICE, _("non-empty client response"));
free (input_str);
free (output);
- return RESP_NO;
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
}
free (input_str);
free (output);
- if (*username == NULL)
+ if (ap->username == NULL)
{
- mu_diag_output (MU_DIAG_NOTICE, _("GSASL %s: cannot get username"), auth_type);
- return RESP_NO;
+ mu_diag_output (MU_DIAG_NOTICE, _("GSASL %s: cannot get username"),
+ ap->auth_type);
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
+ auth_gsasl_capa_init (1);
if (sess_ctx)
{
- mu_stream_t tmp, new_in, new_out;
- mu_stream_t *s;
-
- util_get_input (&tmp);
- if (create_gsasl_stream (&new_in, tmp, MU_STREAM_READ))
- return RESP_NO;
- util_get_output (&tmp);
- if (create_gsasl_stream (&new_out, tmp, MU_STREAM_WRITE))
+ mu_stream_t stream[2], newstream[2];
+
+ stream[0] = stream[1] = NULL;
+ rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream);
+ if (rc)
+ {
+ mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM",
+ mu_stream_strerror (iostream, rc));
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
+ }
+ rc = gsasl_encoder_stream (&newstream[0], stream[0], sess_ctx,
+ MU_STREAM_READ);
+ if (rc)
+ {
+ mu_error (_("%s failed: %s"), "gsasl_encoder_stream",
+ mu_strerror (rc));
+ return restore_and_return (ap, stream, RESP_NO);
+ }
+
+ rc = gsasl_decoder_stream (&newstream[1], stream[1], sess_ctx,
+ MU_STREAM_WRITE);
+ if (rc)
+ {
+ mu_error (_("%s failed: %s"), "gsasl_decoder_stream",
+ mu_strerror (rc));
+ mu_stream_destroy (&newstream[0]);
+ return restore_and_return (ap, stream, RESP_NO);
+ }
+
+ if (ap->username)
{
- mu_stream_destroy (&new_in);
- return RESP_NO;
+ if (imap4d_session_setup (ap->username))
+ return restore_and_return (ap, stream, RESP_NO);
}
- s = calloc (2, sizeof (mu_stream_t));
- s[0] = new_in;
- s[1] = new_out;
- util_register_event (STATE_NONAUTH, STATE_AUTH,
- gsasl_replace_streams, s);
+ /* FIXME: This is not reflected in the transcript. */
+ io_stream_completion_response (stream[1], ap->command, RESP_OK,
+ "%s authentication successful",
+ ap->auth_type);
+ mu_stream_flush (stream[1]);
+
+ rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, newstream);
+ if (rc)
+ {
+ mu_error (_("%s failed when it should not: %s"),
+ "MU_IOCTL_SWAP_STREAM",
+ mu_stream_strerror (iostream, rc));
+ abort ();
+ }
util_atexit (finish_session);
+ return imap4d_auth_ok;
}
- auth_gsasl_capa_init (1);
- return RESP_OK;
+ ap->response = RESP_OK;
+ return imap4d_auth_resp;
}
static void
diff --git a/imap4d/auth_gss.c b/imap4d/auth_gss.c
index 300936245..28ce74a4f 100644
--- a/imap4d/auth_gss.c
+++ b/imap4d/auth_gss.c
@@ -108,9 +108,8 @@ imap4d_gss_userok (gss_buffer_t client_name, char *name)
}
#endif
-static int
-auth_gssapi (struct imap4d_command *command,
- char *auth_type_unused, char **username)
+static enum imap4d_auth_result
+auth_gssapi (struct imap4d_auth *ap)
{
gss_buffer_desc tokbuf, outbuf;
OM_uint32 maj_stat, min_stat, min_stat2;
@@ -147,7 +146,8 @@ auth_gssapi (struct imap4d_command *command,
if (maj_stat != GSS_S_COMPLETE)
{
display_status ("import name", maj_stat, min_stat);
- return RESP_NO;
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
maj_stat = gss_acquire_cred (&min_stat, server_name, 0,
@@ -158,7 +158,8 @@ auth_gssapi (struct imap4d_command *command,
if (maj_stat != GSS_S_COMPLETE)
{
display_status ("acquire credentials", maj_stat, min_stat);
- return RESP_NO;
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
/* Start the dialogue */
@@ -206,7 +207,8 @@ auth_gssapi (struct imap4d_command *command,
maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
gss_release_buffer (&min_stat, &outbuf);
free (token_str);
- return RESP_NO;
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
if (outbuf.length)
@@ -228,7 +230,8 @@ auth_gssapi (struct imap4d_command *command,
{
display_status ("wrap", maj_stat, min_stat);
free (token_str);
- return RESP_NO;
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size);
@@ -246,7 +249,8 @@ auth_gssapi (struct imap4d_command *command,
if (maj_stat != GSS_S_COMPLETE)
{
display_status ("unwrap", maj_stat, min_stat);
- return RESP_NO;
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
sec_level = ntohl (*(OM_uint32 *) outbuf.value);
@@ -261,23 +265,25 @@ auth_gssapi (struct imap4d_command *command,
gss_release_buffer (&min_stat, &outbuf);
maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
gss_release_buffer (&min_stat, &outbuf);
- return RESP_NO;
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
protection_mech = mech;
client_buffer_size = sec_level & 0x00ffffffff;
- *username = malloc (outbuf.length - 4 + 1);
- if (!*username)
+ ap->username = malloc (outbuf.length - 4 + 1);
+ if (!ap->username)
{
mu_diag_output (MU_DIAG_NOTICE, _("not enough memory"));
gss_release_buffer (&min_stat, &outbuf);
maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
gss_release_buffer (&min_stat, &outbuf);
- return RESP_NO;
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
- memcpy (*username, (char *) outbuf.value + 4, outbuf.length - 4);
- (*username)[outbuf.length - 4] = '\0';
+ memcpy (ap->username, (char *) outbuf.value + 4, outbuf.length - 4);
+ ap->username[outbuf.length - 4] = '\0';
gss_release_buffer (&min_stat, &outbuf);
maj_stat = gss_display_name (&min_stat, client, &client_name, &mech_type);
@@ -286,36 +292,40 @@ auth_gssapi (struct imap4d_command *command,
display_status ("get client name", maj_stat, min_stat);
maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
gss_release_buffer (&min_stat, &outbuf);
- free (*username);
- return RESP_NO;
+ free (ap->username);
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
#ifdef WITH_GSS
- baduser = !gss_userok (client, *username);
+ baduser = !gss_userok (client, ap->username);
#else
- baduser = imap4d_gss_userok (&client_name, *username);
+ baduser = imap4d_gss_userok (&client_name, ap->username);
#endif
if (baduser)
{
- mu_diag_output (MU_DIAG_NOTICE, _("GSSAPI user %s is NOT authorized as %s"),
- (char *) client_name.value, *username);
+ mu_diag_output (MU_DIAG_NOTICE,
+ _("GSSAPI user %s is NOT authorized as %s"),
+ (char *) client_name.value, ap->username);
maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
gss_release_buffer (&min_stat, &outbuf);
gss_release_buffer (&min_stat, &client_name);
- free (*username);
- return RESP_NO;
+ free (ap->username);
+ ap->response = RESP_NO;
+ return imap4d_auth_resp;
}
else
{
mu_diag_output (MU_DIAG_NOTICE, _("GSSAPI user %s is authorized as %s"),
- (char *) client_name.value, *username);
+ (char *) client_name.value, ap->username);
}
gss_release_buffer (&min_stat, &client_name);
maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
gss_release_buffer (&min_stat, &outbuf);
- return RESP_OK;
+ ap->response = RESP_OK;
+ return imap4d_auth_resp;
}
void
diff --git a/imap4d/authenticate.c b/imap4d/authenticate.c
index 08ffa146c..166294cdc 100644
--- a/imap4d/authenticate.c
+++ b/imap4d/authenticate.c
@@ -19,7 +19,8 @@
#include "imap4d.h"
-struct imap_auth {
+struct imap_auth
+{
char *name;
imap4d_auth_handler_fp handler;
};
@@ -66,24 +67,17 @@ _auth_capa (void *item, void *usused)
return 0;
}
-struct auth_data {
- struct imap4d_command *command;
- char *auth_type;
- char *arg;
- char *username;
- int result;
-};
-
static int
_auth_try (void *item, void *data)
{
struct imap_auth *p = item;
- struct auth_data *ap = data;
+ struct imap4d_auth *ap = data;
if (strcmp (p->name, ap->auth_type) == 0)
{
- ap->result = p->handler (ap->command, ap->auth_type, &ap->username);
- return 1;
+ int res = p->handler (ap);
+ if (res)
+ return res;
}
return 0;
}
@@ -104,8 +98,9 @@ int
imap4d_authenticate (struct imap4d_command *command, imap4d_tokbuf_t tok)
{
char *auth_type;
- struct auth_data adata;
-
+ struct imap4d_auth adata;
+ enum imap4d_auth_result res;
+
if (imap4d_tokbuf_argc (tok) != 3)
return io_completion_response (command, RESP_BAD, "Invalid arguments");
@@ -117,25 +112,35 @@ imap4d_authenticate (struct imap4d_command *command, imap4d_tokbuf_t tok)
adata.command = command;
adata.auth_type = auth_type;
- adata.arg = NULL;
adata.username = NULL;
- if (mu_list_do (imap_auth_list, _auth_try, &adata) == 0)
- return io_completion_response (command, RESP_NO,
- "Authentication mechanism not supported");
-
- if (adata.result == RESP_OK && adata.username)
+ res = mu_list_do (imap_auth_list, _auth_try, &adata);
+
+ switch (res)
{
- if (imap4d_session_setup (adata.username))
- return io_completion_response (command, RESP_NO,
- "User name or passwd rejected");
- else
- return io_completion_response (command, RESP_OK,
- "%s authentication successful",
- auth_type);
+ case imap4d_auth_nosup:
+ return io_completion_response (command, RESP_NO,
+ "Authentication mechanism not supported");
+ case imap4d_auth_ok:
+ return 0;
+
+ case imap4d_auth_resp:
+ if (adata.response == RESP_OK && adata.username)
+ {
+ if (imap4d_session_setup (adata.username))
+ return io_completion_response (command, RESP_NO,
+ "User name or passwd rejected");
+ else
+ return io_completion_response (command, RESP_OK,
+ "%s authentication successful",
+ auth_type);
+ }
+ /* fall through */
+ case imap4d_auth_fail:
+ adata.response = RESP_NO;
+ break;
}
-
- return io_completion_response (command, adata.result,
- "%s authentication failed", auth_type);
+ return io_completion_response (command, adata.response,
+ "%s authentication failed", auth_type);
}
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h
index b8348a599..ba6ef6516 100644
--- a/imap4d/imap4d.h
+++ b/imap4d/imap4d.h
@@ -218,6 +218,11 @@ extern int io_send_literal (const char *);
extern int io_copy_out (mu_stream_t str, size_t size);
extern int io_completion_response (struct imap4d_command *, int,
const char *, ...) MU_PRINTFLIKE(3,4);
+extern int io_stream_completion_response (mu_stream_t str,
+ struct imap4d_command *command,
+ int rc,
+ const char *format, ...)
+ MU_PRINTFLIKE(4,5);
int io_getline (char **pbuf, size_t *psize, size_t *pnbytes);
void io_setio (FILE*, FILE*);
void io_flush (void);
@@ -368,10 +373,6 @@ int util_type_to_attribute (int type, char **attr_str);
int util_attribute_matches_flag (mu_attribute_t attr, const char *item);
int util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp);
-void util_register_event (int old_state, int new_state,
- mu_list_action_t *action, void *data);
-void util_event_remove (void *id);
-void util_run_events (int old_state, int new_state);
int util_is_master (void);
void util_bye (void);
@@ -385,8 +386,26 @@ int util_trim_nl (char *s, size_t len);
int imap4d_init_tls_server (void);
#endif /* WITH_TLS */
-typedef int (*imap4d_auth_handler_fp) (struct imap4d_command *,
- char *, char **);
+struct imap4d_auth
+{
+ /* input */
+ struct imap4d_command *command;
+ char *auth_type;
+ /* output */
+ char *username;
+ int response;
+};
+
+enum imap4d_auth_result
+ {
+ imap4d_auth_nosup,
+ imap4d_auth_ok,
+ imap4d_auth_resp,
+ imap4d_auth_fail
+ };
+
+typedef enum imap4d_auth_result
+ (*imap4d_auth_handler_fp) (struct imap4d_auth *);
extern void auth_add (char *name, imap4d_auth_handler_fp handler);
extern void auth_remove (char *name);
diff --git a/imap4d/io.c b/imap4d/io.c
index b3cee483a..05645ae62 100644
--- a/imap4d/io.c
+++ b/imap4d/io.c
@@ -219,20 +219,18 @@ io_untagged_response (int rc, const char *format, ...)
/* Send the completion response and reset the state. */
int
-io_completion_response (struct imap4d_command *command, int rc,
- const char *format, ...)
+io_format_completion_response (mu_stream_t str,
+ struct imap4d_command *command, int rc,
+ const char *format, va_list ap)
{
int new_state;
int status = 0;
- va_list ap;
const char *sc = sc2string (rc);
- mu_stream_printf (iostream, "%s %s%s ",
+ mu_stream_printf (str, "%s %s%s ",
command->tag, sc, command->name);
- va_start (ap, format);
- mu_stream_vprintf (iostream, format, ap);
- va_end (ap);
- mu_stream_write (iostream, "\n", 1, NULL);
+ mu_stream_vprintf (str, format, ap);
+ mu_stream_write (str, "\n", 1, NULL);
/* Reset the state. */
if (rc == RESP_OK)
@@ -243,11 +241,35 @@ io_completion_response (struct imap4d_command *command, int rc,
new_state = STATE_NONE;
if (new_state != STATE_NONE)
- {
- util_run_events (state, new_state);
- state = new_state;
- }
+ state = new_state;
+
+ return status;
+}
+
+int
+io_completion_response (struct imap4d_command *command, int rc,
+ const char *format, ...)
+{
+ va_list ap;
+ int status;
+
+ va_start (ap, format);
+ status = io_format_completion_response (iostream, command, rc, format, ap);
+ va_end (ap);
+ return status;
+}
+
+int
+io_stream_completion_response (mu_stream_t str,
+ struct imap4d_command *command, int rc,
+ const char *format, ...)
+{
+ va_list ap;
+ int status;
+ va_start (ap, format);
+ status = io_format_completion_response (str, command, rc, format, ap);
+ va_end (ap);
return status;
}
diff --git a/imap4d/util.c b/imap4d/util.c
index 80cfc6e7a..a4c504331 100644
--- a/imap4d/util.c
+++ b/imap4d/util.c
@@ -20,7 +20,6 @@
#include "imap4d.h"
static int add2set (size_t **, int *, unsigned long);
-static const char *sc2string (int);
/* NOTE: Allocates Memory. */
/* Expand: ~ --> /home/user and to ~guest --> /home/guest. */
@@ -651,74 +650,6 @@ util_bye ()
mu_list_do (atexit_list, atexit_run, 0);
}
-struct state_event
-{
- int old_state;
- int new_state;
- mu_list_action_t *action;
- void *data;
-};
-
-static mu_list_t event_list;
-
-void
-util_register_event (int old_state, int new_state,
- mu_list_action_t *action, void *data)
-{
- struct state_event *evp = malloc (sizeof (*evp));
- if (!evp)
- imap4d_bye (ERR_NO_MEM);
- evp->old_state = old_state;
- evp->new_state = new_state;
- evp->action = action;
- evp->data = data;
- if (!event_list)
- {
- mu_list_create (&event_list);
- mu_list_set_destroy_item (event_list, mu_list_free_item);
- }
- mu_list_append (event_list, (void*)evp);
-}
-
-void
-util_event_remove (void *id)
-{
- mu_list_remove (event_list, id);
-}
-
-static int
-event_exec (void *item, void *data)
-{
- struct state_event *ev = data, *elem = item;
-
- if (ev->old_state == elem->old_state && ev->new_state == elem->new_state)
- return elem->action (item, elem->data);
- return 0;
-}
-
-void
-util_run_events (int old_state, int new_state)
-{
- if (event_list)
- {
- struct state_event ev;
- mu_iterator_t itr;
- ev.old_state = old_state;
- ev.new_state = new_state;
-
- mu_list_get_iterator (event_list, &itr);
- for (mu_iterator_first (itr);
- !mu_iterator_is_done (itr); mu_iterator_next (itr))
- {
- struct state_event *p;
- mu_iterator_current (itr, (void **)&p);
- if (event_exec (p, &ev))
- break;
- }
- mu_iterator_destroy (&itr);
- }
-}
-
void
util_chdir (const char *dir)
{
diff --git a/include/mailutils/gsasl.h b/include/mailutils/gsasl.h
index 583b356db..be5f2bb26 100644
--- a/include/mailutils/gsasl.h
+++ b/include/mailutils/gsasl.h
@@ -36,8 +36,10 @@ extern struct mu_gsasl_module_data mu_gsasl_module_data;
#ifdef WITH_GSASL
#include <gsasl.h>
-int mu_gsasl_stream_create (mu_stream_t *stream, mu_stream_t transport,
- Gsasl_session *ctx, int flags);
+int gsasl_encoder_stream (mu_stream_t *pstr, mu_stream_t transport,
+ Gsasl_session *ctx, int flags);
+int gsasl_decoder_stream (mu_stream_t *pstr, mu_stream_t transport,
+ Gsasl_session *ctx, int flags);
#endif
diff --git a/include/mailutils/sys/Makefile.am b/include/mailutils/sys/Makefile.am
index ce37112b0..bc813e9f1 100644
--- a/include/mailutils/sys/Makefile.am
+++ b/include/mailutils/sys/Makefile.am
@@ -22,6 +22,7 @@ sysinclude_HEADERS = \
dbgstream.h\
file_stream.h\
filter.h\
+ gsasl-stream.h\
header_stream.h\
header.h\
iostream.h\
diff --git a/include/mailutils/sys/gsasl-stream.h b/include/mailutils/sys/gsasl-stream.h
new file mode 100644
index 000000000..c93176790
--- /dev/null
+++ b/include/mailutils/sys/gsasl-stream.h
@@ -0,0 +1,38 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _MAILUTILS_SYS_TLS_STREAM_H
+# define _MAILUTILS_SYS_GSASL_STREAM_H
+
+# include <mailutils/types.h>
+# include <mailutils/stream.h>
+# include <mailutils/sys/stream.h>
+
+struct _mu_gsasl_filter
+{
+ Gsasl_session *sess_ctx; /* Context */
+ int gsasl_err; /* Last Gsasl error code */
+ char *bufptr;
+ size_t bufsize;
+};
+
+struct _mu_gsasl_stream
+{
+ struct _mu_stream stream;
+ mu_stream_t transport;
+};
+
+#endif
diff --git a/libmu_auth/Makefile.am b/libmu_auth/Makefile.am
index 0f97e5521..2533ffbb1 100644
--- a/libmu_auth/Makefile.am
+++ b/libmu_auth/Makefile.am
@@ -26,8 +26,6 @@ lib_LTLIBRARIES = libmu_auth.la
libmu_auth_la_SOURCES = \
gsasl.c\
- lbuf.c\
- lbuf.h\
ldap.c\
pam.c\
radius.c\
diff --git a/libmu_auth/gsasl.c b/libmu_auth/gsasl.c
index bdaa1174b..d03f3e211 100644
--- a/libmu_auth/gsasl.c
+++ b/libmu_auth/gsasl.c
@@ -33,9 +33,10 @@
#include <mailutils/nls.h>
#include <mailutils/stream.h>
#include <mailutils/gsasl.h>
+#include <mailutils/sys/gsasl-stream.h>
+#include <mailutils/filter.h>
#include <gsasl.h>
-#include <lbuf.h>
struct mu_gsasl_module_data mu_gsasl_module_data = {
SITE_CRAM_MD5_PWD
@@ -49,235 +50,172 @@ mu_gsasl_module_init (enum mu_gocs_op op, void *data)
return 0;
}
-struct _gsasl_stream {
- Gsasl_session *sess_ctx; /* Context */
- int last_err; /* Last Gsasl error code */
-
- mu_stream_t stream; /* I/O stream */
- struct _line_buffer *lb;
-};
-
-static void
-_gsasl_destroy (mu_stream_t stream)
-{
- int flags;
- struct _gsasl_stream *s = mu_stream_get_owner (stream);
- mu_stream_get_flags (stream, &flags);
- if (!(flags & MU_STREAM_NO_CLOSE))
- mu_stream_destroy (&s->stream, mu_stream_get_owner (s->stream));
- _auth_lb_destroy (&s->lb);
-}
-
-static int
-_gsasl_readline (mu_stream_t stream, char *optr, size_t osize,
- off_t offset, size_t *nbytes)
+
+static enum mu_filter_result
+_gsasl_encoder (void *xdata,
+ enum mu_filter_command cmd,
+ struct mu_filter_io *iobuf)
{
- struct _gsasl_stream *s = mu_stream_get_owner (stream);
- int rc;
- size_t len, sz;
- char *bufp = NULL;
+ struct _mu_gsasl_filter *flt = xdata;
- if (_auth_lb_level (s->lb))
+ switch (cmd)
{
- len = _auth_lb_readline (s->lb, optr, osize-1);
- optr[len] = 0;
- if (nbytes)
- *nbytes = len;
- return 0;
+ case mu_filter_init:
+ flt->bufptr = NULL;
+ flt->bufsize = 0;
+ flt->gsasl_err = 0;
+ return mu_filter_ok;
+
+ case mu_filter_done:
+ if (flt->bufptr)
+ free (flt->bufptr);
+ free (flt);
+ return mu_filter_ok;
+
+ default:
+ break;
}
- do
+ if (flt->bufptr == NULL)
{
- char c;
- size_t sz;
- int status;
-
- status = mu_stream_sequential_read (s->stream, &c, 1, &sz);
- if (status == EINTR)
- continue;
- else if (status)
+ int status = gsasl_encode (flt->sess_ctx, iobuf->input, iobuf->isize,
+ &flt->bufptr, &flt->bufsize);
+ /* FIXME: Can it require more input? */
+ if (status)
{
- free (bufp);
- return status;
+ flt->gsasl_err = status;
+ return mu_filter_falure;
}
- rc = _auth_lb_grow (s->lb, &c, sz);
- if (rc)
- return rc;
-
- rc = gsasl_decode (s->sess_ctx,
- _auth_lb_data (s->lb),
- _auth_lb_level (s->lb),
- &bufp, &len);
}
- while (rc == GSASL_NEEDS_MORE);
+
+ iobuf->osize = flt->bufsize;
- if (rc != GSASL_OK)
- {
- s->last_err = rc;
- free (bufp);
- return EIO;
- }
-
- sz = len > osize ? osize : len;
-
- if (len > osize)
- {
- memcpy (optr, bufp, osize);
- _auth_lb_drop (s->lb);
- _auth_lb_grow (s->lb, bufp + osize, len - osize);
- len = osize;
- }
- else
- {
- _auth_lb_drop (s->lb);
- memcpy (optr, bufp, len);
- }
+ if (flt->bufsize > iobuf->osize)
+ return mu_filter_moreoutput;
- if (len < osize)
- optr[len] = 0;
-
- if (nbytes)
- *nbytes = len;
-
- free (bufp);
+ memcpy (iobuf->output, flt->bufptr, flt->bufsize);
- return 0;
+ free (flt->bufptr);
+ flt->bufptr = NULL;
+ flt->bufsize = 0;
+
+ return mu_filter_ok;
}
-
-int
-write_chunk (void *data, char *start, char *end)
+
+
+static enum mu_filter_result
+_gsasl_decoder (void *xdata,
+ enum mu_filter_command cmd,
+ struct mu_filter_io *iobuf)
{
- struct _gsasl_stream *s = data;
- size_t chunk_size = end - start + 1;
- size_t len = 0;
- char *buf = NULL;
+ struct _mu_gsasl_filter *flt = xdata;
int status;
-
- gsasl_encode (s->sess_ctx, start, chunk_size, &buf, &len);
-
- status = mu_stream_sequential_write (s->stream, buf, len);
- free (buf);
+ switch (cmd)
+ {
+ case mu_filter_init:
+ flt->bufptr = NULL;
+ flt->bufsize = 0;
+ flt->gsasl_err = 0;
+ return mu_filter_ok;
+
+ case mu_filter_done:
+ if (flt->bufptr)
+ free (flt->bufptr);
+ free (flt);
+ return mu_filter_ok;
+
+ default:
+ break;
+ }
- return status;
-}
+ if (flt->bufptr == NULL)
+ {
+ status = gsasl_decode (flt->sess_ctx, iobuf->input, iobuf->isize,
+ &flt->bufptr, &flt->bufsize);
+ switch (status)
+ {
+ case GSASL_OK:
+ break;
+
+ case GSASL_NEEDS_MORE:
+ iobuf->isize++;
+ return mu_filter_moreinput;
+
+ default:
+ flt->gsasl_err = status;
+ return mu_filter_falure;
+ }
+ }
+ iobuf->osize = flt->bufsize;
-static int
-_gsasl_write (mu_stream_t stream, const char *iptr, size_t isize,
- off_t offset, size_t *nbytes)
-{
- int rc;
- struct _gsasl_stream *s = mu_stream_get_owner (stream);
+ if (flt->bufsize > iobuf->osize)
+ return mu_filter_moreoutput;
- rc = _auth_lb_grow (s->lb, iptr, isize);
- if (rc)
- return rc;
-
- return _auth_lb_writelines (s->lb, iptr, isize, offset,
- write_chunk, s, nbytes);
-}
-
-static int
-_gsasl_flush (mu_stream_t stream)
-{<