diff options
-rw-r--r-- | addressbook/ChangeLog | 25 | ||||
-rw-r--r-- | addressbook/backend/pas/pas-backend-ldap.c | 246 |
2 files changed, 175 insertions, 96 deletions
diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog index 78fb0ebfa6..3a7c7494ba 100644 --- a/addressbook/ChangeLog +++ b/addressbook/ChangeLog @@ -1,5 +1,30 @@ 2002-08-16 Chris Toshok <toshok@ximian.com> + * backend/pas/pas-backend-ldap.c (book_view_notify_status): new + function to save a little typing. + (find_book_view): same. + (pas_backend_ldap_connect): reorder things a bit - set the version + to VERSION3 *before* doing TLS, as tls requires v3, and if we're + doing ldaps://, do tls a little differently (not sure if this is + strictly necessary, but the openldap source did it.. *shrug*). + also, guard the schema check as this function can be called + multiple times for the same server (if the server goes down or + times us out.) + (pas_backend_ldap_reconnect): new function, reconnect and if + necessary reauth the user. + (pas_backend_ldap_process_create_card): use + find_book_view/book_view_notify_status/pas_backend_ldap_reconnect. + (pas_backend_ldap_process_remove_card): same. + (pas_backend_ldap_process_modify_card): same. + (pas_backend_ldap_process_get_vcard): same. + (pas_backend_ldap_process_get_cursor): same. + (pas_backend_ldap_search): same. + (poll_ldap): reconnect if ldap_result returns -1. + (pas_backend_ldap_process_authenticate_user): ick ick ick save off + the dn/passwd we auth with so we can use them to reauthenticate. + +2002-08-16 Chris Toshok <toshok@ximian.com> + [ fix 27333 ] * gui/widgets/e-addressbook-model.c (get_view): "local" -> "do-initial-query". diff --git a/addressbook/backend/pas/pas-backend-ldap.c b/addressbook/backend/pas/pas-backend-ldap.c index 249a652c3a..8ea22275c3 100644 --- a/addressbook/backend/pas/pas-backend-ldap.c +++ b/addressbook/backend/pas/pas-backend-ldap.c @@ -97,6 +97,9 @@ struct _PASBackendLDAPPrivate { int ldap_limit; /* the search limit */ int ldap_timeout; /* the search timeout */ + gchar *auth_dn; + gchar *auth_passwd; + gboolean ldap_v3; /* TRUE if the server supports protocol revision 3 (necessary for TLS) */ gboolean starttls; /* TRUE if the *library* supports @@ -328,6 +331,27 @@ view_destroy(GtkObject *object, gpointer data) } static void +book_view_notify_status (PASBookView *view, const char *status) +{ + if (!view) + return; + pas_book_view_notify_status_message (view, status); +} + +static PASBookView* +find_book_view (PASBackendLDAP *bl) +{ + /* just always use the first book view */ + if (bl->priv->book_views) { + PASBackendLDAPBookView *v = bl->priv->book_views->data; + return v->book_view; + } + else { + return NULL; + } +} + +static void add_to_supported_fields (PASBackendLDAP *bl, char **attrs, GHashTable *attr_hash) { int i; @@ -527,14 +551,6 @@ query_ldap_root_dse (PASBackendLDAP *bl) } - values = ldap_get_values (ldap, resp, "supportedLDAPVersion"); - if (values) { - for (i = 0; values[i]; i++) - if (LDAP_VERSION3 == atoi (values[i])) - bl->priv->ldap_v3 = TRUE; - ldap_value_free (values); - } - values = ldap_get_values (ldap, resp, "subschemaSubentry"); if (!values || !values[0]) { if (values) ldap_value_free (values); @@ -573,6 +589,21 @@ pas_backend_ldap_connect (PASBackendLDAP *bl) int ldap_error; if (bl->priv->use_tls) { + int protocol_version = LDAP_VERSION3; + ldap_error = ldap_set_option (blpriv->ldap, LDAP_OPT_PROTOCOL_VERSION, &protocol_version); + if (LDAP_OPT_SUCCESS != ldap_error) { + g_warning ("failed to set protocol version to LDAPv3"); + bl->priv->ldap_v3 = FALSE; + } + else + bl->priv->ldap_v3 = TRUE; + } + + if (bl->priv->ldap_port == LDAPS_PORT && bl->priv->use_tls == PAS_BACKEND_LDAP_TLS_ALWAYS) { + int tls_level = LDAP_OPT_X_TLS_HARD; + ldap_set_option (blpriv->ldap, LDAP_OPT_X_TLS, &tls_level); + } + else if (bl->priv->use_tls) { ldap_error = ldap_start_tls_s (blpriv->ldap, NULL, NULL); if (LDAP_SUCCESS != ldap_error) { if (bl->priv->use_tls == PAS_BACKEND_LDAP_TLS_ALWAYS) { @@ -591,21 +622,13 @@ pas_backend_ldap_connect (PASBackendLDAP *bl) query_ldap_root_dse (bl); - if (bl->priv->ldap_v3) { - int protocol_version = LDAP_VERSION3; - ldap_error = ldap_set_option (blpriv->ldap, LDAP_OPT_PROTOCOL_VERSION, &protocol_version); - if (LDAP_OPT_SUCCESS != ldap_error) { - g_warning ("failed to set protocol version to LDAPv3"); - bl->priv->ldap_v3 = FALSE; - } - } - blpriv->connected = TRUE; /* check to see if evolutionPerson is supported, if we can (me might not be able to if we can't authenticate. if we can't, try again in auth_user.) */ - check_schema_support (bl); + if (!bl->priv->evolutionPersonChecked) + check_schema_support (bl); return GNOME_Evolution_Addressbook_BookListener_Success; } @@ -620,6 +643,35 @@ pas_backend_ldap_connect (PASBackendLDAP *bl) } } +static gboolean +pas_backend_ldap_reconnect (PASBackendLDAP *bl, PASBookView *book_view, int ldap_status) +{ + /* we need to reconnect if we were previously connected */ + if (bl->priv->connected && ldap_status == LDAP_SERVER_DOWN) { + GNOME_Evolution_Addressbook_BookListener_CallStatus status; + int ldap_error = LDAP_SUCCESS; + + book_view_notify_status (book_view, _("Reconnecting to LDAP server...")); + + status = pas_backend_ldap_connect (bl); + + if (status != GNOME_Evolution_Addressbook_BookListener_Success) { + book_view_notify_status (book_view, ""); + return FALSE; + } + + if (bl->priv->auth_dn) + ldap_error = ldap_simple_bind_s(bl->priv->ldap, + bl->priv->auth_dn, + bl->priv->auth_passwd); + book_view_notify_status (book_view, ""); + return (ldap_error == LDAP_SUCCESS); + } + else { + return FALSE; + } +} + static void ldap_op_add (LDAPOp *op, PASBackend *backend, PASBook *book, PASBookView *view, @@ -1046,7 +1098,7 @@ pas_backend_ldap_process_create_card (PASBackend *backend, { LDAPCreateOp *create_op = g_new (LDAPCreateOp, 1); PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); - PASBookView *book_view = NULL; + PASBookView *book_view; int create_card_msgid; ECard *new_ecard; int response; @@ -1055,10 +1107,7 @@ pas_backend_ldap_process_create_card (PASBackend *backend, LDAPMod **ldap_mods; LDAP *ldap; - if (bl->priv->book_views) { - PASBackendLDAPBookView *v = bl->priv->book_views->data; - book_view = v->book_view; - } + book_view = find_book_view (bl); printf ("vcard = %s\n", req->create.vcard); @@ -1134,11 +1183,13 @@ pas_backend_ldap_process_create_card (PASBackend *backend, ldap_mods = (LDAPMod**)mod_array->pdata; - if (book_view) - pas_book_view_notify_status_message (book_view, _("Adding card to LDAP server...")); + do { + book_view_notify_status (book_view, _("Adding card to LDAP server...")); + + err = ldap_add_ext (ldap, create_op->dn, ldap_mods, + NULL, NULL, &create_card_msgid); - err = ldap_add_ext (ldap, create_op->dn, ldap_mods, - NULL, NULL, &create_card_msgid); + } while (pas_backend_ldap_reconnect (bl, book_view, err)); /* and clean up */ free_mods (mod_array); @@ -1226,23 +1277,21 @@ pas_backend_ldap_process_remove_card (PASBackend *backend, { LDAPRemoveOp *remove_op = g_new (LDAPRemoveOp, 1); PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); - PASBookView *book_view = NULL; + PASBookView *book_view; int remove_msgid; int ldap_error; - if (bl->priv->book_views) { - PASBackendLDAPBookView *v = bl->priv->book_views->data; - book_view = v->book_view; - } + book_view = find_book_view (bl); remove_op->id = g_strdup (req->remove.id); - if (book_view) - pas_book_view_notify_status_message (book_view, _("Removing card from LDAP server...")); + do { + book_view_notify_status (book_view, _("Removing card from LDAP server...")); - ldap_error = ldap_delete_ext (bl->priv->ldap, - remove_op->id, - NULL, NULL, &remove_msgid); + ldap_error = ldap_delete_ext (bl->priv->ldap, + remove_op->id, + NULL, NULL, &remove_msgid); + } while (pas_backend_ldap_reconnect (bl, book_view, ldap_error)); if (ldap_error != LDAP_SUCCESS) { pas_book_respond_remove (remove_op->op.book, @@ -1458,12 +1507,9 @@ pas_backend_ldap_process_modify_card (PASBackend *backend, int ldap_error; LDAP *ldap; int modify_card_msgid; - PASBookView *book_view = NULL; + PASBookView *book_view; - if (bl->priv->book_views) { - PASBackendLDAPBookView *v = bl->priv->book_views->data; - book_view = v->book_view; - } + book_view = find_book_view (bl); modify_op->vcard = g_strdup (req->modify.vcard); new_ecard = e_card_new (modify_op->vcard); @@ -1473,15 +1519,19 @@ pas_backend_ldap_process_modify_card (PASBackend *backend, ldap = bl->priv->ldap; - if (book_view) - pas_book_view_notify_status_message (book_view, _("Modifying card from LDAP server...")); + book_view_notify_status (book_view, _("Modifying card from LDAP server...")); + + do { + book_view_notify_status (book_view, _("Modifying card from LDAP server...")); + + ldap_error = ldap_search_ext (ldap, modify_op->id, + LDAP_SCOPE_BASE, + "(objectclass=*)", + NULL, 0, NULL, NULL, + NULL, /* XXX timeout */ + 1, &modify_card_msgid); - ldap_error = ldap_search_ext (ldap, modify_op->id, - LDAP_SCOPE_BASE, - "(objectclass=*)", - NULL, 0, NULL, NULL, - NULL, /* XXX timeout */ - 1, &modify_card_msgid); + } while (pas_backend_ldap_reconnect (bl, book_view, ldap_error)); if (ldap_error == LDAP_SUCCESS) { ldap_op_add ((LDAPOp*)modify_op, backend, book, @@ -1567,20 +1617,19 @@ pas_backend_ldap_process_get_vcard (PASBackend *backend, PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); LDAP *ldap = bl->priv->ldap; int get_vcard_msgid; - PASBookView *book_view = NULL; + PASBookView *book_view; int ldap_error; - if (bl->priv->book_views) { - PASBackendLDAPBookView *v = bl->priv->book_views->data; - book_view = v->book_view; - } - - ldap_error = ldap_search_ext (ldap, req->get_vcard.id, - LDAP_SCOPE_BASE, - "(objectclass=*)", - NULL, 0, NULL, NULL, - NULL, /* XXX timeout */ - 1, &get_vcard_msgid); + book_view = find_book_view (bl); + + do { + ldap_error = ldap_search_ext (ldap, req->get_vcard.id, + LDAP_SCOPE_BASE, + "(objectclass=*)", + NULL, 0, NULL, NULL, + NULL, /* XXX timeout */ + 1, &get_vcard_msgid); + } while (pas_backend_ldap_reconnect (bl, book_view, ldap_error)); if (ldap_error == LDAP_SUCCESS) { ldap_op_add ((LDAPOp*)get_vcard_op, backend, book, @@ -1730,17 +1779,22 @@ pas_backend_ldap_process_get_cursor (PASBackend *backend, int ldap_error; int get_cursor_msgid; LDAPGetCursorOp *cursor_op; + PASBookView *book_view; + + book_view = find_book_view (bl); cursor_op = g_new0 (LDAPGetCursorOp, 1); cursor_op->cursor_data = g_new0 (PASBackendLDAPCursorPrivate, 1); - ldap_error = ldap_search_ext (ldap, - bl->priv->ldap_rootdn, - bl->priv->ldap_scope, - "(objectclass=*)", - NULL, 0, - NULL, NULL, NULL, /* timeout */ - bl->priv->ldap_limit, &get_cursor_msgid); + do { + ldap_error = ldap_search_ext (ldap, + bl->priv->ldap_rootdn, + bl->priv->ldap_scope, + "(objectclass=*)", + NULL, 0, + NULL, NULL, NULL, /* timeout */ + bl->priv->ldap_limit, &get_cursor_msgid); + } while (pas_backend_ldap_reconnect (bl, book_view, ldap_error)); if (ldap_error == LDAP_SUCCESS) { CORBA_Environment ev; @@ -2596,19 +2650,15 @@ poll_ldap (PASBackendLDAP *bl) rc = ldap_result (ldap, LDAP_RES_ANY, 0, &timeout, &res); if (rc != 0) {/* rc == 0 means timeout exceeded */ -#if 0 - if (rc == -1 && received == 0) { - pas_book_view_notify_status_message (view->book_view, _("Restarting search.")); - /* connection went down and we never got any. */ - bl->priv->connected = FALSE; + if (rc == -1) { + PASBookView *book_view = find_book_view (bl); + g_warning ("ldap_result returned -1, restarting ops"); - /* this will reopen the connection */ - ldap_op_restart ((LDAPOp*)op); - return FALSE; - } + pas_backend_ldap_reconnect (bl, book_view, LDAP_SERVER_DOWN); +#if 0 + if (bl->priv->connected) + restart_ops (bl); #endif - if (rc == -1) { - g_warning ("ldap_result returned -1"); } else { int msgid = ldap_msgid (res); @@ -2690,7 +2740,7 @@ ldap_search_handler (LDAPOp *op, LDAPMessage *res) if (!search_op->notified_receiving_results) { search_op->notified_receiving_results = TRUE; - pas_book_view_notify_status_message (op->view, _("Receiving LDAP search results...")); + book_view_notify_status (op->view, _("Receiving LDAP search results...")); } msg_type = ldap_msgtype (res); @@ -2744,8 +2794,6 @@ pas_backend_ldap_search (PASBackendLDAP *bl, { char *ldap_query; - pas_book_view_notify_status_message (view->book_view, _("Searching...")); - ldap_query = pas_backend_ldap_build_query(bl, view->search); if (ldap_query != NULL) { @@ -2754,24 +2802,28 @@ pas_backend_ldap_search (PASBackendLDAP *bl, GTimeVal search_start; int search_msgid; - ldap_err = ldap_search_ext (ldap, bl->priv->ldap_rootdn, - bl->priv->ldap_scope, - ldap_query, - NULL, 0, - NULL, /* XXX */ - NULL, /* XXX */ - NULL, /* XXX timeout */ - bl->priv->ldap_limit, &search_msgid); + do { + book_view_notify_status (view->book_view, _("Searching...")); + + ldap_err = ldap_search_ext (ldap, bl->priv->ldap_rootdn, + bl->priv->ldap_scope, + ldap_query, + NULL, 0, + NULL, /* XXX */ + NULL, /* XXX */ + NULL, /* XXX timeout */ + bl->priv->ldap_limit, &search_msgid); + } while (pas_backend_ldap_reconnect (bl, view->book_view, ldap_err)); g_free (ldap_query); if (ldap_err != LDAP_SUCCESS) { - pas_book_view_notify_status_message (view->book_view, ldap_err2string(ldap_err)); + book_view_notify_status (view->book_view, ldap_err2string(ldap_err)); return; } else if (search_msgid == -1) { - pas_book_view_notify_status_message (view->book_view, - _("Error performing search")); + book_view_notify_status (view->book_view, + _("Error performing search")); return; } else { @@ -2795,7 +2847,7 @@ pas_backend_ldap_search (PASBackendLDAP *bl, } else { g_warning ("LDAP problem converting search query %s\n", view->search); - pas_book_view_notify_status_message (view->book_view, _("Could not parse query string")); + book_view_notify_status (view->book_view, _("Could not parse query string")); return; } @@ -2893,7 +2945,9 @@ pas_backend_ldap_process_authenticate_user (PASBackend *backend, ldap_error = ldap_simple_bind_s(bl->priv->ldap, dn, req->auth_user.passwd); - g_free (dn); + + bl->priv->auth_dn = dn; + bl->priv->auth_passwd = g_strdup (req->auth_user.passwd); pas_book_respond_authenticate_user (book, ldap_error_to_response (ldap_error)); |