diff options
author | Simo Sorce <idra@samba.org> | 2008-09-24 01:37:16 -0400 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2008-09-24 01:43:57 -0400 |
commit | 83b0c5d43f568222d97f9b8de985f1e39a375fb9 (patch) | |
tree | 97e3aced390fc7db276b1c47d382377a697469dd /source4/libcli | |
parent | 7b20cbb1152af7f3779cbb0dd74d939d8f1637c0 (diff) | |
download | samba-83b0c5d43f568222d97f9b8de985f1e39a375fb9.tar.gz samba-83b0c5d43f568222d97f9b8de985f1e39a375fb9.tar.bz2 samba-83b0c5d43f568222d97f9b8de985f1e39a375fb9.zip |
Fix nasty bug that would come up only if a client connection to a remote
ldap server suddenly dies.
We were creating a wrong talloc hierarchy, so the event.fde was not
freed automatically as expected. This in turn made the event system call
the ldap io handlers with a null packet structure, causing a segfault.
Fix also the ordering in ldap_connection_dead()
Thanks to Metze for the huge help in tracking down this one.
Diffstat (limited to 'source4/libcli')
-rw-r--r-- | source4/libcli/ldap/ldap_bind.c | 1 | ||||
-rw-r--r-- | source4/libcli/ldap/ldap_client.c | 21 |
2 files changed, 13 insertions, 9 deletions
diff --git a/source4/libcli/ldap/ldap_bind.c b/source4/libcli/ldap/ldap_bind.c index 65673116be..b66232c02e 100644 --- a/source4/libcli/ldap/ldap_bind.c +++ b/source4/libcli/ldap/ldap_bind.c @@ -387,6 +387,7 @@ _PUBLIC_ NTSTATUS ldap_bind_sasl(struct ldap_connection *conn, if (NT_STATUS_IS_OK(status)) { struct socket_context *sasl_socket; status = gensec_socket_init(conn->gensec, + conn, conn->sock, conn->event.event_ctx, ldap_read_io_handler, diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c index 844238afdb..d7960f901a 100644 --- a/source4/libcli/ldap/ldap_client.c +++ b/source4/libcli/ldap/ldap_client.c @@ -77,6 +77,12 @@ static void ldap_connection_dead(struct ldap_connection *conn) { struct ldap_request *req; + talloc_free(conn->sock); /* this will also free event.fde */ + talloc_free(conn->packet); + conn->sock = NULL; + conn->event.fde = NULL; + conn->packet = NULL; + /* return an error for any pending request ... */ while (conn->pending) { req = conn->pending; @@ -87,12 +93,6 @@ static void ldap_connection_dead(struct ldap_connection *conn) req->async.fn(req); } } - - talloc_free(conn->sock); /* this will also free event.fde */ - talloc_free(conn->packet); - conn->sock = NULL; - conn->event.fde = NULL; - conn->packet = NULL; } static void ldap_reconnect(struct ldap_connection *conn); @@ -400,6 +400,7 @@ static void ldap_connect_got_sock(struct composite_context *ctx, talloc_steal(conn, conn->sock); if (conn->ldaps) { struct socket_context *tls_socket; + struct socket_context *tmp_socket; char *cafile = private_path(conn->sock, conn->lp_ctx, lp_tls_cafile(conn->lp_ctx)); if (!cafile || !*cafile) { @@ -414,9 +415,11 @@ static void ldap_connect_got_sock(struct composite_context *ctx, talloc_free(conn->sock); return; } - talloc_unlink(conn, conn->sock); - conn->sock = tls_socket; - talloc_steal(conn, conn->sock); + + /* the original socket, must become a child of the tls socket */ + tmp_socket = conn->sock; + conn->sock = talloc_steal(conn, tls_socket); + talloc_steal(conn->sock, tmp_socket); } conn->packet = packet_init(conn); |