Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-gmake3
authorJelmer Vernooij <jelmer@samba.org>
Mon, 3 Mar 2008 09:50:53 +0000 (10:50 +0100)
committerJelmer Vernooij <jelmer@samba.org>
Mon, 3 Mar 2008 09:50:53 +0000 (10:50 +0100)
Conflicts:

source/Makefile
source/build/smb_build/makefile.pm
source/librpc/config.mk
(This used to be commit 3e02fcfd3fb6683f51417ba39f4ec177494eff3e)

26 files changed:
source4/Makefile
source4/build/smb_build/makefile.pm
source4/cluster/ctdb/opendb_ctdb.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/ldb.i
source4/lib/ldb/ldb_wrap.c
source4/lib/registry/dir.c
source4/lib/registry/ldb.c
source4/lib/registry/regf.c
source4/lib/registry/tests/hive.c
source4/librpc/config.mk
source4/ntvfs/common/opendb.c
source4/ntvfs/common/opendb.h
source4/ntvfs/common/opendb_tdb.c
source4/ntvfs/posix/pvfs_open.c
source4/ntvfs/posix/pvfs_qfileinfo.c
source4/ntvfs/posix/pvfs_rename.c
source4/ntvfs/posix/pvfs_resolve.c
source4/ntvfs/posix/pvfs_setfileinfo.c
source4/samba4-knownfail
source4/scripting/python/samba/__init__.py
source4/scripting/python/samba/provision.py
source4/selftest/target/Samba4.pm
source4/torture/raw/chkpath.c
source4/torture/raw/setfileinfo.c
source4/torture/rpc/winreg.c

index 65f8c2de29e35358b51d451b8bfa9143ec5f2020..859d168a6fc0078dddc2c3e32de78430f8ad7f01 100644 (file)
@@ -22,6 +22,13 @@ HOSTLD_FLAGS = $(LDFLAGS) $(SYS_LDFLAGS)
 $(srcdir)/version.h: $(srcdir)/VERSION
        @$(SHELL) script/mkversion.sh VERSION $(srcdir)/version.h $(srcdir)/
 
+.DEFAULT_GOAL := all
+
+ifneq ($(automatic_deps),yes)
+ALL_PREDEP = proto
+.NOTPARALLEL:
+endif
+
 regen_version::
        @$(SHELL) script/mkversion.sh VERSION $(srcdir)/version.h $(srcdir)/
 
index 9aa4e409bd6fcdfe0d6b4fc8060998267de02f57..b889a84718c1613486ad099c104faee60b892a8c 100644 (file)
@@ -350,8 +350,7 @@ sub CFlags($$)
        
        my $cflags = join(' ', @cflags);
 
-       my $ext = "o";
-       $self->output("\$($key->{NAME}_OBJ_LIST) \$(patsubst %.ho,%.d,\$($key->{NAME}_OBJ_LIST:.o=.d)): CFLAGS+=$cflags\n");
+       $self->output("\$(patsubst %.ho,%.d,\$(key->{NAME}_OBJ_LIST:.o=.d)) \$($key->{NAME}_OBJ_LIST): CFLAGS+= $cflags\n");
 }
 
 1;
index 3d67162d6dae2360bc7517f590542d99dd48c2e3..e84f2364d40f183791f8b3052688bee7a82a8481 100644 (file)
@@ -542,6 +542,25 @@ static NTSTATUS odb_ctdb_rename(struct odb_lock *lck, const char *path)
        return odb_push_record(lck, &file);
 }
 
+/*
+  get the path of an open file
+*/
+static NTSTATUS odb_ctdb_get_path(struct odb_lock *lck, const char **path)
+{
+       struct opendb_file file;
+       NTSTATUS status;
+
+       *path = NULL;
+
+       status = odb_pull_record(lck, &file);
+       /* we don't ignore NT_STATUS_OBJECT_NAME_NOT_FOUND here */
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       *path = file.path;
+
+       return NT_STATUS_OK;
+}
+
 /*
   update delete on close flag on an open file
 */
@@ -653,6 +672,7 @@ static const struct opendb_ops opendb_ctdb_ops = {
        .odb_close_file          = odb_ctdb_close_file,
        .odb_remove_pending      = odb_ctdb_remove_pending,
        .odb_rename              = odb_ctdb_rename,
+       .odb_get_path            = odb_ctdb_get_path,
        .odb_set_delete_on_close = odb_ctdb_set_delete_on_close,
        .odb_get_delete_on_close = odb_ctdb_get_delete_on_close,
        .odb_can_open            = odb_ctdb_can_open,
index 2e54920c17eaa7f25ea1906bc26af47cf1a21e7a..2e13a774b987f01ec1fbf603327694668048bb53 100644 (file)
@@ -290,7 +290,7 @@ char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, struct ldb_parse_tree *tree);
    2254 (Section 4). This function also escapes any non-printable
    characters.
 
-   \param ctx the memory context to allocate the return string in.
+   \param mem_ctx the memory context to allocate the return string in.
    \param val the (potentially) binary data to be encoded
 
    \return the encoded data as a null terminated string
