mirror of
https://github.com/samba-team/samba.git
synced 2025-01-13 13:18:06 +03:00
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-gmake3
Conflicts: source/Makefile source/build/smb_build/makefile.pm source/librpc/config.mk
This commit is contained in:
commit
3e02fcfd3f
@ -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)/
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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},
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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. */
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -28,16 +28,22 @@
|
||||
/*
|
||||
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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
# Ignore no 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.
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
||||
printf("Trying rename directory\n");
|
||||
if (!torture_setup_dir(cli, path_dname)) {
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
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_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));
|
||||
}
|
||||
if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, path_fname))) {
|
||||
printf("Failed to delete %s - %s\n", path_fname, smbcli_errstr(cli->tree));
|
||||
}
|
||||
|
||||
smbcli_deltree(cli->tree, BASEDIR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -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,12 +1684,11 @@ 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(struct torture_context *tctx, struct dcerpc_pipe *p,
|
||||
void *userdata)
|
||||
static bool test_Open_Security(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 created3 = false, created_subkey = false;
|
||||
bool ret = true, created2 = false;
|
||||
bool created4 = false;
|
||||
struct winreg_OpenHKLM r;
|
||||
|
||||
@ -1721,15 +1701,86 @@ 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_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, deleted = false;
|
||||
bool created3 = false, created_subkey = 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(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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user