librpc/ndr: apply some const to ndr_push_union_blob()
[samba.git] / source3 / rpc_server / mdssvc / srv_mdssvc_nt.c
blob9a166244df5ea83c8af312e773b8db850aa8e8d6
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_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"
29 #include "mdssvc.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"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_RPC_SRV
40 static NTSTATUS create_mdssvc_policy_handle(TALLOC_CTX *mem_ctx,
41 struct pipes_struct *p,
42 int snum,
43 const char *sharename,
44 const char *path,
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;
51 NTSTATUS status;
53 ZERO_STRUCTP(handle);
55 status = mds_init_ctx(mem_ctx,
56 messaging_tevent_context(p->msg_ctx),
57 p->msg_ctx,
58 session_info,
59 snum,
60 sharename,
61 path,
62 &mds_ctx);
63 if (!NT_STATUS_IS_OK(status)) {
64 DBG_DEBUG("mds_init_ctx() path [%s] failed: %s\n",
65 path, nt_errstr(status));
66 return status;
69 if (!create_policy_hnd(p, handle, 0, mds_ctx)) {
70 talloc_free(mds_ctx);
71 ZERO_STRUCTP(handle);
72 return NT_STATUS_NO_MEMORY;
75 return NT_STATUS_OK;
78 void _mdssvc_open(struct pipes_struct *p, struct mdssvc_open *r)
80 const struct loadparm_substitution *lp_sub =
81 loadparm_s3_global_substitution();
82 int snum;
83 char *outpath = discard_const_p(char, r->out.share_path);
84 char *fake_path = NULL;
85 char *path;
86 NTSTATUS status;
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;
93 outpath[0] = '\0';
95 snum = lp_servicenumber(r->in.share_name);
96 if (!VALID_SNUM(snum)) {
97 return;
100 path = lp_path(talloc_tos(), lp_sub, snum);
101 if (path == NULL) {
102 DBG_ERR("Couldn't create path for %s\n",
103 r->in.share_name);
104 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
105 return;
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",
111 r->in.share_name);
112 talloc_free(path);
113 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
114 return;
117 status = create_mdssvc_policy_handle(p->mem_ctx, p,
118 snum,
119 r->in.share_name,
120 path,
121 r->out.handle);
122 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_VOLUME)) {
123 ZERO_STRUCTP(r->out.handle);
124 talloc_free(path);
125 talloc_free(fake_path);
126 return;
128 if (!NT_STATUS_IS_OK(status)) {
129 DBG_ERR("Couldn't create policy handle for %s\n",
130 r->in.share_name);
131 talloc_free(path);
132 talloc_free(fake_path);
133 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
134 return;
137 strlcpy(outpath, fake_path, 1024);
138 talloc_free(path);
139 talloc_free(fake_path);
140 return;
143 void _mdssvc_unknown1(struct pipes_struct *p, struct mdssvc_unknown1 *r)
145 struct mds_ctx *mds_ctx;
146 NTSTATUS status;
148 mds_ctx = find_policy_by_hnd(p,
149 r->in.handle,
150 DCESRV_HANDLE_ANY,
151 struct mds_ctx,
152 &status);
153 if (!NT_STATUS_IS_OK(status)) {
154 if (ndr_policy_handle_empty(r->in.handle)) {
155 p->fault_state = 0;
156 } else {
157 p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
159 *r->out.status = 0;
160 *r->out.flags = 0;
161 *r->out.unkn7 = 0;
162 return;
165 DEBUG(10, ("%s: path: %s\n", __func__, mds_ctx->spath));
167 *r->out.status = 0;
168 *r->out.flags = 0x6b000001;
169 *r->out.unkn7 = 0;
171 return;
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);
179 bool ok;
180 struct mds_ctx *mds_ctx;
181 NTSTATUS status;
183 mds_ctx = find_policy_by_hnd(p,
184 r->in.handle,
185 DCESRV_HANDLE_ANY,
186 struct mds_ctx,
187 &status);
188 if (!NT_STATUS_IS_OK(status)) {
189 if (ndr_policy_handle_empty(r->in.handle)) {
190 p->fault_state = 0;
191 } else {
192 p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
194 r->out.response_blob->size = 0;
195 *r->out.fragment = 0;
196 *r->out.unkn9 = 0;
197 return;
200 DEBUG(10, ("%s: path: %s\n", __func__, mds_ctx->spath));
202 ok = security_token_is_sid(session_info->security_token,
203 &mds_ctx->sid);
204 if (!ok) {
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;
209 return;
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;
220 return;
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;
226 return;
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;
233 return;
236 /* We currently don't use fragmentation at the mdssvc RPC layer */
237 *r->out.fragment = 0;
239 ok = mds_dispatch(mds_ctx,
240 &r->in.request_blob,
241 r->out.response_blob,
242 r->in.max_fragment_size1);
243 if (ok) {
244 *r->out.unkn9 = 0;
245 } else {
246 /* FIXME: just interpolating from AFP, needs verification */
247 *r->out.unkn9 = UINT32_MAX;
250 return;
253 void _mdssvc_close(struct pipes_struct *p, struct mdssvc_close *r)
255 struct mds_ctx *mds_ctx;
256 NTSTATUS status;
258 mds_ctx = find_policy_by_hnd(p,
259 r->in.in_handle,
260 DCESRV_HANDLE_ANY,
261 struct mds_ctx,
262 &status);
263 if (!NT_STATUS_IS_OK(status)) {
264 DBG_WARNING("invalid handle\n");
265 if (ndr_policy_handle_empty(r->in.in_handle)) {
266 p->fault_state = 0;
267 } else {
268 p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
270 return;
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);
279 *r->out.status = 0;
281 return;
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 \
291 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();
300 bool ok;
302 ok = mds_init(msg_ctx);
303 if (!ok) {
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)
313 mds_shutdown();
315 return mdssvc__op_shutdown_server(dce_ctx, ep_server);
318 /* include the generated boilerplate */
319 #include "librpc/gen_ndr/ndr_mdssvc_scompat.c"