@@ -886,7 +886,7 @@ int ldb_search_default_callback(struct ldb_context *ldb, void *context, struct l
   \param attrs the search attributes for the query (pass NULL if none required)
   \param controls an array of controls
   \param context the callback function context
-  \param the callback function to handle the async replies
+  \param callback the callback function to handle the async replies
 
   \return result code (LDB_SUCCESS on success, or a failure code)
 */
@@ -911,7 +911,7 @@ int ldb_build_search_req(struct ldb_request **ret_req,
   \param message contains the entry to be added 
   \param controls an array of controls
   \param context the callback function context
-  \param the callback function to handle the async replies
+  \param callback the callback function to handle the async replies
 
   \return result code (LDB_SUCCESS on success, or a failure code)
 */
@@ -933,7 +933,7 @@ int ldb_build_add_req(struct ldb_request **ret_req,
   \param message contains the entry to be modified
   \param controls an array of controls
   \param context the callback function context
-  \param the callback function to handle the async replies
+  \param callback the callback function to handle the async replies
 
   \return result code (LDB_SUCCESS on success, or a failure code)
 */
@@ -955,7 +955,7 @@ int ldb_build_mod_req(struct ldb_request **ret_req,
   \param dn the DN to be deleted
   \param controls an array of controls
   \param context the callback function context
-  \param the callback function to handle the async replies
+  \param callback the callback function to handle the async replies
 
   \return result code (LDB_SUCCESS on success, or a failure code)
 */
@@ -978,7 +978,7 @@ int ldb_build_del_req(struct ldb_request **ret_req,
   \param newdn the new DN
   \param controls an array of controls
   \param context the callback function context
-  \param the callback function to handle the async replies
+  \param callback the callback function to handle the async replies
 
   \return result code (LDB_SUCCESS on success, or a failure code)
 */
@@ -997,7 +997,7 @@ int ldb_build_rename_req(struct ldb_request **ret_req,
 
   \param req the request struct where to add the control
   \param oid the object identifier of the control as string
-  \param ciritical whether the control should be critical or not
+  \param critical whether the control should be critical or not
   \param data a talloc pointer to the control specific data
 
   \return result code (LDB_SUCCESS on success, or a failure code)
@@ -1137,7 +1137,7 @@ int ldb_extended_default_callback(struct ldb_context *ldb, void *context, struct
   it needs to be NULL or a valid talloc pointer! talloc_get_type() will be used on it  
   \param controls an array of controls
   \param context the callback function context
-  \param the callback function to handle the async replies
+  \param callback the callback function to handle the async replies
 
   \return result code (LDB_SUCCESS on success, or a failure code)
 */
@@ -1226,6 +1226,7 @@ int ldb_valid_attr_name(const char *s);
 /*
   ldif manipulation functions
 */
+
 /**
    Write an LDIF message
 
@@ -1418,8 +1419,8 @@ bool ldb_dn_is_null(struct ldb_dn *dn);
    This function compares to attribute names. Note that this is a
    case-insensitive comparison.
 
-   \param attr1 the first attribute name to compare
-   \param attr2 the second attribute name to compare
+   \param a the first attribute name to compare
+   \param b the second attribute name to compare
 
    \return 0 if the attribute names are the same, or only differ in
    case; non-zero if there are any differences
@@ -1562,6 +1563,7 @@ int ldb_msg_check_string_attribute(const struct ldb_message *msg,
    This function performs basic sanity / integrity checks on an
    ldb_message.
 
+   \param ldb context in which to perform the checks
    \param msg the message to check
 
    \return LDB_SUCCESS if the message is OK, or a non-zero error code
index 336100c4f0a8bbfad118e67f2016f89b98301c0b..da4c52f77831583ee794cd9f5a6ba4cbff413933 100644 (file)
@@ -547,6 +547,43 @@ PyObject *PyExc_LdbError;
     talloc_free($1);
 };
 
+%typemap(in,numinputs=1) ldb_msg *add_msg {
+    int dict_pos, msg_pos;
+    PyObject *key, *value;
+    ldb_msg_element *msgel;
+
+    if (PyDict_Check($input)) {
+        $1 = ldb_msg_new(NULL);
+        $1->elements = talloc_zero_array($1, struct ldb_message_element, PyDict_Size($input));
+        msg_pos = dict_pos = 0;
+        while (PyDict_Next($input, &dict_pos, &key, &value)) {
+            if (!strcmp(PyString_AsString(key), "dn")) {
+                /* using argp0 (magic SWIG value) here is a hack */
+                if (ldb_dn_from_pyobject($1, value, argp1, &$1->dn) != 0) {
+                    SWIG_exception(SWIG_TypeError, "unable to import dn object");
+                }
+            } else {
+                msgel = ldb_msg_element_from_pyobject($1->elements, value, 0, PyString_AsString(key));
+                if (msgel == NULL) {
+                    SWIG_exception(SWIG_TypeError, "unable to import element");
+                }
+                memcpy(&$1->elements[msg_pos], msgel, sizeof(*msgel));
+                msg_pos++;
+            }
+        }
+
+        if ($1->dn == NULL) {
+            SWIG_exception(SWIG_TypeError, "no dn set");
+        }
+
+        $1->num_elements = msg_pos;
+    } else {
+        if (SWIG_ConvertPtr($input, (void **)&$1, SWIGTYPE_p_ldb_message, 0) != 0) {
+            SWIG_exception(SWIG_TypeError, "unable to convert ldb message");
+        }
+    }
+}
+
 /* Top-level ldb operations */
 typedef struct ldb_context {
     %extend {
@@ -604,53 +641,6 @@ typedef struct ldb_context {
         struct ldb_control **parse_control_strings(TALLOC_CTX *mem_ctx, 
                                                    const char * const*control_strings);
         ldb_error add(ldb_msg *add_msg);
-        ldb_error add(PyObject *py_msg) 
-        {
-            ldb_error ret;
-            int dict_pos, msg_pos;
-            PyObject *key, *value;
-            ldb_msg_element *msgel;
-            ldb_msg *msg = NULL;
-
-            if (PyDict_Check(py_msg)) {
-                msg = ldb_msg_new(NULL);
-                msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_msg));
-                msg_pos = dict_pos = 0;
-                while (PyDict_Next(py_msg, &dict_pos, &key, &value)) {
-                    if (!strcmp(PyString_AsString(key), "dn")) {
-                        if (ldb_dn_from_pyobject(msg, value, $self, &msg->dn) != 0) {
-                            return LDB_ERR_OTHER;
-                        }
-                    } else {
-                        msgel = ldb_msg_element_from_pyobject(msg->elements, value, 0, PyString_AsString(key));
-                        if (msgel == NULL) {
-                            SWIG_exception(SWIG_TypeError, "unable to import element");
-                            return LDB_ERR_OTHER;
-                        }
-                        memcpy(&msg->elements[msg_pos], msgel, sizeof(*msgel));
-                        msg_pos++;
-                    }
-                }
-
-                if (msg->dn == NULL) {
-                    SWIG_exception(SWIG_TypeError, "no dn set");
-                    return LDB_ERR_OTHER;
-                }
-
-                msg->num_elements = msg_pos;
-            } else {
-                if (SWIG_ConvertPtr(py_msg, (void **)&msg, SWIGTYPE_p_ldb_message, 0) != 0)
-                    return LDB_ERR_OTHER;
-            }
-
-            ret = ldb_add($self, msg);
-
-            talloc_free(msg);
-            return ret;
-
-            fail:
-            return LDB_ERR_OTHER;
-        }
         ldb_error modify(ldb_msg *message);
         ldb_dn *get_config_basedn();
         ldb_dn *get_root_basedn();
index 51022e5930e2e2980e574636f0281481c973c2ce..7886778b3a79238b535aa122af35a9cabcdd24fc 100644 (file)
@@ -3113,52 +3113,6 @@ SWIGINTERN ldb_error ldb_search_ex(ldb *self,TALLOC_CTX *mem_ctx,ldb_dn *base,en
             *OUT = res;
             return ret;
         }
-SWIGINTERN ldb_error ldb_add__SWIG_1(ldb *self,PyObject *py_msg){
-            ldb_error ret;
-            int dict_pos, msg_pos;
-            PyObject *key, *value;
-            ldb_msg_element *msgel;
-            ldb_msg *msg = NULL;
-
-            if (PyDict_Check(py_msg)) {
-                msg = ldb_msg_new(NULL);
-                msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_msg));
-                msg_pos = dict_pos = 0;
-                while (PyDict_Next(py_msg, &dict_pos, &key, &value)) {
-                    if (!strcmp(PyString_AsString(key), "dn")) {
-                        if (ldb_dn_from_pyobject(msg, value, self, &msg->dn) != 0) {
-                            return 80;
-                        }
-                    } else {
-                        msgel = ldb_msg_element_from_pyobject(msg->elements, value, 0, PyString_AsString(key));
-                        if (msgel == NULL) {
-                            SWIG_exception(SWIG_TypeError, "unable to import element");
-                            return 80;
-                        }
-                        memcpy(&msg->elements[msg_pos], msgel, sizeof(*msgel));
-                        msg_pos++;
-                    }
-                }
-
-                if (msg->dn == NULL) {
-                    SWIG_exception(SWIG_TypeError, "no dn set");
-                    return 80;
-                }
-
-                msg->num_elements = msg_pos;
-            } else {
-                if (SWIG_ConvertPtr(py_msg, (void **)&msg, SWIGTYPE_p_ldb_message, 0) != 0)
-                    return 80;
-            }
-
-            ret = ldb_add(self, msg);
-
-            talloc_free(msg);
-            return ret;
-
-            fail:
-            return 80;
-        }
 SWIGINTERN PyObject *ldb_schema_format_value(ldb *self,char const *element_name,PyObject *val){
                const struct ldb_schema_attribute *a;
                struct ldb_val old_val;
@@ -4733,27 +4687,61 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Ldb_add__SWIG_0(PyObject *SWIGUNUSEDPARM(self), int nobjs, PyObject **swig_obj) {
+SWIGINTERN PyObject *_wrap_Ldb_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   ldb *arg1 = (ldb *) 0 ;
   ldb_msg *arg2 = (ldb_msg *) 0 ;
   ldb_error result;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "add_msg", NULL 
+  };
   
-  if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ldb_context, 0 |  0 );
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:Ldb_add",kwnames,&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Ldb_add" "', argument " "1"" of type '" "ldb *""'"); 
   }
   arg1 = (ldb *)(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_ldb_message, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Ldb_add" "', argument " "2"" of type '" "ldb_msg *""'"); 
+  {
+    int dict_pos, msg_pos;
+    PyObject *key, *value;
+    ldb_msg_element *msgel;
+    
+    if (PyDict_Check(obj1)) {
+      arg2 = ldb_msg_new(NULL);
+      arg2->elements = talloc_zero_array(arg2, struct ldb_message_element, PyDict_Size(obj1));
+      msg_pos = dict_pos = 0;
+      while (PyDict_Next(obj1, &dict_pos, &key, &value)) {
+        if (!strcmp(PyString_AsString(key), "dn")) {
+          /* using argp0 (magic SWIG value) here is a hack */
+          if (ldb_dn_from_pyobject(arg2, value, argp1, &arg2->dn) != 0) {
+            SWIG_exception(SWIG_TypeError, "unable to import dn object");
+          }
+        } else {
+          msgel = ldb_msg_element_from_pyobject(arg2->elements, value, 0, PyString_AsString(key));
+          if (msgel == NULL) {
+            SWIG_exception(SWIG_TypeError, "unable to import element");
+          }
+          memcpy(&arg2->elements[msg_pos], msgel, sizeof(*msgel));
+          msg_pos++;
+        }
+      }
+      
+      if (arg2->dn == NULL) {
+        SWIG_exception(SWIG_TypeError, "no dn set");
+      }
+      
+      arg2->num_elements = msg_pos;
+    } else {
+      if (SWIG_ConvertPtr(obj1, (void **)&arg2, SWIGTYPE_p_ldb_message, 0) != 0) {
+        SWIG_exception(SWIG_TypeError, "unable to convert ldb message");
+      }
+    }
   }
-  arg2 = (ldb_msg *)(argp2);
   if (arg1 == NULL)
   SWIG_exception(SWIG_ValueError, 
     "ldb context must be non-NULL");
@@ -4772,64 +4760,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Ldb_add__SWIG_1(PyObject *SWIGUNUSEDPARM(self), int nobjs, PyObject **swig_obj) {
-  PyObject *resultobj = 0;
-  ldb *arg1 = (ldb *) 0 ;
-  PyObject *arg2 = (PyObject *) 0 ;
-  ldb_error result;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  
-  if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ldb_context, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Ldb_add" "', argument " "1"" of type '" "ldb *""'"); 
-  }
-  arg1 = (ldb *)(argp1);
-  arg2 = swig_obj[1];
-  if (arg1 == NULL)
-  SWIG_exception(SWIG_ValueError, 
-    "ldb context must be non-NULL");
-  result = ldb_add__SWIG_1(arg1,arg2);
-  if (result != 0) {
-    PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", result, ldb_strerror(result)));
-    SWIG_fail;
-  }
-  resultobj = Py_None;
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Ldb_add(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  
-  if (!(argc = SWIG_Python_UnpackTuple(args,"Ldb_add",0,2,argv))) SWIG_fail;
-  --argc;
-  if (argc == 2) {
-    int _v = 0;
-    {
-      void *vptr = 0;
-      int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_ldb_message, 0);
-      _v = SWIG_CheckState(res);
-    }
-    if (!_v) goto check_1;
-    return _wrap_Ldb_add__SWIG_0(self, argc, argv);
-  }
-check_1:
-  
-  if (argc == 2) {
-    return _wrap_Ldb_add__SWIG_1(self, argc, argv);
-  }
-  
-fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Ldb_add'.\n  Possible C/C++ prototypes are:\n""    add(ldb *,ldb_msg *)\n""    add(ldb *,PyObject *)\n");
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_Ldb_modify(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   ldb *arg1 = (ldb *) 0 ;
@@ -5729,7 +5659,7 @@ static PyMethodDef SwigMethods[] = {
         { (char *)"Ldb_delete", (PyCFunction) _wrap_Ldb_delete, METH_VARARGS | METH_KEYWORDS, NULL},
         { (char *)"Ldb_rename", (PyCFunction) _wrap_Ldb_rename, METH_VARARGS | METH_KEYWORDS, NULL},
         { (char *)"Ldb_parse_control_strings", (PyCFunction) _wrap_Ldb_parse_control_strings, METH_VARARGS | METH_KEYWORDS, NULL},
-        { (char *)"Ldb_add", _wrap_Ldb_add, METH_VARARGS, NULL},
+        { (char *)"Ldb_add", (PyCFunction) _wrap_Ldb_add, METH_VARARGS | METH_KEYWORDS, NULL},
         { (char *)"Ldb_modify", (PyCFunction) _wrap_Ldb_modify, METH_VARARGS | METH_KEYWORDS, NULL},
         { (char *)"Ldb_get_config_basedn", (PyCFunction)_wrap_Ldb_get_config_basedn, METH_O, NULL},
         { (char *)"Ldb_get_root_basedn", (PyCFunction)_wrap_Ldb_get_root_basedn, METH_O, NULL},
index 27cae8c49062ed9ba1ba670f47f3bc594b422763..dc3717e88614e80e312df946033bf00a2a33d866 100644 (file)
@@ -55,18 +55,66 @@ static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx,
        return WERR_GENERAL_FAILURE;
 }
 
+static WERROR reg_dir_delete_recursive(const char *name)
+{
+       DIR *d;
+       struct dirent *e;
+       WERROR werr;
+
+       d = opendir(name);
+       if (d == NULL) {
+               DEBUG(3,("Unable to open '%s': %s\n", name,
+                     strerror(errno)));
+               return WERR_BADFILE;
+       }
+
+       while((e = readdir(d))) {
+               char *path;
+               struct stat stbuf;
+
+               if (ISDOT(e->d_name) || ISDOTDOT(e->d_name))
+                       continue;
+
+               path = talloc_asprintf(name, "%s/%s", name, e->d_name);
+               if (!path)
+                       return WERR_NOMEM;
+
+               stat(path, &stbuf);
+
+               if (!S_ISDIR(stbuf.st_mode)) {
+                       if (unlink(path) < 0) {
+                               talloc_free(path);
+                               closedir(d);
+                               return WERR_GENERAL_FAILURE;
+                       }
+               } else {
+                       werr = reg_dir_delete_recursive(path);
+                       if (!W_ERROR_IS_OK(werr)) {
+                               talloc_free(path);
+                               closedir(d);
+                               return werr;
+                       }
+               }
+
+               talloc_free(path);
+       }
+       closedir(d);
+
+       if (rmdir(name) == 0)
+               return WERR_OK;
+       else if (errno == ENOENT)
+               return WERR_BADFILE;
+       else
+               return WERR_GENERAL_FAILURE;
+}
+
 static WERROR reg_dir_del_key(const struct hive_key *k, const char *name)
 {
        struct dir_key *dk = talloc_get_type(k, struct dir_key);
        char *child = talloc_asprintf(NULL, "%s/%s", dk->path, name);
        WERROR ret;
 
-       if (rmdir(child) == 0)
-               ret = WERR_OK;
-       else if (errno == ENOENT)
-               ret = WERR_BADFILE;
-       else
-               ret = WERR_GENERAL_FAILURE;
+       ret = reg_dir_delete_recursive(child);
 
        talloc_free(child);
 
index dfd368ea80d06c588a14a3d2eaf3c7a0491dc033..a764ca6235322885b4d4049f4a0cfb2d66f41d72 100644 (file)
@@ -442,33 +442,6 @@ static WERROR ldb_add_key(TALLOC_CTX *mem_ctx, const struct hive_key *parent,
        return WERR_OK;
 }
 
-static WERROR ldb_del_key(const struct hive_key *key, const char *name)
-{
-       int ret;
-       struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
-       struct ldb_dn *ldap_path;
-       TALLOC_CTX *mem_ctx = talloc_init("ldb_del_key");
-
-       ldap_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
-
-       ret = ldb_delete(parentkd->ldb, ldap_path);
-
-       talloc_free(mem_ctx);
-
-       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
-               return WERR_BADFILE;
-       } else if (ret != LDB_SUCCESS) {
-               DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(parentkd->ldb)));
-               return WERR_FOOBAR;
-       }
-
-       /* reset cache */
-       talloc_free(parentkd->subkeys);
-       parentkd->subkeys = NULL;
-
-       return WERR_OK;
-}
-
 static WERROR ldb_del_value (struct hive_key *key, const char *child)
 {
        int ret;
@@ -501,6 +474,122 @@ static WERROR ldb_del_value (struct hive_key *key, const char *child)
        return WERR_OK;
 }
 
