From: Matthew Barnes Date: Fri, 19 Nov 2010 23:22:54 +0000 (-0500) Subject: Add an ESource extension for the ldap backend. X-Git-Tag: upstream/3.7.4~862 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=462d61a6f63b3bb63baa55b5533ea78e2cd3e548;p=platform%2Fupstream%2Fevolution-data-server.git Add an ESource extension for the ldap backend. --- diff --git a/addressbook/backends/ldap/Makefile.am b/addressbook/backends/ldap/Makefile.am index 05ea08f..28aab52 100644 --- a/addressbook/backends/ldap/Makefile.am +++ b/addressbook/backends/ldap/Makefile.am @@ -15,7 +15,9 @@ libebookbackendldap_la_CPPFLAGS = \ libebookbackendldap_la_SOURCES = \ e-book-backend-ldap.c \ e-book-backend-ldap.h \ - e-book-backend-ldap-factory.c + e-book-backend-ldap-factory.c \ + e-source-ldap.c \ + e-source-ldap.h libebookbackendldap_la_LIBADD = \ $(top_builddir)/addressbook/libebook/libebook-1.2.la \ diff --git a/addressbook/backends/ldap/e-book-backend-ldap-factory.c b/addressbook/backends/ldap/e-book-backend-ldap-factory.c index 69d99b0..0620043 100644 --- a/addressbook/backends/ldap/e-book-backend-ldap-factory.c +++ b/addressbook/backends/ldap/e-book-backend-ldap-factory.c @@ -27,6 +27,7 @@ #include #include "e-book-backend-ldap.h" +#include "e-source-ldap.h" #define FACTORY_NAME "ldap" @@ -65,6 +66,7 @@ e_book_backend_ldap_factory_init (EBookBackendFactory *factory) G_MODULE_EXPORT void e_module_load (GTypeModule *type_module) { + e_source_ldap_type_register (type_module); e_book_backend_ldap_factory_register_type (type_module); } diff --git a/addressbook/backends/ldap/e-book-backend-ldap.c b/addressbook/backends/ldap/e-book-backend-ldap.c index bcacebd..46fdf18 100644 --- a/addressbook/backends/ldap/e-book-backend-ldap.c +++ b/addressbook/backends/ldap/e-book-backend-ldap.c @@ -125,6 +125,8 @@ #include #include +#include +#include #include #include @@ -133,6 +135,7 @@ #include #include #include "e-book-backend-ldap.h" +#include "e-source-ldap.h" /* this is broken currently, don't enable it */ /*#define ENABLE_SASL_BINDS*/ @@ -141,12 +144,6 @@ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_BOOK_BACKEND_LDAP, EBookBackendLDAPPrivate)) -typedef enum { - E_BOOK_BACKEND_LDAP_TLS_NO, - E_BOOK_BACKEND_LDAP_TLS_ALWAYS, - E_BOOK_BACKEND_LDAP_TLS_WHEN_POSSIBLE -} EBookBackendLDAPUseTLS; - /* interval for our poll_ldap timeout */ #define LDAP_POLL_INTERVAL 20 @@ -177,7 +174,17 @@ typedef struct LDAPOp LDAPOp; #define EDB_ERROR_NOT_CONNECTED() e_data_book_create_error (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Not connected")) #define EDB_ERROR_MSG_TYPE(_msg_type) e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_INVALID_ARG, "Incorrect msg type %d passed to %s", _msg_type, G_STRFUNC) -G_DEFINE_TYPE (EBookBackendLDAP, e_book_backend_ldap, E_TYPE_BOOK_BACKEND) +/* Forward Declarations */ +static void e_book_backend_ldap_source_authenticator_init + (ESourceAuthenticatorInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EBookBackendLDAP, + e_book_backend_ldap, + E_TYPE_BOOK_BACKEND, + G_IMPLEMENT_INTERFACE ( + E_TYPE_SOURCE_AUTHENTICATOR, + e_book_backend_ldap_source_authenticator_init)) struct _EBookBackendLDAPPrivate { gboolean connected; @@ -199,7 +206,7 @@ struct _EBookBackendLDAPPrivate { gboolean starttls; /* TRUE if the *library * supports starttls. will be false if openssl was not built into openldap. */ - EBookBackendLDAPUseTLS use_tls; + ESourceLDAPSecurity security; LDAP *ldap; @@ -441,20 +448,18 @@ static struct prop_info { static gboolean can_browse (EBookBackend *backend) { - ESource *source = NULL; - const gchar *can_browse; + ESource *source; + ESourceLDAP *extension; + const gchar *extension_name; - /* XXX Backend can really be NULL here, or - * are we just being needlessly paranoid? */ - if (backend == NULL) + if (E_IS_BOOK_BACKEND (backend)) return FALSE; source = e_backend_get_source (E_BACKEND (backend)); - g_return_val_if_fail (source != NULL, FALSE); + extension_name = E_SOURCE_EXTENSION_LDAP_BACKEND; + extension = e_source_get_extension (source, extension_name); - can_browse = e_source_get_property (source, "can-browse"); - - return (g_strcmp0 (can_browse, "1") == 0); + return e_source_ldap_get_can_browse (extension); } static gboolean @@ -857,7 +862,7 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl, } #ifdef SUNLDAP - if (bl->priv->use_tls != E_BOOK_BACKEND_LDAP_TLS_NO) { + if (bl->priv->security == E_SOURCE_LDAP_SECURITY_LDAPS) { const gchar *user_data_dir = e_get_user_data_dir (); ldap_flag = ldapssl_client_init (user_data_dir, NULL); blpriv->ldap = ldapssl_init (blpriv->ldap_host, blpriv->ldap_port, 1); @@ -883,22 +888,20 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl, } else bl->priv->ldap_v3 = TRUE; - if (bl->priv->use_tls != E_BOOK_BACKEND_LDAP_TLS_NO) { - - if (!bl->priv->ldap_v3 && bl->priv->use_tls == E_BOOK_BACKEND_LDAP_TLS_ALWAYS) { - g_message ("TLS not available (fatal version), v3 protocol could not be established (ldap_error 0x%02x)", ldap_error); - ldap_unbind (blpriv->ldap); - blpriv->ldap = NULL; - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - g_propagate_error (error, EDB_ERROR (TLS_NOT_AVAILABLE)); - return FALSE; - } + if (!bl->priv->ldap_v3 && bl->priv->security == E_SOURCE_LDAP_SECURITY_STARTTLS) { + g_message ("TLS not available (fatal version), v3 protocol could not be established (ldap_error 0x%02x)", ldap_error); + ldap_unbind (blpriv->ldap); + blpriv->ldap = NULL; + g_static_rec_mutex_unlock (&eds_ldap_handler_lock); + g_propagate_error (error, EDB_ERROR (TLS_NOT_AVAILABLE)); + return FALSE; + } - if (bl->priv->ldap_port == LDAPS_PORT && bl->priv->use_tls == E_BOOK_BACKEND_LDAP_TLS_ALWAYS) { + if (bl->priv->ldap_port == LDAPS_PORT && bl->priv->security == E_SOURCE_LDAP_SECURITY_LDAPS) { #ifdef SUNLDAP - if (ldap_error == LDAP_SUCCESS) { - ldap_set_option (blpriv->ldap, LDAP_OPT_RECONNECT, LDAP_OPT_ON ); - } + if (ldap_error == LDAP_SUCCESS) { + ldap_set_option (blpriv->ldap, LDAP_OPT_RECONNECT, LDAP_OPT_ON ); + } #else #if defined (LDAP_OPT_X_TLS_HARD) && defined (LDAP_OPT_X_TLS) gint tls_level = LDAP_OPT_X_TLS_HARD; @@ -908,46 +911,41 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl, tls_level = LDAP_OPT_X_TLS_ALLOW; ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &tls_level); #elif defined (G_OS_WIN32) - ldap_set_option (blpriv->ldap, LDAP_OPT_SSL, LDAP_OPT_ON); + ldap_set_option (blpriv->ldap, LDAP_OPT_SSL, LDAP_OPT_ON); #else - g_message ("TLS option not available"); + g_message ("TLS option not available"); #endif #endif - } else if (bl->priv->use_tls) { + } else if (bl->priv->security == E_SOURCE_LDAP_SECURITY_STARTTLS) { #ifdef SUNLDAP - if (ldap_error == LDAP_SUCCESS) { - ldap_set_option (blpriv->ldap, LDAP_OPT_RECONNECT, LDAP_OPT_ON ); - } + if (ldap_error == LDAP_SUCCESS) { + ldap_set_option (blpriv->ldap, LDAP_OPT_RECONNECT, LDAP_OPT_ON ); + } #else #ifdef _WIN32 - typedef ULONG (*PFN_ldap_start_tls_s)(PLDAP,PLDAPControl *,PLDAPControl *); - PFN_ldap_start_tls_s pldap_start_tls_s = - (PFN_ldap_start_tls_s) GetProcAddress (GetModuleHandle ("wldap32.dll"), "ldap_start_tls_s"); - if (!pldap_start_tls_s) - (PFN_ldap_start_tls_s) GetProcAddress (GetModuleHandle ("wldap32.dll"), "ldap_start_tls_sA"); - - if (!pldap_start_tls_s) - ldap_error = LDAP_NOT_SUPPORTED; - else - ldap_error = pldap_start_tls_s (blpriv->ldap, NULL, NULL); + typedef ULONG (*PFN_ldap_start_tls_s)(PLDAP,PLDAPControl *,PLDAPControl *); + PFN_ldap_start_tls_s pldap_start_tls_s = + (PFN_ldap_start_tls_s) GetProcAddress (GetModuleHandle ("wldap32.dll"), "ldap_start_tls_s"); + if (!pldap_start_tls_s) + (PFN_ldap_start_tls_s) GetProcAddress (GetModuleHandle ("wldap32.dll"), "ldap_start_tls_sA"); + + if (!pldap_start_tls_s) + ldap_error = LDAP_NOT_SUPPORTED; + else + ldap_error = pldap_start_tls_s (blpriv->ldap, NULL, NULL); #else /* !defined(_WIN32) */ - ldap_error = ldap_start_tls_s (blpriv->ldap, NULL, NULL); + ldap_error = ldap_start_tls_s (blpriv->ldap, NULL, NULL); #endif /* _WIN32 */ #endif - if (ldap_error != LDAP_SUCCESS) { - if (bl->priv->use_tls == E_BOOK_BACKEND_LDAP_TLS_ALWAYS) { - g_message ("TLS not available (fatal version), (ldap_error 0x%02x)", ldap_error); - ldap_unbind (blpriv->ldap); - blpriv->ldap = NULL; - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - g_propagate_error (error, EDB_ERROR (TLS_NOT_AVAILABLE)); - return FALSE; - } else { - g_message ("TLS not available (ldap_error 0x%02x)", ldap_error); - } - } else if (enable_debug) - g_message ("TLS active"); - } + if (ldap_error != LDAP_SUCCESS) { + g_message ("TLS not available (fatal version), (ldap_error 0x%02x)", ldap_error); + ldap_unbind (blpriv->ldap); + blpriv->ldap = NULL; + g_static_rec_mutex_unlock (&eds_ldap_handler_lock); + g_propagate_error (error, EDB_ERROR (TLS_NOT_AVAILABLE)); + return FALSE; + } else if (enable_debug) + g_message ("TLS active"); } /* bind anonymously initially, we'll actually @@ -5128,188 +5126,6 @@ generate_cache (EBookBackendLDAP *book_backend_ldap) } static void -e_book_backend_ldap_authenticate_user (EBookBackend *backend, - GCancellable *cancellable, - ECredentials *credentials) -{ - EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend); - gint ldap_error; - gchar *dn = NULL; - const gchar *auth_method = e_credentials_peek (credentials, E_CREDENTIALS_KEY_AUTH_METHOD); - const gchar *user = e_credentials_peek (credentials, E_CREDENTIALS_KEY_USERNAME); - - if (enable_debug) - printf ("e_book_backend_ldap_authenticate_user ... \n"); - - g_static_rec_mutex_lock (&eds_ldap_handler_lock); - if (!auth_method || !*auth_method) { - ESource *source; - - source = e_backend_get_source (E_BACKEND (backend)); - auth_method = e_source_get_property (source, "auth"); - } - - if (!e_backend_get_online (E_BACKEND (backend))) { - e_book_backend_notify_readonly (backend, TRUE); - e_book_backend_notify_online (backend, FALSE); - e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS)); - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - return; - } - - if (bl->priv->connected) { - /* other client connected meanwhile, report success and return */ - e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS)); - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - return; - } - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - - if (!g_ascii_strncasecmp (auth_method, LDAP_SIMPLE_PREFIX, strlen (LDAP_SIMPLE_PREFIX))) { - - if (bl->priv->ldap && !strcmp (auth_method, "ldap/simple-email")) { - LDAPMessage *res, *e; - gchar *query = g_strdup_printf ("(mail=%s)", user); - - g_static_rec_mutex_lock (&eds_ldap_handler_lock); - ldap_error = ldap_search_s (bl->priv->ldap, - bl->priv->ldap_rootdn, - bl->priv->ldap_scope, - query, - NULL, 0, &res); - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - g_free (query); - - if (ldap_error == LDAP_SUCCESS) { - gchar *entry_dn; - - g_static_rec_mutex_lock (&eds_ldap_handler_lock); - e = ldap_first_entry (bl->priv->ldap, res); - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - if (!e) { - g_warning ("Failed to get the DN for %s", user); - ldap_msgfree (res); - e_book_backend_notify_opened (backend, EDB_ERROR (AUTHENTICATION_FAILED)); - return; - } - - g_static_rec_mutex_lock (&eds_ldap_handler_lock); - entry_dn = ldap_get_dn (bl->priv->ldap, e); - bl->priv->connected = FALSE; /* to reconnect with credentials */ - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - dn = g_strdup (entry_dn); - - ldap_memfree (entry_dn); - ldap_msgfree (res); - } else { - e_book_backend_notify_opened (backend, EDB_ERROR (PERMISSION_DENIED)); - return; - } - } - else if (!g_strcmp0 (auth_method, "ldap/simple-binddn")) { - dn = g_strdup (user); - } - - g_free (bl->priv->auth_dn); - e_credentials_util_safe_free_string (bl->priv->auth_secret); - - bl->priv->auth_dn = dn; - bl->priv->auth_secret = e_credentials_get (credentials, E_CREDENTIALS_KEY_PASSWORD); - - /* now authenticate against the DN we were either supplied or queried for */ - if (enable_debug) - printf ("simple auth as %s\n", dn); - g_static_rec_mutex_lock (&eds_ldap_handler_lock); - if (!bl->priv->connected || !bl->priv->ldap) { - GError *error = NULL; - - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - - if (!e_book_backend_ldap_connect (bl, &error)) { - if (error) - e_book_backend_notify_opened (backend, error); - return; - } - } - - ldap_error = ldap_simple_bind_s (bl->priv->ldap, - bl->priv->auth_dn, - bl->priv->auth_secret); - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - /* Some ldap servers are returning (ex active directory ones) LDAP_SERVER_DOWN - * when we try to do an ldap operation after being idle - * for some time. This error is handled by poll_ldap in case of search operations - * We need to handle it explicitly for this bind call. We call reconnect so that - * we get a fresh ldap handle Fixes #67541 */ - - if (ldap_error == LDAP_SERVER_DOWN) { - if (e_book_backend_ldap_reconnect (bl, find_book_view (bl), ldap_error)) { - ldap_error = LDAP_SUCCESS; - } - - } - - e_book_backend_notify_opened (backend, ldap_error_to_response (ldap_error)); - } -#ifdef ENABLE_SASL_BINDS - else if (!g_ascii_strncasecmp (auth_method, SASL_PREFIX, strlen (SASL_PREFIX))) { - g_print ("sasl bind (mech = %s) as %s", auth_method + strlen (SASL_PREFIX), user); - g_static_rec_mutex_lock (&eds_ldap_handler_lock); - if (!bl->priv->connected || !bl->priv->ldap) { - GError *error = NULL; - - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - - if (!e_book_backend_ldap_connect (bl)) { - if (error) - e_book_backend_notify_opened (backend, error); - return; - } - } - ldap_error = ldap_sasl_bind_s (bl->priv->ldap, - NULL, - auth_method + strlen (SASL_PREFIX), - e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD), - NULL, - NULL, - NULL); - g_static_rec_mutex_unlock (&eds_ldap_handler_lock); - - if (ldap_error == LDAP_NOT_SUPPORTED) - e_book_backend_notify_opened (backend, EDB_ERROR (UNSUPPORTED_AUTHENTICATION_METHOD)); - else - e_book_backend_notify_opened (backend, ldap_error_to_response (ldap_error)); - } -#endif - else { - e_book_backend_notify_opened (backend, EDB_ERROR (UNSUPPORTED_AUTHENTICATION_METHOD)); - return; - } - - if (ldap_error == LDAP_SUCCESS) { - e_book_backend_notify_readonly (backend, FALSE); - - /* force a requery on the root dse since some ldap - * servers are set up such that they don't report - * anything (including the schema DN) until the user - * is authenticated */ - if (!bl->priv->evolutionPersonChecked) { - ldap_error = query_ldap_root_dse (bl); - - if (LDAP_SUCCESS == ldap_error) { - if (!bl->priv->evolutionPersonChecked) - check_schema_support (bl); - } - else - g_warning ("Failed to perform root dse query after authenticating, (ldap_error 0x%02x)", ldap_error); - } - - if (bl->priv->marked_for_offline && bl->priv->cache) - generate_cache (bl); - } -} - -static void ldap_cancel_op (gpointer key, gpointer value, gpointer data) @@ -5342,78 +5158,68 @@ e_book_backend_ldap_open (EBookBackend *backend, gboolean only_if_exists) { EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend); + ESourceAuthentication *auth_extension; + ESourceLDAP *ldap_extension; + ESourceOffline *offline_extension; + ESourceRegistry *registry; ESource *source; - LDAPURLDesc *lud; - gint ldap_error; - gint limit = 100; - gint timeout = 60; /* 1 minute */ - gchar *uri; + const gchar *extension_name; const gchar *cache_dir; - const gchar *str; - const gchar *offline; gchar *filename; - GError *err = NULL; gboolean auth_required; + GError *error = NULL; - g_assert (bl->priv->connected == FALSE); + g_return_if_fail (!bl->priv->connected); if (enable_debug) printf ("%s ... \n", G_STRFUNC); source = e_backend_get_source (E_BACKEND (backend)); - uri = e_source_get_uri (source); cache_dir = e_book_backend_get_cache_dir (backend); - offline = e_source_get_property (source, "offline_sync"); - if (offline && g_str_equal (offline, "1")) - bl->priv->marked_for_offline = TRUE; - str = e_source_get_property (source, "limit"); - if (str) - limit = atoi (str); + registry = e_book_backend_get_registry (backend); - bl->priv->use_tls = E_BOOK_BACKEND_LDAP_TLS_NO; + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + auth_extension = e_source_get_extension (source, extension_name); - str = e_source_get_property (source, "ssl"); - if (str) { - if (!strcmp (str, "always")) - bl->priv->use_tls = E_BOOK_BACKEND_LDAP_TLS_ALWAYS; - else if (!strcmp (str, "whenever_possible")) - bl->priv->use_tls = E_BOOK_BACKEND_LDAP_TLS_WHEN_POSSIBLE; - else if (strcmp (str, "never")) - g_warning ("Unhandled value for 'ssl', not using it."); - } + extension_name = E_SOURCE_EXTENSION_LDAP_BACKEND; + ldap_extension = e_source_get_extension (source, extension_name); - str = e_source_get_property (source, "timeout"); - if (str) - timeout = atoi (str); + extension_name = E_SOURCE_EXTENSION_OFFLINE; + offline_extension = e_source_get_extension (source, extension_name); - ldap_error = ldap_url_parse ((gchar *) uri, &lud); + bl->priv->marked_for_offline = + e_source_offline_get_stay_synchronized (offline_extension); - if (ldap_error == LDAP_SUCCESS) { - bl->priv->ldap_host = g_strdup (lud->lud_host); - bl->priv->ldap_port = lud->lud_port; - /* if a port wasn't specified, default to LDAP_PORT */ - if (bl->priv->ldap_port == 0) - bl->priv->ldap_port = LDAP_PORT; - bl->priv->ldap_rootdn = g_strdup (lud->lud_dn); - /* in case of migration, filter will be set to NULL and hence the search will fail */ - if (lud->lud_filter) - bl->priv->ldap_search_filter = g_strdup (lud->lud_filter); - bl->priv->ldap_limit = limit; - bl->priv->ldap_timeout = timeout; - bl->priv->ldap_scope = lud->lud_scope; - - ldap_free_urldesc (lud); - } else { - if (enable_debug) - printf ("%s ... failed to parse the ldap URI %s\n", G_STRFUNC, uri); - g_free (uri); - e_book_backend_respond_opened (backend, book, opid, EDB_ERROR_EX (OTHER_ERROR, "Failed to parse LDAP URI")); - return; - } + bl->priv->security = e_source_ldap_get_security (ldap_extension); + + bl->priv->ldap_host = + e_source_authentication_dup_host (auth_extension); - if (bl->priv->ldap_port == LDAPS_PORT) - bl->priv->use_tls = E_BOOK_BACKEND_LDAP_TLS_ALWAYS; + bl->priv->ldap_port = + e_source_authentication_get_port (auth_extension); + /* If a port wasn't specified, default to LDAP_PORT. */ + if (bl->priv->ldap_port == 0) + bl->priv->ldap_port = LDAP_PORT; + + bl->priv->ldap_rootdn = + e_source_ldap_dup_root_dn (ldap_extension); + + bl->priv->ldap_search_filter = + e_source_ldap_dup_filter (ldap_extension); + + bl->priv->ldap_limit = e_source_ldap_get_limit (ldap_extension); + + switch (e_source_ldap_get_scope (ldap_extension)) { + case E_SOURCE_LDAP_SCOPE_ONELEVEL: + bl->priv->ldap_scope = LDAP_SCOPE_ONELEVEL; + break; + case E_SOURCE_LDAP_SCOPE_SUBTREE: + bl->priv->ldap_scope = LDAP_SCOPE_SUBTREE; + break; + default: + g_warn_if_reached (); + } if (bl->priv->cache) { g_object_unref (bl->priv->cache); @@ -5424,66 +5230,48 @@ e_book_backend_ldap_open (EBookBackend *backend, bl->priv->cache = e_book_backend_cache_new (filename); g_free (filename); - g_free (uri); - if (!e_backend_get_online (E_BACKEND (backend))) { /* Offline */ e_book_backend_notify_readonly (backend, TRUE); e_book_backend_notify_online (backend, FALSE); - if (!bl->priv->marked_for_offline) { - e_book_backend_respond_opened (backend, book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE)); - return; - } + if (!bl->priv->marked_for_offline) + error = EDB_ERROR (OFFLINE_UNAVAILABLE); -#if 0 - if (!e_book_backend_cache_is_populated (bl->priv->cache)) { - e_book_backend_respond_opened (backend, book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE)); - return; - } -#endif - e_book_backend_respond_opened (backend, book, opid, NULL /* Success */); + e_book_backend_respond_opened (backend, book, opid, error); return; - } else { - e_book_backend_notify_readonly (backend, FALSE); - e_book_backend_notify_online (backend, TRUE); } - str = e_source_get_property (source, "auth"); - auth_required = str && *str && !g_str_equal (str, "none") && !g_str_equal (str, "0"); - if (auth_required && !g_str_equal (str, "ldap/simple-email")) { - /* Requires authentication, do not try to bind without it, - * but report success instead, as we are loaded. */ - if (enable_debug) - printf ("%s ... skipping anonymous bind, because auth required\n", G_STRFUNC); + e_book_backend_notify_readonly (backend, FALSE); + e_book_backend_notify_online (backend, TRUE); - if (!e_book_backend_is_opened (backend)) - e_book_backend_notify_auth_required (backend, TRUE, NULL); - else - e_book_backend_notify_opened (backend, NULL); - e_data_book_respond_open (book, opid, NULL /* Success */); - return; - } + auth_required = e_source_authentication_required (auth_extension); - /* Online */ - if (!e_book_backend_ldap_connect (bl, &err)) { - if (enable_debug) - printf ("%s ... failed to connect to server \n", G_STRFUNC); - e_book_backend_respond_opened (backend, book, opid, err); - return; - } + if (!auth_required) + e_book_backend_ldap_connect (bl, &error); - if (auth_required && !e_book_backend_is_opened (backend)) { - e_book_backend_notify_auth_required (E_BOOK_BACKEND (bl), TRUE, NULL); - e_data_book_respond_open (book, opid, NULL /* Success */); - return; + if (g_error_matches ( + error, E_DATA_BOOK_ERROR, + E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED)) { + + g_clear_error (&error); + auth_required = TRUE; } - if (bl->priv->marked_for_offline) + if (auth_required && error == NULL) + e_source_registry_authenticate_sync ( + registry, source, + E_SOURCE_AUTHENTICATOR (backend), + cancellable, &error); + + if (error != NULL && enable_debug) + printf ("%s ... failed to connect to server \n", G_STRFUNC); + + if (error == NULL && bl->priv->marked_for_offline) generate_cache (bl); - e_book_backend_respond_opened (backend, book, opid, NULL /* Success */); + e_book_backend_respond_opened (backend, book, opid, error); } static void @@ -5643,10 +5431,12 @@ e_book_backend_ldap_notify_online_cb (EBookBackend *backend, if (e_book_backend_is_opened (backend)) { GError *error = NULL; - if (e_book_backend_ldap_connect (bl, &error)) - e_book_backend_notify_auth_required (backend, TRUE, NULL); + if (!e_book_backend_ldap_connect (bl, &error)) { + e_book_backend_notify_error ( + backend, error->message); + g_error_free (error); + } - g_clear_error (&error); #if 0 start_views (backend); #endif @@ -5725,6 +5515,226 @@ e_book_backend_ldap_finalize (GObject *object) G_OBJECT_CLASS (e_book_backend_ldap_parent_class)->finalize (object); } +static ESourceAuthenticationResult +book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator, + const GString *password, + GCancellable *cancellable, + GError **error) +{ + ESourceAuthenticationResult result; + EBookBackendLDAP *bl; + ESourceAuthentication *auth_extension; + ESource *source; + gint ldap_error; + gchar *dn = NULL; + const gchar *extension_name; + gchar *method; + gchar *user; + + bl = E_BOOK_BACKEND_LDAP (authenticator); + source = e_backend_get_source (E_BACKEND (authenticator)); + + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + auth_extension = e_source_get_extension (source, extension_name); + + /* We should not have gotten here if we're offline. */ + g_return_val_if_fail ( + e_backend_get_online (E_BACKEND (authenticator)), + E_SOURCE_AUTHENTICATION_ERROR); + + method = e_source_authentication_dup_method (auth_extension); + user = e_source_authentication_dup_user (auth_extension); + + if (!g_ascii_strncasecmp (method, LDAP_SIMPLE_PREFIX, strlen (LDAP_SIMPLE_PREFIX))) { + + if (bl->priv->ldap && !strcmp (method, "ldap/simple-email")) { + LDAPMessage *res, *e; + gchar *query = g_strdup_printf ("(mail=%s)", user); + gchar *entry_dn; + + g_static_rec_mutex_lock (&eds_ldap_handler_lock); + ldap_error = ldap_search_s (bl->priv->ldap, + bl->priv->ldap_rootdn, + bl->priv->ldap_scope, + query, + NULL, 0, &res); + g_static_rec_mutex_unlock (&eds_ldap_handler_lock); + g_free (query); + + if (ldap_error != LDAP_SUCCESS) + goto exit; + + g_static_rec_mutex_lock (&eds_ldap_handler_lock); + e = ldap_first_entry (bl->priv->ldap, res); + g_static_rec_mutex_unlock (&eds_ldap_handler_lock); + if (!e) { + ldap_msgfree (res); + g_set_error ( + error, G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + _("Failed to get the DN " + "for user '%s'"), user); + return E_SOURCE_AUTHENTICATION_ERROR; + } + + g_static_rec_mutex_lock (&eds_ldap_handler_lock); + entry_dn = ldap_get_dn (bl->priv->ldap, e); + bl->priv->connected = FALSE; /* to reconnect with credentials */ + g_static_rec_mutex_unlock (&eds_ldap_handler_lock); + dn = g_strdup (entry_dn); + + ldap_memfree (entry_dn); + ldap_msgfree (res); + + } else if (!g_strcmp0 (method, "ldap/simple-binddn")) { + dn = g_strdup (user); + } + + g_free (bl->priv->auth_dn); + g_free (bl->priv->auth_secret); + + bl->priv->auth_dn = dn; + bl->priv->auth_secret = g_strdup (password->str); + + /* now authenticate against the DN we were either supplied or queried for */ + if (enable_debug) + printf ("simple auth as %s\n", dn); + + g_static_rec_mutex_lock (&eds_ldap_handler_lock); + + if (!bl->priv->connected || !bl->priv->ldap) { + GError *local_error = NULL; + + g_static_rec_mutex_unlock (&eds_ldap_handler_lock); + + e_book_backend_ldap_connect (bl, &local_error); + + if (local_error == NULL) { + return E_SOURCE_AUTHENTICATION_ACCEPTED; + + } else if (g_error_matches ( + local_error, E_DATA_BOOK_ERROR, + E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED)) { + + g_clear_error (&local_error); + return E_SOURCE_AUTHENTICATION_REJECTED; + + } else { + g_propagate_error (error, local_error); + return E_SOURCE_AUTHENTICATION_ERROR; + } + } + + ldap_error = ldap_simple_bind_s (bl->priv->ldap, + bl->priv->auth_dn, + bl->priv->auth_secret); + g_static_rec_mutex_unlock (&eds_ldap_handler_lock); + + /* Some ldap servers are returning (ex active directory ones) + * LDAP_SERVER_DOWN when we try to do an ldap operation after + * being idle for some time. This error is handled by poll_ldap + * in case of search operations. + * + * We need to handle it explicitly for this bind call. + * We call reconnect so that we get a fresh ldap handle. + * Fixes #67541 */ + if (ldap_error == LDAP_SERVER_DOWN) { + if (e_book_backend_ldap_reconnect (bl, find_book_view (bl), ldap_error)) + ldap_error = LDAP_SUCCESS; + } + } +#ifdef ENABLE_SASL_BINDS + else if (!g_ascii_strncasecmp (method, SASL_PREFIX, strlen (SASL_PREFIX))) { + g_print ("sasl bind (mech = %s) as %s", method + strlen (SASL_PREFIX), user); + g_static_rec_mutex_lock (&eds_ldap_handler_lock); + + if (!bl->priv->connected || !bl->priv->ldap) { + GError *local_error = NULL; + + g_static_rec_mutex_unlock (&eds_ldap_handler_lock); + + e_book_backend_ldap_connect (bl, &local_error); + + if (local_error == NULL) { + return E_SOURCE_AUTHENTICATION_ACCEPTED; + + } else if (g_error_matches ( + local_error, E_DATA_BOOK_ERROR, + E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED)) { + + g_clear_error (&local_error); + return E_SOURCE_AUTHENTICATION_REJECTED; + + } else { + g_propagate_error (error, local_error); + return E_SOURCE_AUTHENTICATION_ERROR; + } + } + + ldap_error = ldap_sasl_bind_s (bl->priv->ldap, + NULL, + method + strlen (SASL_PREFIX), + bl->priv->auth_secret, + NULL, + NULL, + NULL); + g_static_rec_mutex_unlock (&eds_ldap_handler_lock); + } +#endif + else { + ldap_error = LDAP_NOT_SUPPORTED; + } + +exit: + switch (ldap_error) { + case LDAP_SUCCESS: + e_book_backend_notify_readonly ( + E_BOOK_BACKEND (authenticator), FALSE); + + /* force a requery on the root dse since some ldap + * servers are set up such that they don't report + * anything (including the schema DN) until the user + * is authenticated */ + if (!bl->priv->evolutionPersonChecked) { + ldap_error = query_ldap_root_dse (bl); + + if (LDAP_SUCCESS == ldap_error) { + if (!bl->priv->evolutionPersonChecked) + check_schema_support (bl); + } else + g_warning ("Failed to perform root dse query after authenticating, (ldap_error 0x%02x)", ldap_error); + } + + if (bl->priv->marked_for_offline && bl->priv->cache) + generate_cache (bl); + + result = E_SOURCE_AUTHENTICATION_ACCEPTED; + break; + + case LDAP_INVALID_CREDENTIALS: + result = E_SOURCE_AUTHENTICATION_REJECTED; + break; + + case LDAP_NOT_SUPPORTED: + g_propagate_error ( + error, EDB_ERROR ( + UNSUPPORTED_AUTHENTICATION_METHOD)); + result = E_SOURCE_AUTHENTICATION_ERROR; + break; + + default: + g_propagate_error ( + error, ldap_error_to_response (ldap_error)); + result = E_SOURCE_AUTHENTICATION_ERROR; + break; + } + + g_free (method); + g_free (user); + + return result; +} + static void e_book_backend_ldap_class_init (EBookBackendLDAPClass *class) { @@ -5752,9 +5762,17 @@ e_book_backend_ldap_class_init (EBookBackendLDAPClass *class) parent_class->get_contact_list_uids = e_book_backend_ldap_get_contact_list_uids; parent_class->start_book_view = e_book_backend_ldap_start_book_view; parent_class->stop_book_view = e_book_backend_ldap_stop_book_view; - parent_class->authenticate_user = e_book_backend_ldap_authenticate_user; object_class->finalize = e_book_backend_ldap_finalize; + + /* Register our ESource extension. */ + E_TYPE_SOURCE_LDAP; +} + +static void +e_book_backend_ldap_source_authenticator_init (ESourceAuthenticatorInterface *interface) +{ + interface->try_password_sync = book_backend_ldap_try_password_sync; } static void diff --git a/addressbook/backends/ldap/e-source-ldap.c b/addressbook/backends/ldap/e-source-ldap.c new file mode 100644 index 0000000..4e182dc --- /dev/null +++ b/addressbook/backends/ldap/e-source-ldap.c @@ -0,0 +1,659 @@ +/* + * e-source-ldap.c + * + * This program 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 2 of the License, or (at your option) version 3. + * + * This program 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 the program; if not, see + * + */ + +#include "e-source-ldap.h" + +#include + +#include +#include +#include + +#define E_SOURCE_LDAP_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SOURCE_LDAP, ESourceLDAPPrivate)) + +struct _ESourceLDAPPrivate { + GMutex *property_lock; + gboolean can_browse; + gchar *filter; + guint limit; + gchar *root_dn; + ESourceLDAPScope scope; + + /* These are bound to other extensions. */ + ESourceLDAPAuthentication authentication; + ESourceLDAPSecurity security; +}; + +enum { + PROP_0, + PROP_AUTHENTICATION, + PROP_CAN_BROWSE, + PROP_FILTER, + PROP_LIMIT, + PROP_ROOT_DN, + PROP_SCOPE, + PROP_SECURITY +}; + +static GType e_source_ldap_authentication_type = G_TYPE_INVALID; +static GType e_source_ldap_scope_type = G_TYPE_INVALID; +static GType e_source_ldap_security_type = G_TYPE_INVALID; + +G_DEFINE_DYNAMIC_TYPE ( + ESourceLDAP, + e_source_ldap, + E_TYPE_SOURCE_EXTENSION) + +static gboolean +source_ldap_transform_enum_nick_to_value (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer not_used) +{ + GEnumClass *enum_class; + GEnumValue *enum_value; + const gchar *string; + gboolean success = FALSE; + + enum_class = g_type_class_peek (G_VALUE_TYPE (target_value)); + g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), FALSE); + + string = g_value_get_string (source_value); + enum_value = g_enum_get_value_by_nick (enum_class, string); + if (enum_value != NULL) { + g_value_set_enum (target_value, enum_value->value); + success = TRUE; + } + + return success; +} + +static gboolean +source_ldap_transform_enum_value_to_nick (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer not_used) +{ + GEnumClass *enum_class; + GEnumValue *enum_value; + gint value; + gboolean success = FALSE; + + enum_class = g_type_class_peek (G_VALUE_TYPE (source_value)); + g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), FALSE); + + value = g_value_get_enum (source_value); + enum_value = g_enum_get_value (enum_class, value); + if (enum_value != NULL) { + g_value_set_string (target_value, enum_value->value_nick); + success = TRUE; + } + + return success; +} + +static void +source_ldap_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_AUTHENTICATION: + e_source_ldap_set_authentication ( + E_SOURCE_LDAP (object), + g_value_get_enum (value)); + return; + + case PROP_CAN_BROWSE: + e_source_ldap_set_can_browse ( + E_SOURCE_LDAP (object), + g_value_get_boolean (value)); + return; + + case PROP_FILTER: + e_source_ldap_set_filter ( + E_SOURCE_LDAP (object), + g_value_get_string (value)); + return; + + case PROP_LIMIT: + e_source_ldap_set_limit ( + E_SOURCE_LDAP (object), + g_value_get_uint (value)); + return; + + case PROP_ROOT_DN: + e_source_ldap_set_root_dn ( + E_SOURCE_LDAP (object), + g_value_get_string (value)); + return; + + case PROP_SCOPE: + e_source_ldap_set_scope ( + E_SOURCE_LDAP (object), + g_value_get_enum (value)); + return; + + case PROP_SECURITY: + e_source_ldap_set_security ( + E_SOURCE_LDAP (object), + g_value_get_enum (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +source_ldap_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_AUTHENTICATION: + g_value_set_enum ( + value, + e_source_ldap_get_authentication ( + E_SOURCE_LDAP (object))); + return; + + case PROP_CAN_BROWSE: + g_value_set_boolean ( + value, + e_source_ldap_get_can_browse ( + E_SOURCE_LDAP (object))); + return; + + case PROP_FILTER: + g_value_take_string ( + value, + e_source_ldap_dup_filter ( + E_SOURCE_LDAP (object))); + return; + + case PROP_LIMIT: + g_value_set_uint ( + value, + e_source_ldap_get_limit ( + E_SOURCE_LDAP (object))); + return; + + case PROP_ROOT_DN: + g_value_take_string ( + value, + e_source_ldap_dup_root_dn ( + E_SOURCE_LDAP (object))); + return; + + case PROP_SCOPE: + g_value_set_enum ( + value, + e_source_ldap_get_scope ( + E_SOURCE_LDAP (object))); + return; + + case PROP_SECURITY: + g_value_set_enum ( + value, + e_source_ldap_get_security ( + E_SOURCE_LDAP (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +source_ldap_finalize (GObject *object) +{ + ESourceLDAPPrivate *priv; + + priv = E_SOURCE_LDAP_GET_PRIVATE (object); + + g_mutex_free (priv->property_lock); + + g_free (priv->filter); + g_free (priv->root_dn); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_source_ldap_parent_class)->finalize (object); +} + +static void +source_ldap_constructed (GObject *object) +{ + ESource *source; + ESourceExtension *this_extension; + ESourceExtension *other_extension; + const gchar *extension_name; + + this_extension = E_SOURCE_EXTENSION (object); + source = e_source_extension_get_source (this_extension); + + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + other_extension = e_source_get_extension (source, extension_name); + + g_object_bind_property_full ( + other_extension, "method", + this_extension, "authentication", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE, + source_ldap_transform_enum_nick_to_value, + source_ldap_transform_enum_value_to_nick, + NULL, (GDestroyNotify) NULL); + + extension_name = E_SOURCE_EXTENSION_SECURITY; + other_extension = e_source_get_extension (source, extension_name); + + g_object_bind_property_full ( + other_extension, "method", + this_extension, "security", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE, + source_ldap_transform_enum_nick_to_value, + source_ldap_transform_enum_value_to_nick, + NULL, (GDestroyNotify) NULL); +} + +static void +e_source_ldap_class_init (ESourceLDAPClass *class) +{ + GObjectClass *object_class; + ESourceExtensionClass *extension_class; + + g_type_class_add_private (class, sizeof (ESourceLDAPPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = source_ldap_set_property; + object_class->get_property = source_ldap_get_property; + object_class->finalize = source_ldap_finalize; + object_class->constructed = source_ldap_constructed; + + extension_class = E_SOURCE_EXTENSION_CLASS (class); + extension_class->name = E_SOURCE_EXTENSION_LDAP_BACKEND; + + /* This is bound to the authentication extension. + * Do not use E_SOURCE_PARAM_SETTING here. */ + g_object_class_install_property ( + object_class, + PROP_AUTHENTICATION, + g_param_spec_enum ( + "authentication", + "Authentication", + "LDAP authentication method", + E_TYPE_SOURCE_LDAP_AUTHENTICATION, + E_SOURCE_LDAP_AUTHENTICATION_NONE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_CAN_BROWSE, + g_param_spec_boolean ( + "can-browse", + "Can Browse", + "Allow browsing contacts", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + E_SOURCE_PARAM_SETTING)); + + g_object_class_install_property ( + object_class, + PROP_FILTER, + g_param_spec_string ( + "filter", + "Filter", + "LDAP search filter", + "", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + E_SOURCE_PARAM_SETTING)); + + g_object_class_install_property ( + object_class, + PROP_LIMIT, + g_param_spec_uint ( + "limit", + "Limit", + "Download limit", + 0, G_MAXUINT, 100, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + E_SOURCE_PARAM_SETTING)); + + g_object_class_install_property ( + object_class, + PROP_ROOT_DN, + g_param_spec_string ( + "root-dn", + "Root DN", + "LDAP search base", + "", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + E_SOURCE_PARAM_SETTING)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE, + g_param_spec_enum ( + "scope", + "Scope", + "LDAP search scope", + E_TYPE_SOURCE_LDAP_SCOPE, + E_SOURCE_LDAP_SCOPE_ONELEVEL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + E_SOURCE_PARAM_SETTING)); + + /* This is bound to the security extension. + * Do not use E_SOURCE_PARAM_SETTING here. */ + g_object_class_install_property ( + object_class, + PROP_SECURITY, + g_param_spec_enum ( + "security", + "Security", + "LDAP security method", + E_TYPE_SOURCE_LDAP_SECURITY, + E_SOURCE_LDAP_SECURITY_NONE, + G_PARAM_READWRITE)); +} + +static void +e_source_ldap_class_finalize (ESourceLDAPClass *class) +{ +} + +static void +e_source_ldap_init (ESourceLDAP *extension) +{ + extension->priv = E_SOURCE_LDAP_GET_PRIVATE (extension); + extension->priv->property_lock = g_mutex_new (); +} + +void +e_source_ldap_type_register (GTypeModule *type_module) +{ + static const GEnumValue e_source_ldap_authentication_values[] = { + { E_SOURCE_LDAP_AUTHENTICATION_NONE, + "E_SOURCE_LDAP_AUTHENTICATION_NONE", + "none" }, + { E_SOURCE_LDAP_AUTHENTICATION_EMAIL, + "E_SOURCE_LDAP_AUTHENTICATION_EMAIL", + "ldap/simple-email" }, + { E_SOURCE_LDAP_AUTHENTICATION_BINDDN, + "E_SOURCE_LDAP_AUTHENTICATION_BINDDN", + "ldap/simple-binddn" }, + { 0, NULL, NULL } + }; + + static const GEnumValue e_source_ldap_scope_values[] = { + { E_SOURCE_LDAP_SCOPE_ONELEVEL, + "E_SOURCE_LDAP_SCOPE_ONELEVEL", + "onelevel" }, + { E_SOURCE_LDAP_SCOPE_SUBTREE, + "E_SOURCE_LDAP_SCOPE_SUBTREE", + "subtree" }, + { 0, NULL, NULL } + }; + + static const GEnumValue e_source_ldap_security_values[] = { + { E_SOURCE_LDAP_SECURITY_NONE, + "E_SOURCE_LDAP_SECURITY_NONE", + "none" }, + { E_SOURCE_LDAP_SECURITY_LDAPS, + "E_SOURCE_LDAP_SECURITY_LDAPS", + "ldaps" }, + { E_SOURCE_LDAP_SECURITY_STARTTLS, + "E_SOURCE_LDAP_SECURITY_STARTTLS", + "starttls" }, + { 0, NULL, NULL } + }; + + e_source_ldap_authentication_type = + g_type_module_register_enum ( + type_module, "ESourceLDAPAuthentication", + e_source_ldap_authentication_values); + + e_source_ldap_scope_type = + g_type_module_register_enum ( + type_module, "ESourceLDAPScope", + e_source_ldap_scope_values); + + e_source_ldap_security_type = + g_type_module_register_enum ( + type_module, "ESourceLDAPSecurity", + e_source_ldap_security_values); + + /* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration + * function, so we have to wrap it with a public function in + * order to register types from a separate compilation unit. */ + e_source_ldap_register_type (type_module); +} + +ESourceLDAPAuthentication +e_source_ldap_get_authentication (ESourceLDAP *extension) +{ + g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0); + + return extension->priv->authentication; +} + +void +e_source_ldap_set_authentication (ESourceLDAP *extension, + ESourceLDAPAuthentication authentication) +{ + g_return_if_fail (E_IS_SOURCE_LDAP (extension)); + + extension->priv->authentication = authentication; + + g_object_notify (G_OBJECT (extension), "authentication"); +} + +gboolean +e_source_ldap_get_can_browse (ESourceLDAP *extension) +{ + g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), FALSE); + + return extension->priv->can_browse; +} + +void +e_source_ldap_set_can_browse (ESourceLDAP *extension, + gboolean can_browse) +{ + g_return_if_fail (E_IS_SOURCE_LDAP (extension)); + + extension->priv->can_browse = can_browse; + + g_object_notify (G_OBJECT (extension), "can-browse"); +} + +const gchar * +e_source_ldap_get_filter (ESourceLDAP *extension) +{ + g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL); + + return extension->priv->filter; +} + +gchar * +e_source_ldap_dup_filter (ESourceLDAP *extension) +{ + const gchar *protected; + gchar *duplicate; + + g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL); + + g_mutex_lock (extension->priv->property_lock); + + protected = e_source_ldap_get_filter (extension); + duplicate = g_strdup (protected); + + g_mutex_unlock (extension->priv->property_lock); + + return duplicate; +} + +void +e_source_ldap_set_filter (ESourceLDAP *extension, + const gchar *filter) +{ + gboolean needs_parens; + + g_return_if_fail (E_IS_SOURCE_LDAP (extension)); + + needs_parens = + (filter != NULL) && (*filter != '\0') && + !g_str_has_prefix (filter, "(") && + !g_str_has_suffix (filter, ")"); + + g_mutex_lock (extension->priv->property_lock); + + g_free (extension->priv->filter); + if (needs_parens) + extension->priv->filter = g_strdup_printf ("(%s)", filter); + else + extension->priv->filter = g_strdup (filter); + + g_mutex_unlock (extension->priv->property_lock); + + g_object_notify (G_OBJECT (extension), "filter"); +} + +guint +e_source_ldap_get_limit (ESourceLDAP *extension) +{ + g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0); + + return extension->priv->limit; +} + +void +e_source_ldap_set_limit (ESourceLDAP *extension, + guint limit) +{ + g_return_if_fail (E_IS_SOURCE_LDAP (extension)); + + extension->priv->limit = limit; + + g_object_notify (G_OBJECT (extension), "limit"); +} + +const gchar * +e_source_ldap_get_root_dn (ESourceLDAP *extension) +{ + g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL); + + return extension->priv->root_dn; +} + +gchar * +e_source_ldap_dup_root_dn (ESourceLDAP *extension) +{ + const gchar *protected; + gchar *duplicate; + + g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL); + + g_mutex_lock (extension->priv->property_lock); + + protected = e_source_ldap_get_root_dn (extension); + duplicate = g_strdup (protected); + + g_mutex_unlock (extension->priv->property_lock); + + return duplicate; +} + +void +e_source_ldap_set_root_dn (ESourceLDAP *extension, + const gchar *root_dn) +{ + g_return_if_fail (E_IS_SOURCE_LDAP (extension)); + + g_mutex_lock (extension->priv->property_lock); + + g_free (extension->priv->root_dn); + extension->priv->root_dn = e_util_strdup_strip (root_dn); + + g_mutex_unlock (extension->priv->property_lock); + + g_object_notify (G_OBJECT (extension), "root-dn"); +} + +ESourceLDAPScope +e_source_ldap_get_scope (ESourceLDAP *extension) +{ + g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0); + + return extension->priv->scope; +} + +void +e_source_ldap_set_scope (ESourceLDAP *extension, + ESourceLDAPScope scope) +{ + g_return_if_fail (E_IS_SOURCE_LDAP (extension)); + + extension->priv->scope = scope; + + g_object_notify (G_OBJECT (extension), "scope"); +} + +ESourceLDAPSecurity +e_source_ldap_get_security (ESourceLDAP *extension) +{ + g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0); + + return extension->priv->security; +} + +void +e_source_ldap_set_security (ESourceLDAP *extension, + ESourceLDAPSecurity security) +{ + g_return_if_fail (E_IS_SOURCE_LDAP (extension)); + + extension->priv->security = security; + + g_object_notify (G_OBJECT (extension), "security"); +} + +GType +e_source_ldap_authentication_get_type (void) +{ + return e_source_ldap_authentication_type; +} + +GType +e_source_ldap_scope_get_type (void) +{ + return e_source_ldap_scope_type; +} + +GType +e_source_ldap_security_get_type (void) +{ + return e_source_ldap_security_type; +} diff --git a/addressbook/backends/ldap/e-source-ldap.h b/addressbook/backends/ldap/e-source-ldap.h new file mode 100644 index 0000000..ea9cb9f --- /dev/null +++ b/addressbook/backends/ldap/e-source-ldap.h @@ -0,0 +1,123 @@ +/* + * e-source-ldap.h + * + * This program 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 2 of the License, or (at your option) version 3. + * + * This program 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 the program; if not, see + * + */ + +#ifndef E_SOURCE_LDAP_H +#define E_SOURCE_LDAP_H + +#include + +/* Standard GObject macros */ +#define E_TYPE_SOURCE_LDAP \ + (e_source_ldap_get_type ()) +#define E_SOURCE_LDAP(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SOURCE_LDAP, ESourceLDAP)) +#define E_SOURCE_LDAP_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SOURCE_LDAP, ESourceLDAPClass)) +#define E_IS_SOURCE_LDAP(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SOURCE_LDAP)) +#define E_IS_SOURCE_LDAP_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_SOURCE_LDAP)) +#define E_SOURCE_LDAP_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SOURCE_LDAP, ESourceLDAPClass)) + +#define E_TYPE_SOURCE_LDAP_AUTHENTICATION \ + (e_source_ldap_authentication_get_type ()) + +#define E_TYPE_SOURCE_LDAP_SCOPE \ + (e_source_ldap_scope_get_type ()) + +#define E_TYPE_SOURCE_LDAP_SECURITY \ + (e_source_ldap_security_get_type ()) + +#define E_SOURCE_EXTENSION_LDAP_BACKEND "LDAP Backend" + +G_BEGIN_DECLS + +typedef struct _ESourceLDAP ESourceLDAP; +typedef struct _ESourceLDAPClass ESourceLDAPClass; +typedef struct _ESourceLDAPPrivate ESourceLDAPPrivate; + +struct _ESourceLDAP { + ESourceExtension parent; + ESourceLDAPPrivate *priv; +}; + +struct _ESourceLDAPClass { + ESourceExtensionClass parent_class; +}; + +typedef enum { + E_SOURCE_LDAP_AUTHENTICATION_NONE, + E_SOURCE_LDAP_AUTHENTICATION_EMAIL, + E_SOURCE_LDAP_AUTHENTICATION_BINDDN +} ESourceLDAPAuthentication; + +typedef enum { + E_SOURCE_LDAP_SCOPE_ONELEVEL, + E_SOURCE_LDAP_SCOPE_SUBTREE +} ESourceLDAPScope; + +typedef enum { + E_SOURCE_LDAP_SECURITY_NONE, + E_SOURCE_LDAP_SECURITY_LDAPS, + E_SOURCE_LDAP_SECURITY_STARTTLS +} ESourceLDAPSecurity; + +GType e_source_ldap_get_type (void); +void e_source_ldap_type_register (GTypeModule *type_module); +ESourceLDAPAuthentication + e_source_ldap_get_authentication + (ESourceLDAP *extension); +void e_source_ldap_set_authentication + (ESourceLDAP *extension, + ESourceLDAPAuthentication authentication); +gboolean e_source_ldap_get_can_browse (ESourceLDAP *extension); +void e_source_ldap_set_can_browse (ESourceLDAP *extension, + gboolean can_browse); +const gchar * e_source_ldap_get_filter (ESourceLDAP *extension); +gchar * e_source_ldap_dup_filter (ESourceLDAP *extension); +void e_source_ldap_set_filter (ESourceLDAP *extension, + const gchar *filter); +guint e_source_ldap_get_limit (ESourceLDAP *extension); +void e_source_ldap_set_limit (ESourceLDAP *extension, + guint limit); +const gchar * e_source_ldap_get_root_dn (ESourceLDAP *extension); +gchar * e_source_ldap_dup_root_dn (ESourceLDAP *extension); +void e_source_ldap_set_root_dn (ESourceLDAP *extension, + const gchar *root_dn); +ESourceLDAPScope + e_source_ldap_get_scope (ESourceLDAP *extension); +void e_source_ldap_set_scope (ESourceLDAP *extension, + ESourceLDAPScope scope); +ESourceLDAPSecurity + e_source_ldap_get_security (ESourceLDAP *extension); +void e_source_ldap_set_security (ESourceLDAP *extension, + ESourceLDAPSecurity security); + +GType e_source_ldap_authentication_get_type (void); +GType e_source_ldap_scope_get_type (void); +GType e_source_ldap_security_get_type (void); + +G_END_DECLS + +#endif /* E_SOURCE_LDAP_H */ diff --git a/libedataserver/e-system-source.c b/libedataserver/e-system-source.c deleted file mode 100644 index 12a7d1a..0000000 --- a/libedataserver/e-system-source.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * e-system-source.c - * - * This program 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 2 of the License, or (at your option) version 3. - * - * This program 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 the program; if not, see - * - */ - -#include "e-system-source.h" - -#include -#include - -#include "e-data-server-util.h" - -G_DEFINE_TYPE ( - ESystemSource, - e_system_source, - E_TYPE_SOURCE) - -static void -system_source_notify (GObject *object, - GParamSpec *pspec) -{ - ESource *source = E_SOURCE (object); - - /* GObject does not allow subclasses to override property flags, - * so we'll keep the "backend-name" and "display-name" properties - * fixed by intercepting attempts to change them and setting them - * back to their proper values. Hokey but works. */ - - if (g_strcmp0 (pspec->name, "backend-name") == 0) { - if (e_source_get_backend_name (source) != NULL) { - e_source_set_backend_name (source, NULL); - return; - } - } - - if (g_strcmp0 (pspec->name, "display-name") == 0) { - const gchar *display_name; - const gchar *proper_value; - - display_name = e_source_get_display_name (source); - proper_value = _("Personal"); - - if (g_strcmp0 (display_name, proper_value) != 0) { - e_source_set_display_name (source, proper_value); - return; - } - } - - /* Chain up to parent's notify() method. */ - G_OBJECT_CLASS (e_system_source_parent_class)->notify (object, pspec); -} - -static void -e_system_source_class_init (ESystemSourceClass *class) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (class); - object_class->notify = system_source_notify; -} - -static void -e_system_source_init (ESystemSource *source) -{ -} - -ESource * -e_system_source_new (void) -{ - GSettings *settings; - ESource *source; - GFile *file; - const gchar *data_dir; - gchar *path; - - data_dir = e_get_user_data_dir (); - path = g_build_filename (data_dir, "sources", "system", NULL); - file = g_file_new_for_path (path); - g_free (path); - - /* This function must not fail, so if a "system" key file - * exists and fails to load, delete it and try again. */ - source = g_initable_new ( - E_TYPE_SYSTEM_SOURCE, NULL, NULL, "file", file, NULL); - if (source == NULL) { - g_file_delete (file, NULL, NULL); - source = g_initable_new ( - E_TYPE_SYSTEM_SOURCE, NULL, NULL, "file", file, NULL); - } - - g_object_unref (file); - - g_return_val_if_fail (E_IS_SYSTEM_SOURCE (source), NULL); - - /* Set the "parent" key directly through its GSettings. - * - * XXX To set this during object construction we would have - * to override the GInitable interface. Too much hassle - * for now. Maybe revisit this in the future. */ - settings = e_source_get_settings (source); - g_settings_set_string (settings, "parent", "local"); - - return source; -} diff --git a/libedataserver/e-system-source.h b/libedataserver/e-system-source.h deleted file mode 100644 index 959a8f2..0000000 --- a/libedataserver/e-system-source.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * e-system-source.h - * - * This program 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 2 of the License, or (at your option) version 3. - * - * This program 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 the program; if not, see - * - */ - -#ifndef E_SYSTEM_SOURCE_H -#define E_SYSTEM_SOURCE_H - -#include - -/* Standard GObject macros */ -#define E_TYPE_SYSTEM_SOURCE \ - (e_system_source_get_type ()) -#define E_SYSTEM_SOURCE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_SYSTEM_SOURCE, ESystemSource)) -#define E_SYSTEM_SOURCE_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_SYSTEM_SOURCE, ESystemSourceClass)) -#define E_IS_SYSTEM_SOURCE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_SYSTEM_SOURCE)) -#define E_IS_SYSTEM_SOURCE_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_SYSTEM_SOURCE)) -#define E_SYSTEM_SOURCE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_SOURCE, ESystemSourceClass)) - -G_BEGIN_DECLS - -typedef struct _ESystemSource ESystemSource; -typedef struct _ESystemSourceClass ESystemSourceClass; -typedef struct _ESystemSourcePrivate ESystemSourcePrivate; - -struct _ESystemSource { - ESource parent; - ESystemSourcePrivate *priv; -}; - -struct _ESystemSourceClass { - ESourceClass parent_class; -}; - -GType e_system_source_get_type (void) G_GNUC_CONST; -ESource * e_system_source_new (void); - -G_END_DECLS - -#endif /* E_SYSTEM_SOURCE_H */