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 dcesrv_call_state
*dce_call
= p
->dce_call
;
48 struct auth_session_info
*session_info
=
49 dcesrv_call_session_info(dce_call
);
50 struct mds_ctx
*mds_ctx
;
55 status
= mds_init_ctx(mem_ctx
,
56 messaging_tevent_context(p
->msg_ctx
),
63 if (!NT_STATUS_IS_OK(status
)) {
64 DBG_DEBUG("mds_init_ctx() path [%s] failed: %s\n",
65 path
, nt_errstr(status
));
69 if (!create_policy_hnd(p
, handle
, 0, mds_ctx
)) {
72 return NT_STATUS_NO_MEMORY
;
78 void _mdssvc_open(struct pipes_struct
*p
, struct mdssvc_open
*r
)
80 const struct loadparm_substitution
*lp_sub
=
81 loadparm_s3_global_substitution();
83 char *outpath
= discard_const_p(char, r
->out
.share_path
);
84 char *fake_path
= NULL
;
88 DBG_DEBUG("[%s]\n", r
->in
.share_name
);
90 *r
->out
.device_id
= *r
->in
.device_id
;
91 *r
->out
.unkn2
= *r
->in
.unkn2
;
92 *r
->out
.unkn3
= *r
->in
.unkn3
;
95 snum
= lp_servicenumber(r
->in
.share_name
);
96 if (!VALID_SNUM(snum
)) {
100 path
= lp_path(talloc_tos(), lp_sub
, snum
);
102 DBG_ERR("Couldn't create path for %s\n",
104 p
->fault_state
= DCERPC_FAULT_CANT_PERFORM
;
108 fake_path
= talloc_asprintf(p
->mem_ctx
, "/%s", r
->in
.share_name
);
109 if (fake_path
== NULL
) {
110 DBG_ERR("Couldn't create fake share path for %s\n",
113 p
->fault_state
= DCERPC_FAULT_CANT_PERFORM
;
117 status
= create_mdssvc_policy_handle(p
->mem_ctx
, p
,
122 if (NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_VOLUME
)) {
123 ZERO_STRUCTP(r
->out
.handle
);
125 talloc_free(fake_path
);
128 if (!NT_STATUS_IS_OK(status
)) {
129 DBG_ERR("Couldn't create policy handle for %s\n",
132 talloc_free(fake_path
);
133 p
->fault_state
= DCERPC_FAULT_CANT_PERFORM
;
137 strlcpy(outpath
, fake_path
, 1024);
139 talloc_free(fake_path
);
143 void _mdssvc_unknown1(struct pipes_struct
*p
, struct mdssvc_unknown1
*r
)
145 struct mds_ctx
*mds_ctx
;
148 mds_ctx
= find_policy_by_hnd(p
,
153 if (!NT_STATUS_IS_OK(status
)) {
154 if (ndr_policy_handle_empty(r
->in
.handle
)) {
157 p
->fault_state
= DCERPC_NCA_S_PROTO_ERROR
;
165 DEBUG(10, ("%s: path: %s\n", __func__
, mds_ctx
->spath
));
168 *r
->out
.flags
= 0x6b000001;
174 void _mdssvc_cmd(struct pipes_struct
*p
, struct mdssvc_cmd
*r
)
176 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
177 struct auth_session_info
*session_info
=
178 dcesrv_call_session_info(dce_call
);
180 struct mds_ctx
*mds_ctx
;
183 mds_ctx
= find_policy_by_hnd(p
,
188 if (!NT_STATUS_IS_OK(status
)) {
189 if (ndr_policy_handle_empty(r
->in
.handle
)) {
192 p
->fault_state
= DCERPC_NCA_S_PROTO_ERROR
;
194 r
->out
.response_blob
->size
= 0;
195 *r
->out
.fragment
= 0;
200 DEBUG(10, ("%s: path: %s\n", __func__
, mds_ctx
->spath
));
202 ok
= security_token_is_sid(session_info
->security_token
,
205 struct dom_sid_buf buf
;
206 DBG_WARNING("not the same sid: %s\n",
207 dom_sid_str_buf(&mds_ctx
->sid
, &buf
));
208 p
->fault_state
= DCERPC_FAULT_ACCESS_DENIED
;
212 if (geteuid() != mds_ctx
->uid
) {
213 DEBUG(0, ("uid mismatch: %d/%d\n", geteuid(), mds_ctx
->uid
));
214 smb_panic("uid mismatch");
217 if (r
->in
.request_blob
.size
> MAX_SL_FRAGMENT_SIZE
) {
218 DEBUG(1, ("%s: request size too large\n", __func__
));
219 p
->fault_state
= DCERPC_FAULT_CANT_PERFORM
;
223 if (r
->in
.request_blob
.length
> MAX_SL_FRAGMENT_SIZE
) {
224 DEBUG(1, ("%s: request length too large\n", __func__
));
225 p
->fault_state
= DCERPC_FAULT_CANT_PERFORM
;
229 if (r
->in
.max_fragment_size1
> MAX_SL_FRAGMENT_SIZE
) {
230 DEBUG(1, ("%s: request fragment size too large: %u\n",
231 __func__
, (unsigned)r
->in
.max_fragment_size1
));
232 p
->fault_state
= DCERPC_FAULT_CANT_PERFORM
;
236 /* We currently don't use fragmentation at the mdssvc RPC layer */
237 *r
->out
.fragment
= 0;
239 ok
= mds_dispatch(mds_ctx
,
241 r
->out
.response_blob
,
242 r
->in
.max_fragment_size1
);
246 /* FIXME: just interpolating from AFP, needs verification */
247 *r
->out
.unkn9
= UINT32_MAX
;
253 void _mdssvc_close(struct pipes_struct
*p
, struct mdssvc_close
*r
)
255 struct mds_ctx
*mds_ctx
;
258 mds_ctx
= find_policy_by_hnd(p
,
263 if (!NT_STATUS_IS_OK(status
)) {
264 DBG_WARNING("invalid handle\n");
265 if (ndr_policy_handle_empty(r
->in
.in_handle
)) {
268 p
->fault_state
= DCERPC_NCA_S_PROTO_ERROR
;
273 DBG_DEBUG("Close mdssvc handle for path: %s\n", mds_ctx
->spath
);
274 TALLOC_FREE(mds_ctx
);
276 *r
->out
.out_handle
= *r
->in
.in_handle
;
277 close_policy_hnd(p
, r
->in
.in_handle
);
284 static NTSTATUS
mdssvc__op_init_server(struct dcesrv_context
*dce_ctx
,
285 const struct dcesrv_endpoint_server
*ep_server
);
287 static NTSTATUS
mdssvc__op_shutdown_server(struct dcesrv_context
*dce_ctx
,
288 const struct dcesrv_endpoint_server
*ep_server
);
290 #define DCESRV_INTERFACE_MDSSVC_INIT_SERVER \
293 #define DCESRV_INTERFACE_MDSSVC_SHUTDOWN_SERVER \
294 mdssvc_shutdown_server
296 static NTSTATUS
mdssvc_init_server(struct dcesrv_context
*dce_ctx
,
297 const struct dcesrv_endpoint_server
*ep_server
)
299 struct messaging_context
*msg_ctx
= global_messaging_context();
302 ok
= mds_init(msg_ctx
);
304 return NT_STATUS_UNSUCCESSFUL
;
307 return mdssvc__op_init_server(dce_ctx
, ep_server
);
310 static NTSTATUS
mdssvc_shutdown_server(struct dcesrv_context
*dce_ctx
,
311 const struct dcesrv_endpoint_server
*ep_server
)
315 return mdssvc__op_shutdown_server(dce_ctx
, ep_server
);
318 /* include the generated boilerplate */
319 #include "librpc/gen_ndr/ndr_mdssvc_scompat.c"