+static WERROR ldb_del_key(const struct hive_key *key, const char *name)
+{
+       int i, ret;
+       struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
+       struct ldb_dn *ldap_path;
+       TALLOC_CTX *mem_ctx = talloc_init("ldb_del_key");
+       struct ldb_context *c = parentkd->ldb;
+       struct ldb_result *res_keys;
+       struct ldb_result *res_vals;
+       WERROR werr;
+       struct hive_key *hk;
+
+       /* Verify key exists by opening it */
+       werr = ldb_open_key(mem_ctx, key, name, &hk);
+       if (!W_ERROR_IS_OK(werr)) {
+               talloc_free(mem_ctx);
+               return werr;
+       }
+
+       ldap_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
+       if (!ldap_path) {
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       /* Search for subkeys */
+       ret = ldb_search(c, ldap_path, LDB_SCOPE_ONELEVEL,
+                        "(key=*)", NULL, &res_keys);
+
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0, ("Error getting subkeys for '%s': %s\n",
+                     ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       /* Search for values */
+       ret = ldb_search(c, ldap_path, LDB_SCOPE_ONELEVEL,
+                        "(value=*)", NULL, &res_vals);
+
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0, ("Error getting values for '%s': %s\n",
+                     ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       /* Start an explicit transaction */
+       ret = ldb_transaction_start(c);
+
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0, ("ldb_transaction_start: %s\n", ldb_errstring(c)));
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       if (res_keys->count || res_vals->count)
+       {
+               /* Delete any subkeys */
+               for (i = 0; i < res_keys->count; i++)
+               {
+                       werr = ldb_del_key(hk, ldb_msg_find_attr_as_string(
+                                                       res_keys->msgs[i],
+                                                       "key", NULL));
+                       if (!W_ERROR_IS_OK(werr)) {
+                               ret = ldb_transaction_cancel(c);
+                               talloc_free(mem_ctx);
+                               return werr;
+                       }
+               }
+
+               /* Delete any values */
+               for (i = 0; i < res_vals->count; i++)
+               {
+                       werr = ldb_del_value(hk, ldb_msg_find_attr_as_string(
+                                                       res_vals->msgs[i],
+                                                       "value", NULL));
+                       if (!W_ERROR_IS_OK(werr)) {
+                               ret = ldb_transaction_cancel(c);
+                               talloc_free(mem_ctx);
+                               return werr;
+                       }
+               }
+       }
+
+       /* Delete the key itself */
+       ret = ldb_delete(c, ldap_path);
+
+       if (ret != LDB_SUCCESS)
+       {
+               DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(c)));
+               ret = ldb_transaction_cancel(c);
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       /* Commit the transaction */
+       ret = ldb_transaction_commit(c);
+
+       if (ret != LDB_SUCCESS)
+       {
+               DEBUG(0, ("ldb_transaction_commit: %s\n", ldb_errstring(c)));
+               ret = ldb_transaction_cancel(c);
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       talloc_free(mem_ctx);
+
+       /* reset cache */
+       talloc_free(parentkd->subkeys);
+       parentkd->subkeys = NULL;
+
+       return WERR_OK;
+}
+
 static WERROR ldb_set_value(struct hive_key *parent,
                            const char *name, uint32_t type,
                            const DATA_BLOB data)
index cf3e564c0e2c6d1369dd33eb39a9d66eae445ec7..a192f3be4ddc14c656435552d22ce3b0ed7d356a 100644 (file)
@@ -1618,10 +1618,55 @@ static WERROR regf_del_key(const struct hive_key *parent, const char *name)
                return WERR_BADFILE;
        }
 
-       if (key->nk->subkeys_offset != -1 ||
-               key->nk->values_offset != -1) {
-               DEBUG(0, ("Key '%s' is not empty.\n", name));
-               return WERR_FILE_EXISTS;
+       if (key->nk->subkeys_offset != -1) {
+               char *sk_name;
+               struct hive_key *sk = (struct hive_key *)key;
+               int i = key->nk->num_subkeys;
+               while (i--) {
+                       /* Get subkey information. */
+                       error = regf_get_subkey_by_index(parent_nk, sk, 0,
+                                                        (const char **)&sk_name,
+                                                        NULL, NULL);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't retrieve subkey by index.\n"));
+                               return error;
+                       }
+
+                       /* Delete subkey. */
+                       error = regf_del_key(sk, sk_name);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't delete key '%s'.\n", sk_name));
+                               return error;
+                       }
+
+                       talloc_free(sk_name);
+               }
+       }
+
+       if (key->nk->values_offset != -1) {
+               char *val_name;
+               struct hive_key *sk = (struct hive_key *)key;
+               DATA_BLOB data;
+               int i = key->nk->num_values;
+               while (i--) {
+                       /* Get value information. */
+                       error = regf_get_value(parent_nk, sk, 0,
+                                              (const char **)&val_name,
+                                              NULL, &data);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't retrieve value by index.\n"));
+                               return error;
+                       }
+
+                       /* Delete value. */
+                       error = regf_del_value(sk, val_name);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't delete value '%s'.\n", val_name));
+                               return error;
+                       }
+
+                       talloc_free(val_name);
+               }
        }
 
        /* Delete it from the subkey list. */
index 1dcb464d8015f2b808fc2af982a6bf1fd4c33cf0..1e56f125c5d168eac047c08a69328aff48881181 100644 (file)
@@ -111,6 +111,38 @@ static bool test_add_subkey(struct torture_context *tctx,
        return true;
 }
 
+static bool test_del_recursive(struct torture_context *tctx,
+                              const void *test_data)
+{
+       WERROR error;
+       struct hive_key *subkey;
+       struct hive_key *subkey2;
+       const struct hive_key *root = (const struct hive_key *)test_data;
+       TALLOC_CTX *mem_ctx = tctx;
+       uint32_t data = 42;
+
+       /* Create a new key under the root */
+       error = hive_key_add_name(mem_ctx, root, "Parent Key", NULL,
+                                 NULL, &subkey);
+       torture_assert_werr_ok(tctx, error, "hive_key_add_name");
+
+       /* Create a new key under "Parent Key" */
+       error = hive_key_add_name(mem_ctx, subkey, "Child Key", NULL,
+                                 NULL, &subkey2);
+       torture_assert_werr_ok(tctx, error, "hive_key_add_name");
+
+       /* Create a new value under "Child Key" */
+       error = hive_key_set_value(subkey2, "Answer Recursive", REG_DWORD,
+                              data_blob_talloc(mem_ctx, &data, sizeof(data)));
+       torture_assert_werr_ok(tctx, error, "hive_key_set_value");
+
+       /* Deleting "Parent Key" will also delete "Child Key" and the value. */
+       error = hive_key_del(root, "Parent Key");
+       torture_assert_werr_ok(tctx, error, "hive_key_del");
+
+       return true;
+}
+
 static bool test_flush_key(struct torture_context *tctx, void *test_data)
 {
        struct hive_key *root = (struct hive_key *)test_data;
@@ -273,6 +305,11 @@ static void tcase_add_tests(struct torture_tcase *tcase)
                                                test_add_subkey);
        torture_tcase_add_simple_test(tcase, "flush_key",
                                                test_flush_key);
+       /* test_del_recursive() test must run before test_keyinfo_root().
+          test_keyinfo_root() checks the number of subkeys, which verifies
+          the recursive delete worked properly. */
+       torture_tcase_add_simple_test_const(tcase, "del_recursive",
+                                               test_del_recursive);
        torture_tcase_add_simple_test_const(tcase, "get_info",
                                                test_keyinfo_root);
        torture_tcase_add_simple_test(tcase, "get_info_nums",
index 8a5e1478f6a6436f6e8880bc6ff6e9cf8847edca..7abc693960e6369055ff18424603b5ccb285c3ae 100644 (file)
@@ -298,8 +298,8 @@ include librpc/idl-deps
 
 librpc/gen_ndr/tables.c: $(IDL_NDR_PARSE_H_FILES)
        @echo Generating $@
-       @$(PERL) $(srcdir)/librpc/tables.pl --output=$@ $(IDL_NDR_PARSE_H_FILES) > librpc/gen_ndr/tables.x
-       mv librpc/gen_ndr/tables.x $@
+       @$(PERL) $(srcdir)/librpc/tables.pl --output=$@ $^ > librpc/gen_ndr/tables.x
+       @mv librpc/gen_ndr/tables.x $@
 
 [SUBSYSTEM::NDR_TABLE]
 OBJ_FILES = ndr/ndr_table.o gen_ndr/tables.o
index d8cb67686b9221ff3938e7fc9e0e8b407fdf5fa9..6c1a9c070ae82426afd6d946512d3ae10c149e2b 100644 (file)
@@ -142,6 +142,14 @@ _PUBLIC_ NTSTATUS odb_rename(struct odb_lock *lck, const char *path)
        return ops->odb_rename(lck, path);
 }
 
+/*
+  get back the path of an open file
+*/
+_PUBLIC_ NTSTATUS odb_get_path(struct odb_lock *lck, const char **path)
+{
+       return ops->odb_get_path(lck, path);
+}
+
 /*
   update delete on close flag on an open file
 */
index 33f2e1c88d21a9fdf59b5e784ba5a32430de6c68..69a7f718ba6d4d14398fbfa415769696eabe71d0 100644 (file)
@@ -36,6 +36,7 @@ struct opendb_ops {
                                   const char **delete_path);
        NTSTATUS (*odb_remove_pending)(struct odb_lock *lck, void *private);
        NTSTATUS (*odb_rename)(struct odb_lock *lck, const char *path);
+       NTSTATUS (*odb_get_path)(struct odb_lock *lck, const char **path);
        NTSTATUS (*odb_set_delete_on_close)(struct odb_lock *lck, bool del_on_close);
        NTSTATUS (*odb_get_delete_on_close)(struct odb_context *odb, 
                                            DATA_BLOB *key, bool *del_on_close);
index 37c1c0850b1d9e69681d3c9a3c9b6ff6b165100f..47b35f594c61d24b4c9651b18c113dd251ba5d40 100644 (file)
@@ -713,6 +713,25 @@ static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
        return odb_push_record(lck, &file);
 }
 
