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_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"
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
);
42 ok
= init_service_mdssvc(msg_ctx
);
50 static bool mdssvc_shutdown_cb(void *ptr
)
52 shutdown_service_mdssvc();
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
;
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
)) {
76 if (service_mode
!= RPC_SERVICE_MODE_EMBEDDED
77 || mdssvc_type
!= RPC_DAEMON_EMBEDDED
) {
81 status
= rpc_setup_embedded(ev_ctx
, msg_ctx
, t
, pipe_name
);
82 if (!NT_STATUS_IS_OK(status
)) {
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
,
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
,
117 const char *sharename
,
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
),
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
;
145 void _mdssvc_open(struct pipes_struct
*p
, struct mdssvc_open
*r
)
148 char *outpath
= discard_const_p(char, r
->out
.share_path
);
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
;
159 snum
= lp_servicenumber(r
->in
.share_name
);
160 if (!VALID_SNUM(snum
)) {
164 path
= lp_path(talloc_tos(), snum
);
166 DBG_ERR("Couldn't create policy handle for %s\n",
168 p
->fault_state
= DCERPC_FAULT_CANT_PERFORM
;
172 status
= create_mdssvc_policy_handle(p
->mem_ctx
, p
,
177 if (!NT_STATUS_IS_OK(status
)) {
178 DBG_ERR("Couldn't create policy handle for %s\n",
181 p
->fault_state
= DCERPC_FAULT_CANT_PERFORM
;
185 strlcpy(outpath
, path
, 1024);
190 static bool is_zero_policy_handle(const struct policy_handle
*h
)
192 struct GUID zero_uuid
= {0};
194 if (h
->handle_type
!= 0) {
197 if (!GUID_equal(&h
->uuid
, &zero_uuid
)) {
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
)) {
211 p
->fault_state
= DCERPC_NCA_S_PROTO_ERROR
;
219 DEBUG(10, ("%s: path: %s\n", __func__
, mds_ctx
->spath
));
222 *r
->out
.flags
= 0x6b000001;
228 void _mdssvc_cmd(struct pipes_struct
*p
, struct mdssvc_cmd
*r
)
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
)) {
238 p
->fault_state
= DCERPC_NCA_S_PROTO_ERROR
;
240 r
->out
.response_blob
->size
= 0;
241 *r
->out
.fragment
= 0;
246 DEBUG(10, ("%s: path: %s\n", __func__
, mds_ctx
->spath
));
248 ok
= security_token_is_sid(p
->session_info
->security_token
,
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
;
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
;
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
;
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
;
282 rbuf
= talloc_zero_array(p
->mem_ctx
, char, r
->in
.max_fragment_size1
);
284 p
->fault_state
= DCERPC_FAULT_CANT_PERFORM
;
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
);
297 /* FIXME: just interpolating from AFP, needs verification */
298 *r
->out
.unkn9
= UINT32_MAX
;
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
)) {
313 p
->fault_state
= DCERPC_NCA_S_PROTO_ERROR
;
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
);