2 Unix SMB/CIFS implementation.
4 Copyright (C) Ralph Boehme 2017
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "smbd/smbd.h"
22 #include "smbd/globals.h"
23 #include "dbwrap/dbwrap.h"
24 #include "dbwrap/dbwrap_rbt.h"
25 #include "dbwrap/dbwrap_open.h"
26 #include "../lib/util/util_tdb.h"
27 #include "librpc/gen_ndr/ndr_ioctl.h"
28 #include "librpc/gen_ndr/ioctl.h"
29 #include "offload_token.h"
31 struct vfs_offload_ctx {
33 struct db_context *db_ctx;
36 NTSTATUS vfs_offload_token_ctx_init(TALLOC_CTX *mem_ctx,
37 struct vfs_offload_ctx **_ctx)
39 struct vfs_offload_ctx *ctx = *_ctx;
42 if (!ctx->initialized) {
43 return NT_STATUS_INTERNAL_ERROR;
48 ctx = talloc_zero(mem_ctx, struct vfs_offload_ctx);
50 return NT_STATUS_NO_MEMORY;
53 ctx->db_ctx = db_open_rbt(mem_ctx);
54 if (ctx->db_ctx == NULL) {
56 return NT_STATUS_INTERNAL_ERROR;
59 ctx->initialized = true;
64 struct fsp_token_link {
65 struct vfs_offload_ctx *ctx;
69 static int fsp_token_link_destructor(struct fsp_token_link *link)
71 DATA_BLOB token_blob = link->token_blob;
72 TDB_DATA key = make_tdb_data(token_blob.data, token_blob.length);
75 status = dbwrap_delete(link->ctx->db_ctx, key);
76 if (!NT_STATUS_IS_OK(status)) {
77 DBG_ERR("dbwrap_delete failed: %s. Token:\n", nt_errstr(status));
78 dump_data(0, token_blob.data, token_blob.length);
85 NTSTATUS vfs_offload_token_db_store_fsp(struct vfs_offload_ctx *ctx,
86 const files_struct *fsp,
87 const DATA_BLOB *token_blob)
89 struct db_record *rec = NULL;
90 struct fsp_token_link *link = NULL;
91 TDB_DATA key = make_tdb_data(token_blob->data, token_blob->length);
95 rec = dbwrap_fetch_locked(ctx->db_ctx, talloc_tos(), key);
97 return NT_STATUS_INTERNAL_ERROR;
100 value = dbwrap_record_get_value(rec);
101 if (value.dsize != 0) {
103 files_struct *token_db_fsp = NULL;
105 if (value.dsize != sizeof(ptr)) {
106 DBG_ERR("Bad db entry for token:\n");
107 dump_data(1, token_blob->data, token_blob->length);
109 return NT_STATUS_INTERNAL_ERROR;
111 memcpy(&ptr, value.dptr, value.dsize);
114 token_db_fsp = talloc_get_type_abort(ptr, struct files_struct);
115 if (token_db_fsp != fsp) {
116 DBG_ERR("token for fsp [%s] matches already known "
117 "but different fsp [%s]:\n",
118 fsp_str_dbg(fsp), fsp_str_dbg(token_db_fsp));
119 dump_data(1, token_blob->data, token_blob->length);
120 return NT_STATUS_INTERNAL_ERROR;
126 link = talloc_zero(fsp, struct fsp_token_link);
128 return NT_STATUS_NO_MEMORY;
131 link->token_blob = data_blob_talloc(link, token_blob->data,
133 if (link->token_blob.data == NULL) {
135 return NT_STATUS_NO_MEMORY;
137 talloc_set_destructor(link, fsp_token_link_destructor);
139 value = make_tdb_data((uint8_t *)&fsp, sizeof(files_struct *));
141 status = dbwrap_record_store(rec, value, 0);
142 if (!NT_STATUS_IS_OK(status)) {
143 DBG_ERR("dbwrap_record_store for [%s] failed: %s. Token\n",
144 fsp_str_dbg(fsp), nt_errstr(status));
145 dump_data(0, token_blob->data, token_blob->length);
155 NTSTATUS vfs_offload_token_db_fetch_fsp(struct vfs_offload_ctx *ctx,
156 const DATA_BLOB *token_blob,
159 struct db_record *rec = NULL;
160 TDB_DATA key = make_tdb_data(token_blob->data, token_blob->length);
164 rec = dbwrap_fetch_locked(ctx->db_ctx, talloc_tos(), key);
166 return NT_STATUS_INTERNAL_ERROR;
169 value = dbwrap_record_get_value(rec);
170 if (value.dsize == 0) {
171 DBG_DEBUG("Unknown token:\n");
172 dump_data(10, token_blob->data, token_blob->length);
174 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
177 if (value.dsize != sizeof(ptr)) {
178 DBG_ERR("Bad db entry for token:\n");
179 dump_data(1, token_blob->data, token_blob->length);
181 return NT_STATUS_INTERNAL_ERROR;
184 memcpy(&ptr, value.dptr, value.dsize);
187 *fsp = talloc_get_type_abort(ptr, struct files_struct);
191 NTSTATUS vfs_offload_token_create_blob(TALLOC_CTX *mem_ctx,
192 const files_struct *fsp,
194 DATA_BLOB *token_blob)
199 case FSCTL_DUP_EXTENTS_TO_FILE:
202 case FSCTL_SRV_REQUEST_RESUME_KEY:
206 DBG_ERR("Invalid fsctl [%" PRIu32 "]\n", fsctl);
207 return NT_STATUS_NOT_SUPPORTED;
210 *token_blob = data_blob_talloc_zero(mem_ctx, len);
211 if (token_blob->length == 0) {
212 return NT_STATUS_NO_MEMORY;
215 /* combine persistent and volatile handles for the resume key */
216 SBVAL(token_blob->data, 0, fsp->op->global->open_persistent_id);
217 SBVAL(token_blob->data, 8, fsp->op->global->open_volatile_id);
218 SIVAL(token_blob->data, 16, fsctl);