typedef struct files_struct {
struct files_struct *next, *prev;
int fnum;
- struct smbXsrv_open0 *smbXsrv;
struct connection_struct *conn;
struct fd_handle *fh;
unsigned int num_smb_operations;
struct auth_session_info *session_info;
struct gensec_security *gensec_security;
-
- struct smbXsrv_session0 *session;
} user_struct;
/*
#ifdef HAVE_CTDB_CONTROL_CHECK_SRVIDS_DECL
if (lp_clustering()) {
-// return ctdb_serverids_exist(messaging_ctdbd_connection(),
-// ids, num_ids, results);
+ return ctdb_serverids_exist(messaging_ctdbd_connection(),
+ ids, num_ids, results);
}
#endif
if (!processes_exist(ids, num_ids, results)) {
if (!results[i]) {
continue;
}
-#if 0
- typedef [public] struct {
- hyper pid;
- uint32 task_id;
- uint32 vnn;
- hyper unique_id;
- } server_id;
-#endif
- if (ids[i].unique_id == UINT64_MAX) {
- // bug #8760 :-)
- continue;
- }
serverid_fill_key(&ids[i], &key);
tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
num_remote_pids = 0;
for (i=0; i<num_pids; i++) {
- results[i] = false;
-
if (procid_is_me(&pids[i])) {
results[i] = true;
continue;
}
-#if 0
- typedef [public] struct {
- hyper pid;
- uint32 task_id;
- uint32 vnn;
- hyper unique_id;
- } server_id;
-#endif
- if (pids[i].pid == UINT64_MAX &&
- pids[i].task_id == UINT32_MAX &&
- pids[i].vnn == UINT32_MAX &&
- pids[i].unique_id == UINT64_MAX) {
- // bug #8760 :-) :-) ok
- results[i] = true;
- continue;
- }
if (procid_is_local(&pids[i])) {
results[i] = ((kill(pids[i].pid,0) == 0) ||
(errno != ESRCH));
static void add_share_mode_entry(struct share_mode_data *d,
const struct share_mode_entry *entry)
{
- uint32_t i = 0;
-
- while (i < d->num_share_modes) {
- struct share_mode_entry *e = &d->share_modes[i];
- if (e->pid.pid == UINT64_MAX &&
- e->pid.task_id == UINT32_MAX &&
- e->pid.vnn == UINT32_MAX &&
- e->pid.unique_id == UINT64_MAX) {
- *e = d->share_modes[d->num_share_modes-1];
- d->num_share_modes -= 1;
- d->modified = True;
- continue;
- }
-
- i += 1;
- }
-
ADD_TO_ARRAY(d, struct share_mode_entry, *entry,
&d->share_modes, &d->num_share_modes);
d->modified = True;
bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
{
struct share_mode_entry entry, *e;
- uint32_t i = 0;
/* Don't care about the pid owner being correct here - just a search. */
fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
*e = lck->data->share_modes[lck->data->num_share_modes-1];
lck->data->num_share_modes -= 1;
lck->data->modified = True;
-
- while (i < lck->data->num_share_modes) {
- e = &lck->data->share_modes[i];
-
- if (e->pid.pid == UINT64_MAX &&
- e->pid.task_id == UINT32_MAX &&
- e->pid.vnn == UINT32_MAX &&
- e->pid.unique_id == UINT64_MAX) {
- *e = lck->data->share_modes[lck->data->num_share_modes-1];
- lck->data->num_share_modes -= 1;
- continue;
- }
-
- i += 1;
- }
-
return True;
}
DEBUG(10, ("parse_share_modes:\n"));
NDR_PRINT_DEBUG(share_mode_data, d);
}
-#if 0
- typedef [public] struct {
- hyper pid;
- uint32 task_id;
- uint32 vnn;
- hyper unique_id;
- } server_id;
-#endif
- if (d->num_share_modes == 1) {
- struct share_mode_entry *e = &d->share_modes[0];
-
- if (e->pid.pid == UINT64_MAX &&
- e->pid.task_id == UINT32_MAX &&
- e->pid.vnn == UINT32_MAX &&
- e->pid.unique_id == UINT64_MAX) {
- return d;
- }
- }
-//return d;
/*
* Ensure that each entry has a real process attached.
*/
d->modified = True;
continue;
}
- if (e->pid.pid == UINT64_MAX &&
- e->pid.task_id == UINT32_MAX &&
- e->pid.vnn == UINT32_MAX &&
- e->pid.unique_id == UINT64_MAX) {
- *e = d->share_modes[d->num_share_modes-1];
- d->num_share_modes -= 1;
- d->modified = True;
- continue;
- }
-
i += 1;
}
TALLOC_FREE(pid_exists);
status, map_nt_error_from_unix(ret));
}
- if (fsp->smbXsrv->global->durable && close_type == SHUTDOWN_CLOSE) {
- struct share_mode_lock *lck;
-
- lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
- if (lck != NULL && lck->data->num_share_modes == 1) {
- lck->data->share_modes[0].pid.pid = UINT64_MAX;
- lck->data->share_modes[0].pid.task_id = UINT32_MAX;
- lck->data->share_modes[0].pid.vnn = UINT32_MAX;
- lck->data->share_modes[0].pid.unique_id = UINT64_MAX; //todo place NTTIME expire timer here
- lck->data->modified = true;
-#if 0
- } else if (lck != NULL) {
- uint32_t i;
-
- for (i=0; i < lck->data->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->data->share_modes[i];
- char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
-
- if (procid_is_me(&e->pid)) {
- continue;
- }
-
- share_mode_entry_to_message(msg, e);
-
- messaging_send_buf(fsp->conn->sconn->msg_ctx,
- e->pid,
- MSG_SMB_BREAK_RESPONSE,
- (uint8 *)msg,
- MSG_SMB_SHARE_MODE_ENTRY_SIZE);
- }
- }
-#endif
-
- tmp = close_filestruct(fsp);
- status = ntstatus_keeperror(status, tmp);
-
- if (fsp->oplock_type == LEVEL_II_OPLOCK) {
- level_II_oplocks_open--;
- } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
- exclusive_oplocks_open--;
- }
-
- SMB_ASSERT(exclusive_oplocks_open>=0);
- SMB_ASSERT(level_II_oplocks_open>=0);
-
- TALLOC_FREE(lck);
-
- tmp = fd_close(fsp);
- status = ntstatus_keeperror(status, tmp);
- file_free(req, fsp);
- return status;
- }
-
- TALLOC_FREE(lck);
-
-#if 0
- TALLOC_FREE(lck);
-
- tmp = fd_close(fsp);
- status = ntstatus_keeperror(status, tmp);
- file_free(req, fsp);
- return status;
-#endif
- }
-
/*
* If we're flushing on a close we can get a write
* error here, we must remember this.
#include <ccan/hash/hash.h>
#include "lib/util/bitmap.h"
+#define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files))
+
#define FILE_HANDLE_OFFSET 0x1000
/****************************************************************************
if (sconn->file_gen_counter == 0) {
sconn->file_gen_counter += 1;
}
-
return sconn->file_gen_counter;
}
files_struct **result)
{
struct smbd_server_connection *sconn = conn->sconn;
+ int i;
files_struct *fsp;
NTSTATUS status;
- struct smbXsrv_open *op;
- NTTIME now = 0;
+
+ /* we want to give out file handles differently on each new
+ connection because of a common bug in MS clients where they try to
+ reuse a file descriptor from an earlier smb connection. This code
+ increases the chance that the errant client will get an error rather
+ than causing corruption */
+ if (sconn->first_file == 0) {
+ sconn->first_file = (getpid() ^ (int)time(NULL));
+ sconn->first_file %= sconn->real_max_open_files;
+ }
+
+ /* TODO: Port the id-tree implementation from Samba4 */
+
+ i = bitmap_find(sconn->file_bmap, sconn->first_file);
+ if (i == -1) {
+ DEBUG(0,("ERROR! Out of file structures\n"));
+ /* TODO: We have to unconditionally return a DOS error here,
+ * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
+ * NTSTATUS negotiated */
+ return NT_STATUS_TOO_MANY_OPENED_FILES;
+ }
/*
* Make a child of the connection_struct as an fsp can't exist
fsp->fh->gen_id = get_gen_count(sconn);
GetTimeOfDay(&fsp->open_time);
- if (sconn->conn) {
- status = smbXsrv_open_create(sconn->conn, now, &op);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(fsp);
- return status;
- }
- fsp->smbXsrv = op;
- op->fsp = fsp;
- fsp->fnum = op->local_id;
- } else {
- /*
- * hack for printer driver upload
- */
-/* if (sconn->files_used > 0) {
- TALLOC_FREE(fsp);
- return NT_STATUS_INSUFFICIENT_RESOURCES;
- }
-*/ fsp->fnum = -1;
- }
+ sconn->first_file = (i+1) % (sconn->real_max_open_files);
+
+ bitmap_set(sconn->file_bmap, i);
- //talloc_set_destructor(fsp, smbd_fsp_destructor);
+ fsp->fnum = i + FILE_HANDLE_OFFSET;
+ SMB_ASSERT(fsp->fnum < 65536);
/*
* Create an smb_filename with "" for the base_name. There are very
DLIST_ADD(sconn->files, fsp);
sconn->num_files += 1;
- DEBUG(5,("allocated file structure, fnum = %d (%u used)\n",
- fsp->fnum, (unsigned int)sconn->num_files));
+ DEBUG(5,("allocated file structure %d, fnum = %d (%u used)\n",
+ i, fsp->fnum, (unsigned int)sconn->num_files));
if (req != NULL) {
req->chain_fsp = fsp;
for (fsp=conn->sconn->files; fsp; fsp=next) {
next = fsp->next;
- if (fsp->conn != conn) {
- continue;
- }
- if (conn->sconn->using_smb2 && fsp->smbXsrv->global->durable) {
- close_file(NULL, fsp, NORMAL_CLOSE);
- } else {
+ if (fsp->conn == conn) {
close_file(NULL, fsp, SHUTDOWN_CLOSE);
}
}
SMB_ASSERT(sconn->real_max_open_files > 100);
+ sconn->file_bmap = bitmap_talloc(sconn, sconn->real_max_open_files);
+
+ if (!sconn->file_bmap) {
+ return false;
+ }
return true;
}
/* Ensure this event will never fire. */
TALLOC_FREE(fsp->update_write_time_event);
- TALLOC_FREE(fsp->smbXsrv);
-
+ bitmap_clear(sconn->file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
DEBUG(5,("freed files structure %d (%u used)\n",
fsp->fnum, (unsigned int)sconn->num_files));
static struct files_struct *file_fnum(struct smbd_server_connection *sconn,
uint16 fnum)
{
- NTSTATUS status;
- struct smbXsrv_open *op;
- NTTIME now = 0;
files_struct *fsp;
int count=0;
- if (sconn->conn == NULL) {
- return NULL;
- }
-
- status = smb1srv_open_lookup(&sconn->conn->open_table,
- fnum, now, &op);
- if (!NT_STATUS_IS_OK(status)) {
- return NULL;
- }
-
- return op->fsp;
-
for (fsp=sconn->files; fsp; fsp=fsp->next, count++) {
if (fsp->fnum == fnum) {
if (count > 10) {
NTTIME now,
struct smbXsrv_open **_open);
NTSTATUS smbXsrv_open_update(struct smbXsrv_open *_open);
+
NTSTATUS smb1srv_open_table_init(struct smbXsrv_connection *conn);
NTSTATUS smb1srv_open_lookup(struct smbXsrv_open_table *table,
uint16_t vuid, NTTIME now,
struct smbXsrv_open **_open);
+
NTSTATUS smb2srv_open_table_init(struct smbXsrv_connection *conn);
NTSTATUS smb2srv_open_lookup(struct smbXsrv_open_table *table,
uint64_t open_id, NTTIME now,
uint64_t vuid;
struct gensec_security *gensec_security;
struct auth_session_info *session_info;
- //DATA_BLOB session_key;
- //bool do_signing;
-
- struct smbXsrv_session *smbXsrv;
+ DATA_BLOB session_key;
+ bool do_signing;
user_struct *compat_vuser;
size_t num_files;
struct files_struct *files;
+ struct bitmap *file_bmap;
int real_max_open_files;
struct fsp_singleton_cache fsp_fi_cache;
unsigned long file_gen_counter;
+ int first_file;
struct pending_message_list *deferred_open_queue;
struct tstream_context *stream;
bool negprot_2ff;
struct {
+ /* an id tree used to allocate vuids */
+ /* this holds info on session vuids that are already
+ * validated for this VC */
+ struct idr_context *idtree;
+
+ /* this is the limit of vuid values for this connection */
+ uint64_t limit;
+
struct smbd_smb2_session *list;
} sessions;
struct {
bool supports_multicredit;
struct bitmap *credits_bitmap;
bool compound_related_in_progress;
- DATA_BLOB serverguid;
- uint32_t capabilities;
} smb2;
struct smbXsrv_connection *conn;
(unsigned int)entry->share_access,
(unsigned int)entry->private_options));
- if (entry->pid.pid == UINT64_MAX) {
- return false;
- }
-
DEBUG(10,("share_conflict: access_mask = 0x%x, share_access = 0x%x\n",
(unsigned int)access_mask, (unsigned int)share_access));
return false;
}
- if (batch_entry->pid.pid == UINT64_MAX) {
- /* TODO: clean up */
- return false;
- }
-
/* Found a batch oplock */
send_break_message(fsp, batch_entry, mid, oplock_request);
return true;
return false;
}
- if (ex_entry->pid.pid == UINT64_MAX) {
- /* TODO: clean up */
- return false;
- }
-
/* Found an exclusive or batch oplock */
delay_it = is_delete_request(fsp) ?
int register_initial_vuid(struct smbd_server_connection *sconn)
{
user_struct *vuser;
- NTSTATUS status;
/* Limit allowed vuids to 16bits - VUID_OFFSET. */
if (sconn->num_users >= 0xFFFF-VUID_OFFSET) {
sconn->num_users++;
DLIST_ADD(sconn->users, vuser);
- status = smbXsrv_session_create(sconn->conn,
- 0, /* now */
- &vuser->session);
- DEBUG(0,("%s: smbXsrv_session_create() %s\n",
- __location__, nt_errstr(status)));
-
return vuser->vuid;
}
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
uint8_t in_oplock_level,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile);
static NTSTATUS smbd_smb2_oplock_break_recv(struct tevent_req *req,
uint8_t *out_oplock_level);
in_file_id_persistent = BVAL(inbody, 0x08);
in_file_id_volatile = BVAL(inbody, 0x10);
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
subreq = smbd_smb2_oplock_break_send(req,
req->sconn->ev_ctx,
req,
in_oplock_level,
- in_file_id_persistent,
in_file_id_volatile);
if (subreq == NULL) {
return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
uint8_t in_oplock_level,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile)
{
struct tevent_req *req;
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
}
- if (smb2req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
if (conn != fsp->conn) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
(unsigned int)smb2_oplock_level ));
status = smbd_smb2_send_oplock_break(fsp->conn->sconn,
- (uint64_t)fsp->smbXsrv->global->open_persistent_id,
- (uint64_t)fsp->smbXsrv->global->open_volatile_id,
+ (uint64_t)fsp->fnum,
+ (uint64_t)fsp->fnum,
smb2_oplock_level);
if (!NT_STATUS_IS_OK(status)) {
smbd_server_connection_terminate(fsp->conn->sconn,
static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
uint16_t in_flags,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
DATA_BLOB *outbody);
in_file_id_persistent = BVAL(inbody, 0x08);
in_file_id_volatile = BVAL(inbody, 0x10);
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
status = smbd_smb2_close(req,
in_flags,
- in_file_id_persistent,
in_file_id_volatile,
&outbody);
if (!NT_STATUS_IS_OK(status)) {
static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
uint16_t in_flags,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
DATA_BLOB *outbody)
{
if (fsp == NULL) {
return NT_STATUS_FILE_CLOSED;
}
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- return NT_STATUS_FILE_CLOSED;
- }
if (conn != fsp->conn) {
return NT_STATUS_FILE_CLOSED;
}
#include "smbd/globals.h"
#include "../libcli/smb/smb_common.h"
#include "../librpc/gen_ndr/ndr_security.h"
-#include "libcli/security/security.h"
#include "../lib/util/tevent_ntstatus.h"
#include "messages.h"
-#include "librpc/gen_ndr/open_files.h"
-#include "serverid.h"
int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level)
{
}
}
-/*
- * TODO: needs to be moved - copied from source3/smbd/files.c
- */
-static unsigned long get_gen_count(struct smbd_server_connection *sconn)
-{
- sconn->file_gen_counter += 1;
- if (sconn->file_gen_counter == 0) {
- sconn->file_gen_counter += 1;
- }
-
- return sconn->file_gen_counter;
-}
-
-static NTSTATUS new_durable_reconnect_fsp(struct smbXsrv_open *op,
- struct connection_struct *conn,
- struct smb_filename *smb_fname,
- TALLOC_CTX *mem_ctx,
- files_struct **_fsp)
-{
- NTSTATUS status = NT_STATUS_NO_MEMORY;
- files_struct *fsp = NULL;
- TALLOC_CTX *frame = talloc_stackframe();
- struct smbd_server_connection *sconn = op->connection->sconn;
-
- fsp = talloc_zero(frame, struct files_struct);
- if (fsp == NULL) {
- goto fail;
- }
-
- /*
- * This can't be a child of fsp because the file_handle can be ref'd
- * when doing a dos/fcb open, which will then share the file_handle
- * across multiple fsps.
- */
- fsp->fh = talloc_zero(frame, struct fd_handle);
- if (fsp->fh == NULL) {
- goto fail;
- }
-
- fsp->fh->ref_count = 1;
- fsp->fh->fd = -1;
- fsp->fh->gen_id = get_gen_count(sconn);
-
- fsp->conn = conn;
-
- status = fsp_set_smb_fname(fsp, smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
-
-
- /* success */
-
- talloc_steal(mem_ctx, fsp);
- talloc_steal(mem_ctx, fsp->fh);
- *_fsp = fsp;
-
- status = NT_STATUS_OK;
-
-fail:
- talloc_free(frame);
- return status;
-}
-
-static NTSTATUS smb2_create_durable_reconnect(struct smbXsrv_open *op,
- struct connection_struct *conn,
- struct smb_request *smb1req,
- struct smb_filename *smb_fname,
- TALLOC_CTX *mem_ctx,
- files_struct **_fsp,
- int *info)
-{
- struct share_mode_lock *sharemode_lock;
- struct share_mode_entry *e;
- files_struct *fsp = NULL;
- NTSTATUS status;
- bool ok;
-
-DEBUG(0, ("OBNOX - durable_reconnect enter: (%s:%s)\n", __location__, __FUNCTION__));
-
- /* 1. check entry in locking.tdb */
-
- sharemode_lock = get_existing_share_mode_lock(mem_ctx,
- op->global->backend_file_id);
- if (sharemode_lock == NULL) {
- /* TODO: use/create other fetch func with better error code */
-DEBUG(0, ("OBNOX - durable_reconnect: share-mode lock not obtained from db (%s:%s)\n", __location__, __FUNCTION__));
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
-
- if (sharemode_lock->data->num_share_modes == 0) {
- /* should not happen? internal error? */
-DEBUG(0, ("OBNOX - durable_reconnect: no share-mode entry (%s:%s)\n", __location__, __FUNCTION__));
- return NT_STATUS_INTERNAL_DB_ERROR;
- }
-
- if (sharemode_lock->data->num_share_modes > 1) {
- /*
- * It can't be durable if there is more than one handle
- * on the file.
- */
-DEBUG(0, ("OBNOX - durable_reconnect: more than one share-mode entry - can't be durable (%s:%s)\n", __location__, __FUNCTION__));
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
-
- e = &sharemode_lock->data->share_modes[0];
-
- if (e->pid.pid != UINT64_MAX && serverid_exists(&e->pid)) {
- /*
- * server still exists
- * TODO: check whether session exists
- * (could have been a session_logoff())
- */
-DEBUG(0, ("OBNOX - durable_reconnect: serverid exists - denying access to durable (%s:%s)\n", __location__, __FUNCTION__));
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
-
- /* 2. proceed with opening file */
-
- /*
- * circumstances seems ok, do the open
- */
- status = new_durable_reconnect_fsp(op, conn, smb_fname, conn, &fsp);
- if (!NT_STATUS_IS_OK(status)) {
-DEBUG(0, ("OBNOX - durable_reconnect: failed to create new fsp: %s (%s:%s)\n", nt_errstr(status), __location__, __FUNCTION__));
- return status;
- }
-
-DEBUG(0, ("OBNOX - durable_reconnect: new fsp created (%s:%s)\n", __location__, __FUNCTION__));
-
- fsp->fh->private_options = e->private_options;
- fsp->file_id = op->global->backend_file_id;
- fsp->initial_allocation_size = 0;//TODO
- fsp->file_pid = smb1req->smbpid;
- fsp->vuid = smb1req->vuid;//
- fsp->open_time = e->time;
- fsp->access_mask = e->access_mask;
- fsp->share_access = e->share_access;
- fsp->can_lock = true;//from->can_lock;
- fsp->can_read = (fsp->access_mask & (FILE_READ_DATA)) ? True : False;
- if (!CAN_WRITE(conn)) {
- fsp->can_write = False;
- } else {
- fsp->can_write = (fsp->access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
- }
- fsp->modified = false;//from->modified;
- fsp->is_directory = false;//from->is_directory;
- fsp->aio_write_behind = false;//from->aio_write_behind;
-
- fsp->oplock_type = e->op_type;
-
-
- sharemode_lock->data->modified = true;
- e->pid = messaging_server_id(op->connection->sconn->msg_ctx);
- e->op_mid = smb1req->mid;
- e->share_file_id = fsp->fh->gen_id;
-
-DEBUG(0, ("OBNOX - durable_reconnect: before open file (%s:%s)\n", __location__, __FUNCTION__));
-
-
- fsp->fh->fd = SMB_VFS_OPEN(conn,
- smb_fname,
- fsp,
- e->flags | O_RDWR, /* TODO: parse open flags */
- 0 /* mode */);
- if (fsp->fh->fd == -1) {
- status = map_nt_error_from_unix(errno);
-DEBUG(0, ("OBNOX - durable_reconnect: failed to open file: %s (%s:%s)\n", nt_errstr(status), __location__, __FUNCTION__));
- return status;
- }
-
- ok = set_file_oplock(fsp, e->op_type);
-
- DLIST_ADD(conn->sconn->files, fsp);
- conn->sconn->num_files += 1;
-
- DEBUG(5,("allocated file structure, fnum = %d (%d used)\n",
- fsp->fnum, (unsigned int)conn->sconn->num_files));
-
- smb1req->chain_fsp = fsp;
-
-DEBUG(0, ("OBNOX - durable_reconnect: opened file (%s:%s)\n", __location__, __FUNCTION__));
-
- /* - release the sharemode lock: this writes the changes */
- talloc_free(sharemode_lock);
-
-
- /* Q: do this in fsp creation? */
- op->fsp = fsp;
- fsp->smbXsrv = op;
- *_fsp = fsp;
-
- /*
- * - return
- *
- * ... think about seek()
- */
-
- *info = FILE_WAS_OPENED;
- return NT_STATUS_OK;
-}
-
struct smbd_smb2_create_state {
struct smbd_smb2_request *smb2req;
struct smb_request *smb1req;
struct timespec write_time_ts;
struct smb2_create_blobs out_context_blobs;
int requested_oplock_level;
- struct smbXsrv_open *op = NULL;
ZERO_STRUCT(out_context_blobs);
uint64_t allocation_size = 0;
struct smb2_create_blob *twrp = NULL;
struct smb2_create_blob *qfid = NULL;
- struct smb2_create_blob *dh2q = NULL;
- struct smb2_create_blob *dh2c = NULL;
- bool do_durable_reconnect = false;
- bool persistent_requested = false;
- bool persistent_granted = false;
- uint32_t durable_v2_timeout = 0;
exta = smb2_create_blob_find(&in_context_blobs,
SMB2_CREATE_TAG_EXTA);
SMB2_CREATE_TAG_TWRP);
qfid = smb2_create_blob_find(&in_context_blobs,
SMB2_CREATE_TAG_QFID);
- dh2q = smb2_create_blob_find(&in_context_blobs,
- SMB2_CREATE_TAG_DH2Q);
- dh2c = smb2_create_blob_find(&in_context_blobs,
- SMB2_CREATE_TAG_DH2C);
fname = talloc_strdup(state, in_name);
if (tevent_req_nomem(fname, req)) {
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
-
-
- /*
- * durable handle request is processed below.
- */
- }
-
- if (dh2q) {
- uint32_t dh2q_flags;
-
- if (dh2q->data.length != 32) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- /* TODO - sanity checks - other blobs */
-
- /*
- * durable handle v2 request processed below
- */
-
- durable_v2_timeout = SVAL(dh2q->data.data, 0);
- dh2q_flags = SVAL(dh2q->data.data, 4);
- persistent_requested = dh2q_flags & SMB2_DHANDLE_FLAG_PERSISTENT;
-
- persistent_granted = persistent_requested;
-
/*
- * TODO: extract create guid
+ * we don't support durable handles yet
+ * and have to ignore this
*/
}
if (dhnc) {
- uint64_t persistent_id;
-
-DEBUG(0, ("OBNOX - dhnc found (%s:%s)\n", __location__, __FUNCTION__));
-
if (dhnc->data.length != 16) {
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
-
- persistent_id = BVAL(dhnc->data.data, 0);
-
- status = smb2srv_open_recreate(smb2req->sconn->conn,
- persistent_id,
- &op);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- /* TODO: needed? or is successful global_lookup enough?) */
-
- if (!op->global->durable) {
- talloc_free(op);
- tevent_req_nterror(req,
- NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return tevent_req_post(req, ev);
- }
-
- do_durable_reconnect = true;
- }
-
- if (dh2c) {
- uint64_t persistent_id;
- uint32_t dh2c_flags;
-
-DEBUG(0, ("OBNOX - dh2c found (%s:%s)\n", __location__, __FUNCTION__));
-
- if (dh2c->data.length != 36) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- persistent_id = BVAL(dh2c->data.data, 0);
- /*
- * TODO: extract and check create guid
- */
- dh2c_flags = SVAL(dh2c->data.data, 32);
- persistent_requested = dh2c_flags & SMB2_DHANDLE_FLAG_PERSISTENT;
-
- status = smb2srv_open_recreate(smb2req->sconn->conn,
- persistent_id,
- &op);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- if (!op->global->durable) {
- talloc_free(op);
- tevent_req_nterror(req,
- NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return tevent_req_post(req, ev);
- }
-
- if (persistent_requested && op->global->persistent) {
- persistent_granted = true;
- }
-
- do_durable_reconnect = true;
+ /* we don't support durable handles yet */
+ tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+ return tevent_req_post(req, ev);
}
if (alsi) {
smb1req->conn,
smb1req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0, /* unix_convert flags */
- NULL, /* ppath_contains_wcards */
+ 0,
+ NULL,
&smb_fname);
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
in_file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
- DEBUG(5, ("%s: open execution phase\n", __FUNCTION__));
-
- /*
- * For the backend file open procedure, there are
- * two possible modes: durable_reconnect or not.
- */
- if (do_durable_reconnect) {
- status = smb2_create_durable_reconnect(op,
- smb1req->conn,
- smb1req,
- smb_fname,
- mem_ctx,
- &result,
- &info);
-
-DEBUG(0, ("OBNOX - durable_reconnect result: %s (%s:%s)\n", nt_errstr(status), __location__, __FUNCTION__));
-
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- } else {
- status = SMB_VFS_CREATE_FILE(smb1req->conn,
- smb1req,
- 0, /* root_dir_fid */
- smb_fname,
- in_desired_access,
- in_share_access,
- in_create_disposition,
- in_create_options,
- in_file_attributes,
- map_smb2_oplock_levels_to_samba(requested_oplock_level),
- allocation_size,
- 0, /* private_flags */
- sec_desc,
- ea_list,
- &result,
- &info);
- if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(smb1req->sconn, smb1req->mid)) {
- return req;
- }
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
+ status = SMB_VFS_CREATE_FILE(smb1req->conn,
+ smb1req,
+ 0, /* root_dir_fid */
+ smb_fname,
+ in_desired_access,
+ in_share_access,
+ in_create_disposition,
+ in_create_options,
+ in_file_attributes,
+ map_smb2_oplock_levels_to_samba(requested_oplock_level),
+ allocation_size,
+ 0, /* private_flags */
+ sec_desc,
+ ea_list,
+ &result,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (open_was_deferred(smb1req->sconn, smb1req->mid)) {
+ return req;
}
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
}
- DEBUG(5, ("%s: response construction phase\n", __FUNCTION__));
-
if (mxac) {
NTTIME last_write_time;
}
}
- /*
- * windows creates a dhnc response blob upon dbnc request.
- * this seems to contradict the documentation, though
- * --> TODO:dochelp
- */
- if (dhnc || (dhnq && BATCH_OPLOCK_TYPE(result->oplock_type))) {
- uint8_t p[8];
- DATA_BLOB blob = data_blob_const(p, sizeof(p));
-
-DEBUG(0, ("OBNOX - constructing a dhnq response blob (%s: %s)\n", __location__, __FUNCTION__));
-
- result->smbXsrv->global->backend_file_id = result->file_id;
- result->smbXsrv->global->durable = true;
-
- status = smbXsrv_open_update(result->smbXsrv);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- ZERO_STRUCT(p); /* fill with zeroes */
-
- status = smb2_create_blob_add(state, &out_context_blobs,
- SMB2_CREATE_TAG_DHNQ,
- blob);
-
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- }
-
- if (dh2c || (dh2q && BATCH_OPLOCK_TYPE(result->oplock_type))) {
- uint8_t p[8];
- DATA_BLOB blob = data_blob_const(p, sizeof(p));
- uint32_t durable_v2_response_flags = 0;
-
-DEBUG(0, ("OBNOX - constructing a dh2q response blob (%s: %s)\n", __location__, __FUNCTION__));
-
- if (persistent_granted) {
- durable_v2_response_flags |= SMB2_DHANDLE_FLAG_PERSISTENT;
- }
-
- SIVAL(p, 0, durable_v2_timeout);
- SIVAL(p, 4, durable_v2_response_flags);
-
- result->smbXsrv->global->backend_file_id = result->file_id;
- result->smbXsrv->global->durable = true;
- result->smbXsrv->global->persistent = persistent_granted;
-
- status = smbXsrv_open_update(result->smbXsrv);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- status = smb2_create_blob_add(state, &out_context_blobs,
- SMB2_CREATE_TAG_DH2Q,
- blob);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- }
-
if (qfid) {
uint8_t p[32];
uint64_t file_index = get_FileIndex(result->conn,
if (state->out_file_attributes == 0) {
state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
}
-
- state->out_file_id_persistent = result->smbXsrv->global->open_persistent_id;
- state->out_file_id_volatile = result->smbXsrv->global->open_volatile_id;
+ state->out_file_id_persistent = result->fnum;
+ state->out_file_id_volatile = result->fnum;
state->out_context_blobs = out_context_blobs;
tevent_req_done(req);
uint8_t in_file_info_class,
uint8_t in_flags,
uint32_t in_file_index,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
uint32_t in_output_buffer_length,
const char *in_file_name);
return smbd_smb2_request_error(req, NT_STATUS_OBJECT_NAME_INVALID);
}
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
subreq = smbd_smb2_find_send(req,
req->sconn->ev_ctx,
req,
in_file_info_class,
in_flags,
in_file_index,
- in_file_id_persistent,
in_file_id_volatile,
in_output_buffer_length,
in_file_name_string);
uint8_t in_file_info_class,
uint8_t in_flags,
uint32_t in_file_index,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
uint32_t in_output_buffer_length,
const char *in_file_name)
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
}
- if (smb2req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
if (conn != fsp->conn) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile);
static NTSTATUS smbd_smb2_flush_recv(struct tevent_req *req);
in_file_id_persistent = BVAL(inbody, 0x08);
in_file_id_volatile = BVAL(inbody, 0x10);
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
subreq = smbd_smb2_flush_send(req,
req->sconn->ev_ctx,
req,
- in_file_id_persistent,
in_file_id_volatile);
if (subreq == NULL) {
return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile)
{
struct tevent_req *req;
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
}
- if (smb2req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
if (smbreq->conn != fsp->conn) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
DATA_BLOB in_input_buffer,
uint32_t in_additional_information,
uint32_t in_flags,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile);
static NTSTATUS smbd_smb2_getinfo_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
return smbd_smb2_request_error(req, status);
}
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
subreq = smbd_smb2_getinfo_send(req,
req->sconn->ev_ctx,
req,
in_input_buffer,
in_additional_information,
in_flags,
- in_file_id_persistent,
in_file_id_volatile);
if (subreq == NULL) {
return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
DATA_BLOB in_input_buffer,
uint32_t in_additional_information,
uint32_t in_flags,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile)
{
struct tevent_req *req;
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
}
- if (smb2req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
if (conn != fsp->conn) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
uint32_t in_ctl_code,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
DATA_BLOB in_input,
uint32_t in_max_output,
in_input_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
in_input_buffer.length = in_input_length;
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent == UINT64_MAX &&
+ in_file_id_volatile == UINT64_MAX) {
+ /* without a handle */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
subreq = smbd_smb2_ioctl_send(req,
req->sconn->ev_ctx,
req,
in_ctl_code,
- in_file_id_persistent,
in_file_id_volatile,
in_input_buffer,
in_max_output_length,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
uint32_t in_ctl_code,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
DATA_BLOB in_input,
uint32_t in_max_output,
}
state->smbreq = smbreq;
- if (in_file_id_volatile != UINT64_MAX &&
- in_file_id_persistent != UINT64_MAX) {
+ if (in_file_id_volatile != UINT64_MAX) {
fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
if (fsp == NULL) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
}
- if (smb2req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
if (smbreq->conn != fsp->conn) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
uint32_t in_smbpid,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
uint16_t in_lock_count,
struct smbd_smb2_lock_element *in_locks);
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
}
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
in_locks = talloc_array(req, struct smbd_smb2_lock_element,
in_lock_count);
if (in_locks == NULL) {
req->sconn->ev_ctx,
req,
in_smbpid,
- in_file_id_persistent,
in_file_id_volatile,
in_lock_count,
in_locks);
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
uint32_t in_smbpid,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
uint16_t in_lock_count,
struct smbd_smb2_lock_element *in_locks)
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
}
- if (smb2req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
if (conn != fsp->conn) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
capabilities |= SMB2_CAP_DFS;
}
- /* persistent */
- capabilities += 0x10;
/*
* 0x10000 (65536) is the maximum allowed message size
* for SMB 2.0
req->sconn->smb2.max_read = max_read;
req->sconn->smb2.max_write = max_write;
- req->sconn->smb2.serverguid = data_blob_talloc_zero(req->sconn, 16);
- memcpy(req->sconn->smb2.serverguid.data, negprot_spnego_blob.data, 16);
- req->sconn->smb2.capabilities = capabilities;
-
return smbd_smb2_request_done(req, outbody, &outdyn);
}
struct smbd_smb2_request *smb2req,
uint16_t in_flags,
uint32_t in_output_buffer_length,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
uint64_t in_completion_filter);
static NTSTATUS smbd_smb2_notify_recv(struct tevent_req *req,
return smbd_smb2_request_error(req, status);
}
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
subreq = smbd_smb2_notify_send(req,
req->sconn->ev_ctx,
req,
in_flags,
in_output_buffer_length,
- in_file_id_persistent,
in_file_id_volatile,
in_completion_filter);
if (subreq == NULL) {
struct smbd_smb2_request *smb2req,
uint16_t in_flags,
uint32_t in_output_buffer_length,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
uint64_t in_completion_filter)
{
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
}
- if (smb2req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
if (conn != fsp->conn) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
uint32_t in_smbpid,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
uint32_t in_length,
uint64_t in_offset,
return smbd_smb2_request_error(req, status);
}
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
subreq = smbd_smb2_read_send(req,
req->sconn->ev_ctx,
req,
in_smbpid,
- in_file_id_persistent,
in_file_id_volatile,
in_length,
in_offset,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
uint32_t in_smbpid,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
uint32_t in_length,
uint64_t in_offset,
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
}
- if (smb2req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
if (conn != fsp->conn) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
return NT_STATUS_NO_MEMORY;
}
+ sconn->smb2.sessions.idtree = idr_init(sconn);
+ if (sconn->smb2.sessions.idtree == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ sconn->smb2.sessions.limit = 0x0000FFFE;
sconn->smb2.sessions.list = NULL;
sconn->smb2.seqnum_low = 0;
sconn->smb2.credits_granted = 0;
/* Re-sign if needed. */
if (nreq->do_signing) {
NTSTATUS status;
- struct smbXsrv_session *x = nreq->session->smbXsrv;
- struct smbXsrv_connection *conn = x->connection;
- DATA_BLOB signing_key = x->global->channels[0].signing_key;
-
- status = smb2_signing_sign_pdu(signing_key,
- conn->protocol,
- &nreq->out.vector[i], 3);
+ status = smb2_signing_sign_pdu(nreq->session->session_key,
+ get_Protocol(),
+ &nreq->out.vector[i], 3);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (req->do_signing) {
NTSTATUS status;
- struct smbXsrv_session *x = req->session->smbXsrv;
- struct smbXsrv_connection *conn = x->connection;
- DATA_BLOB signing_key = x->global->channels[0].signing_key;
- status = smb2_signing_sign_pdu(signing_key,
- conn->protocol,
- &state->vector[1], 2);
+ status = smb2_signing_sign_pdu(req->session->session_key,
+ get_Protocol(),
+ &state->vector[1], 2);
if (!NT_STATUS_IS_OK(status)) {
smbd_server_connection_terminate(req->sconn,
nt_errstr(status));
int i = req->current_idx;
uint32_t in_flags;
uint64_t in_session_id;
+ void *p;
struct smbd_smb2_session *session;
- struct smbXsrv_session *smbXsrv;
- NTSTATUS status;
- NTTIME now = 0;
req->session = NULL;
req->tcon = NULL;
}
/* lookup an existing session */
- status = smb2srv_session_lookup(&req->sconn->conn->session_table,
- in_session_id, now,
- &smbXsrv);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
+ if (p == NULL) {
+ return NT_STATUS_USER_SESSION_DELETED;
}
- session = smbXsrv->smb2sess;
+ session = talloc_get_type_abort(p, struct smbd_smb2_session);
+
if (!NT_STATUS_IS_OK(session->status)) {
return NT_STATUS_ACCESS_DENIED;
}
NTSTATUS session_status;
uint32_t allowed_flags;
NTSTATUS return_value;
- struct smbXsrv_session *x = NULL;
inhdr = (const uint8_t *)req->in.vector[i].iov_base;
if (opcode == SMB2_OP_CANCEL) {
allowed_flags |= SMB2_HDR_FLAG_ASYNC;
}
- if (true /* TODO - which OPs ? */) {
- allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
- }
if ((flags & ~allowed_flags) != 0) {
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
}
* we defer the check of the session_status
*/
session_status = smbd_smb2_request_check_session(req);
- if (req->session) {
- x = req->session->smbXsrv;
- }
req->do_signing = false;
if (flags & SMB2_HDR_FLAG_SIGNED) {
- struct smbXsrv_connection *conn = x->connection;
- DATA_BLOB signing_key = x->global->channels[0].signing_key;
-
if (!NT_STATUS_IS_OK(session_status)) {
return smbd_smb2_request_error(req, session_status);
}
req->do_signing = true;
- status = smb2_signing_check_pdu(signing_key,
- conn->protocol,
+ status = smb2_signing_check_pdu(req->session->session_key,
+ get_Protocol(),
&req->in.vector[i], 3);
if (!NT_STATUS_IS_OK(status)) {
return smbd_smb2_request_error(req, status);
}
} else if (opcode == SMB2_OP_CANCEL) {
/* Cancel requests are allowed to skip the signing */
- } else if (x && x->global->signing_required) {
+ } else if (req->session && req->session->do_signing) {
return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
}
if (req->do_signing) {
NTSTATUS status;
- struct smbXsrv_session *x = req->session->smbXsrv;
- struct smbXsrv_connection *conn = x->connection;
- DATA_BLOB signing_key = x->global->channels[0].signing_key;
-
- status = smb2_signing_sign_pdu(signing_key,
- conn->protocol,
+ status = smb2_signing_sign_pdu(req->session->session_key,
+ get_Protocol(),
&req->out.vector[i], 3);
if (!NT_STATUS_IS_OK(status)) {
return status;
talloc_free(session->tcons.list);
}
+ idr_remove(session->sconn->smb2.sessions.idtree, session->vuid);
DLIST_REMOVE(session->sconn->smb2.sessions.list, session);
invalidate_vuid(session->sconn, session->vuid);
session->status = NT_STATUS_USER_SESSION_DELETED;
session->sconn = NULL;
- TALLOC_FREE(session->smbXsrv);
-
return 0;
}
uint16_t *out_session_flags,
uint64_t *out_session_id)
{
- NTSTATUS status;
bool guest = false;
- uint8_t session_key[16];
- struct smbXsrv_session *x = session->smbXsrv;
- struct smbXsrv_connection *conn = x->connection;
if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
lp_server_signing() == SMB_SIGNING_REQUIRED) {
- x->global->signing_required = true;
+ session->do_signing = true;
}
if (security_session_user_level(session->session_info, NULL) < SECURITY_USER) {
*out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
*out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
/* force no signing */
- x->global->signing_required = false;
+ session->do_signing = false;
guest = true;
}
- //session->session_key = session->session_info->session_key;
-
- ZERO_STRUCT(session_key);
- memcpy(session_key, session->session_info->session_key.data,
- MIN(session->session_info->session_key.length, sizeof(session_key)));
-
- x->global->signing_key = data_blob_talloc(x->global,
- session_key,
- sizeof(session_key));
- if (x->global->signing_key.data == NULL) {
- ZERO_STRUCT(session_key);
- return NT_STATUS_NO_MEMORY;
- }
-
- if (conn->protocol >= PROTOCOL_SMB2_24) {
-#define _STRING_BLOB(x) data_blob_const((const uint8_t *)(x), sizeof(x))
- const DATA_BLOB label = _STRING_BLOB("SMB2AESCMAC");
- const DATA_BLOB context = _STRING_BLOB("SmbSign");
-#undef _STRING_BLOB
-
- smb2_key_derivation(session_key, sizeof(session_key),
- label.data, label.length,
- context.data, context.length,
- x->global->signing_key.data);
- }
-
- x->global->application_key = data_blob_dup_talloc(x->global,
- x->global->signing_key);
- if (x->global->application_key.data == NULL) {
- ZERO_STRUCT(session_key);
- return NT_STATUS_NO_MEMORY;
- }
-
- if (conn->protocol >= PROTOCOL_SMB2_24) {
-#define _STRING_BLOB(x) data_blob_const((const uint8_t *)(x), sizeof(x))
- const DATA_BLOB label = _STRING_BLOB("SMB2APP");
- const DATA_BLOB context = _STRING_BLOB("SmbRpc");
-#undef _STRING_BLOB
-
- smb2_key_derivation(session_key, sizeof(session_key),
- label.data, label.length,
- context.data, context.length,
- x->global->application_key.data);
- }
- ZERO_STRUCT(session_key);
-
- x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
- x->global->signing_key);
- if (x->global->channels[0].signing_key.data == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- data_blob_clear_free(&session->session_info->session_key);
- session->session_info->session_key = data_blob_dup_talloc(session->session_info,
- x->global->application_key);
- if (session->session_info->session_key.data == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+ session->session_key = session->session_info->session_key;
session->compat_vuser = talloc_zero(session, user_struct);
if (session->compat_vuser == NULL) {
reload_services(smb2req->sconn, conn_snum_used, true);
- session->smbXsrv->status = NT_STATUS_OK;
- session->smbXsrv->global->auth_session_info = session->session_info;
-
- status = smbXsrv_session_update(session->smbXsrv);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("smb2: Failed to update session for vuid=%d - %s\n",
- session->compat_vuser->vuid, nt_errstr(status)));
- TALLOC_FREE(session);
- return NT_STATUS_LOGON_FAILURE;
- }
-
session->status = NT_STATUS_OK;
/*
DATA_BLOB *out_security_buffer,
uint64_t *out_session_id)
{
- struct smbd_smb2_session *smb2sess;
- struct smbXsrv_session *session;
- NTSTATUS status;
- NTTIME now = 0;
+ struct smbd_smb2_session *session;
*out_session_flags = 0;
*out_session_id = 0;
if (in_session_id == 0) {
+ int id;
+
/* create a new session */
- smb2sess = talloc_zero(smb2req->sconn, struct smbd_smb2_session);
- if (smb2sess == NULL) {
+ session = talloc_zero(smb2req->sconn, struct smbd_smb2_session);
+ if (session == NULL) {
return NT_STATUS_NO_MEMORY;
}
-
- status = smbXsrv_session_create(smb2req->sconn->conn,
- now, &session);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+ id = idr_get_new_random(smb2req->sconn->smb2.sessions.idtree,
+ session,
+ smb2req->sconn->smb2.sessions.limit);
+ if (id == -1) {
+ return NT_STATUS_INSUFFICIENT_RESOURCES;
}
- smb2sess->smbXsrv = session;
- session->smb2sess = smb2sess;
- talloc_set_destructor(smb2sess, smbd_smb2_session_destructor);
+ session->vuid = id;
- smb2sess->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
- smb2sess->vuid = session->global->session_wire_id;
-
- smb2sess->tcons.idtree = idr_init(smb2sess);
- if (smb2sess->tcons.idtree == NULL) {
+ session->tcons.idtree = idr_init(session);
+ if (session->tcons.idtree == NULL) {
return NT_STATUS_NO_MEMORY;
}
- smb2sess->tcons.limit = 0x0000FFFE;
- smb2sess->tcons.list = NULL;
+ session->tcons.limit = 0x0000FFFE;
+ session->tcons.list = NULL;
- DLIST_ADD_END(smb2req->sconn->smb2.sessions.list, smb2sess,
+ DLIST_ADD_END(smb2req->sconn->smb2.sessions.list, session,
struct smbd_smb2_session *);
- smb2sess->sconn = smb2req->sconn;
+ session->sconn = smb2req->sconn;
+ talloc_set_destructor(session, smbd_smb2_session_destructor);
} else {
- status = smb2srv_session_lookup(&smb2req->sconn->conn->session_table,
- in_session_id, now,
- &session);
- if (NT_STATUS_IS_OK(status)) {
- return NT_STATUS_REQUEST_NOT_ACCEPTED;
- }
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ void *p;
- return status;
+ /* lookup an existing session */
+ p = idr_find(smb2req->sconn->smb2.sessions.idtree, in_session_id);
+ if (p == NULL) {
+ return NT_STATUS_USER_SESSION_DELETED;
}
-
- smb2sess = session->smb2sess;
+ session = talloc_get_type_abort(p, struct smbd_smb2_session);
}
- if (NT_STATUS_IS_OK(smb2sess->status)) {
+ if (NT_STATUS_IS_OK(session->status)) {
return NT_STATUS_REQUEST_NOT_ACCEPTED;
}
- return smbd_smb2_auth_generic(smb2sess,
+ return smbd_smb2_auth_generic(session,
smb2req,
in_security_mode,
in_security_buffer,
uint8_t in_file_info_class,
DATA_BLOB in_input_buffer,
uint32_t in_additional_information,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile);
static NTSTATUS smbd_smb2_setinfo_recv(struct tevent_req *req);
return smbd_smb2_request_error(req, status);
}
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
subreq = smbd_smb2_setinfo_send(req,
req->sconn->ev_ctx,
req,
in_file_info_class,
in_input_buffer,
in_additional_information,
- in_file_id_persistent,
in_file_id_volatile);
if (subreq == NULL) {
return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
uint8_t in_file_info_class,
DATA_BLOB in_input_buffer,
uint32_t in_additional_information,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile)
{
struct tevent_req *req = NULL;
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
}
- if (smb2req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
if (conn != fsp->conn) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
*out_share_flags |= SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM;
}
- /*announce CA + cluster */
- *out_capabilities += 0x10;
- *out_capabilities += 0x40;
-
*out_maximal_access = tcon->compat_conn->share_access;
*out_tree_id = tcon->tid;
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
uint32_t in_smbpid,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
DATA_BLOB in_data,
uint64_t in_offset,
return smbd_smb2_request_error(req, status);
}
+ if (req->compat_chain_fsp) {
+ /* skip check */
+ } else if (in_file_id_persistent != in_file_id_volatile) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
subreq = smbd_smb2_write_send(req,
req->sconn->ev_ctx,
req,
in_smbpid,
- in_file_id_persistent,
in_file_id_volatile,
in_data_buffer,
in_offset,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
uint32_t in_smbpid,
- uint64_t in_file_id_persistent,
uint64_t in_file_id_volatile,
DATA_BLOB in_data,
uint64_t in_offset,
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);
}
- if (smb2req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != fsp->smbXsrv->global->open_persistent_id) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
if (conn != fsp->conn) {
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
return tevent_req_post(req, ev);