aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-sasl.c
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2001-03-02 06:23:23 +0800
committerDan Winship <danw@src.gnome.org>2001-03-02 06:23:23 +0800
commit61a496ffcad857b0dac176861206c4a98edc1620 (patch)
tree7c82b6f1f675b9baee5b06bd1b7406663e771b74 /camel/camel-sasl.c
parent63a09dc65bc9f54ec389cabb99c848ce56ef2fbc (diff)
downloadgsoc2013-evolution-61a496ffcad857b0dac176861206c4a98edc1620.tar.gz
gsoc2013-evolution-61a496ffcad857b0dac176861206c4a98edc1620.tar.zst
gsoc2013-evolution-61a496ffcad857b0dac176861206c4a98edc1620.zip
Take a GByteArray as input as well. Comment that you can pass %NULL for
* camel-sasl.c (camel_sasl_challenge): Take a GByteArray as input as well. Comment that you can pass %NULL for @token to get the initial auth data for mechanisms that are client-initiated. (camel_sasl_challenge_base64): Convenience function for protocols that use base64-encoded SASL. (camel_sasl_authenticated): Implement this... (it was prototyped already) (camel_sasl_new): Function to take a service name, a mechanism name, and a CamelService, and return a CamelSasl for it. (camel_sasl_authtype, camel_sasl_authtype_list): Functions to return CamelServiceAuthType information about SASL mechanisms, to allow providers to deal with them generically. * camel-sasl-anonymous.c, camel-sasl-plain.c: Update/simplify for CamelSasl changes. Both of these are single-round (client-initiated) mechanisms, so they don't need to keep state. (camel_sasl_plain_new): Removed; use camel_sasl_new instead. (Can't get rid of camel_sasl_anonymous_new though...) * camel-sasl-cram-md5.c: Update/simplify for CamelSasl changes. (camel_sasl_cram_md5_new): Removed; use camel_sasl_new instead. (cram_md5_challenge): Use md5_get_digest where possible, and various other minor simplifications. CRAM-MD5 only has a single round, so there's no need to keep track of state. This code is now tested (against Cyrus IMAPd) and known to work. * camel-sasl-kerberos4.h: Update/simplify for CamelSasl changes. Make only a single #ifdef HAVE_KRB4. Remove stuff from priv that isn't needed between rounds. (camel_sasl_kerberos4_new): Removed; use camel_sasl_new instead (krb4_challenge): Fix up the logic I broke in my previous "at least make it compile" fixes, update to match other changes, and remove IMAP-isms that shouldn't be in the generic code. This still isn't tested, because we're stuck behind a NAT right now... svn path=/trunk/; revision=8462
Diffstat (limited to 'camel/camel-sasl.c')
-rw-r--r--camel/camel-sasl.c175
1 files changed, 164 insertions, 11 deletions
diff --git a/camel/camel-sasl.c b/camel/camel-sasl.c
index a5aebe737c..1e7fc9108c 100644
--- a/camel/camel-sasl.c
+++ b/camel/camel-sasl.c
@@ -22,13 +22,19 @@
#include <config.h>
#include "camel-sasl.h"
+#include "camel-mime-utils.h"
+#include "camel-service.h"
+
+#include "camel-sasl-cram-md5.h"
+#include "camel-sasl-kerberos4.h"
+#include "camel-sasl-plain.h"
static CamelObjectClass *parent_class = NULL;
/* Returns the class for a CamelSasl */
#define CS_CLASS(so) CAMEL_SASL_CLASS (CAMEL_OBJECT_GET_CLASS (so))
-static GByteArray *sasl_challenge (CamelSasl *sasl, const char *token, CamelException *ex);
+static GByteArray *sasl_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex);
static void
camel_sasl_class_init (CamelSaslClass *camel_sasl_class)
@@ -39,6 +45,13 @@ camel_sasl_class_init (CamelSaslClass *camel_sasl_class)
camel_sasl_class->challenge = sasl_challenge;
}
+static void
+camel_sasl_finalize (CamelSasl *sasl)
+{
+ g_free (sasl->service_name);
+ camel_object_unref (CAMEL_OBJECT (sasl->service));
+}
+
CamelType
camel_sasl_get_type (void)
{
@@ -52,7 +65,7 @@ camel_sasl_get_type (void)
(CamelObjectClassInitFunc) camel_sasl_class_init,
NULL,
NULL,
- NULL );
+ (CamelObjectFinalizeFunc) camel_sasl_finalize);
}
return type;
@@ -60,7 +73,7 @@ camel_sasl_get_type (void)
static GByteArray *
-sasl_challenge (CamelSasl *sasl, const char *token, CamelException *ex)
+sasl_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex)
{
g_warning ("sasl_challenge: Using default implementation!");
return NULL;
@@ -68,20 +81,160 @@ sasl_challenge (CamelSasl *sasl, const char *token, CamelException *ex)
/**
* camel_sasl_challenge:
- * @sasl: a sasl object
- * @token: a token
+ * @sasl: a SASL object
+ * @token: a token, or %NULL
* @ex: exception
*
- * Generate the next sasl challenge to send to the server.
+ * If @token is %NULL, generate the initial SASL message to send to
+ * the server. (This will be %NULL if the client doesn't initiate the
+ * exchange.) Otherwise, @token is a challenge from the server, and
+ * the return value is the response.
*
- * Return value: a string containing the base64 encoded sasl challenge
- * or NULL on either an error or if the negotiation is complete. If an
- * error has occured, @ex will also be set.
+ * Return value: The SASL response or %NULL. If an error occurred, @ex
+ * will also be set.
**/
GByteArray *
-camel_sasl_challenge (CamelSasl *sasl, const char *token, CamelException *ex)
+camel_sasl_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex)
{
g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
-
+
return CS_CLASS (sasl)->challenge (sasl, token, ex);
}
+
+/**
+ * camel_sasl_challenge_base64:
+ * @sasl: a SASL object
+ * @token: a base64-encoded token
+ * @ex: exception
+ *
+ * As with camel_sasl_challenge(), but the challenge @token and the
+ * response are both base64-encoded.
+ *
+ * Return value: As with camel_sasl_challenge(), but base64-encoded.
+ **/
+char *
+camel_sasl_challenge_base64 (CamelSasl *sasl, const char *token, CamelException *ex)
+{
+ GByteArray *token_binary, *ret_binary;
+ char *ret;
+ int len;
+
+ g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
+
+ if (token) {
+ token_binary = g_byte_array_new ();
+ len = strlen (token);
+ g_byte_array_append (token_binary, token, len);
+ token_binary->len = base64_decode_simple (token_binary->data, len);
+ } else
+ token_binary = NULL;
+
+ ret_binary = camel_sasl_challenge (sasl, token_binary, ex);
+ if (token_binary)
+ g_byte_array_free (token_binary, TRUE);
+ if (!ret_binary)
+ return NULL;
+
+ ret = base64_encode_simple (ret_binary->data, ret_binary->len);
+ g_byte_array_free (ret_binary, TRUE);
+
+ return ret;
+}
+
+/**
+ * camel_sasl_authenticated:
+ * @sasl: a SASL object
+ *
+ * Return value: whether or not @sasl has successfully authenticated
+ * the user. This will be %TRUE after it returns the last needed response.
+ * The caller must still pass that information on to the server and verify
+ * that it has accepted it.
+ **/
+gboolean
+camel_sasl_authenticated (CamelSasl *sasl)
+{
+ return sasl->authenticated;
+}
+
+
+/**
+ * camel_sasl_new:
+ * @service_name: the SASL service name
+ * @mechanism: the SASL mechanism
+ * @service: the CamelService that will be using this SASL
+ *
+ * Return value: a new CamelSasl for the given @service_name,
+ * @mechanism, and @service, or %NULL if the mechanism is not
+ * supported.
+ **/
+CamelSasl *
+camel_sasl_new (const char *service_name, const char *mechanism, CamelService *service)
+{
+ CamelSasl *sasl;
+
+ g_return_val_if_fail (service_name != NULL, NULL);
+ g_return_val_if_fail (mechanism != NULL, NULL);
+ g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
+
+ /* We don't do ANONYMOUS here, because it's a little bit weird. */
+
+ if (!strcmp (mechanism, "CRAM-MD5"))
+ sasl = (CamelSasl *)camel_object_new (CAMEL_SASL_CRAM_MD5_TYPE);
+#ifdef HAVE_KRB4
+ else if (!strcmp (mechanism, "KERBEROS_V4"))
+ sasl = (CamelSasl *)camel_object_new (CAMEL_SASL_KERBEROS4_TYPE);
+#endif
+ else if (!strcmp (mechanism, "PLAIN"))
+ sasl = (CamelSasl *)camel_object_new (CAMEL_SASL_PLAIN_TYPE);
+ else
+ return NULL;
+
+ sasl->service_name = g_strdup (service_name);
+ sasl->service = service;
+ camel_object_ref (CAMEL_OBJECT (service));
+
+ return sasl;
+}
+
+/**
+ * camel_sasl_authtype_list:
+ *
+ * Return value: a GList of SASL-supported authtypes. The caller must
+ * free the list, but not the contents.
+ **/
+GList *
+camel_sasl_authtype_list (void)
+{
+ GList *types = NULL;
+
+ /* We don't do PLAIN here, because it's considered to be
+ * normal password authentication, just behind SSL.
+ */
+
+ types = g_list_prepend (types, &camel_sasl_cram_md5_authtype);
+#ifdef HAVE_KRB4
+ types = g_list_prepend (types, &camel_sasl_kerberos4_authtype);
+#endif
+
+ return types;
+}
+
+/**
+ * camel_sasl_authtype:
+ * @mechanism: the SASL mechanism to get an authtype for
+ *
+ * Return value: a CamelServiceAuthType for the given mechanism, if
+ * it is supported.
+ **/
+CamelServiceAuthType *
+camel_sasl_authtype (const char *mechanism)
+{
+ if (!strcmp (mechanism, "CRAM-MD5"))
+ return &camel_sasl_cram_md5_authtype;
+#ifdef HAVE_KRB4
+ else if (!strcmp (mechanism, "KERBEROS_V4"))
+ return &camel_sasl_kerberos4_authtype;
+#endif
+ else
+ return NULL;
+}