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
+ */
+ }
+
if (dhnc) {
uint64_t persistent_id;
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;
+ }
+
if (alsi) {
if (dhnc) {
tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
}
}
+ 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);
+ }
+
+ ZERO_STRUCT(p);
+
+ 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,