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/>.
23 #include "rpc_server/rpc_server.h"
24 #include "rpc_server/rpc_config.h"
25 #include "rpc_server/mdssvc/srv_mdssvc_nt.h"
26 #include "libcli/security/security_token.h"
27 #include "libcli/security/dom_sid.h"
28 #include "gen_ndr/auth.h"
30 #include "smbd/globals.h"
32 #include "librpc/rpc/dcesrv_core.h"
33 #include "librpc/gen_ndr/ndr_mdssvc.h"
34 #include "librpc/gen_ndr/ndr_mdssvc_scompat.h"
35 #include "lib/global_contexts.h"
38 #define DBGC_CLASS DBGC_RPC_SRV
40 static NTSTATUS create_mdssvc_policy_handle(TALLOC_CTX *mem_ctx,
41 struct pipes_struct *p,
43 const char *sharename,
45 struct policy_handle *handle)
47 struct mds_ctx *mds_ctx;
51 mds_ctx = mds_init_ctx(mem_ctx,
52 messaging_tevent_context(p->msg_ctx),
58 if (mds_ctx == NULL) {
59 DEBUG(1, ("error in mds_init_ctx for: %s\n", path));
60 return NT_STATUS_UNSUCCESSFUL;
63 if (!create_policy_hnd(p, handle, 0, mds_ctx)) {
66 return NT_STATUS_NO_MEMORY;
72 void _mdssvc_open(struct pipes_struct *p, struct mdssvc_open *r)
74 const struct loadparm_substitution *lp_sub =
75 loadparm_s3_global_substitution();
77 char *outpath = discard_const_p(char, r->out.share_path);
81 DBG_DEBUG("[%s]\n", r->in.share_name);
83 *r->out.device_id = *r->in.device_id;
84 *r->out.unkn2 = *r->in.unkn2;
85 *r->out.unkn3 = *r->in.unkn3;
88 snum = lp_servicenumber(r->in.share_name);
89 if (!VALID_SNUM(snum)) {
93 path = lp_path(talloc_tos(), lp_sub, snum);
95 DBG_ERR("Couldn't create policy handle for %s\n",
97 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
101 status = create_mdssvc_policy_handle(p->mem_ctx, p,
106 if (!NT_STATUS_IS_OK(status)) {
107 DBG_ERR("Couldn't create policy handle for %s\n",
110 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
114 strlcpy(outpath, path, 1024);
119 void _mdssvc_unknown1(struct pipes_struct *p, struct mdssvc_unknown1 *r)
121 struct mds_ctx *mds_ctx;
124 mds_ctx = find_policy_by_hnd(p,
129 if (!NT_STATUS_IS_OK(status)) {
130 if (ndr_policy_handle_empty(r->in.handle)) {
133 p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
141 DEBUG(10, ("%s: path: %s\n", __func__, mds_ctx->spath));
144 *r->out.flags = 0x6b000001;
150 void _mdssvc_cmd(struct pipes_struct *p, struct mdssvc_cmd *r)
154 struct mds_ctx *mds_ctx;
157 mds_ctx = find_policy_by_hnd(p,
162 if (!NT_STATUS_IS_OK(status)) {
163 if (ndr_policy_handle_empty(r->in.handle)) {
166 p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
168 r->out.response_blob->size = 0;
169 *r->out.fragment = 0;
174 DEBUG(10, ("%s: path: %s\n", __func__, mds_ctx->spath));
176 ok = security_token_is_sid(p->session_info->security_token,
179 struct dom_sid_buf buf;
180 DBG_WARNING("not the same sid: %s\n",
181 dom_sid_str_buf(&mds_ctx->sid, &buf));
182 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
186 if (geteuid() != mds_ctx->uid) {
187 DEBUG(0, ("uid mismatch: %d/%d\n", geteuid(), mds_ctx->uid));
188 smb_panic("uid mismatch");
191 if (r->in.request_blob.size > MAX_SL_FRAGMENT_SIZE) {
192 DEBUG(1, ("%s: request size too large\n", __func__));
193 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
197 if (r->in.request_blob.length > MAX_SL_FRAGMENT_SIZE) {
198 DEBUG(1, ("%s: request length too large\n", __func__));
199 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
203 if (r->in.max_fragment_size1 > MAX_SL_FRAGMENT_SIZE) {
204 DEBUG(1, ("%s: request fragment size too large: %u\n",
205 __func__, (unsigned)r->in.max_fragment_size1));
206 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
210 rbuf = talloc_zero_array(p->mem_ctx, char, r->in.max_fragment_size1);
212 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
215 r->out.response_blob->spotlight_blob = (uint8_t *)rbuf;
216 r->out.response_blob->size = r->in.max_fragment_size1;
218 /* We currently don't use fragmentation at the mdssvc RPC layer */
219 *r->out.fragment = 0;
221 ok = mds_dispatch(mds_ctx, &r->in.request_blob, r->out.response_blob);
225 /* FIXME: just interpolating from AFP, needs verification */
226 *r->out.unkn9 = UINT32_MAX;
232 void _mdssvc_close(struct pipes_struct *p, struct mdssvc_close *r)
234 struct mds_ctx *mds_ctx;
237 mds_ctx = find_policy_by_hnd(p,
242 if (!NT_STATUS_IS_OK(status)) {
243 DBG_WARNING("invalid handle\n");
244 if (ndr_policy_handle_empty(r->in.in_handle)) {
247 p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
252 DBG_DEBUG("Close mdssvc handle for path: %s\n", mds_ctx->spath);
253 TALLOC_FREE(mds_ctx);
255 *r->out.out_handle = *r->in.in_handle;
256 close_policy_hnd(p, r->in.in_handle);
263 static NTSTATUS mdssvc__op_init_server(struct dcesrv_context *dce_ctx,
264 const struct dcesrv_endpoint_server *ep_server);
266 static NTSTATUS mdssvc__op_shutdown_server(struct dcesrv_context *dce_ctx,
267 const struct dcesrv_endpoint_server *ep_server);
269 #define DCESRV_INTERFACE_MDSSVC_INIT_SERVER \
272 #define DCESRV_INTERFACE_MDSSVC_SHUTDOWN_SERVER \
273 mdssvc_shutdown_server
275 static NTSTATUS mdssvc_init_server(struct dcesrv_context *dce_ctx,
276 const struct dcesrv_endpoint_server *ep_server)
278 struct messaging_context *msg_ctx = global_messaging_context();
281 ok = mds_init(msg_ctx);
283 return NT_STATUS_UNSUCCESSFUL;
286 return mdssvc__op_init_server(dce_ctx, ep_server);
289 static NTSTATUS mdssvc_shutdown_server(struct dcesrv_context *dce_ctx,
290 const struct dcesrv_endpoint_server *ep_server)
294 return mdssvc__op_shutdown_server(dce_ctx, ep_server);
297 /* include the generated boilerplate */
298 #include "librpc/gen_ndr/ndr_mdssvc_scompat.c"