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/>.
22 #include "rpc_server/rpc_service_setup.h"
23 #include "rpc_server/rpc_config.h"
24 #include "rpc_server/rpc_modules.h"
25 #include "rpc_server/mdssvc/srv_mdssvc_nt.h"
26 #include "../librpc/gen_ndr/srv_mdssvc.h"
27 #include "libcli/security/security_token.h"
28 #include "gen_ndr/auth.h"
32 #define DBGC_CLASS DBGC_RPC_SRV
34 static bool mdssvc_init_cb(void *ptr)
36 struct messaging_context *msg_ctx =
37 talloc_get_type_abort(ptr, struct messaging_context);
40 ok = init_service_mdssvc(msg_ctx);
48 static bool mdssvc_shutdown_cb(void *ptr)
50 shutdown_service_mdssvc();
55 static bool rpc_setup_mdssvc(struct tevent_context *ev_ctx,
56 struct messaging_context *msg_ctx)
58 const struct ndr_interface_table *t = &ndr_table_mdssvc;
59 const char *pipe_name = "mdssvc";
60 struct rpc_srv_callbacks mdssvc_cb;
62 enum rpc_service_mode_e service_mode = rpc_service_mode(t->name);
63 enum rpc_daemon_type_e mdssvc_type = rpc_mdssd_daemon();
65 mdssvc_cb.init = mdssvc_init_cb;
66 mdssvc_cb.shutdown = mdssvc_shutdown_cb;
67 mdssvc_cb.private_data = msg_ctx;
69 status = rpc_mdssvc_init(&mdssvc_cb);
70 if (!NT_STATUS_IS_OK(status)) {
74 if (service_mode != RPC_SERVICE_MODE_EMBEDDED
75 || mdssvc_type != RPC_DAEMON_EMBEDDED) {
79 return rpc_setup_embedded(ev_ctx, msg_ctx, t, pipe_name);
82 static struct rpc_module_fns rpc_module_mdssvc_fns = {
83 .setup = rpc_setup_mdssvc,
84 .init = rpc_mdssvc_init,
85 .shutdown = rpc_mdssvc_shutdown,
89 NTSTATUS rpc_mdssvc_module_init(void)
91 DBG_DEBUG("Registering mdsvc RPC service\n");
93 return register_rpc_module(&rpc_module_mdssvc_fns, "mdssvc");
97 bool init_service_mdssvc(struct messaging_context *msg_ctx)
99 return mds_init(msg_ctx);
102 bool shutdown_service_mdssvc(void)
104 return mds_shutdown();
107 static NTSTATUS create_mdssvc_policy_handle(TALLOC_CTX *mem_ctx,
108 struct pipes_struct *p,
110 struct policy_handle *handle)
112 struct mds_ctx *mds_ctx;
114 ZERO_STRUCTP(handle);
116 mds_ctx = mds_init_ctx(mem_ctx, p->session_info, path);
117 if (mds_ctx == NULL) {
118 DEBUG(1, ("error in mds_init_ctx for: %s\n", path));
119 return NT_STATUS_UNSUCCESSFUL;
122 if (!create_policy_hnd(p, handle, mds_ctx)) {
123 talloc_free(mds_ctx);
124 ZERO_STRUCTP(handle);
125 return NT_STATUS_NO_MEMORY;
131 void _mdssvc_open(struct pipes_struct *p, struct mdssvc_open *r)
137 DEBUG(10, ("%s: [%s]\n", __func__, r->in.share_name));
139 snum = lp_servicenumber(r->in.share_name);
140 if (!VALID_SNUM(snum)) {
141 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
145 if (lp_spotlight(snum)) {
146 DEBUG(10, ("Spotlight enabled: %s\n", r->in.share_name));
148 path = lp_path(talloc_tos(), snum);
150 DEBUG(1, ("Couldn't create policy handle for %s\n",
152 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
156 status = create_mdssvc_policy_handle(p->mem_ctx, p, path,
158 if (!NT_STATUS_IS_OK(status)) {
159 DEBUG(1, ("Couldn't create policy handle for %s\n",
162 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
166 strlcpy(discard_const_p(char, r->out.share_path), path, 1024);
168 *r->out.device_id = *r->in.device_id;
171 *r->out.unkn2 = 0x17;
177 void _mdssvc_unknown1(struct pipes_struct *p, struct mdssvc_unknown1 *r)
179 struct mds_ctx *mds_ctx;
181 if (!find_policy_by_hnd(p, &r->in.handle, (void **)(void *)&mds_ctx)) {
182 DEBUG(1, ("%s: invalid handle\n", __func__));
186 DEBUG(10, ("%s: path: %s\n", __func__, mds_ctx->spath));
189 *r->out.flags = 0x6b000001;
195 void _mdssvc_cmd(struct pipes_struct *p, struct mdssvc_cmd *r)
199 struct mds_ctx *mds_ctx;
201 if (!find_policy_by_hnd(p, &r->in.handle, (void **)(void *)&mds_ctx)) {
202 DEBUG(1, ("%s: invalid handle\n", __func__));
206 DEBUG(10, ("%s: path: %s\n", __func__, mds_ctx->spath));
208 ok = security_token_is_sid(p->session_info->security_token,
211 DEBUG(1,("%s: not the same sid: %s\n", __func__,
212 sid_string_tos(&mds_ctx->sid)));
213 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
217 if (geteuid() != mds_ctx->uid) {
218 DEBUG(0, ("uid mismatch: %d/%d\n", geteuid(), mds_ctx->uid));
219 smb_panic("uid mismatch");
222 if (r->in.request_blob.size > MAX_SL_FRAGMENT_SIZE) {
223 DEBUG(1, ("%s: request size too large\n", __func__));
224 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
228 if (r->in.request_blob.length > MAX_SL_FRAGMENT_SIZE) {
229 DEBUG(1, ("%s: request length too large\n", __func__));
230 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
234 if (r->in.max_fragment_size1 > MAX_SL_FRAGMENT_SIZE) {
235 DEBUG(1, ("%s: request fragment size too large: %u\n",
236 __func__, (unsigned)r->in.max_fragment_size1));
237 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
241 rbuf = talloc_zero_array(p->mem_ctx, char, r->in.max_fragment_size1);
243 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
246 r->out.response_blob->spotlight_blob = (uint8_t *)rbuf;
247 r->out.response_blob->size = r->in.max_fragment_size1;
249 ok = mds_dispatch(mds_ctx, &r->in.request_blob, r->out.response_blob);
254 /* FIXME: just interpolating from AFP, needs verification */
255 *r->out.status = UINT32_MAX;
256 *r->out.unkn9 = UINT32_MAX;
262 void _mdssvc_close(struct pipes_struct *p, struct mdssvc_close *r)
264 struct mds_ctx *mds_ctx;
266 if (!find_policy_by_hnd(p, &r->in.in_handle, (void **)(void *)&mds_ctx)) {
267 DEBUG(1, ("%s: invalid handle\n", __func__));
271 DEBUG(10, ("%s: path: %s\n", __func__, mds_ctx->spath));
273 close_policy_hnd(p, &r->in.in_handle);
275 ZERO_STRUCTP(r->out.out_handle);