smbd: Fix CID 1452293 Incorrect expression (NO_EFFECT)
[Samba.git] / source3 / rpc_server / mdssvc / srv_mdssvc_nt.c
blob4c252ceadc56c08e50c9e08bc89e764fe4ef7eb8
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines for mdssvc
4 * Copyright (C) Ralph Boehme 2014
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/>.
20 #include "includes.h"
21 #include "messages.h"
22 #include "ntdomain.h"
23 #include "rpc_server/rpc_service_setup.h"
24 #include "rpc_server/rpc_config.h"
25 #include "rpc_server/rpc_modules.h"
26 #include "rpc_server/mdssvc/srv_mdssvc_nt.h"
27 #include "../librpc/gen_ndr/srv_mdssvc.h"
28 #include "libcli/security/security_token.h"
29 #include "libcli/security/dom_sid.h"
30 #include "gen_ndr/auth.h"
31 #include "mdssvc.h"
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_SRV
36 static bool mdssvc_init_cb(void *ptr)
38 struct messaging_context *msg_ctx =
39 talloc_get_type_abort(ptr, struct messaging_context);
40 bool ok;
42 ok = init_service_mdssvc(msg_ctx);
43 if (!ok) {
44 return false;
47 return true;
50 static bool mdssvc_shutdown_cb(void *ptr)
52 shutdown_service_mdssvc();
54 return true;
57 static bool rpc_setup_mdssvc(struct tevent_context *ev_ctx,
58 struct messaging_context *msg_ctx)
60 const struct ndr_interface_table *t = &ndr_table_mdssvc;
61 const char *pipe_name = "mdssvc";
62 struct rpc_srv_callbacks mdssvc_cb;
63 NTSTATUS status;
64 enum rpc_service_mode_e service_mode = rpc_service_mode(t->name);
65 enum rpc_daemon_type_e mdssvc_type = rpc_mdssd_daemon();
67 mdssvc_cb.init = mdssvc_init_cb;
68 mdssvc_cb.shutdown = mdssvc_shutdown_cb;
69 mdssvc_cb.private_data = msg_ctx;
71 status = rpc_mdssvc_init(&mdssvc_cb);
72 if (!NT_STATUS_IS_OK(status)) {
73 return false;
76 if (service_mode != RPC_SERVICE_MODE_EMBEDDED
77 || mdssvc_type != RPC_DAEMON_EMBEDDED) {
78 return true;
81 status = rpc_setup_embedded(ev_ctx, msg_ctx, t, pipe_name);
82 if (!NT_STATUS_IS_OK(status)) {
83 return false;
86 return true;
89 static struct rpc_module_fns rpc_module_mdssvc_fns = {
90 .setup = rpc_setup_mdssvc,
91 .init = rpc_mdssvc_init,
92 .shutdown = rpc_mdssvc_shutdown,
95 static_decl_rpc;
96 NTSTATUS rpc_mdssvc_module_init(TALLOC_CTX *mem_ctx)
98 DBG_DEBUG("Registering mdsvc RPC service\n");
100 return register_rpc_module(&rpc_module_mdssvc_fns, "mdssvc");
104 bool init_service_mdssvc(struct messaging_context *msg_ctx)
106 return mds_init(msg_ctx);
109 bool shutdown_service_mdssvc(void)
111 return mds_shutdown();
114 static NTSTATUS create_mdssvc_policy_handle(TALLOC_CTX *mem_ctx,
115 struct pipes_struct *p,
116 int snum,
117 const char *sharename,
118 const char *path,
119 struct policy_handle *handle)
121 struct mds_ctx *mds_ctx;
123 ZERO_STRUCTP(handle);
125 mds_ctx = mds_init_ctx(mem_ctx,
126 messaging_tevent_context(p->msg_ctx),
127 p->session_info,
128 snum,
129 sharename,
130 path);
131 if (mds_ctx == NULL) {
132 DEBUG(1, ("error in mds_init_ctx for: %s\n", path));
133 return NT_STATUS_UNSUCCESSFUL;
136 if (!create_policy_hnd(p, handle, mds_ctx)) {
137 talloc_free(mds_ctx);
138 ZERO_STRUCTP(handle);
139 return NT_STATUS_NO_MEMORY;
142 return NT_STATUS_OK;
145 void _mdssvc_open(struct pipes_struct *p, struct mdssvc_open *r)
147 int snum;
148 char *outpath = discard_const_p(char, r->out.share_path);
149 char *path;
150 NTSTATUS status;
152 DBG_DEBUG("[%s]\n", r->in.share_name);
154 *r->out.device_id = *r->in.device_id;
155 *r->out.unkn2 = *r->in.unkn2;
156 *r->out.unkn3 = *r->in.unkn3;
157 outpath[0] = '\0';
159 snum = lp_servicenumber(r->in.share_name);
160 if (!VALID_SNUM(snum)) {
161 return;
164 path = lp_path(talloc_tos(), snum);
165 if (path == NULL) {
166 DBG_ERR("Couldn't create policy handle for %s\n",
167 r->in.share_name);
168 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
169 return;
172 status = create_mdssvc_policy_handle(p->mem_ctx, p,
173 snum,
174 r->in.share_name,
175 path,
176 r->out.handle);
177 if (!NT_STATUS_IS_OK(status)) {
178 DBG_ERR("Couldn't create policy handle for %s\n",
179 r->in.share_name);
180 talloc_free(path);
181 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
182 return;
185 strlcpy(outpath, path, 1024);
186 talloc_free(path);
187 return;
190 static bool is_zero_policy_handle(const struct policy_handle *h)
192 struct GUID zero_uuid = {0};
194 if (h->handle_type != 0) {
195 return false;
197 if (!GUID_equal(&h->uuid, &zero_uuid)) {
198 return false;
200 return true;
203 void _mdssvc_unknown1(struct pipes_struct *p, struct mdssvc_unknown1 *r)
205 struct mds_ctx *mds_ctx;
207 if (!find_policy_by_hnd(p, &r->in.handle, (void **)(void *)&mds_ctx)) {
208 if (is_zero_policy_handle(&r->in.handle)) {
209 p->fault_state = 0;
210 } else {
211 p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
213 *r->out.status = 0;
214 *r->out.flags = 0;
215 *r->out.unkn7 = 0;
216 return;
219 DEBUG(10, ("%s: path: %s\n", __func__, mds_ctx->spath));
221 *r->out.status = 0;
222 *r->out.flags = 0x6b000001;
223 *r->out.unkn7 = 0;
225 return;
228 void _mdssvc_cmd(struct pipes_struct *p, struct mdssvc_cmd *r)
230 bool ok;
231 char *rbuf;
232 struct mds_ctx *mds_ctx;
234 if (!find_policy_by_hnd(p, &r->in.handle, (void **)(void *)&mds_ctx)) {
235 if (is_zero_policy_handle(&r->in.handle)) {
236 p->fault_state = 0;
237 } else {
238 p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
240 r->out.response_blob->size = 0;
241 *r->out.fragment = 0;
242 *r->out.unkn9 = 0;
243 return;
246 DEBUG(10, ("%s: path: %s\n", __func__, mds_ctx->spath));
248 ok = security_token_is_sid(p->session_info->security_token,
249 &mds_ctx->sid);
250 if (!ok) {
251 struct dom_sid_buf buf;
252 DBG_WARNING("not the same sid: %s\n",
253 dom_sid_str_buf(&mds_ctx->sid, &buf));
254 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
255 return;
258 if (geteuid() != mds_ctx->uid) {
259 DEBUG(0, ("uid mismatch: %d/%d\n", geteuid(), mds_ctx->uid));
260 smb_panic("uid mismatch");
263 if (r->in.request_blob.size > MAX_SL_FRAGMENT_SIZE) {
264 DEBUG(1, ("%s: request size too large\n", __func__));
265 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
266 return;
269 if (r->in.request_blob.length > MAX_SL_FRAGMENT_SIZE) {
270 DEBUG(1, ("%s: request length too large\n", __func__));
271 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
272 return;
275 if (r->in.max_fragment_size1 > MAX_SL_FRAGMENT_SIZE) {
276 DEBUG(1, ("%s: request fragment size too large: %u\n",
277 __func__, (unsigned)r->in.max_fragment_size1));
278 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
279 return;
282 rbuf = talloc_zero_array(p->mem_ctx, char, r->in.max_fragment_size1);
283 if (rbuf == NULL) {
284 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
285 return;
287 r->out.response_blob->spotlight_blob = (uint8_t *)rbuf;
288 r->out.response_blob->size = r->in.max_fragment_size1;
290 /* We currently don't use fragmentation at the mdssvc RPC layer */
291 *r->out.fragment = 0;
293 ok = mds_dispatch(mds_ctx, &r->in.request_blob, r->out.response_blob);
294 if (ok) {
295 *r->out.unkn9 = 0;
296 } else {
297 /* FIXME: just interpolating from AFP, needs verification */
298 *r->out.unkn9 = UINT32_MAX;
301 return;
304 void _mdssvc_close(struct pipes_struct *p, struct mdssvc_close *r)
306 struct mds_ctx *mds_ctx;
308 if (!find_policy_by_hnd(p, &r->in.in_handle, (void **)(void *)&mds_ctx)) {
309 DEBUG(1, ("%s: invalid handle\n", __func__));
310 if (is_zero_policy_handle(&r->in.in_handle)) {
311 p->fault_state = 0;
312 } else {
313 p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
315 return;
318 DEBUG(10, ("%s: path: %s\n", __func__, mds_ctx->spath));
320 *r->out.out_handle = r->in.in_handle;
321 close_policy_hnd(p, &r->in.in_handle);
323 *r->out.status = 0;
325 return;