Fix more valgrind issues.
[samba.git] / source4 / ldap_server / ldap_backend.c
index de99280ded60df63725946a6c22676449ea6d1be..9b43d7bd742ca757cc76089d1ab5c214b2bb60fe 100644 (file)
@@ -5,7 +5,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -14,8 +14,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "libcli/ldap/ldap.h"
 #include "lib/ldb/include/ldb.h"
 #include "lib/ldb/include/ldb_errors.h"
-#include "lib/db_wrap.h"
+#include "lib/ldb_wrap.h"
 #include "auth/credentials/credentials.h"
 #include "auth/gensec/gensec.h"
+#include "param/param.h"
 
 #define VALID_DN_SYNTAX(dn,i) do {\
        if (!(dn)) {\
@@ -55,7 +55,10 @@ static int map_ldb_error(struct ldb_context *ldb, int err, const char **errstrin
 */
 NTSTATUS ldapsrv_backend_Init(struct ldapsrv_connection *conn) 
 {
-       conn->ldb = ldb_wrap_connect(conn, lp_sam_url(), conn->session_info,
+       conn->ldb = ldb_wrap_connect(conn, 
+                                    conn->lp_ctx,
+                                    lp_sam_url(conn->lp_ctx), 
+                                    conn->session_info,
                                     NULL, conn->global_catalog ? LDB_FLG_RDONLY : 0, NULL);
        if (conn->ldb == NULL) {
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
@@ -64,10 +67,8 @@ NTSTATUS ldapsrv_backend_Init(struct ldapsrv_connection *conn)
        if (conn->server_credentials) {
                char **sasl_mechs = NULL;
                struct gensec_security_ops **backends = gensec_security_all();
-               enum credentials_use_kerberos use_kerberos
-                       = cli_credentials_get_kerberos_state(conn->server_credentials);
                struct gensec_security_ops **ops
-                       = gensec_use_kerberos_mechs(conn, backends, use_kerberos);
+                       = gensec_use_kerberos_mechs(conn, backends, conn->server_credentials);
                int i, j = 0;
                for (i = 0; ops && ops[i]; i++) {
                        if (ops[i]->sasl_name && ops[i]->server_start) {
@@ -90,10 +91,6 @@ NTSTATUS ldapsrv_backend_Init(struct ldapsrv_connection *conn)
                ldb_set_opaque(conn->ldb, "supportedSASLMechanims", sasl_mechs);
        }
 
-       if (conn->global_catalog) {
-               ldb_set_opaque(conn->ldb, "global_catalog", (void *)(-1));
-       }
-
        return NT_STATUS_OK;
 }
 
@@ -123,7 +120,7 @@ void ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
        DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
 }
 
-NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
+static NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
 {
        struct ldapsrv_reply *reply;
        struct ldap_ExtendedResponse *r;
@@ -160,7 +157,7 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
        struct ldb_request *lreq;
        enum ldb_scope scope = LDB_SCOPE_DEFAULT;
        const char **attrs = NULL;
-       const char *errstr = NULL;
+       const char *scope_str, *errstr = NULL;
        int success_limit = 1;
        int result = -1;
        int ldb_ret = -1;
@@ -181,25 +178,26 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
 
        switch (req->scope) {
                case LDAP_SEARCH_SCOPE_BASE:
-                       DEBUG(10,("SearchRequest: scope: [BASE]\n"));
+                       scope_str = "BASE";
                        scope = LDB_SCOPE_BASE;
                        success_limit = 0;
                        break;
                case LDAP_SEARCH_SCOPE_SINGLE:
-                       DEBUG(10,("SearchRequest: scope: [ONE]\n"));
+                       scope_str = "ONE";
                        scope = LDB_SCOPE_ONELEVEL;
                        success_limit = 0;
                        break;
                case LDAP_SEARCH_SCOPE_SUB:
-                       DEBUG(10,("SearchRequest: scope: [SUB]\n"));
+                       scope_str = "SUB";
                        scope = LDB_SCOPE_SUBTREE;
                        success_limit = 0;
                        break;
                default:
                        result = LDAP_PROTOCOL_ERROR;
                        errstr = "Invalid scope";
-                       break;
+                       goto reply;
        }
+       DEBUG(10,("SearchRequest: scope: [%s]\n", scope_str));
 
        if (req->num_attributes >= 1) {
                attrs = talloc_array(local_ctx, const char *, req->num_attributes+1);
@@ -212,15 +210,12 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
                attrs[i] = NULL;
        }
 
-       DEBUG(5,("ldb_request dn=%s filter=%s\n", 
-                req->basedn, ldb_filter_from_tree(call, req->tree)));
+       DEBUG(5,("ldb_request %s dn=%s filter=%s\n", 
+                scope_str, req->basedn, ldb_filter_from_tree(call, req->tree)));
 
        lreq = talloc(local_ctx, struct ldb_request);
        NT_STATUS_HAVE_NO_MEMORY(lreq);
 
-       res = talloc_zero(local_ctx, struct ldb_result);
-       NT_STATUS_HAVE_NO_MEMORY(res);
-       
        lreq->operation = LDB_SEARCH;
        lreq->op.search.base = basedn;
        lreq->op.search.scope = scope;
@@ -229,6 +224,24 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
 
        lreq->controls = call->request->controls;
 
+       if (call->conn->global_catalog) {
+               struct ldb_control *search_control = ldb_request_get_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID);
+               
+               struct ldb_search_options_control *search_options = NULL;
+               if (search_control) {
+                       search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
+                       search_options->search_options |= LDB_SEARCH_OPTION_PHANTOM_ROOT;
+               } else {
+                       search_options = talloc(lreq, struct ldb_search_options_control);
+                       NT_STATUS_HAVE_NO_MEMORY(search_options);
+                       search_options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
+                       ldb_request_add_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID, false, search_options);
+               }
+       }
+
+       res = talloc_zero(lreq, struct ldb_result);
+       NT_STATUS_HAVE_NO_MEMORY(res);
+       
        lreq->context = res;
        lreq->callback = ldb_search_default_callback;
 
@@ -248,8 +261,13 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
                        ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
                        NT_STATUS_HAVE_NO_MEMORY(ent_r);
 
+                       /* Better to have the whole message kept here,
+                        * than to find someone further up didn't put
+                        * a value in the right spot in the talloc tree */
+                       talloc_steal(ent_r, res->msgs[i]);
+                       
                        ent = &ent_r->msg->r.SearchResultEntry;
-                       ent->dn = ldb_dn_linearize(ent_r, res->msgs[i]->dn);
+                       ent->dn = ldb_dn_alloc_linearized(ent_r, res->msgs[i]->dn);
                        ent->num_attributes = 0;
                        ent->attributes = NULL;
                        if (res->msgs[i]->num_elements == 0) {
@@ -288,10 +306,6 @@ reply:
                        DEBUG(10,("SearchRequest: results: [%d]\n", res->count));
                        result = LDAP_SUCCESS;
                        errstr = NULL;
-               } else if (res->count == 0) {
-                       DEBUG(10,("SearchRequest: no results\n"));
-                       result = LDAP_NO_SUCH_OBJECT;
-                       errstr = ldb_errstring(samdb);
                }
                if (res->controls) {
                        done_r->msg->controls = res->controls;
@@ -340,7 +354,6 @@ static NTSTATUS ldapsrv_ModifyRequest(struct ldapsrv_call *call)
        NT_STATUS_HAVE_NO_MEMORY(msg);
 
        msg->dn = dn;
-       msg->private_data = NULL;
        msg->num_elements = 0;
        msg->elements = NULL;
 
@@ -444,7 +457,6 @@ static NTSTATUS ldapsrv_AddRequest(struct ldapsrv_call *call)
        NT_STATUS_HAVE_NO_MEMORY(msg);
 
        msg->dn = dn;
-       msg->private_data = NULL;
        msg->num_elements = 0;
        msg->elements = NULL;
 
@@ -612,6 +624,7 @@ static NTSTATUS ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
                result = LDAP_OTHER;
                goto reply;
        }
+       newdn = parentdn;
 
 reply:
        modifydn_r = ldapsrv_init_reply(call, LDAP_TAG_ModifyDNResponse);
@@ -713,6 +726,18 @@ static NTSTATUS ldapsrv_AbandonRequest(struct ldapsrv_call *call)
 
 NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
 {
+       int i;
+       struct ldap_message *msg = call->request;
+       /* Check for undecoded critical extensions */
+       for (i=0; msg->controls && msg->controls[i]; i++) {
+               if (!msg->controls_decoded[i] && 
+                   msg->controls[i]->critical) {
+                       DEBUG(3, ("ldapsrv_do_call: Critical extension %s is not known to this server\n",
+                                 msg->controls[i]->oid));
+                       return ldapsrv_unwilling(call, LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
+               }
+       }
+
        switch(call->request->type) {
        case LDAP_TAG_BindRequest:
                return ldapsrv_BindRequest(call);