+/*
+  get the path of an open file
+*/
+static NTSTATUS odb_tdb_get_path(struct odb_lock *lck, const char **path)
+{
+       struct opendb_file file;
+       NTSTATUS status;
+
+       *path = NULL;
+
+       status = odb_pull_record(lck, &file);
+       /* we don't ignore NT_STATUS_OBJECT_NAME_NOT_FOUND here */
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       *path = file.path;
+
+       return NT_STATUS_OK;
+}
+
 /*
   update delete on close flag on an open file
 */
@@ -802,6 +821,7 @@ static const struct opendb_ops opendb_tdb_ops = {
        .odb_close_file          = odb_tdb_close_file,
        .odb_remove_pending      = odb_tdb_remove_pending,
        .odb_rename              = odb_tdb_rename,
+       .odb_get_path            = odb_tdb_get_path,
        .odb_set_delete_on_close = odb_tdb_set_delete_on_close,
        .odb_get_delete_on_close = odb_tdb_get_delete_on_close,
        .odb_can_open            = odb_tdb_can_open,
index 740a0a9d13626f3e3774f604c90700b9da4f9ac9..adf4c1ac185080f4a8f7a7d629aeea9dd6e29de9 100644 (file)
@@ -144,8 +144,8 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs,
   form the lock context used for opendb locking. Note that we must
   zero here to take account of possible padding on some architectures
 */
-static NTSTATUS pvfs_locking_key(struct pvfs_filename *name, 
-                                TALLOC_CTX *mem_ctx, DATA_BLOB *key)
+NTSTATUS pvfs_locking_key(struct pvfs_filename *name,
+                         TALLOC_CTX *mem_ctx, DATA_BLOB *key)
 {
        struct {
                dev_t device;
index 6ed729541f03ebe6a748a9a1492dbf8561309daf..6bc21e5e3e90a507b101cc9deb3cdc68e9121564 100644 (file)
@@ -368,7 +368,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
        }
 
        /* update the file information */
-       status = pvfs_resolve_name_fd(pvfs, h->fd, h->name);
+       status = pvfs_resolve_name_handle(pvfs, h);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
index 185e35f8007268f58c28726b0217c05f244e5954..29b2d030059a2ca5e8a110de8c0cc559308e2f7f 100644 (file)
 /*
   do a file rename, and send any notify triggers
 */
-NTSTATUS pvfs_do_rename(struct pvfs_state *pvfs, const struct pvfs_filename *name1, 
+NTSTATUS pvfs_do_rename(struct pvfs_state *pvfs,
+                       struct odb_lock *lck,
+                       const struct pvfs_filename *name1,
                        const char *name2)
 {
        const char *r1, *r2;
        uint32_t mask;
+       NTSTATUS status;
 
        if (rename(name1->full_name, name2) == -1) {
                return pvfs_map_errno(pvfs, errno);
        }
 
+       status = odb_rename(lck, name2);
+       NT_STATUS_NOT_OK_RETURN(status);
+
        if (name1->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
                mask = FILE_NOTIFY_CHANGE_DIR_NAME;
        } else {
@@ -315,11 +321,7 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs,
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = pvfs_do_rename(pvfs, name1, fname2);
-
-       if (NT_STATUS_IS_OK(status)) {
-               status = odb_rename(lck, fname2);
-       }
+       status = pvfs_do_rename(pvfs, lck, name1, fname2);
 
 failed:
        talloc_free(mem_ctx);
@@ -448,9 +450,9 @@ static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs,
                return status;
        }
 
-       status = pvfs_do_rename(pvfs, name1, name2->full_name);
-       if (NT_STATUS_IS_OK(status)) {
-               status = odb_rename(lck, name2->full_name);
+       status = pvfs_do_rename(pvfs, lck, name1, name2->full_name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
        
        return NT_STATUS_OK;
@@ -532,10 +534,7 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs,
        case RENAME_FLAG_RENAME:
                status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE);
                NT_STATUS_NOT_OK_RETURN(status);
-               status = pvfs_do_rename(pvfs, name1, name2->full_name);
-               if (NT_STATUS_IS_OK(status)) {
-                       status = odb_rename(lck, name2->full_name);
-               }
+               status = pvfs_do_rename(pvfs, lck, name1, name2->full_name);
                NT_STATUS_NOT_OK_RETURN(status);
                break;
 
index 2bfc47beffeef1029dff20c080f6fab87618f42b..325bc74f8f00180cc764747bcc60d61509284e1b 100644 (file)
@@ -265,8 +265,15 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name,
                                   of a name */
                                return NT_STATUS_ILLEGAL_CHARACTER;
                        }
-                       if (p > p_start && p[1] == 0) {
-                               *p = 0;
+                       if (p > p_start && (p[1] == '\\' || p[1] == '\0')) {
+                               /* see if it is definately a "\\" or
+                                * a trailing "\". If it is then fail here,
+                                * and let the next layer up try again after
+                                * pvfs_reduce_name() if it wants to. This is
+                                * much more efficient on average than always
+                                * scanning for these separately
+                                */
+                               return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                        } else {
                                *p = '/';
                        }
@@ -399,7 +406,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx,
                if (ISDOTDOT(components[i])) {
                        if (i < 1) return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                        memmove(&components[i-1], &components[i+1], 
-                               sizeof(char *)*(num_components-(i+1)));
+                               sizeof(char *)*(num_components-i));
                        i -= 2;
                        continue;
                }
@@ -616,6 +623,86 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd,
        return pvfs_fill_dos_info(pvfs, name, fd);
 }
 
+/*
+  fill in the pvfs_filename info for an open file, given the current
+  info for a (possibly) non-open file. This is used by places that need
+  to update the pvfs_filename stat information, and the path
+  after a possible rename on a different handle.
+*/
+NTSTATUS pvfs_resolve_name_handle(struct pvfs_state *pvfs,
+                                 struct pvfs_file_handle *h)
+{
+       NTSTATUS status;
+
+       if (h->have_opendb_entry) {
+               struct odb_lock *lck;
+               const char *name = NULL;
+
+               lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);
+               if (lck == NULL) {
+                       DEBUG(0,("%s: failed to lock file '%s' in opendb\n",
+                                __FUNCTION__, h->name->full_name));
+                       /* we were supposed to do a blocking lock, so something
+                          is badly wrong! */
+                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               }
+
+               status = odb_get_path(lck, &name);
+               if (NT_STATUS_IS_OK(status)) {
+                       /*
+                        * This relies an the fact that
+                        * renames of open files are only
+                        * allowed by setpathinfo() and setfileinfo()
+                        * and there're only renames within the same
+                        * directory supported
+                        */
+                       if (strcmp(h->name->full_name, name) != 0) {
+                               const char *orig_dir;
+                               const char *new_file;
+                               const char *new_orig;
+                               char *delim;
+
+                               delim = strrchr(name, '/');
+                               if (!delim) {
+                                       talloc_free(lck);
+                                       return NT_STATUS_INTERNAL_ERROR;
+                               }
+
+                               new_file = delim + 1;
+                               delim = strrchr(h->name->original_name, '\\');
+                               if (delim) {
+                                       delim[0] = '\0';
+                                       orig_dir = h->name->original_name;
+                                       new_orig = talloc_asprintf(h->name, "%s\\%s",
+                                                                  orig_dir, new_file);
+                                       if (!new_orig) {
+                                               talloc_free(lck);
+                                               return NT_STATUS_NO_MEMORY;
+                                       }
+                               } else {
+                                       new_orig = talloc_strdup(h->name, new_file);
+                                       if (!new_orig) {
+                                               talloc_free(lck);
+                                               return NT_STATUS_NO_MEMORY;
+                                       }
+                               }
+
+                               talloc_free(h->name->original_name);
+                               talloc_free(h->name->full_name);
+                               h->name->full_name = talloc_steal(h->name, name);
+                               h->name->original_name = new_orig;
+                       }
+               }
+
+               talloc_free(lck);
+       }
+
+       status = pvfs_resolve_name_fd(pvfs, h->fd, h->name);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       return NT_STATUS_OK;
+}
+
 
 /*
   resolve the parent of a given name
index da1e31e63904bc397c0cf230c9ea4c8ff2b610cb..ad47fe90c9bf643ae3e01c5a1b64d984e2aca4cc 100644 (file)
@@ -82,11 +82,13 @@ static uint32_t pvfs_setfileinfo_access(union smb_setfileinfo *info)
 static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs, 
                                        struct ntvfs_request *req, 
                                        struct pvfs_filename *name,
+                                       DATA_BLOB *odb_locking_key,
                                        union smb_setfileinfo *info)
 {
        NTSTATUS status;
        struct pvfs_filename *name2;
        char *new_name, *p;
+       struct odb_lock *lck = NULL;
 
        /* renames are only allowed within a directory */
        if (strchr_m(info->rename_information.in.new_name, '\\') &&
@@ -94,11 +96,6 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
                return NT_STATUS_NOT_SUPPORTED;
        }
 
-       if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
-               /* don't allow this for now */
-               return NT_STATUS_FILE_IS_A_DIRECTORY;
-       }
-
        /* don't allow stream renames for now */
        if (name->stream_name) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -168,7 +165,15 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
                return status;
        }
 
