summaryrefslogtreecommitdiff
path: root/imap4d
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2003-01-22 13:26:21 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2003-01-22 13:26:21 +0000
commit66ad72714b35295c9cbaaa199ff7bb37f015c011 (patch)
tree7afe3bf88af6ed5d4f62839200ad20a3bd46591a /imap4d
parentc98fcdb87b2037746d23c061090848078b08ca30 (diff)
downloadmailutils-66ad72714b35295c9cbaaa199ff7bb37f015c011.tar.gz
mailutils-66ad72714b35295c9cbaaa199ff7bb37f015c011.tar.bz2
Added to the repository
Diffstat (limited to 'imap4d')
-rw-r--r--imap4d/auth_gsasl.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/imap4d/auth_gsasl.c b/imap4d/auth_gsasl.c
new file mode 100644
index 000000000..7eb5bf09e
--- /dev/null
+++ b/imap4d/auth_gsasl.c
@@ -0,0 +1,245 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Mailutils 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "imap4d.h"
+#include <gsasl.h>
+#include <mailutils/gsasl.h>
+
+static Gsasl_ctx *ctx;
+static Gsasl_session_ctx *sess_ctx;
+
+static int
+create_gsasl_stream (stream_t *newstr, stream_t str, int flags)
+{
+ int rc;
+
+ rc = gsasl_stream_create (newstr, str, sess_ctx, flags);
+ if (rc)
+ {
+ syslog (LOG_ERR, _("cannot create SASL stream: %s"),
+ mu_errstring (rc));
+ return RESP_NO;
+ }
+
+ if ((rc = stream_open (*newstr)) != 0)
+ {
+ char *p;
+ if (stream_strerror (*newstr, &p))
+ p = mu_errstring (rc);
+ syslog (LOG_ERR, _("cannot open SASL input stream: %s"), p);
+ return RESP_NO;
+ }
+
+ return RESP_OK;
+}
+
+
+static int
+auth_gsasl (struct imap4d_command *command,
+ char *auth_type, char *arg, char **username)
+{
+ char *input = NULL;
+ char output[512];
+ size_t output_len;
+ char *s, *client_init;
+ int rc;
+
+ client_init = util_getword (arg, &s);
+ if (!client_init)
+ return RESP_BAD;
+ util_unquote (&client_init);
+
+ rc = gsasl_server_start (ctx, auth_type, &sess_ctx);
+ if (rc != GSASL_OK)
+ {
+ syslog (LOG_NOTICE, _("SASL gsasl_server_start: %s"),
+ gsasl_strerror(rc));
+ return 0;
+ }
+
+ gsasl_server_application_data_set (sess_ctx, username);
+
+ input = client_init;
+ output[0] = '\0';
+ output_len = sizeof (output);
+
+ while ((rc = gsasl_server_step_base64 (sess_ctx, input, output, output_len))
+ == GSASL_NEEDS_MORE)
+ {
+ util_send ("+ %s\r\n", output);
+ input = imap4d_readline_ex ();
+ }
+ while (rc == GSASL_NEEDS_MORE);
+
+ if (rc != GSASL_OK)
+ {
+ syslog (LOG_NOTICE, _("GSASL error: %s"), gsasl_strerror (rc));
+ return RESP_NO;
+ }
+
+ if (*username == NULL)
+ {
+ syslog (LOG_NOTICE, _("GSASL %s: cannot get username"), auth_type);
+ return RESP_NO;
+ }
+
+ if (sess_ctx)
+ {
+ stream_t in, out, new_in, new_out;
+
+ util_get_input (&in);
+ util_get_output (&out);
+ if (create_gsasl_stream (&new_in, in, MU_STREAM_READ))
+ return RESP_NO;
+ if (create_gsasl_stream (&new_out, out, MU_STREAM_WRITE))
+ {
+ stream_destroy (&new_in, stream_get_owner (new_in));
+ return RESP_NO;
+ }
+
+ util_set_input (new_in);
+ util_set_output (new_out);
+ }
+
+ auth_gsasl_capa_init (1);
+ return RESP_OK;
+}
+
+static void
+auth_gsasl_capa_init (int disable)
+{
+ int rc;
+ char *listmech, *name, *s;
+ size_t size;
+
+ rc = gsasl_server_listmech (ctx, NULL, &size);
+ if (rc != GSASL_OK)
+ return;
+
+ listmech = malloc (size);
+ if (!listmech)
+ imap4d_bye (ERR_NO_MEM);
+
+ rc = gsasl_server_listmech (ctx, listmech, &size);
+ if (rc != GSASL_OK)
+ return;
+
+ for (name = strtok_r (listmech, " ", &s); name;
+ name = strtok_r (NULL, " ", &s))
+ {
+ if (disable)
+ auth_remove (name);
+ else
+ auth_add (strdup (name), auth_gsasl);
+ }
+
+ free (listmech);
+}
+
+/* This is for DIGEST-MD5 */
+static int
+cb_realm (Gsasl_session_ctx *ctx, char *out, size_t *outlen, size_t nth)
+{
+ char *realm = util_localname ();
+
+ if (nth > 0)
+ return GSASL_NO_MORE_REALMS;
+
+ if (out)
+ {
+ if (*outlen < strlen (realm))
+ return GSASL_TOO_SMALL_BUFFER;
+ memcpy (out, realm, strlen (realm));
+ }
+
+ *outlen = strlen (realm);
+
+ return GSASL_OK;
+}
+
+static int
+cb_validate (Gsasl_session_ctx *ctx,
+ const char *authorization_id,
+ const char *authentication_id,
+ const char *password)
+{
+ char **username = gsasl_server_application_data_get (ctx);
+ *username = strdup (authentication_id ?
+ authentication_id : authorization_id);
+ return GSASL_OK;
+}
+
+#define GSSAPI_SERVICE "imap"
+
+static int
+cb_service (Gsasl_session_ctx *ctx, char *srv, size_t *srvlen,
+ char *host, size_t *hostlen)
+{
+ char *hostname = util_localname ();
+
+ if (srv)
+ {
+ if (*srvlen < strlen (GSSAPI_SERVICE))
+ return GSASL_TOO_SMALL_BUFFER;
+
+ memcpy (srv, GSSAPI_SERVICE, strlen (GSSAPI_SERVICE));
+ }
+
+ if (srvlen)
+ *srvlen = strlen (GSSAPI_SERVICE);
+
+ if (host)
+ {
+ if (*hostlen < strlen (hostname))
+ return GSASL_TOO_SMALL_BUFFER;
+
+ memcpy (host, hostname, strlen (hostname));
+ }
+
+ if (hostlen)
+ *hostlen = strlen (hostname);
+
+ return GSASL_OK;
+}
+
+/* This gets called when SASL mechanism EXTERNAL is invoked */
+static int
+cb_external (Gsasl_session_ctx *ctx)
+{
+ return GSASL_AUTHENTICATION_ERROR;
+}
+
+void
+auth_gsasl_init ()
+{
+ int rc;
+
+ rc = gsasl_init (&ctx);
+ if (rc != GSASL_OK)
+ {
+ syslog (LOG_NOTICE, _("cannot initialize libgsasl: %s"),
+ gsasl_strerror (rc));
+ }
+
+ gsasl_server_callback_realm_set (ctx, cb_realm);
+ gsasl_server_callback_external_set (ctx, cb_external);
+ gsasl_server_callback_validate_set (ctx, cb_validate);
+ gsasl_server_callback_service_set (ctx, cb_service);
+
+ auth_gsasl_capa_init (0);
+}
+

Return to:

Send suggestions and report system problems to the System administrator.