1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Authors: Jeffrey Stedfast <fejj@ximian.com>
5 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
29 #include "camel-debug.h"
30 #include "camel-mime-utils.h"
31 #include "camel-sasl-anonymous.h"
32 #include "camel-sasl-cram-md5.h"
33 #include "camel-sasl-digest-md5.h"
34 #include "camel-sasl-gssapi.h"
35 #include "camel-sasl-login.h"
36 #include "camel-sasl-ntlm.h"
37 #include "camel-sasl-plain.h"
38 #include "camel-sasl-popb4smtp.h"
39 #include "camel-sasl.h"
40 #include "camel-service.h"
42 #define CAMEL_SASL_GET_PRIVATE(obj) \
43 (G_TYPE_INSTANCE_GET_PRIVATE \
44 ((obj), CAMEL_TYPE_SASL, CamelSaslPrivate))
48 typedef struct _AsyncContext AsyncContext;
50 struct _CamelSaslPrivate {
51 CamelService *service;
52 gboolean authenticated;
57 struct _AsyncContext {
64 gchar *base64_response;
75 G_DEFINE_ABSTRACT_TYPE (CamelSasl, camel_sasl, CAMEL_TYPE_OBJECT)
78 async_context_free (AsyncContext *async_context)
80 if (async_context->token != NULL)
81 g_byte_array_free (async_context->token, TRUE);
83 if (async_context->response != NULL)
84 g_byte_array_free (async_context->response, TRUE);
86 g_free (async_context->base64_token);
87 g_free (async_context->base64_response);
89 g_slice_free (AsyncContext, async_context);
93 sasl_build_class_table_rec (GType type,
94 GHashTable *class_table)
99 children = g_type_children (type, &n_children);
101 for (ii = 0; ii < n_children; ii++) {
102 GType type = children[ii];
103 CamelSaslClass *sasl_class;
106 /* Recurse over the child's children. */
107 sasl_build_class_table_rec (type, class_table);
109 /* Skip abstract types. */
110 if (G_TYPE_IS_ABSTRACT (type))
113 sasl_class = g_type_class_ref (type);
115 if (sasl_class->auth_type == NULL) {
117 "%s has an empty CamelServiceAuthType",
118 G_OBJECT_CLASS_NAME (sasl_class));
119 g_type_class_unref (sasl_class);
123 key = (gpointer) sasl_class->auth_type->authproto;
124 g_hash_table_insert (class_table, key, sasl_class);
131 sasl_build_class_table (void)
133 GHashTable *class_table;
135 /* Register known types. */
136 CAMEL_TYPE_SASL_ANONYMOUS;
137 CAMEL_TYPE_SASL_CRAM_MD5;
138 CAMEL_TYPE_SASL_DIGEST_MD5;
140 CAMEL_TYPE_SASL_GSSAPI;
142 CAMEL_TYPE_SASL_LOGIN;
143 CAMEL_TYPE_SASL_NTLM;
144 CAMEL_TYPE_SASL_PLAIN;
145 CAMEL_TYPE_SASL_POPB4SMTP;
147 class_table = g_hash_table_new_full (
148 (GHashFunc) g_str_hash,
149 (GEqualFunc) g_str_equal,
150 (GDestroyNotify) NULL,
151 (GDestroyNotify) g_type_class_unref);
153 sasl_build_class_table_rec (CAMEL_TYPE_SASL, class_table);
159 sasl_set_mechanism (CamelSasl *sasl,
160 const gchar *mechanism)
162 g_return_if_fail (mechanism != NULL);
163 g_return_if_fail (sasl->priv->mechanism == NULL);
165 sasl->priv->mechanism = g_strdup (mechanism);
169 sasl_set_service (CamelSasl *sasl,
170 CamelService *service)
172 g_return_if_fail (CAMEL_IS_SERVICE (service));
173 g_return_if_fail (sasl->priv->service == NULL);
175 sasl->priv->service = g_object_ref (service);
179 sasl_set_service_name (CamelSasl *sasl,
180 const gchar *service_name)
182 g_return_if_fail (service_name != NULL);
183 g_return_if_fail (sasl->priv->service_name == NULL);
185 sasl->priv->service_name = g_strdup (service_name);
189 sasl_set_property (GObject *object,
194 switch (property_id) {
195 case PROP_AUTHENTICATED:
196 camel_sasl_set_authenticated (
198 g_value_get_boolean (value));
204 g_value_get_string (value));
210 g_value_get_object (value));
213 case PROP_SERVICE_NAME:
214 sasl_set_service_name (
216 g_value_get_string (value));
220 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
224 sasl_get_property (GObject *object,
229 switch (property_id) {
230 case PROP_AUTHENTICATED:
231 g_value_set_boolean (
232 value, camel_sasl_get_authenticated (
233 CAMEL_SASL (object)));
238 value, camel_sasl_get_mechanism (
239 CAMEL_SASL (object)));
244 value, camel_sasl_get_service (
245 CAMEL_SASL (object)));
248 case PROP_SERVICE_NAME:
250 value, camel_sasl_get_service_name (
251 CAMEL_SASL (object)));
255 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
259 sasl_dispose (GObject *object)
261 CamelSaslPrivate *priv;
263 priv = CAMEL_SASL_GET_PRIVATE (object);
265 if (priv->service != NULL) {
266 g_object_unref (priv->service);
267 priv->service = NULL;
270 /* Chain up to parent's dispose() method. */
271 G_OBJECT_CLASS (camel_sasl_parent_class)->dispose (object);
275 sasl_finalize (GObject *object)
277 CamelSaslPrivate *priv;
279 priv = CAMEL_SASL_GET_PRIVATE (object);
281 g_free (priv->mechanism);
282 g_free (priv->service_name);
284 /* Chain up to parent's finalize() method. */
285 G_OBJECT_CLASS (camel_sasl_parent_class)->finalize (object);
289 sasl_challenge_thread (GSimpleAsyncResult *simple,
291 GCancellable *cancellable)
293 AsyncContext *async_context;
294 GError *error = NULL;
296 async_context = g_simple_async_result_get_op_res_gpointer (simple);
298 async_context->response = camel_sasl_challenge_sync (
299 CAMEL_SASL (object), async_context->token,
300 cancellable, &error);
303 g_simple_async_result_take_error (simple, error);
307 sasl_challenge (CamelSasl *sasl,
310 GCancellable *cancellable,
311 GAsyncReadyCallback callback,
314 GSimpleAsyncResult *simple;
315 AsyncContext *async_context;
317 async_context = g_slice_new0 (AsyncContext);
318 async_context->token = g_byte_array_new ();
320 g_byte_array_append (async_context->token, token->data, token->len);
322 simple = g_simple_async_result_new (
323 G_OBJECT (sasl), callback, user_data, sasl_challenge);
325 g_simple_async_result_set_check_cancellable (simple, cancellable);
327 g_simple_async_result_set_op_res_gpointer (
328 simple, async_context, (GDestroyNotify) async_context_free);
330 g_simple_async_result_run_in_thread (
331 simple, sasl_challenge_thread, io_priority, cancellable);
333 g_object_unref (simple);
337 sasl_challenge_finish (CamelSasl *sasl,
338 GAsyncResult *result,
341 GSimpleAsyncResult *simple;
342 AsyncContext *async_context;
343 GByteArray *response;
345 g_return_val_if_fail (
346 g_simple_async_result_is_valid (
347 result, G_OBJECT (sasl), sasl_challenge), NULL);
349 simple = G_SIMPLE_ASYNC_RESULT (result);
350 async_context = g_simple_async_result_get_op_res_gpointer (simple);
352 if (g_simple_async_result_propagate_error (simple, error))
355 response = async_context->response;
356 async_context->response = NULL;
362 sasl_try_empty_password_thread (GSimpleAsyncResult *simple,
364 GCancellable *cancellable)
367 GError *error = NULL;
369 res = camel_sasl_try_empty_password_sync (
370 CAMEL_SASL (object), cancellable, &error);
371 g_simple_async_result_set_op_res_gboolean (simple, res);
374 g_simple_async_result_take_error (simple, error);
378 sasl_try_empty_password (CamelSasl *sasl,
380 GCancellable *cancellable,
381 GAsyncReadyCallback callback,
384 GSimpleAsyncResult *simple;
386 simple = g_simple_async_result_new (
387 G_OBJECT (sasl), callback, user_data, sasl_try_empty_password);
389 g_simple_async_result_set_check_cancellable (simple, cancellable);
391 g_simple_async_result_run_in_thread (
392 simple, sasl_try_empty_password_thread,
393 io_priority, cancellable);
395 g_object_unref (simple);
399 sasl_try_empty_password_finish (CamelSasl *sasl,
400 GAsyncResult *result,
403 GSimpleAsyncResult *simple;
405 g_return_val_if_fail (
406 g_simple_async_result_is_valid (
407 result, G_OBJECT (sasl), sasl_try_empty_password), FALSE);
409 simple = G_SIMPLE_ASYNC_RESULT (result);
411 if (g_simple_async_result_propagate_error (simple, error))
414 return g_simple_async_result_get_op_res_gboolean (simple);
418 camel_sasl_class_init (CamelSaslClass *class)
420 GObjectClass *object_class;
422 g_type_class_add_private (class, sizeof (CamelSaslPrivate));
424 object_class = G_OBJECT_CLASS (class);
425 object_class->set_property = sasl_set_property;
426 object_class->get_property = sasl_get_property;
427 object_class->dispose = sasl_dispose;
428 object_class->finalize = sasl_finalize;
430 class->challenge = sasl_challenge;
431 class->challenge_finish = sasl_challenge_finish;
432 class->try_empty_password = sasl_try_empty_password;
433 class->try_empty_password_finish = sasl_try_empty_password_finish;
435 g_object_class_install_property (
438 g_param_spec_boolean (
445 g_object_class_install_property (
448 g_param_spec_string (
454 G_PARAM_CONSTRUCT_ONLY));
456 g_object_class_install_property (
459 g_param_spec_object (
465 G_PARAM_CONSTRUCT_ONLY));
467 g_object_class_install_property (
470 g_param_spec_string (
476 G_PARAM_CONSTRUCT_ONLY));
480 camel_sasl_init (CamelSasl *sasl)
482 sasl->priv = CAMEL_SASL_GET_PRIVATE (sasl);
487 * @service_name: the SASL service name
488 * @mechanism: the SASL mechanism
489 * @service: the CamelService that will be using this SASL
491 * Returns: a new #CamelSasl object for the given @service_name,
492 * @mechanism, and @service, or %NULL if the mechanism is not
496 camel_sasl_new (const gchar *service_name,
497 const gchar *mechanism,
498 CamelService *service)
500 GHashTable *class_table;
501 CamelSaslClass *sasl_class;
502 CamelSasl *sasl = NULL;
504 g_return_val_if_fail (service_name != NULL, NULL);
505 g_return_val_if_fail (mechanism != NULL, NULL);
506 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
508 class_table = sasl_build_class_table ();
509 sasl_class = g_hash_table_lookup (class_table, mechanism);
511 if (sasl_class != NULL)
512 sasl = g_object_new (
513 G_OBJECT_CLASS_TYPE (sasl_class),
514 "mechanism", mechanism,
516 "service-name", service_name,
519 g_hash_table_destroy (class_table);
525 * camel_sasl_get_authenticated:
526 * @sasl: a #CamelSasl
528 * Returns: whether or not @sasl has successfully authenticated the
529 * user. This will be %TRUE after it returns the last needed response.
530 * The caller must still pass that information on to the server and
531 * verify that it has accepted it.
534 camel_sasl_get_authenticated (CamelSasl *sasl)
536 g_return_val_if_fail (CAMEL_IS_SASL (sasl), FALSE);
538 return sasl->priv->authenticated;
542 * camel_sasl_try_empty_password_sync:
543 * @sasl: a #CamelSasl object
544 * @cancellable: optional #GCancellable object, or %NULL
545 * @error: return location for a #GError, or %NULL
547 * Returns: whether or not @sasl can attempt to authenticate without a
548 * password being provided by the caller. This will be %TRUE for an
549 * authentication method which can attempt to use single-sign-on
550 * credentials, but which can fall back to using a provided password
551 * so it still has the @need_password flag set in its description.
556 camel_sasl_try_empty_password_sync (CamelSasl *sasl,
557 GCancellable *cancellable,
560 CamelSaslClass *class;
562 g_return_val_if_fail (CAMEL_IS_SASL (sasl), FALSE);
564 class = CAMEL_SASL_GET_CLASS (sasl);
566 if (class->try_empty_password_sync == NULL)
569 return class->try_empty_password_sync (sasl, cancellable, error);
573 * camel_sasl_try_empty_password:
574 * @sasl: a #CamelSasl
575 * @io_priority: the I/O priority of the request
576 * @cancellable: optional #GCancellable object, or %NULL
577 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
578 * @user_data: data to pass to the callback function
580 * Asynchronously determine whether @sasl can be used for password-less
581 * authentication, for example single-sign-on using system credentials.
583 * When the operation is finished, @callback will be called. You can then
584 * call camel_sasl_try_empty_password_finish() to get the result of the
590 camel_sasl_try_empty_password (CamelSasl *sasl,
592 GCancellable *cancellable,
593 GAsyncReadyCallback callback,
596 CamelSaslClass *class;
598 g_return_if_fail (CAMEL_IS_SASL (sasl));
600 class = CAMEL_SASL_GET_CLASS (sasl);
601 g_return_if_fail (class->try_empty_password != NULL);
603 class->try_empty_password (
604 sasl, io_priority, cancellable, callback, user_data);
608 * camel_sasl_try_empty_password_finish:
609 * @sasl: a #CamelSasl
610 * @result: a #GAsyncResult
611 * @error: return location for a #GError, or %NULL
613 * Finishes the operation started with camel_sasl_try_empty_password().
615 * Returns: the SASL response. If an error occurred, @error will also be set.
620 camel_sasl_try_empty_password_finish (CamelSasl *sasl,
621 GAsyncResult *result,
624 CamelSaslClass *class;
626 g_return_val_if_fail (CAMEL_IS_SASL (sasl), FALSE);
627 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
629 class = CAMEL_SASL_GET_CLASS (sasl);
630 g_return_val_if_fail (class->try_empty_password_finish != NULL, FALSE);
632 return class->try_empty_password_finish (sasl, result, error);
636 * camel_sasl_set_authenticated:
637 * @sasl: a #CamelSasl
638 * @authenticated: whether we have successfully authenticated
643 camel_sasl_set_authenticated (CamelSasl *sasl,
644 gboolean authenticated)
646 g_return_if_fail (CAMEL_IS_SASL (sasl));
648 if (sasl->priv->authenticated == authenticated)
651 sasl->priv->authenticated = authenticated;
653 g_object_notify (G_OBJECT (sasl), "authenticated");
657 * camel_sasl_get_mechanism:
658 * @sasl: a #CamelSasl
663 camel_sasl_get_mechanism (CamelSasl *sasl)
665 g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
667 return sasl->priv->mechanism;
671 * camel_sasl_get_service:
672 * @sasl: a #CamelSasl
677 camel_sasl_get_service (CamelSasl *sasl)
679 g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
681 return sasl->priv->service;
685 * camel_sasl_get_service_name:
686 * @sasl: a #CamelSasl
691 camel_sasl_get_service_name (CamelSasl *sasl)
693 g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
695 return sasl->priv->service_name;
699 * camel_sasl_challenge_sync:
700 * @sasl: a #CamelSasl
701 * @token: a token, or %NULL
702 * @cancellable: optional #GCancellable object, or %NULL
703 * @error: return location for a #GError, or %NULL
705 * If @token is %NULL, generate the initial SASL message to send to
706 * the server. (This will be %NULL if the client doesn't initiate the
707 * exchange.) Otherwise, @token is a challenge from the server, and
708 * the return value is the response.
710 * Free the returned #GByteArray with g_byte_array_free().
712 * Returns: the SASL response or %NULL. If an error occurred, @error will
716 camel_sasl_challenge_sync (CamelSasl *sasl,
718 GCancellable *cancellable,
721 CamelSaslClass *class;
722 GByteArray *response;
724 g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
726 class = CAMEL_SASL_GET_CLASS (sasl);
727 g_return_val_if_fail (class->challenge_sync != NULL, NULL);
729 response = class->challenge_sync (sasl, token, cancellable, error);
732 sasl, challenge_sync, response != NULL, error);
738 * camel_sasl_challenge:
739 * @sasl: a #CamelSasl
740 * @token: a token, or %NULL
741 * @io_priority: the I/O priority of the request
742 * @cancellable: optional #GCancellable object, or %NULL
743 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
744 * @user_data: data to pass to the callback function
746 * If @token is %NULL, asynchronously generate the initial SASL message
747 * to send to the server. (This will be %NULL if the client doesn't
748 * initiate the exchange.) Otherwise, @token is a challenge from the
749 * server, and the asynchronous result is the response.
751 * When the operation is finished, @callback will be called. You can then
752 * call camel_sasl_challenge_finish() to get the result of the operation.
757 camel_sasl_challenge (CamelSasl *sasl,
760 GCancellable *cancellable,
761 GAsyncReadyCallback callback,
764 CamelSaslClass *class;
766 g_return_if_fail (CAMEL_IS_SASL (sasl));
768 class = CAMEL_SASL_GET_CLASS (sasl);
769 g_return_if_fail (class->challenge != NULL);
772 sasl, token, io_priority, cancellable, callback, user_data);
776 * camel_sasl_challenge_finish:
777 * @sasl: a #CamelSasl
778 * @result: a #GAsyncResult
779 * @error: return location for a #GError, or %NULL
781 * Finishes the operation started with camel_sasl_challenge(). Free the
782 * returned #GByteArray with g_byte_array_free().
784 * Returns: the SASL response or %NULL. If an error occurred, @error will
790 camel_sasl_challenge_finish (CamelSasl *sasl,
791 GAsyncResult *result,
794 CamelSaslClass *class;
796 g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
797 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
799 class = CAMEL_SASL_GET_CLASS (sasl);
800 g_return_val_if_fail (class->challenge_finish != NULL, NULL);
802 return class->challenge_finish (sasl, result, error);
806 * camel_sasl_challenge_base64_sync:
807 * @sasl: a #CamelSasl
808 * @token: a base64-encoded token
809 * @cancellable: optional #GCancellable object, or %NULL
810 * @error: return location for a #GError, or %NULL
812 * As with camel_sasl_challenge_sync(), but the challenge @token and the
813 * response are both base64-encoded.
815 * Returns: the base64-encoded response
820 camel_sasl_challenge_base64_sync (CamelSasl *sasl,
822 GCancellable *cancellable,
825 GByteArray *token_binary;
826 GByteArray *response_binary;
829 g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
831 if (token != NULL && *token != '\0') {
835 data = g_base64_decode (token, &length);
836 token_binary = g_byte_array_new ();
837 g_byte_array_append (token_binary, data, length);
842 response_binary = camel_sasl_challenge_sync (
843 sasl, token_binary, cancellable, error);
845 g_byte_array_free (token_binary, TRUE);
846 if (response_binary == NULL)
849 if (response_binary->len > 0)
850 response = g_base64_encode (
851 response_binary->data, response_binary->len);
853 response = g_strdup ("");
855 g_byte_array_free (response_binary, TRUE);
860 /* Helper for camel_sasl_challenge_base64() */
862 sasl_challenge_base64_thread (GSimpleAsyncResult *simple,
864 GCancellable *cancellable)
866 AsyncContext *async_context;
867 GError *error = NULL;
869 async_context = g_simple_async_result_get_op_res_gpointer (simple);
871 async_context->base64_response = camel_sasl_challenge_base64_sync (
872 CAMEL_SASL (object), async_context->base64_token,
873 cancellable, &error);
876 g_simple_async_result_take_error (simple, error);
880 * camel_sasl_challenge_base64:
881 * @sasl: a #CamelSasl
882 * @token: a base64-encoded token
883 * @io_priority: the I/O priority of the request
884 * @cancellable: optional #GCancellable object, or %NULL
885 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
886 * @user_data: data to pass to the callback function
888 * As with camel_sasl_challenge(), but the challenge @token and the
889 * response are both base64-encoded.
891 * When the operation is finished, @callback will be called. You can
892 * then call camel_store_challenge_base64_finish() to get the result of
898 camel_sasl_challenge_base64 (CamelSasl *sasl,
901 GCancellable *cancellable,
902 GAsyncReadyCallback callback,
905 GSimpleAsyncResult *simple;
906 AsyncContext *async_context;
908 g_return_if_fail (CAMEL_IS_SASL (sasl));
910 async_context = g_slice_new0 (AsyncContext);
911 async_context->base64_token = g_strdup (token);
913 simple = g_simple_async_result_new (
914 G_OBJECT (sasl), callback, user_data,
915 camel_sasl_challenge_base64);
917 g_simple_async_result_set_check_cancellable (simple, cancellable);
919 g_simple_async_result_set_op_res_gpointer (
920 simple, async_context, (GDestroyNotify) async_context_free);
922 g_simple_async_result_run_in_thread (
923 simple, sasl_challenge_base64_thread,
924 io_priority, cancellable);
926 g_object_unref (simple);
930 * camel_sasl_challenge_base64_finish:
931 * @sasl: a #CamelSasl
932 * @result: a #GAsyncResult
933 * @error: return location for a #GError, or %NULL
935 * Finishes the operation started with camel_sasl_challenge_base64().
937 * Returns: the base64-encoded response
942 camel_sasl_challenge_base64_finish (CamelSasl *sasl,
943 GAsyncResult *result,
946 GSimpleAsyncResult *simple;
947 AsyncContext *async_context;
950 g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
951 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
953 g_return_val_if_fail (
954 g_simple_async_result_is_valid (
955 result, G_OBJECT (sasl), camel_sasl_challenge_base64), NULL);
957 simple = G_SIMPLE_ASYNC_RESULT (result);
958 async_context = g_simple_async_result_get_op_res_gpointer (simple);
960 if (g_simple_async_result_propagate_error (simple, error))
963 response = async_context->base64_response;
964 async_context->base64_response = NULL;
970 * camel_sasl_authtype_list:
971 * @include_plain: whether or not to include the PLAIN mechanism
973 * Returns: a #GList of SASL-supported authtypes. The caller must
974 * free the list, but not the contents.
977 camel_sasl_authtype_list (gboolean include_plain)
979 CamelSaslClass *sasl_class;
980 GHashTable *class_table;
983 /* XXX I guess these are supposed to be common SASL auth types,
984 * since this is called by the IMAP, POP and SMTP providers.
985 * The returned list can be extended with other auth types
986 * by way of camel_sasl_authtype(), so maybe we should just
987 * drop the ad-hoc "include_plain" parameter? */
989 class_table = sasl_build_class_table ();
991 sasl_class = g_hash_table_lookup (class_table, "CRAM-MD5");
992 g_return_val_if_fail (sasl_class != NULL, types);
993 types = g_list_prepend (types, sasl_class->auth_type);
995 sasl_class = g_hash_table_lookup (class_table, "DIGEST-MD5");
996 g_return_val_if_fail (sasl_class != NULL, types);
997 types = g_list_prepend (types, sasl_class->auth_type);
1000 sasl_class = g_hash_table_lookup (class_table, "GSSAPI");
1001 g_return_val_if_fail (sasl_class != NULL, types);
1002 types = g_list_prepend (types, sasl_class->auth_type);
1005 sasl_class = g_hash_table_lookup (class_table, "NTLM");
1006 g_return_val_if_fail (sasl_class != NULL, types);
1007 types = g_list_prepend (types, sasl_class->auth_type);
1009 if (include_plain) {
1010 sasl_class = g_hash_table_lookup (class_table, "PLAIN");
1011 g_return_val_if_fail (sasl_class != NULL, types);
1012 types = g_list_prepend (types, sasl_class->auth_type);
1015 g_hash_table_destroy (class_table);
1021 * camel_sasl_authtype:
1022 * @mechanism: the SASL mechanism to get an authtype for
1024 * Returns: a #CamelServiceAuthType for the given mechanism, if
1027 CamelServiceAuthType *
1028 camel_sasl_authtype (const gchar *mechanism)
1030 GHashTable *class_table;
1031 CamelSaslClass *sasl_class;
1032 CamelServiceAuthType *auth_type;
1034 g_return_val_if_fail (mechanism != NULL, NULL);
1036 class_table = sasl_build_class_table ();
1037 sasl_class = g_hash_table_lookup (class_table, mechanism);
1038 auth_type = (sasl_class != NULL) ? sasl_class->auth_type : NULL;
1039 g_hash_table_destroy (class_table);