-       status = pvfs_do_rename(pvfs, name, name2->full_name);
+       lck = odb_lock(req, pvfs->odb_context, odb_locking_key);
+       if (lck == NULL) {
+               DEBUG(0,("Unable to lock opendb for can_stat\n"));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       status = pvfs_do_rename(pvfs, lck, name, name2->full_name);
+       talloc_free(lck);
+       NT_STATUS_NOT_OK_RETURN(status);
        if (NT_STATUS_IS_OK(status)) {
                name->full_name = talloc_steal(name, name2->full_name);
                name->original_name = talloc_steal(name, name2->original_name);
@@ -289,7 +294,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
        }
 
        /* update the file information */
-       status = pvfs_resolve_name_fd(pvfs, h->fd, h->name);
+       status = pvfs_resolve_name_handle(pvfs, h);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -391,7 +396,8 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
 
        case RAW_SFILEINFO_RENAME_INFORMATION:
        case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
-               return pvfs_setfileinfo_rename(pvfs, req, h->name, 
+               return pvfs_setfileinfo_rename(pvfs, req, h->name,
+                                              &h->odb_locking_key,
                                               info);
 
        case RAW_SFILEINFO_SEC_DESC:
@@ -565,6 +571,7 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
        uint32_t access_needed;
        uint32_t change_mask = 0;
        struct odb_lock *lck = NULL;
+       DATA_BLOB odb_locking_key;
 
        /* resolve the cifs name to a posix name */
        status = pvfs_resolve_name(pvfs, req, info->generic.in.file.path, 
@@ -696,8 +703,12 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
 
        case RAW_SFILEINFO_RENAME_INFORMATION:
        case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
-               return pvfs_setfileinfo_rename(pvfs, req, name, 
-                                              info);
+               status = pvfs_locking_key(name, name, &odb_locking_key);
+               NT_STATUS_NOT_OK_RETURN(status);
+               status = pvfs_setfileinfo_rename(pvfs, req, name,
+                                                &odb_locking_key, info);
+               NT_STATUS_NOT_OK_RETURN(status);
+               return NT_STATUS_OK;
 
        case RAW_SFILEINFO_DISPOSITION_INFO:
        case RAW_SFILEINFO_DISPOSITION_INFORMATION:
index aaa11774aea8ca73457e4a464fbd7514cdfa8cd4..66565ca6fc9cd445af816f3b5cdb1a404b6c72a4 100644 (file)
@@ -3,9 +3,7 @@ local.iconv.*.next_codepoint()
 base.delaywrite.finfo update on close
 base.delete.*.deltest20a
 base.delete.*.deltest20b
-raw.oplock.*BATCH19
-raw.oplock.*BATCH20
-rpc.winreg
+rpc.winreg.*security
 local.registry.*.security # Not implemented yet
 rpc.wkssvc
 rpc.handles.*.lsarpc-shared
@@ -35,5 +33,4 @@ rpc.netlogon.*.GetTrustPasswords
 base.charset.*.Testing partial surrogate
 .*net.api.delshare.*                           # DelShare isn't implemented yet
 rap.*netservergetinfo
-samba4.blackbox.provision.py.reprovision # Fails with entry already exists
 local.torture.provision
index b041165800fc1de0c65ae41f613f71f59f4a2e9c..8d5f4250c957ec53860faeecea90daa64dcf5b33 100644 (file)
@@ -127,7 +127,7 @@ class Ldb(ldb.Ldb):
             try:
                 self.delete(msg.dn)
             except ldb.LdbError, (LDB_ERR_NO_SUCH_OBJECT, _):
-                # Ignor eno such object errors
+                # Ignorno such object errors
                 pass
 
         res = self.search(basedn, ldb.SCOPE_SUBTREE, "(&(|(objectclass=*)(distinguishedName=*))(!(distinguishedName=@BASEINFO)))", ["distinguishedName"])
@@ -151,7 +151,14 @@ class Ldb(ldb.Ldb):
                 previous_remaining = current_remaining
                 current_remaining = len(res2)
                 for msg in res2:
-                    self.delete(msg.dn)
+                    try:
+                        self.delete(msg.dn)
+                    # Ignore no such object errors
+                    except ldb.LdbError, (LDB_ERR_NO_SUCH_OBJECT, _):
+                        pass
+                    # Ignore not allowed on non leaf errors
+                    except ldb.LdbError, (LDB_ERR_NOT_ALLOWED_ON_NON_LEAF, _):
+                        pass
 
     def load_ldif_file_add(self, ldif_path):
         """Load a LDIF file.
index 55935b0037cb3fac81fb20a7e1d604ba1a24a93a..ea2feb981bbfb3ea378cf30b1bfaa1e776199d34 100644 (file)
@@ -279,8 +279,6 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
     
     Alternatively, provision() may call this, and then populate the database.
     
-    :param erase: Remove the existing data present in the database.
-     
     :note: This will wipe the Sam Database!
     
     :note: This function always removes the local SAM LDB file. The erase 
@@ -289,10 +287,15 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
     """
     assert session_info is not None
 
-    if os.path.exists(samdb_path):
+    samdb = SamDB(samdb_path, session_info=session_info, 
+                  credentials=credentials, lp=lp)
+
+    # Wipes the database
+    try:
+        samdb.erase()
+    except:
         os.unlink(samdb_path)
 
-    # Also wipes the database
     samdb = SamDB(samdb_path, session_info=session_info, 
                   credentials=credentials, lp=lp)
 
@@ -547,7 +550,7 @@ def setup_self_join(samdb, configdn, schemadn, domaindn,
 
 def setup_samdb(path, setup_path, session_info, credentials, lp, 
                 schemadn, configdn, domaindn, dnsdomain, realm, 
-                netbiosname, message, hostname, rootdn, erase, 
+                netbiosname, message, hostname, rootdn, 
                 domainsid, aci, domainguid, policyguid, 
                 domainname, fill, adminpass, krbtgtpass, 
                 machinepass, hostguid, invocationid, dnspass,
@@ -560,6 +563,8 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
 
     assert serverrole in ("domain controller", "member server")
 
+    erase = (fill != FILL_DRS)    
+
     # Also wipes the database
     setup_samdb_partitions(path, setup_path, schemadn=schemadn, configdn=configdn, 
                            domaindn=domaindn, message=message, lp=lp,
@@ -726,7 +731,7 @@ def provision(lp, setup_dir, message, paths, session_info,
               hostguid=None, adminpass=None, krbtgtpass=None, domainguid=None, 
               policyguid=None, invocationid=None, machinepass=None, 
               dnspass=None, root=None, nobody=None, nogroup=None, users=None, 
-              wheel=None, backup=None, aci=None, serverrole=None, erase=False,
+              wheel=None, backup=None, aci=None, serverrole=None,
               ldap_backend=None, ldap_backend_type=None, sitename=DEFAULTSITE):
     """Provision samba4
     
@@ -830,7 +835,7 @@ def provision(lp, setup_dir, message, paths, session_info,
         message("Setting up smb.conf")
         if serverrole == "domain controller":
             smbconfsuffix = "dc"
-        elif serverrole == "member":
+        elif serverrole == "member server":
             smbconfsuffix = "member"
         setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix), 
                    paths.smbconf, {
@@ -873,7 +878,7 @@ def provision(lp, setup_dir, message, paths, session_info,
                         configdn=configdn, domaindn=domaindn,
                         dnsdomain=dnsdomain, netbiosname=netbiosname, 
                         realm=realm, message=message, hostname=hostname, 
-                        rootdn=rootdn, erase=erase, domainsid=domainsid, 
+                        rootdn=rootdn, domainsid=domainsid, 
                         aci=aci, domainguid=domainguid, policyguid=policyguid, 
                         domainname=domain, fill=samdb_fill, 
                         adminpass=adminpass, krbtgtpass=krbtgtpass,
index e0be8048a0c5ce744d7e4f74e8e7fd188d050729..48fda1759930477d67ff9f2d53c6c29e8084a1e2 100644 (file)
@@ -389,25 +389,26 @@ yoZeAErTALjyZYZEPcECQQDlUi0N8DFxQ/lOwWyR3Hailft+mPqoPCa8QHlQZnlG
 EOF
 
        #generated with 
-       #hxtool issue-certificate --self-signed --issue-ca --ca-private-key=FILE:$KEYFILE \
-       #          --subject="CN=CA,$BASEDN" --certificate="FILE:$CAFILE"
+       # hxtool issue-certificate --self-signed --issue-ca \
+       # --ca-private-key="FILE:$KEYFILE" \
+       # --subject="CN=CA,DC=samba,DC=example,DC=com" \
+       # --certificate="FILE:$CAFILE" --lifetime="25 years"
 
        open(CAFILE, ">$cafile");
        print CAFILE <<EOF;
 -----BEGIN CERTIFICATE-----
-MIIChTCCAe6gAwIBAgIUFZoF6jt0R+hQBdF7cWPy0tT3fGwwCwYJKoZIhvcNAQEFMFIxEzAR
+MIICcTCCAdqgAwIBAgIUaBPmjnPVqyFqR5foICmLmikJTzgwCwYJKoZIhvcNAQEFMFIxEzAR
 BgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxlMRUwEwYKCZImiZPy
-LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDcwMTIzMDU1MzA5WhgPMjAwODAxMjQw
-NTUzMDlaMFIxEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl
+LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDgwMzAxMTIyMzEyWhgPMjAzMzAyMjQx
+MjIzMTJaMFIxEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl
 MRUwEwYKCZImiZPyLGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMIGfMA0GCSqGSIb3DQEBAQUA
 A4GNADCBiQKBgQDKg6pAwCHUMA1DfHDmWhZfd+F0C+9Jxcqvpw9ii9En3E1uflpcol3+S9/6
 I/uaTmJHZre+DF3dTzb/UOZo0Zem8N+IzzkgoGkFafjXuT3BL5UPY2/H6H+pPqVIRLOmrWIm
-ai359YyoKhFyo37Y6HPeU8QcZ+u2rS9geapIWfeuowIDAQABo1YwVDAOBgNVHQ8BAf8EBAMC
-AqQwEgYDVR0lBAswCQYHKwYBBQIDBTAdBgNVHQ4EFgQUwtm596AMotmzRU7IVdgrUvozyjIw
-DwYDVR0TBAgwBgEB/wIBADANBgkqhkiG9w0BAQUFAAOBgQBgzh5uLDmESGYv60iUdEfuk/T9
-VCpzb1z3VJVWt3uJoQYbcpR00SKeyMdlfTTLzO6tSPMmlk4hwqfvLkPzGCSObR4DRRYa0BtY
-2laBVlg9X59bGpMUvpFQfpvxjvFWNJDL+377ELCVpLNdoR23I9TKXlalj0bY5Ks46CVIrm6W
-EA==
+ai359YyoKhFyo37Y6HPeU8QcZ+u2rS9geapIWfeuowIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
+AaYwHQYDVR0OBBYEFMLZufegDKLZs0VOyFXYK1L6M8oyMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
+KoZIhvcNAQEFBQADgYEAAZJbCAAkaqgFJ0xgNovn8Ydd0KswQPjicwiODPgw9ZPoD2HiOUVO
+yYDRg/dhFF9y656OpcHk4N7qZ2sl3RlHkzDu+dseETW+CnKvQIoXNyeARRJSsSlwrwcoD4JR
+HTLk2sGigsWwrJ2N99sG/cqSJLJ1MFwLrs6koweBnYU0f/g=
 -----END CERTIFICATE-----
 EOF
 
@@ -434,17 +435,23 @@ EOF
        close(CERTFILE);
 
        #KDC certificate
-       # hxtool request-create --subject="CN=krbtgt,cn=users,$basedn" --key=FILE:$KEYFILE $KDCREQ
+       # hxtool request-create \
+       # --subject="CN=krbtgt,CN=users,DC=samba,DC=example,DC=com" \
+       # --key="FILE:$KEYFILE" $KDCREQ
 
-       # hxtool issue-certificate --ca-certificate=FILE:$CAFILE,$KEYFILE --type="pkinit-kdc" --pk-init-principal="krbtgt/$RELAM@$REALM" --req="$KDCREQ" --certificate="FILE:$KDCCERTFILE"
+       # hxtool issue-certificate --ca-certificate=FILE:$CAFILE,$KEYFILE \
+       # --type="pkinit-kdc" \
+       # --pk-init-principal="krbtgt/SAMBA.EXAMPLE.COM@SAMBA.EXAMPLE.COM" \
+       # --req="PKCS10:$KDCREQ" --certificate="FILE:$KDCCERTFILE" \
+       # --lifetime="25 years"
 
        open(KDCCERTFILE, ">$kdccertfile");
        print KDCCERTFILE <<EOF;
 -----BEGIN CERTIFICATE-----
-MIIDDDCCAnWgAwIBAgIUDEhjaOT1ZjHjHHEn+l5eYO05oK8wCwYJKoZIhvcNAQEFMFIxEzAR
+MIIDDDCCAnWgAwIBAgIUI2Tzj+JnMzMcdeabcNo30rovzFAwCwYJKoZIhvcNAQEFMFIxEzAR
 BgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxlMRUwEwYKCZImiZPy
-LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDcwMTIzMDcwNzA4WhgPMjAwODAxMjQw
-NzA3MDhaMGYxEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl
+LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDgwMzAxMTMxOTIzWhgPMjAzMzAyMjQx
+MzE5MjNaMGYxEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl
 MRUwEwYKCZImiZPyLGQBGQwFc2FtYmExDjAMBgNVBAMMBXVzZXJzMQ8wDQYDVQQDDAZrcmJ0
 Z3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMqDqkDAIdQwDUN8cOZaFl934XQL70nF
 yq+nD2KL0SfcTW5+WlyiXf5L3/oj+5pOYkdmt74MXd1PNv9Q5mjRl6bw34jPOSCgaQVp+Ne5
@@ -453,32 +460,40 @@ AAGjgcgwgcUwDgYDVR0PAQH/BAQDAgWgMBIGA1UdJQQLMAkGBysGAQUCAwUwVAYDVR0RBE0w
 S6BJBgYrBgEFAgKgPzA9oBMbEVNBTUJBLkVYQU1QTEUuQ09NoSYwJKADAgEBoR0wGxsGa3Ji
 dGd0GxFTQU1CQS5FWEFNUExFLkNPTTAfBgNVHSMEGDAWgBTC2bn3oAyi2bNFTshV2CtS+jPK
 MjAdBgNVHQ4EFgQUwtm596AMotmzRU7IVdgrUvozyjIwCQYDVR0TBAIwADANBgkqhkiG9w0B
-AQUFAAOBgQCMSgLkIv9RobE0a95H2ECA+5YABBwKXIt4AyN/HpV7iJdRx7B9PE6vM+nboVKY
-E7i7ECUc3bu6NgrLu7CKHelNclHWWMiZzSUwhkXyvG/LE9qtr/onNu9NfLt1OV+dwQwyLdEP
-n63FxSmsKg3dfi3ryQI/DIKeisvipwDtLqOn9g==
+AQUFAAOBgQBmrVD5MCmZjfHp1nEnHqTIh8r7lSmVtDx4s9MMjxm9oNrzbKXynvdhwQYFVarc
+ge4yRRDXtSebErOl71zVJI9CVeQQpwcH+tA85oGA7oeFtO/S7ls581RUU6tGgyxV4veD+lJv
+KPH5LevUtgD+q9H4LU4Sq5N3iFwBaeryB0g2wg==
 -----END CERTIFICATE-----
 EOF
 
-       #hxtool request-create --subject="CN=Administrator,cn=users,$basedn" --key=FILE:$ADMINKEYFILE $ADMINREQFILE
-       #hxtool issue-certificate --ca-certificate=FILE:$CAFILE,$KEYFILE --type="pkinit-client" --pk-init-principal="administrator@$REALM" --req="$ADMINREQFILE" --certificate="FILE:$ADMINCERTFILE"
+       # hxtool request-create \
+       # --subject="CN=Administrator,CN=users,DC=samba,DC=example,DC=com" \
+       # --key="FILE:$ADMINKEYFILE" $ADMINREQFILE
+
+       # hxtool issue-certificate --ca-certificate=FILE:$CAFILE,$KEYFILE \
+       # --type="pkinit-client" \
+       # --pk-init-principal="administrator@SAMBA.EXAMPLE.COM" \
+       # --req="PKCS10:$ADMINREQFILE" --certificate="FILE:$ADMINCERTFILE" \
+       # --lifetime="25 years"
        
        open(ADMINCERTFILE, ">$admincertfile");
        print ADMINCERTFILE <<EOF;
 -----BEGIN CERTIFICATE-----
-MIICwjCCAiugAwIBAgIUXyECoq4im33ByZDWZMGhtpvHYWEwCwYJKoZIhvcNAQEFMFIxEzAR
+MIIDHTCCAoagAwIBAgIUC0W5dW/N9kE+NgD0mKK34YgyqQ0wCwYJKoZIhvcNAQEFMFIxEzAR
 BgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxlMRUwEwYKCZImiZPy
-LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDcwMTIzMDcyMzE2WhgPMjAwODAxMjQw
-NzIzMTZaMCgxDjAMBgNVBAMMBXVzZXJzMRYwFAYDVQQDDA1BZG1pbmlzdHJhdG9yMIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQD0+OL7TQBj0RejbIH1+g5GeRaWaM9xF43uE5y7jUHE
-si5owhZF5iIoHZeeL6cpDF5y1BZRs0JlA1VqMry1jjKlzFYVEMMFxB6esnXhl0Jpip1JkUMM
-XLOP1m/0dqayuHBWozj9f/cdyCJr0wJIX1Z8Pr+EjYRGPn/MF0xdl3JRlwIDAQABo4G8MIG5
-MA4GA1UdDwEB/wQEAwIFoDASBgNVHSUECzAJBgcrBgEFAgMEMEgGA1UdEQRBMD+gPQYGKwYB
-BQICoDMwMaATGxFTQU1CQS5FWEFNUExFLkNPTaEaMBigAwIBAaERMA8bDWFkbWluaXN0cmF0
-b3IwHwYDVR0jBBgwFoAUwtm596AMotmzRU7IVdgrUvozyjIwHQYDVR0OBBYEFCDzVsvJ8IDz
-wLYH8EONeUa5oVrGMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADgYEAbTCnaPTieVZPV3bH
-UmAMbnF9+YN1mCbe2xZJ0xzve+Yw1XO82iv/9kZaZkcRkaQt2qcwsBK/aSPOgfqGx+mJ7hXQ
-AGWvAJhnWi25PawNaRysCN8WC6+nWKR4d2O2m5rpj3T9kH5WE7QbG0bCu92dGaS29FvWDCP3
-q9pRtDOoAZc=
+LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDgwMzAxMTMyMzAwWhgPMjAzMzAyMjQx
+MzIzMDBaMG0xEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl
+MRUwEwYKCZImiZPyLGQBGQwFc2FtYmExDjAMBgNVBAMMBXVzZXJzMRYwFAYDVQQDDA1BZG1p
+bmlzdHJhdG9yMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD0+OL7TQBj0RejbIH1+g5G
+eRaWaM9xF43uE5y7jUHEsi5owhZF5iIoHZeeL6cpDF5y1BZRs0JlA1VqMry1jjKlzFYVEMMF
+xB6esnXhl0Jpip1JkUMMXLOP1m/0dqayuHBWozj9f/cdyCJr0wJIX1Z8Pr+EjYRGPn/MF0xd
+l3JRlwIDAQABo4HSMIHPMA4GA1UdDwEB/wQEAwIFoDAoBgNVHSUEITAfBgcrBgEFAgMEBggr
+BgEFBQcDAgYKKwYBBAGCNxQCAjBIBgNVHREEQTA/oD0GBisGAQUCAqAzMDGgExsRU0FNQkEu
+RVhBTVBMRS5DT02hGjAYoAMCAQGhETAPGw1hZG1pbmlzdHJhdG9yMB8GA1UdIwQYMBaAFMLZ
+ufegDKLZs0VOyFXYK1L6M8oyMB0GA1UdDgQWBBQg81bLyfCA88C2B/BDjXlGuaFaxjAJBgNV
+HRMEAjAAMA0GCSqGSIb3DQEBBQUAA4GBAHsqSqul0hZCXn4t8Kfp3v/JLMiUMJihR1XOgzoa
+ufLOQ1HNzFUHKuo1JEQ1+i5gHT/arLu/ZBF4BfQol7vW27gKIEt0fkRV8EvoPxXvSokHq0Ku
+HCuPOhYNEP3wYiwB3g93NMCinWVlz0mh5aijEU7y/XrjlZxBKFFrTE+BJi1o
 -----END CERTIFICATE-----
 EOF
        close(ADMINCERTFILE);
index 42a3c3cebe427f9335e7f479b0bb6d59f6da0b9b..fa69c92caa950895dfc6c608bf2605d13c0a474d 100644 (file)
@@ -54,24 +54,68 @@ static NTSTATUS single_search(struct smbcli_state *cli,
        return status;
 }
 
-static bool test_path(struct smbcli_state *cli, const char *path, NTSTATUS expected, NTSTATUS dos_expected)
+static bool test_path_ex(struct smbcli_state *cli, struct torture_context *tctx,
+                        const char *path, const char *path_expected,
+                        NTSTATUS expected, NTSTATUS dos_expected)
 {
        union smb_chkpath io;
+       union smb_fileinfo finfo;
        NTSTATUS status;
+
        io.chkpath.in.path = path;
        status = smb_raw_chkpath(cli->tree, &io);
        if (!NT_STATUS_EQUAL(status, expected) && !NT_STATUS_EQUAL(status, dos_expected)) {
-               printf("%-40s FAILED %s should be %s or %s\n", 
+               printf("FAILED %-30s chkpath %s should be %s or %s\n",
                       path, nt_errstr(status), nt_errstr(expected), nt_errstr(dos_expected));
                return false;
        } else {
-               printf("%-40s correct (%s)\n", path, nt_errstr(status));
+               printf("%-30s chkpath correct (%s)\n", path, nt_errstr(status));
+       }
+
+       if (NT_STATUS_EQUAL(expected, NT_STATUS_NOT_A_DIRECTORY)) {
+               expected = NT_STATUS_OK;
+       }
+
+       ZERO_STRUCT(finfo);
+       finfo.generic.level = RAW_FILEINFO_NAME_INFO;
+       finfo.generic.in.file.path = path;
+       status = smb_raw_pathinfo(cli->tree, cli, &finfo);
+       if (!NT_STATUS_EQUAL(status, expected) && !NT_STATUS_EQUAL(status, dos_expected)) {
+               printf("FAILED: %-30s pathinfo %s should be %s or %s\n",
+                      path, nt_errstr(status), nt_errstr(expected), nt_errstr(dos_expected));
+               return false;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("%-30s chkpath correct (%s)\n", path, nt_errstr(status));
+               return true;
+       }
 
+       if (path_expected &&
+           (!finfo.name_info.out.fname.s ||
+            strcmp(finfo.name_info.out.fname.s, path_expected) != 0)) {
+               if (tctx && torture_setting_bool(tctx, "samba4", false)) {
+                       printf("IGNORE: %-30s => %-20s should be %s\n",
+                               path, finfo.name_info.out.fname.s, path_expected);
+                       return true;
+               }
+               printf("FAILED: %-30s => %-20s should be %s\n",
+                       path, finfo.name_info.out.fname.s, path_expected);
+               return false;
        }
+       printf("%-30s => %-20s correct\n",
+               path, finfo.name_info.out.fname.s);
+
        return true;
 }
 
-static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_path(struct smbcli_state *cli, const char *path,
+                     NTSTATUS expected, NTSTATUS dos_expected)
+{
+       return test_path_ex(cli, NULL, path, path, expected, dos_expected);
+}
+
+static bool test_chkpath(struct smbcli_state *cli, struct torture_context *tctx)
 {
        union smb_chkpath io;
        NTSTATUS status;
@@ -86,7 +130,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 
        ret &= test_path(cli, BASEDIR "\\nodir", NT_STATUS_OBJECT_NAME_NOT_FOUND, NT_STATUS_DOS(ERRDOS,ERRbadpath));
 
-       fnum = create_complex_file(cli, mem_ctx, BASEDIR "\\test.txt..");
+       fnum = create_complex_file(cli, tctx, BASEDIR "\\test.txt..");
        if (fnum == -1) {
                printf("failed to open test.txt - %s\n", smbcli_errstr(cli->tree));
                ret = false;
@@ -101,9 +145,20 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                goto done;
        }
 
-       ret &= test_path(cli, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
-       ret &= test_path(cli, BASEDIR "\\foo\\..\\test.txt..", NT_STATUS_NOT_A_DIRECTORY, NT_STATUS_DOS(ERRDOS,ERRbadpath));
-       ret &= test_path(cli, "", NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, BASEDIR, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, ((char *)BASEDIR) + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\\\") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\foo\\..") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\f\\o\\o\\..\\..\\..") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\foo\\\\\..\\\\") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, BASEDIR"\\", BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, BASEDIR"\\\\..\\"BASEDIR, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, BASEDIR"\\\\\\", BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, "\\\\\\\\"BASEDIR"\\\\\\\\", BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, "\\\\\\\\"BASEDIR, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, BASEDIR "\\foo\\..\\test.txt..", BASEDIR "\\test.txt..",
+                           NT_STATUS_NOT_A_DIRECTORY, NT_STATUS_DOS(ERRDOS,ERRbadpath));
+       ret &= test_path_ex(cli, tctx, "", "\\", NT_STATUS_OK, NT_STATUS_OK);
        ret &= test_path(cli, ".", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath));
        ret &= test_path(cli, ".\\", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath));
        ret &= test_path(cli, "\\\\\\.\\", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath));
@@ -122,7 +177,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
          give different NT status returns for chkpth and findfirst. */
 
        printf("testing findfirst on %s\n", "\\.\\\\\\\\\\\\.");
-       status = single_search(cli, mem_ctx, "\\.\\\\\\\\\\\\.");
+       status = single_search(cli, tctx, "\\.\\\\\\\\\\\\.");
        CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID,NT_STATUS_DOS(ERRDOS,ERRinvalidname));
 
        ret &= test_path(cli, "\\.\\\\\\\\\\\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
@@ -164,7 +219,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        ret &= test_path(cli, "\\..\\", NT_STATUS_OBJECT_PATH_SYNTAX_BAD,NT_STATUS_DOS(ERRDOS,ERRinvalidpath));
        ret &= test_path(cli, "\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD,NT_STATUS_DOS(ERRDOS,ERRinvalidpath));
        ret &= test_path(cli, BASEDIR "\\.", NT_STATUS_OBJECT_NAME_INVALID,NT_STATUS_DOS(ERRDOS,ERRbadpath));
-       ret &= test_path(cli, BASEDIR "\\..", NT_STATUS_OK,NT_STATUS_OK);
+       ret &= test_path_ex(cli, tctx, BASEDIR "\\..", "\\", NT_STATUS_OK,NT_STATUS_OK);
        ret &= test_path(cli, BASEDIR "\\nt\\V S\\VB98\\vb600", NT_STATUS_OBJECT_NAME_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
        ret &= test_path(cli, BASEDIR "\\nt\\V S\\VB98\\vb6.exe", NT_STATUS_NOT_A_DIRECTORY,NT_STATUS_DOS(ERRDOS,ERRbadpath));
 
@@ -183,7 +238,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
 
        printf("testing findfirst on %s\n", BASEDIR".\\.\\.\\.\\foo\\..\\.\\");
-       status = single_search(cli, mem_ctx, BASEDIR".\\.\\.\\.\\foo\\..\\.\\");
+       status = single_search(cli, tctx, BASEDIR".\\.\\.\\.\\foo\\..\\.\\");
        CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
 
        /* We expect this open to fail with the same error code as the chkpath below. */
index e58b3fd7601ed53422ed55302a11a29c693c657d..90ccde72133d06125aa90911dd82c49862863542 100644 (file)
@@ -453,6 +453,10 @@ bool torture_raw_sfileinfo_rename(struct torture_context *torture,
        char *fnum_fname_new;
        char *path_fname;
        char *path_fname_new;
+       char *path_dname;
+       char *path_dname_new;
+       char *saved_name;
+       char *saved_name_new;
        union smb_fileinfo finfo1, finfo2;
        union smb_setfileinfo sfinfo;
        NTSTATUS status, status2;
@@ -464,6 +468,8 @@ bool torture_raw_sfileinfo_rename(struct torture_context *torture,
        asprintf(&path_fname_new, BASEDIR "\\fname_test_new_%d.txt", n);
        asprintf(&fnum_fname, BASEDIR "\\fnum_test_%d.txt", n);
        asprintf(&fnum_fname_new, BASEDIR "\\fnum_test_new_%d.txt", n);
+       asprintf(&path_dname, BASEDIR "\\dname_test_%d", n);
+       asprintf(&path_dname_new, BASEDIR "\\dname_test_new_%d", n);
 
        if (!torture_setup_dir(cli, BASEDIR)) {
                return false;
@@ -553,17 +559,112 @@ bool torture_raw_sfileinfo_rename(struct torture_context *torture,
        sfinfo.rename_information.in.root_fid = d_fnum;
        CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_INVALID_PARAMETER);
        CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
+       smbcli_close(cli->tree, d_fnum);
 
-done:
-       smb_raw_exit(cli->session);
-       smbcli_close(cli->tree, fnum);
-       if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fnum_fname))) {
-               printf("Failed to delete %s - %s\n", fnum_fname, smbcli_errstr(cli->tree));
+       printf("Trying rename directory\n");
+       if (!torture_setup_dir(cli, path_dname)) {
+               ret = false;
+               goto done;
        }
-       if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, path_fname))) {
-               printf("Failed to delete %s - %s\n", path_fname, smbcli_errstr(cli->tree));
+       saved_name = path_fname;
+       saved_name_new = path_fname_new;
+       path_fname = path_dname;
+       path_fname_new = path_dname_new;
+       sfinfo.rename_information.in.new_name  = path_dname_new+strlen(BASEDIR)+1;
+       sfinfo.rename_information.in.overwrite = 0;
+       sfinfo.rename_information.in.root_fid  = 0;
+       CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
+       CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
+       path_fname = saved_name;
+       path_fname_new = saved_name_new;
+
+       if (torture_setting_bool(torture, "samba3", false)) {
+               printf("SKIP: Trying rename directory with a handle\n");
+               printf("SKIP: Trying rename by path while a handle is open\n");
+               printf("SKIP: Trying rename directory by path while a handle is open\n");
+               goto done;
        }
 
+       printf("Trying rename directory with a handle\n");
+       status = create_directory_handle(cli->tree, path_dname_new, &d_fnum);
+       fnum_saved = fnum;
+       fnum = d_fnum;
+       saved_name = fnum_fname;
+       saved_name_new = fnum_fname_new;
+       fnum_fname = path_dname;
+       fnum_fname_new = path_dname_new;
+       sfinfo.rename_information.in.new_name  = path_dname+strlen(BASEDIR)+1;
+       sfinfo.rename_information.in.overwrite = 0;
+       sfinfo.rename_information.in.root_fid  = 0;
+       CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
+       CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
+       smbcli_close(cli->tree, d_fnum);
+       fnum = fnum_saved;
+       fnum_fname = saved_name;
+       fnum_fname_new = saved_name_new;
+
+       printf("Trying rename by path while a handle is open\n");
+       fnum_saved = fnum;
+       fnum = create_complex_file(cli, torture, path_fname);
+       sfinfo.rename_information.in.new_name  = path_fname_new+strlen(BASEDIR)+1;
+       sfinfo.rename_information.in.overwrite = 0;
+       sfinfo.rename_information.in.root_fid  = 0;
+       CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
+       CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
+       /* check that the handle returns the same name */
+       check_fnum = true;
+       CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
+       /* rename it back on the handle */
+       sfinfo.rename_information.in.new_name  = path_fname+strlen(BASEDIR)+1;
+       CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
+       CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
+       check_fnum = false;
+       CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
+       smbcli_close(cli->tree, fnum);
+       fnum = fnum_saved;
+
+       printf("Trying rename directory by path while a handle is open\n");
+       status = create_directory_handle(cli->tree, path_dname, &d_fnum);
+       fnum_saved = fnum;
+       fnum = d_fnum;
+       saved_name = path_fname;
+       saved_name_new = path_fname_new;
+       path_fname = path_dname;
+       path_fname_new = path_dname_new;
+       sfinfo.rename_information.in.new_name  = path_dname_new+strlen(BASEDIR)+1;
+       sfinfo.rename_information.in.overwrite = 0;
+       sfinfo.rename_information.in.root_fid  = 0;
+       CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
+       CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
+       path_fname = saved_name;
+       path_fname_new = saved_name_new;
+       saved_name = fnum_fname;
+       saved_name_new = fnum_fname_new;
+       fnum_fname = path_dname;
+       fnum_fname_new = path_dname_new;
+       /* check that the handle returns the same name */
+       check_fnum = true;
+       CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
+       /* rename it back on the handle */
+       sfinfo.rename_information.in.new_name  = path_dname+strlen(BASEDIR)+1;
+       CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
+       CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
+       fnum_fname = saved_name;
+       fnum_fname_new = saved_name_new;
+       saved_name = path_fname;
+       saved_name_new = path_fname_new;
+       path_fname = path_dname;
+       path_fname_new = path_dname_new;
+       check_fnum = false;
+       CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
+       smbcli_close(cli->tree, d_fnum);
+       fnum = fnum_saved;
+       path_fname = saved_name;
+       path_fname_new = saved_name_new;
+
+done:
+       smb_raw_exit(cli->session);
+       smbcli_deltree(cli->tree, BASEDIR);
        return ret;
 }
 
index 469573367102b7d34982150718e8fcd5db21f23d..8b602ef652dce3d270b29fa1f1f9ab51e07e8edd 100644 (file)
@@ -848,7 +848,6 @@ static bool test_SecurityDescriptorInheritance(struct dcerpc_pipe *p,
 
  out:
        test_CloseKey(p, tctx, &new_handle);
-       test_Cleanup(p, tctx, handle, TEST_SUBSUBKEY_SD);
        test_Cleanup(p, tctx, handle, TEST_SUBKEY_SD);
        test_RestoreSecurity(p, tctx, handle, key, sd_orig);
 
@@ -971,7 +970,6 @@ static bool test_SecurityDescriptorBlockInheritance(struct dcerpc_pipe *p,
 
  out:
        test_CloseKey(p, tctx, &new_handle);
-       test_Cleanup(p, tctx, handle, TEST_SUBSUBKEY_SD);
        test_Cleanup(p, tctx, handle, TEST_SUBKEY_SD);
        test_RestoreSecurity(p, tctx, handle, key, sd_orig);
 
@@ -1386,27 +1384,6 @@ static bool test_DeleteKey(struct dcerpc_pipe *p, struct torture_context *tctx,
        return true;
 }
 
-/* DeleteKey on a key with subkey(s) should
- * return WERR_ACCESS_DENIED. */
-static bool test_DeleteKeyWithSubkey(struct dcerpc_pipe *p,
-                                    struct torture_context *tctx,
-                                    struct policy_handle *handle,
-                                    const char *key)
-{
-       struct winreg_DeleteKey r;
-
-       r.in.handle = handle;
-       init_winreg_String(&r.in.key, key);
-
-       torture_assert_ntstatus_ok(tctx, dcerpc_winreg_DeleteKey(p, tctx, &r),
-                                  "DeleteKeyWithSubkey failed");
-
-       torture_assert_werr_equal(tctx, r.out.result, WERR_ACCESS_DENIED,
-                                 "DeleteKeyWithSubkey failed");
-
-       return true;
-}
-
 static bool test_QueryInfoKey(struct dcerpc_pipe *p,
                              struct torture_context *tctx,
                              struct policy_handle *handle, char *class)
@@ -1443,10 +1420,12 @@ static bool test_QueryInfoKey(struct dcerpc_pipe *p,
 }
 
 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
-                    struct policy_handle *handle, int depth);
+                    struct policy_handle *handle, int depth,
+                    bool test_security);
 
 static bool test_EnumKey(struct dcerpc_pipe *p, struct torture_context *tctx,
-                        struct policy_handle *handle, int depth)
+                        struct policy_handle *handle, int depth,
+                        bool test_security)
 {
        struct winreg_EnumKey r;
        struct winreg_StringBuf class, name;
@@ -1479,7 +1458,8 @@ static bool test_EnumKey(struct dcerpc_pipe *p, struct torture_context *tctx,
                        if (!test_OpenKey(p, tctx, handle, r.out.name->name,
                                          &key_handle)) {
                        } else {
-                               test_key(p, tctx, &key_handle, depth + 1);
+                               test_key(p, tctx, &key_handle,
+                                        depth + 1, test_security);
                        }
                }
 
@@ -1676,7 +1656,8 @@ static bool test_InitiateSystemShutdownEx(struct torture_context *tctx,
 #define MAX_DEPTH 2            /* Only go this far down the tree */
 
 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
-                    struct policy_handle *handle, int depth)
+                    struct policy_handle *handle, int depth,
+                    bool test_security)
 {
        if (depth == MAX_DEPTH)
                return true;
@@ -1687,10 +1668,10 @@ static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
        if (!test_NotifyChangeKeyValue(p, tctx, handle)) {
        }
 
-       if (!test_GetKeySecurity(p, tctx, handle, NULL)) {
+       if (test_security && !test_GetKeySecurity(p, tctx, handle, NULL)) {
        }
 
-       if (!test_EnumKey(p, tctx, handle, depth)) {
+       if (!test_EnumKey(p, tctx, handle, depth, test_security)) {
        }
 
        if (!test_EnumValue(p, tctx, handle, 0xFF, 0xFFFF)) {
@@ -1703,13 +1684,85 @@ static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
 
 typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
 
+static bool test_Open_Security(struct torture_context *tctx,
+                              struct dcerpc_pipe *p, void *userdata)
+{
+       struct policy_handle handle, newhandle;
+       bool ret = true, created2 = false;
+       bool created4 = false;
+       struct winreg_OpenHKLM r;
+
+       winreg_open_fn open_fn = userdata;
+
+       r.in.system_name = 0;
+       r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       r.out.handle = &handle;
+
+       torture_assert_ntstatus_ok(tctx, open_fn(p, tctx, &r),
+                                  "open");
+
+       test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
+
+       if (!test_CreateKey(p, tctx, &handle, TEST_KEY_BASE, NULL)) {
+               torture_comment(tctx,
+                               "CreateKey (TEST_KEY_BASE) failed\n");
+       }
+
+       if (test_CreateKey_sd(p, tctx, &handle, TEST_KEY2,
+                             NULL, &newhandle)) {
+               created2 = true;
+       }
+
+       if (created2 && !test_CloseKey(p, tctx, &newhandle)) {
+               printf("CloseKey failed\n");
+               ret = false;
+       }
+
+       if (test_CreateKey_sd(p, tctx, &handle, TEST_KEY4, NULL, &newhandle)) {
+               created4 = true;
+       }
+
+       if (created4 && !test_CloseKey(p, tctx, &newhandle)) {
+               printf("CloseKey failed\n");
+               ret = false;
+       }
+
+       if (created4 && !test_SecurityDescriptors(p, tctx, &handle, TEST_KEY4)) {
+               ret = false;
+       }
+
+       if (created4 && !test_DeleteKey(p, tctx, &handle, TEST_KEY4)) {
+               printf("DeleteKey failed\n");
+               ret = false;
+       }
+
+       if (created2 && !test_DeleteKey(p, tctx, &handle, TEST_KEY2)) {
+               printf("DeleteKey failed\n");
+               ret = false;
+       }
+
+       /* The HKCR hive has a very large fanout */
+       if (open_fn == (void *)dcerpc_winreg_OpenHKCR) {
+               if(!test_key(p, tctx, &handle, MAX_DEPTH - 1, true)) {
+                       ret = false;
+               }
+       } else {
+               if (!test_key(p, tctx, &handle, 0, true)) {
+                       ret = false;
+               }
+       }
+
+       test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
+
+       return ret;
+}
+
 static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
                      void *userdata)
 {
        struct policy_handle handle, newhandle;
-       bool ret = true, created = false, created2 = false, deleted = false;
+       bool ret = true, created = false, deleted = false;
        bool created3 = false, created_subkey = false;
-       bool created4 = false;
        struct winreg_OpenHKLM r;
 
        winreg_open_fn open_fn = userdata;
@@ -1721,15 +1774,13 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
        torture_assert_ntstatus_ok(tctx, open_fn(p, tctx, &r),
                                   "open");
 
-       test_Cleanup(p, tctx, &handle, TEST_KEY1);
-       test_Cleanup(p, tctx, &handle, TEST_SUBSUBKEY_SD);
-       test_Cleanup(p, tctx, &handle, TEST_SUBKEY_SD);
-       test_Cleanup(p, tctx, &handle, TEST_KEY4);
-       test_Cleanup(p, tctx, &handle, TEST_KEY2);
-       test_Cleanup(p, tctx, &handle, TEST_SUBKEY);
-       test_Cleanup(p, tctx, &handle, TEST_KEY3);
        test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
 
+       if (!test_CreateKey(p, tctx, &handle, TEST_KEY_BASE, NULL)) {
+               torture_comment(tctx,
+                               "CreateKey (TEST_KEY_BASE) failed\n");
+       }
+
        if (!test_CreateKey(p, tctx, &handle, TEST_KEY1, NULL)) {
                torture_comment(tctx,
                                "CreateKey failed - not considering a failure\n");
@@ -1763,9 +1814,12 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
        }
 
        if (created && deleted &&
-           test_OpenKey(p, tctx, &handle, TEST_KEY1, &newhandle)) {
+           !_test_OpenKey(p, tctx, &handle, TEST_KEY1,
+                          SEC_FLAG_MAXIMUM_ALLOWED, &newhandle,
+                          WERR_BADFILE, NULL)) {
                torture_comment(tctx,
-                               "DeleteKey failed (OpenKey after Delete worked)\n");
+                               "DeleteKey failed (OpenKey after Delete "
+                               "did not return WERR_BADFILE)\n");
                ret = false;
        }
 
@@ -1774,40 +1828,6 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
                ret = false;
        }
 
-       if (created && test_CreateKey_sd(p, tctx, &handle, TEST_KEY2,
-                                        NULL, &newhandle)) {
-               created2 = true;
-       }
-
-       if (created2 && !test_CloseKey(p, tctx, &newhandle)) {
-               printf("CloseKey failed\n");
-               ret = false;
-       }
-
-       if (test_CreateKey_sd(p, tctx, &handle, TEST_KEY4, NULL, &newhandle)) {
-               created4 = true;
-       }
-
-       if (!created4 && !test_CloseKey(p, tctx, &newhandle)) {
-               printf("CloseKey failed\n");
-               ret = false;
-       }
-
-       if (created4 && !test_SecurityDescriptors(p, tctx, &handle, TEST_KEY4)) {
-               ret = false;
-       }
-
-       if (created4 && !test_DeleteKey(p, tctx, &handle, TEST_KEY4)) {
-               printf("DeleteKey failed\n");
-               ret = false;
-       }
-
-
-       if (created && !test_DeleteKey(p, tctx, &handle, TEST_KEY2)) {
-               printf("DeleteKey failed\n");
-               ret = false;
-       }
-
        if (created && test_CreateKey(p, tctx, &handle, TEST_KEY3, NULL)) {
                created3 = true;
        }
@@ -1818,19 +1838,6 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
        }
 
        if (created_subkey &&
-           !test_DeleteKeyWithSubkey(p, tctx, &handle, TEST_KEY3)) {
-               printf("DeleteKeyWithSubkey failed "
-                      "(DeleteKey didn't return ACCESS_DENIED)\n");
-               ret = false;
-       }
-
-       if (created_subkey &&
-           !test_DeleteKey(p, tctx, &handle, TEST_SUBKEY)) {
-               printf("DeleteKey failed\n");
-               ret = false;
-       }
-
-       if (created3 &&
            !test_DeleteKey(p, tctx, &handle, TEST_KEY3)) {
                printf("DeleteKey failed\n");
                ret = false;
@@ -1838,13 +1845,13 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
 
        /* The HKCR hive has a very large fanout */
        if (open_fn == (void *)dcerpc_winreg_OpenHKCR) {
-               if(!test_key(p, tctx, &handle, MAX_DEPTH - 1)) {
+               if(!test_key(p, tctx, &handle, MAX_DEPTH - 1, false)) {
+                       ret = false;
+               }
+       } else {
+               if (!test_key(p, tctx, &handle, 0, false)) {
                        ret = false;
                }
-       }
-
-       if (!test_key(p, tctx, &handle, 0)) {
-               ret = false;
        }
 
        test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
@@ -1854,14 +1861,6 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
 
 struct torture_suite *torture_rpc_winreg(TALLOC_CTX *mem_ctx)
 {
-       struct {
-               const char *name;
-               winreg_open_fn fn;
-       } open_fns[] = {{"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
-                       {"OpenHKU",  (winreg_open_fn)dcerpc_winreg_OpenHKU },
-                       {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR },
-                       {"OpenHKCU", (winreg_open_fn)dcerpc_winreg_OpenHKCU }};
-       int i;
        struct torture_rpc_tcase *tcase;
        struct torture_suite *suite = torture_suite_create(mem_ctx, "WINREG");
        struct torture_test *test;
@@ -1877,10 +1876,33 @@ struct torture_suite *torture_rpc_winreg(TALLOC_CTX *mem_ctx)
                                          test_InitiateSystemShutdownEx);
        test->dangerous = true;
 
-       for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
-               torture_rpc_tcase_add_test_ex(tcase, open_fns[i].name,
-                                             test_Open, open_fns[i].fn);
-       }
+       /* Basic tests without security descriptors */
+       torture_rpc_tcase_add_test_ex(tcase, "HKLM-basic",
+                                     test_Open,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKLM);
+       torture_rpc_tcase_add_test_ex(tcase, "HKU-basic",
+                                     test_Open,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKU);
+       torture_rpc_tcase_add_test_ex(tcase, "HKCR-basic",
+                                     test_Open,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKCR);
+       torture_rpc_tcase_add_test_ex(tcase, "HKCU-basic",
+                                     test_Open,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKCU);
+
+       /* Security descriptor tests */
+       torture_rpc_tcase_add_test_ex(tcase, "HKLM-security",
+                                     test_Open_Security,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKLM);
+       torture_rpc_tcase_add_test_ex(tcase, "HKU-security",
+                                     test_Open_Security,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKU);
+       torture_rpc_tcase_add_test_ex(tcase, "HKCR-security",
+                                     test_Open_Security,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKCR);
+       torture_rpc_tcase_add_test_ex(tcase, "HKCU-security",
+                                     test_Open_Security,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKCU);
 
        return suite;
 }