summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs-xml/manpages-3/pam_winbind.7.xml9
-rw-r--r--docs-xml/smbdotconf/winbind/winbindnormalizenames.xml2
-rw-r--r--librpc/idl/IDL_LICENSE.txt9
-rw-r--r--source3/include/proto.h5
-rw-r--r--source3/librpc/gen_ndr/ndr_notify.c63
-rw-r--r--source3/librpc/gen_ndr/ndr_notify.h3
-rw-r--r--source3/librpc/gen_ndr/notify.h7
-rw-r--r--source3/librpc/idl/IDL_LICENSE.txt9
-rw-r--r--source3/librpc/idl/notify.idl5
-rw-r--r--source3/libsmb/cliconnect.c2
-rwxr-xr-xsource3/script/tests/test_posix_s3.sh2
-rw-r--r--source3/smbd/files.c4
-rw-r--r--source3/smbd/notify.c10
-rw-r--r--source3/smbd/notify_internal.c307
-rw-r--r--source3/smbd/uid.c11
-rw-r--r--source3/torture/torture.c45
-rw-r--r--source3/utils/net_conf.c8
-rw-r--r--source4/torture/rpc/lsa_lookup.c90
-rw-r--r--source4/torture/rpc/rpc.c1
19 files changed, 579 insertions, 13 deletions
diff --git a/docs-xml/manpages-3/pam_winbind.7.xml b/docs-xml/manpages-3/pam_winbind.7.xml
index 80f7dc8273..ff88de8197 100644
--- a/docs-xml/manpages-3/pam_winbind.7.xml
+++ b/docs-xml/manpages-3/pam_winbind.7.xml
@@ -142,8 +142,15 @@
</para></listitem>
</varlistentry>
- </variablelist>
+ <varlistentry>
+ <term>warn_pwd_expire</term>
+ <listitem><para>
+ Defines number of days before pam_winbind starts to warn about passwords that are
+ going to expire. Defaults to 14 days.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
</para>
diff --git a/docs-xml/smbdotconf/winbind/winbindnormalizenames.xml b/docs-xml/smbdotconf/winbind/winbindnormalizenames.xml
index 5b68bca912..ba7168665f 100644
--- a/docs-xml/smbdotconf/winbind/winbindnormalizenames.xml
+++ b/docs-xml/smbdotconf/winbind/winbindnormalizenames.xml
@@ -16,7 +16,7 @@
</para>
<para>This feature also enables the name aliasing API which can
- be used to make domain user and group names to a non-qlaified
+ be used to make domain user and group names to a non-qualified
version. Please refer to the manpage for the configured
idmap and nss_info plugin for the specifics on how to configure
name aliasing for a specific configuration. Name aliasing takes
diff --git a/librpc/idl/IDL_LICENSE.txt b/librpc/idl/IDL_LICENSE.txt
new file mode 100644
index 0000000000..01ae670b69
--- /dev/null
+++ b/librpc/idl/IDL_LICENSE.txt
@@ -0,0 +1,9 @@
+The IDL files in this directory are made available by the Samba Team
+under the following license:
+
+ Permission to use, copy, modify, and distribute these interface
+ definitions for any purpose is hereby granted without fee.
+
+ This work is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 25e81fde11..07e04edc3b 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6554,6 +6554,11 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0,
void (*callback)(void *, const struct notify_event *),
void *private_data);
NTSTATUS notify_remove(struct notify_context *notify, void *private_data);
+NTSTATUS notify_remove_onelevel(struct notify_context *notify,
+ const struct file_id *fid,
+ void *private_data);
+void notify_onelevel(struct notify_context *notify, uint32_t action,
+ uint32_t filter, struct file_id fid, const char *name);
void notify_trigger(struct notify_context *notify,
uint32_t action, uint32_t filter, const char *path);
diff --git a/source3/librpc/gen_ndr/ndr_notify.c b/source3/librpc/gen_ndr/ndr_notify.c
index d4ac42e961..844c278cd2 100644
--- a/source3/librpc/gen_ndr/ndr_notify.c
+++ b/source3/librpc/gen_ndr/ndr_notify.c
@@ -68,6 +68,69 @@ _PUBLIC_ void ndr_print_notify_entry(struct ndr_print *ndr, const char *name, co
ndr->depth--;
}
+_PUBLIC_ enum ndr_err_code ndr_push_notify_entry_array(struct ndr_push *ndr, int ndr_flags, const struct notify_entry_array *r)
+{
+ uint32_t cntr_entries_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->num_entries));
+ for (cntr_entries_0 = 0; cntr_entries_0 < r->num_entries; cntr_entries_0++) {
+ NDR_CHECK(ndr_push_notify_entry(ndr, NDR_SCALARS, &r->entries[cntr_entries_0]));
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ for (cntr_entries_0 = 0; cntr_entries_0 < r->num_entries; cntr_entries_0++) {
+ NDR_CHECK(ndr_push_notify_entry(ndr, NDR_BUFFERS, &r->entries[cntr_entries_0]));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_notify_entry_array(struct ndr_pull *ndr, int ndr_flags, struct notify_entry_array *r)
+{
+ uint32_t cntr_entries_0;
+ TALLOC_CTX *_mem_save_entries_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 8));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->num_entries));
+ NDR_PULL_ALLOC_N(ndr, r->entries, r->num_entries);
+ _mem_save_entries_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->entries, 0);
+ for (cntr_entries_0 = 0; cntr_entries_0 < r->num_entries; cntr_entries_0++) {
+ NDR_CHECK(ndr_pull_notify_entry(ndr, NDR_SCALARS, &r->entries[cntr_entries_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_entries_0, 0);
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ _mem_save_entries_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->entries, 0);
+ for (cntr_entries_0 = 0; cntr_entries_0 < r->num_entries; cntr_entries_0++) {
+ NDR_CHECK(ndr_pull_notify_entry(ndr, NDR_BUFFERS, &r->entries[cntr_entries_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_entries_0, 0);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_notify_entry_array(struct ndr_print *ndr, const char *name, const struct notify_entry_array *r)
+{
+ uint32_t cntr_entries_0;
+ ndr_print_struct(ndr, name, "notify_entry_array");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "num_entries", r->num_entries);
+ ndr->print(ndr, "%s: ARRAY(%d)", "entries", (int)r->num_entries);
+ ndr->depth++;
+ for (cntr_entries_0=0;cntr_entries_0<r->num_entries;cntr_entries_0++) {
+ char *idx_0=NULL;
+ if (asprintf(&idx_0, "[%d]", cntr_entries_0) != -1) {
+ ndr_print_notify_entry(ndr, "entries", &r->entries[cntr_entries_0]);
+ free(idx_0);
+ }
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
static enum ndr_err_code ndr_push_notify_depth(struct ndr_push *ndr, int ndr_flags, const struct notify_depth *r)
{
uint32_t cntr_entries_0;
diff --git a/source3/librpc/gen_ndr/ndr_notify.h b/source3/librpc/gen_ndr/ndr_notify.h
index 23d3d3fc0a..fa2972dbc6 100644
--- a/source3/librpc/gen_ndr/ndr_notify.h
+++ b/source3/librpc/gen_ndr/ndr_notify.h
@@ -10,6 +10,9 @@
enum ndr_err_code ndr_push_notify_entry(struct ndr_push *ndr, int ndr_flags, const struct notify_entry *r);
enum ndr_err_code ndr_pull_notify_entry(struct ndr_pull *ndr, int ndr_flags, struct notify_entry *r);
void ndr_print_notify_entry(struct ndr_print *ndr, const char *name, const struct notify_entry *r);
+enum ndr_err_code ndr_push_notify_entry_array(struct ndr_push *ndr, int ndr_flags, const struct notify_entry_array *r);
+enum ndr_err_code ndr_pull_notify_entry_array(struct ndr_pull *ndr, int ndr_flags, struct notify_entry_array *r);
+void ndr_print_notify_entry_array(struct ndr_print *ndr, const char *name, const struct notify_entry_array *r);
void ndr_print_notify_depth(struct ndr_print *ndr, const char *name, const struct notify_depth *r);
enum ndr_err_code ndr_push_notify_array(struct ndr_push *ndr, int ndr_flags, const struct notify_array *r);
enum ndr_err_code ndr_pull_notify_array(struct ndr_pull *ndr, int ndr_flags, struct notify_array *r);
diff --git a/source3/librpc/gen_ndr/notify.h b/source3/librpc/gen_ndr/notify.h
index a5ec4a46e6..a390fa8a0b 100644
--- a/source3/librpc/gen_ndr/notify.h
+++ b/source3/librpc/gen_ndr/notify.h
@@ -2,6 +2,8 @@
#include <stdint.h>
+#include "libcli/util/ntstatus.h"
+
#ifndef _HEADER_notify
#define _HEADER_notify
@@ -16,6 +18,11 @@ struct notify_entry {
void* private_data;
}/* [public] */;
+struct notify_entry_array {
+ uint32_t num_entries;
+ struct notify_entry *entries;
+}/* [public] */;
+
struct notify_depth {
uint32_t max_mask;
uint32_t max_mask_subdir;
diff --git a/source3/librpc/idl/IDL_LICENSE.txt b/source3/librpc/idl/IDL_LICENSE.txt
new file mode 100644
index 0000000000..01ae670b69
--- /dev/null
+++ b/source3/librpc/idl/IDL_LICENSE.txt
@@ -0,0 +1,9 @@
+The IDL files in this directory are made available by the Samba Team
+under the following license:
+
+ Permission to use, copy, modify, and distribute these interface
+ definitions for any purpose is hereby granted without fee.
+
+ This work is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/source3/librpc/idl/notify.idl b/source3/librpc/idl/notify.idl
index 550783b5cd..0e80679074 100644
--- a/source3/librpc/idl/notify.idl
+++ b/source3/librpc/idl/notify.idl
@@ -25,6 +25,11 @@ interface notify
pointer private_data;
} notify_entry;
+ typedef [public] struct {
+ uint32 num_entries;
+ notify_entry entries[num_entries];
+ } notify_entry_array;
+
/*
to allow for efficient search for matching entries, we
divide them by the directory depth, with a separate array
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 53a812d222..0ff9f253ef 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1211,7 +1211,7 @@ bool cli_ulogoff(struct cli_state *cli)
return False;
}
- cli->cnum = -1;
+ cli->vuid = -1;
return True;
}
diff --git a/source3/script/tests/test_posix_s3.sh b/source3/script/tests/test_posix_s3.sh
index b3a66e1db7..89a7ea73d2 100755
--- a/source3/script/tests/test_posix_s3.sh
+++ b/source3/script/tests/test_posix_s3.sh
@@ -40,7 +40,7 @@ raw="$raw RAW-SAMBA3ROOTDIRFID"
rpc="RPC-AUTHCONTEXT RPC-BINDSAMBA3 RPC-SAMBA3-SRVSVC RPC-SAMBA3-SHARESEC"
rpc="$rpc RPC-SAMBA3-SPOOLSS RPC-SAMBA3-WKSSVC"
rpc="$rpc RPC-NETLOGSAMBA3 RPC-SAMBA3SESSIONKEY RPC-SAMBA3-GETUSERNAME"
-rpc="$rpc RPC-SVCCTL RPC-SPOOLSS-WIN RPC-NTSVCS"
+rpc="$rpc RPC-SVCCTL RPC-SPOOLSS-WIN RPC-NTSVCS RPC-LSA-LOOKUPSIDS"
# NOTE: to enable the UNIX-WHOAMI test, we need to change the default share
# config to allow guest access. I'm not sure whether this would break other
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 36e80a086a..d2ea520146 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -433,6 +433,10 @@ void file_free(struct smb_request *req, files_struct *fsp)
}
if (fsp->notify) {
+ if (fsp->is_directory) {
+ notify_remove_onelevel(fsp->conn->notify_ctx,
+ &fsp->file_id, fsp);
+ }
notify_remove(fsp->conn->notify_ctx, fsp);
TALLOC_FREE(fsp->notify);
}
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index d141fb2180..12a75cc9f6 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -339,6 +339,9 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
const char *path)
{
char *fullpath;
+ char *parent;
+ const char *name;
+ SMB_STRUCT_STAT sbuf;
if (path[0] == '.' && path[1] == '/') {
path += 2;
@@ -348,6 +351,13 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
return;
}
+ if (parent_dirname(talloc_tos(), path, &parent, &name)
+ && (SMB_VFS_STAT(conn, parent, &sbuf) != -1)) {
+ notify_onelevel(conn->notify_ctx, action, filter,
+ SMB_VFS_FILE_ID_CREATE(conn, &sbuf),
+ name);
+ }
+
notify_trigger(conn->notify_ctx, action, filter, fullpath);
SAFE_FREE(fullpath);
}
diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c
index 1e45c54cbb..a42404db3e 100644
--- a/source3/smbd/notify_internal.c
+++ b/source3/smbd/notify_internal.c
@@ -27,7 +27,8 @@
#include "librpc/gen_ndr/ndr_notify.h"
struct notify_context {
- struct db_context *db;
+ struct db_context *db_recursive;
+ struct db_context *db_onelevel;
struct server_id server;
struct messaging_context *messaging_ctx;
struct notify_list *list;
@@ -91,10 +92,18 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
return NULL;
}
- notify->db = db_open(notify, lock_path("notify.tdb"),
- 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
- O_RDWR|O_CREAT, 0644);
- if (notify->db == NULL) {
+ notify->db_recursive = db_open(notify, lock_path("notify.tdb"),
+ 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
+ O_RDWR|O_CREAT, 0644);
+ if (notify->db_recursive == NULL) {
+ talloc_free(notify);
+ return NULL;
+ }
+
+ notify->db_onelevel = db_open(notify, lock_path("notify_onelevel.tdb"),
+ 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
+ O_RDWR|O_CREAT, 0644);
+ if (notify->db_onelevel == NULL) {
talloc_free(notify);
return NULL;
}
@@ -103,7 +112,8 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
notify->messaging_ctx = messaging_ctx;
notify->list = NULL;
notify->array = NULL;
- notify->seqnum = notify->db->get_seqnum(notify->db);
+ notify->seqnum = notify->db_recursive->get_seqnum(
+ notify->db_recursive);
notify->key = string_term_tdb_data(NOTIFY_KEY);
talloc_set_destructor(notify, notify_destructor);
@@ -123,7 +133,8 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
*/
static NTSTATUS notify_fetch_locked(struct notify_context *notify, struct db_record **rec)
{
- *rec = notify->db->fetch_locked(notify->db, notify, notify->key);
+ *rec = notify->db_recursive->fetch_locked(notify->db_recursive,
+ notify, notify->key);
if (*rec == NULL) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -140,7 +151,7 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec
NTSTATUS status;
int seqnum;
- seqnum = notify->db->get_seqnum(notify->db);
+ seqnum = notify->db_recursive->get_seqnum(notify->db_recursive);
if (seqnum == notify->seqnum && notify->array != NULL) {
return NT_STATUS_OK;
@@ -153,7 +164,8 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec
NT_STATUS_HAVE_NO_MEMORY(notify->array);
if (!rec) {
- if (notify->db->fetch(notify->db, notify, notify->key, &dbuf) != 0) {
+ if (notify->db_recursive->fetch(notify->db_recursive, notify,
+ notify->key, &dbuf) != 0) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
} else {
@@ -344,6 +356,96 @@ static NTSTATUS notify_add_array(struct notify_context *notify, struct db_record
}
/*
+ Add a non-recursive watch
+*/
+
+static void notify_add_onelevel(struct notify_context *notify,
+ struct notify_entry *e, void *private_data)
+{
+ struct notify_entry_array *array;
+ struct db_record *rec;
+ DATA_BLOB blob;
+ TDB_DATA dbuf;
+ enum ndr_err_code ndr_err;
+ NTSTATUS status;
+
+ array = talloc_zero(talloc_tos(), struct notify_entry_array);
+ if (array == NULL) {
+ return;
+ }
+
+ rec = notify->db_onelevel->fetch_locked(
+ notify->db_onelevel, talloc_tos(),
+ make_tdb_data((uint8_t *)&e->dir_id, sizeof(e->dir_id)));
+ if (rec == NULL) {
+ DEBUG(10, ("notify_add_onelevel: fetch_locked for %s failed"
+ "\n", file_id_string_tos(&e->dir_id)));
+ TALLOC_FREE(array);
+ return;
+ }
+
+ blob.data = (uint8_t *)rec->value.dptr;
+ blob.length = rec->value.dsize;
+
+ if (blob.length > 0) {
+ ndr_err = ndr_pull_struct_blob(
+ &blob, array, NULL, array,
+ (ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",
+ ndr_errstr(ndr_err)));
+ TALLOC_FREE(array);
+ return;
+ }
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10, ("notify_add_onelevel:\n"));
+ NDR_PRINT_DEBUG(notify_entry_array, array);
+ }
+ }
+
+ array->entries = talloc_realloc(array, array->entries,
+ struct notify_entry,
+ array->num_entries+1);
+ if (array->entries == NULL) {
+ TALLOC_FREE(array);
+ return;
+ }
+ array->entries[array->num_entries] = *e;
+ array->entries[array->num_entries].private_data = private_data;
+ array->entries[array->num_entries].server = notify->server;
+ array->num_entries += 1;
+
+ ndr_err = ndr_push_struct_blob(
+ &blob, rec, NULL, array,
+ (ndr_push_flags_fn_t)ndr_push_notify_entry_array);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(10, ("ndr_push_notify_entry_array failed: %s\n",
+ ndr_errstr(ndr_err)));
+ TALLOC_FREE(array);
+ return;
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10, ("notify_add_onelevel:\n"));
+ NDR_PRINT_DEBUG(notify_entry_array, array);
+ }
+
+ dbuf.dptr = blob.data;
+ dbuf.dsize = blob.length;
+
+ status = rec->store(rec, dbuf, TDB_REPLACE);
+ TALLOC_FREE(array);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("notify_add_onelevel: store failed: %s\n",
+ nt_errstr(status)));
+ return;
+ }
+ e->filter = 0;
+ return;
+}
+
+
+/*
add a notify watch. This is called when a notify is first setup on a open
directory handle.
*/
@@ -411,6 +513,11 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0,
}
}
+ if (e.filter != 0) {
+ notify_add_onelevel(notify, &e, private_data);
+ status = NT_STATUS_OK;
+ }
+
/* if the system notify handler couldn't handle some of the
filter bits, or couldn't handle a request for recursion
then we need to install it in the array used for the
@@ -426,6 +533,102 @@ done:
return status;
}
+NTSTATUS notify_remove_onelevel(struct notify_context *notify,
+ const struct file_id *fid,
+ void *private_data)
+{
+ struct notify_entry_array *array;
+ struct db_record *rec;
+ DATA_BLOB blob;
+ TDB_DATA dbuf;
+ enum ndr_err_code ndr_err;
+ NTSTATUS status;
+ int i;
+
+ array = talloc_zero(talloc_tos(), struct notify_entry_array);
+ if (array == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rec = notify->db_onelevel->fetch_locked(
+ notify->db_onelevel, talloc_tos(),
+ make_tdb_data((uint8_t *)fid, sizeof(*fid)));
+ if (rec == NULL) {
+ DEBUG(10, ("notify_remove_onelevel: fetch_locked for %s failed"
+ "\n", file_id_string_tos(fid)));
+ TALLOC_FREE(array);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ blob.data = (uint8_t *)rec->value.dptr;
+ blob.length = rec->value.dsize;
+
+ if (blob.length > 0) {
+ ndr_err = ndr_pull_struct_blob(
+ &blob, array, NULL, array,
+ (ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",
+ ndr_errstr(ndr_err)));
+ TALLOC_FREE(array);
+ return ndr_map_error2ntstatus(ndr_err);
+ }
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10, ("notify_remove_onelevel:\n"));
+ NDR_PRINT_DEBUG(notify_entry_array, array);
+ }
+ }
+
+ for (i=0; i<array->num_entries; i++) {
+ if ((private_data == array->entries[i].private_data) &&
+ cluster_id_equal(&notify->server,
+ &array->entries[i].server)) {
+ break;
+ }
+ }
+
+ if (i == array->num_entries) {
+ TALLOC_FREE(array);
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ array->entries[i] = array->entries[array->num_entries-1];
+ array->num_entries -= 1;
+
+ if (array->num_entries == 0) {
+ rec->delete_rec(rec);
+ TALLOC_FREE(array);
+ return NT_STATUS_OK;
+ }
+
+ ndr_err = ndr_push_struct_blob(
+ &blob, rec, NULL, array,
+ (ndr_push_flags_fn_t)ndr_push_notify_entry_array);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(10, ("ndr_push_notify_entry_array failed: %s\n",
+ ndr_errstr(ndr_err)));
+ TALLOC_FREE(array);
+ return ndr_map_error2ntstatus(ndr_err);
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10, ("notify_add_onelevel:\n"));
+ NDR_PRINT_DEBUG(notify_entry_array, array);
+ }
+
+ dbuf.dptr = blob.data;
+ dbuf.dsize = blob.length;
+
+ status = rec->store(rec, dbuf, TDB_REPLACE);
+ TALLOC_FREE(array);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("notify_add_onelevel: store failed: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+ return NT_STATUS_OK;
+}
+
/*
remove a notify watch. Called when the directory handle is closed
*/
@@ -574,6 +777,92 @@ static NTSTATUS notify_send(struct notify_context *notify, struct notify_entry *
return status;
}
+void notify_onelevel(struct notify_context *notify, uint32_t action,
+ uint32_t filter, struct file_id fid, const char *name)
+{
+ struct notify_entry_array *array;
+ TDB_DATA dbuf;
+ DATA_BLOB blob;
+ bool have_dead_entries = false;
+ int i;
+
+ array = talloc_zero(talloc_tos(), struct notify_entry_array);
+ if (array == NULL) {
+ return;
+ }
+
+ if (notify->db_onelevel->fetch(
+ notify->db_onelevel, array,
+ make_tdb_data((uint8_t *)&fid, sizeof(fid)),
+ &dbuf) == -1) {
+ TALLOC_FREE(array);
+ return;
+ }
+
+ blob.data = (uint8 *)dbuf.dptr;
+ blob.length = dbuf.dsize;
+
+ if (blob.length > 0) {
+ enum ndr_err_code ndr_err;
+ ndr_err = ndr_pull_struct_blob(
+ &blob, array, NULL, array,
+ (ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",
+ ndr_errstr(ndr_err)));
+ TALLOC_FREE(array);
+ return;
+ }
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10, ("notify_onelevel:\n"));
+ NDR_PRINT_DEBUG(notify_entry_array, array);
+ }
+ }
+
+ for (i=0; i<array->num_entries; i++) {
+ struct notify_entry *e = &array->entries[i];
+
+ if ((e->filter & filter) != 0) {
+ NTSTATUS status;
+
+ status = notify_send(notify, e, name, action);
+ if (NT_STATUS_EQUAL(
+ status, NT_STATUS_INVALID_HANDLE)) {
+ /*
+ * Mark the entry as dead. All entries have a
+ * path set. The marker used here is setting
+ * that to NULL.
+ */
+ e->path = NULL;
+ have_dead_entries = true;
+ }
+ }
+ }
+
+ if (!have_dead_entries) {
+ TALLOC_FREE(array);
+ return;
+ }
+
+ for (i=0; i<array->num_entries; i++) {
+ struct notify_entry *e = &array->entries[i];
+ if (e->path != NULL) {
+ continue;
+ }
+ DEBUG(10, ("Deleting notify entries for process %s because "
+ "it's gone\n", procid_str_static(&e->server)));
+ /*
+ * Potential TODO: This might need optimizing,
+ * notify_remove_onelevel() does a fetch_locked() operation at
+ * every call. But this would only matter if a process with
+ * MANY notifies has died without shutting down properly.
+ */
+ notify_remove_onelevel(notify, &e->dir_id, e->private_data);
+ }
+
+ TALLOC_FREE(array);
+ return;
+}
/*
trigger a notify message for anyone waiting on a matching event
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index f8c55b1b8f..b8ed321a45 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -164,6 +164,10 @@ void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid)
if (ent->vuid == vuid) {
ent->vuid = UID_FIELD_INVALID;
+ /* Ensure we're not freeing an active pointer. */
+ if (conn->server_info == ent->server_info) {
+ conn->server_info = NULL;
+ }
TALLOC_FREE(ent->server_info);
ent->read_only = False;
ent->admin_user = False;
@@ -216,6 +220,13 @@ bool change_to_user(connection_struct *conn, uint16 vuid)
server_info = vuser ? vuser->server_info : conn->server_info;
+ if (!server_info) {
+ /* Invalid vuid sent - even with security = share. */
+ DEBUG(2,("change_to_user: Invalid vuid %d used on "
+ "share %s.\n",vuid, lp_servicename(snum) ));
+ return false;
+ }
+
if (!check_user_ok(conn, vuid, server_info, snum)) {
DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
"not permitted access to share %s.\n",
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 804e772516..33358307ae 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -5199,6 +5199,50 @@ static bool run_cli_echo(int dummy)
return NT_STATUS_IS_OK(status);
}
+static bool run_uid_regression_test(int dummy)
+{
+ static struct cli_state *cli;
+ int16_t old_vuid;
+ bool correct = True;
+
+ printf("starting uid regression test\n");
+
+ if (!torture_open_connection(&cli, 0)) {
+ return False;
+ }
+
+ cli_sockopt(cli, sockops);
+
+ /* Ok - now save then logoff our current user. */
+ old_vuid = cli->vuid;
+
+ if (!cli_ulogoff(cli)) {
+ d_printf("(%s) cli_ulogoff failed: %s\n",
+ __location__, cli_errstr(cli));
+ correct = false;
+ goto out;
+ }
+
+ cli->vuid = old_vuid;
+
+ /* Try an operation. */
+ if (!cli_mkdir(cli, "\\uid_reg_test")) {
+ /* We expect bad uid. */
+ if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
+ NT_STATUS_NO_SUCH_USER)) {
+ return False;
+ }
+ goto out;
+ }
+
+ cli_rmdir(cli, "\\uid_reg_test");
+
+ out:
+
+ torture_close_connection(cli);
+ return correct;
+}
+
static bool run_local_substitute(int dummy)
{
bool ok = true;
@@ -5778,6 +5822,7 @@ static struct {
{"RW3", run_readwritelarge, 0},
{"OPEN", run_opentest, 0},
{"POSIX", run_simple_posix_open_test, 0},
+ { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
#if 1
{"OPENATTR", run_openattrtest, 0},
#endif
diff --git a/source3/utils/net_conf.c b/source3/utils/net_conf.c
index 3fa547baf4..663c5925c7 100644
--- a/source3/utils/net_conf.c
+++ b/source3/utils/net_conf.c
@@ -340,6 +340,14 @@ static int net_conf_import(struct net_context *c, struct smbconf_ctx *conf_ctx,
if (!W_ERROR_IS_OK(werr)) {
goto cancel;
}
+
+ werr = smbconf_transaction_start(conf_ctx);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_printf("error starting transaction: %s\n",
+ win_errstr(werr));
+ goto done;
+ }
+
werr = import_process_service(c, conf_ctx, service);
if (!W_ERROR_IS_OK(werr)) {
goto cancel;
diff --git a/source4/torture/rpc/lsa_lookup.c b/source4/torture/rpc/lsa_lookup.c
index 0124ce1741..0a4c9904d7 100644
--- a/source4/torture/rpc/lsa_lookup.c
+++ b/source4/torture/rpc/lsa_lookup.c
@@ -88,6 +88,7 @@ static NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, uint16_t level,
{
struct lsa_LookupSids r;
struct lsa_SidArray sidarray;
+ struct lsa_RefDomainList *domains;
uint32_t count = 0;
uint32_t i;
@@ -108,6 +109,7 @@ static NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, uint16_t level,
r.in.count = &count;
r.out.names = names;
r.out.count = &count;
+ r.out.domains = &domains;
return dcerpc_lsa_LookupSids(p, mem_ctx, &r);
}
@@ -322,3 +324,91 @@ bool torture_rpc_lsa_lookup(struct torture_context *torture)
return ret;
}
+
+static bool test_LookupSidsReply(struct torture_context *tctx,
+ struct dcerpc_pipe *p)
+{
+ struct policy_handle *handle;
+
+ struct dom_sid **sids;
+ uint32_t num_sids = 1;
+
+ struct lsa_LookupSids r;
+ struct lsa_SidArray sidarray;
+ struct lsa_RefDomainList *domains = NULL;
+ struct lsa_TransNameArray names;
+ uint32_t count = 0;
+
+ uint32_t i;
+ NTSTATUS status;
+ const char *dom_sid = "S-1-5-21-1111111111-2222222222-3333333333";
+ const char *dom_admin_sid;
+
+ if (!open_policy(tctx, p, &handle)) {
+ return false;
+ }
+
+ dom_admin_sid = talloc_asprintf(tctx, "%s-%d", dom_sid, 512);
+
+ sids = talloc_array(tctx, struct dom_sid *, num_sids);
+
+ sids[0] = dom_sid_parse_talloc(tctx, dom_admin_sid);
+
+ names.count = 0;
+ names.names = NULL;
+
+ sidarray.num_sids = num_sids;
+ sidarray.sids = talloc_array(tctx, struct lsa_SidPtr, num_sids);
+
+ for (i=0; i<num_sids; i++) {
+ sidarray.sids[i].sid = sids[i];
+ }
+
+ r.in.handle = handle;
+ r.in.sids = &sidarray;
+ r.in.names = &names;
+ r.in.level = LSA_LOOKUP_NAMES_ALL;
+ r.in.count = &count;
+ r.out.names = &names;
+ r.out.count = &count;
+ r.out.domains = &domains;
+
+ status = dcerpc_lsa_LookupSids(p, tctx, &r);
+
+ torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NONE_MAPPED,
+ "unexpected error code");
+
+ torture_assert_int_equal(tctx, names.count, num_sids,
+ "unexpected names count");
+ torture_assert(tctx, names.names,
+ "unexpected names pointer");
+ torture_assert_str_equal(tctx, names.names[0].name.string, dom_admin_sid,
+ "unexpected names[0].string");
+
+#if 0
+ /* vista sp1 passes, w2k3 sp2 fails */
+ torture_assert_int_equal(tctx, domains->count, num_sids,
+ "unexpected domains count");
+ torture_assert(tctx, domains->domains,
+ "unexpected domains pointer");
+ torture_assert_str_equal(tctx, dom_sid_string(tctx, domains->domains[0].sid), dom_sid,
+ "unexpected domain sid");
+#endif
+
+ return true;
+}
+
+/* check for lookup sids results */
+struct torture_suite *torture_rpc_lsa_lookup_sids(TALLOC_CTX *mem_ctx)
+{
+ struct torture_suite *suite;
+ struct torture_rpc_tcase *tcase;
+
+ suite = torture_suite_create(mem_ctx, "LSA-LOOKUPSIDS");
+ tcase = torture_suite_add_rpc_iface_tcase(suite, "lsa",
+ &ndr_table_lsarpc);
+
+ torture_rpc_tcase_add_test(tcase, "LookupSidsReply", test_LookupSidsReply);
+
+ return suite;
+}
diff --git a/source4/torture/rpc/rpc.c b/source4/torture/rpc/rpc.c
index 069bb51a89..5624c32b96 100644
--- a/source4/torture/rpc/rpc.c
+++ b/source4/torture/rpc/rpc.c
@@ -378,6 +378,7 @@ NTSTATUS torture_rpc_init(void)
torture_suite_add_simple_test(suite, "LSA", torture_rpc_lsa);
torture_suite_add_simple_test(suite, "LSALOOKUP", torture_rpc_lsa_lookup);
torture_suite_add_simple_test(suite, "LSA-GETUSER", torture_rpc_lsa_get_user);
+ torture_suite_add_suite(suite, torture_rpc_lsa_lookup_sids(suite));
torture_suite_add_suite(suite, torture_rpc_lsa_secrets(suite));
torture_suite_add_suite(suite, torture_rpc_echo(suite));
torture_suite_add_simple_test(suite, "DFS", torture_rpc_dfs);