From 448b434a862da0ca621c3b695dc800e9ec5e8fcf Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Thu, 16 Apr 2009 10:25:29 +1000 Subject: In net_conf_import, start a transaction when importing a single share. Commit d69c3db9d44ad5d9fd1f5d7a9499f3bd79ecfb47 caused the transaction start to be conditional but the commit is still unconditional, so an error occurs when importing a single share. An alternate fix would be to return the transaction start to be unconditional but then it would occur before other error checking. Signed-off-by: Martin Schwenke Signed-off-by: Michael Adam --- source3/utils/net_conf.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3') 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; -- cgit From ea3a022ca3ed97f0ac3f16536832e8ec43683f8c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Apr 2009 14:56:35 +0200 Subject: Rename notify_context->db to db_recursive --- source3/smbd/notify_internal.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'source3') diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 1e45c54cbb..1b66865cb6 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -27,7 +27,7 @@ #include "librpc/gen_ndr/ndr_notify.h" struct notify_context { - struct db_context *db; + struct db_context *db_recursive; struct server_id server; struct messaging_context *messaging_ctx; struct notify_list *list; @@ -91,10 +91,10 @@ 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; } @@ -103,7 +103,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 +124,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 +142,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 +155,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 { -- cgit From 32a36e470333abae2745e27074a24ab54777b41e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Apr 2009 20:39:14 +0200 Subject: Add notify_onelevel.tdb This optimizes non-recursive notifys. For non-recursive notifies we can use a per-directory file-id indexed notify record. This matters for the Windows Explorer and IIS cases which do not use recursive notifies. In these cases, we do not have to shuffle around the whole notify record on every change. For the cluster case, this improves correctness of the notifies, ctdb only distributes the tdb seqnum once a second, so we can lose notifies. --- source3/include/proto.h | 5 + source3/librpc/gen_ndr/ndr_notify.c | 63 ++++++++ source3/librpc/gen_ndr/ndr_notify.h | 3 + source3/librpc/gen_ndr/notify.h | 7 + source3/librpc/idl/notify.idl | 5 + source3/smbd/files.c | 4 + source3/smbd/notify.c | 10 ++ source3/smbd/notify_internal.c | 286 ++++++++++++++++++++++++++++++++++++ 8 files changed, 383 insertions(+) (limited to 'source3') 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_0num_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 +#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/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/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 1b66865cb6..a42404db3e 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -28,6 +28,7 @@ struct notify_context { struct db_context *db_recursive; + struct db_context *db_onelevel; struct server_id server; struct messaging_context *messaging_ctx; struct notify_list *list; @@ -99,6 +100,14 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, 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; + } + notify->server = server; notify->messaging_ctx = messaging_ctx; notify->list = NULL; @@ -346,6 +355,96 @@ static NTSTATUS notify_add_array(struct notify_context *notify, struct db_record return notify_save(notify, rec); } +/* + 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. @@ -414,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 @@ -429,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; inum_entries; i++) { + if ((private_data == array->entries[i].private_data) && + cluster_id_equal(¬ify->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 */ @@ -577,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; inum_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; inum_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 -- cgit From 6fc8ed7b1fd57f22fba4793b3fc20f77bc7f7e83 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Apr 2009 12:09:16 -0700 Subject: Fix IDL licensing file that got missed when IDL files were moved. Jeremy. --- source3/librpc/idl/IDL_LICENSE.txt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 source3/librpc/idl/IDL_LICENSE.txt (limited to 'source3') 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. -- cgit From 265829c32fdeea2d00a75a21b4225211b24ea62d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Apr 2009 15:15:10 -0700 Subject: When doing a cli_ulogoff don't invalidate the cnum, invalidate the vuid. Jeremy. --- source3/libsmb/cliconnect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') 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; } -- cgit From d55ec4fd237ef6ebea2ee9a55c7d85dfe21f7737 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Apr 2009 16:19:10 -0700 Subject: Fix bug found by Tim Prouty, logging off and then re-using a vuid can cause smbd to access a freed structure. Jeremy. --- source3/smbd/uid.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3') 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", -- cgit From 37b1b9cfe90c81ec64486e68867fbd024250701f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Apr 2009 16:21:31 -0700 Subject: Add torture tester to ensure we don't regress the ulogoff bug. Jeremy. --- source3/torture/torture.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'source3') 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 -- cgit From deb719a62e0909d476b9817c45a32766dc9709d7 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 17 Apr 2009 01:30:16 +0200 Subject: s3-selftest: enable RPC-LSA-LOOKUPSIDS against samba 3. Guenther --- source3/script/tests/test_posix_s3.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') 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 -- cgit