diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
commit | 4f5791ebd03eaec1c7da0865a383175b05102712 (patch) | |
tree | 8ce7b00f7a76baa386372422adebbe64510812d4 /source4/rpc_server/srvsvc | |
parent | Initial commit. (diff) | |
download | samba-4f5791ebd03eaec1c7da0865a383175b05102712.tar.xz samba-4f5791ebd03eaec1c7da0865a383175b05102712.zip |
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source4/rpc_server/srvsvc')
-rw-r--r-- | source4/rpc_server/srvsvc/dcesrv_srvsvc.c | 2300 | ||||
-rw-r--r-- | source4/rpc_server/srvsvc/srvsvc_ntvfs.c | 139 |
2 files changed, 2439 insertions, 0 deletions
diff --git a/source4/rpc_server/srvsvc/dcesrv_srvsvc.c b/source4/rpc_server/srvsvc/dcesrv_srvsvc.c new file mode 100644 index 0000000..d7a2262 --- /dev/null +++ b/source4/rpc_server/srvsvc/dcesrv_srvsvc.c @@ -0,0 +1,2300 @@ +/* + Unix SMB/CIFS implementation. + + endpoint server for the srvsvc pipe + + Copyright (C) Stefan (metze) Metzmacher 2004-2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "ntvfs/ntvfs.h" +#include "rpc_server/dcerpc_server.h" +#include "librpc/gen_ndr/ndr_srvsvc.h" +#include "rpc_server/common/common.h" +#include "rpc_server/common/share.h" +#include "auth/auth.h" +#include "libcli/security/security.h" +#include "system/time.h" +#include "rpc_server/srvsvc/proto.h" +#include "param/param.h" + +#undef strcasecmp +#undef strncasecmp + +#define SRVSVC_CHECK_ADMIN_ACCESS do { \ + struct auth_session_info *si = dcesrv_call_session_info(dce_call); \ + struct security_token *t = si->security_token; \ + if (!security_token_has_builtin_administrators(t) && \ + !security_token_has_sid(t, &global_sid_Builtin_Server_Operators)) { \ + return WERR_ACCESS_DENIED; \ + } \ +} while (0) + +/* + srvsvc_NetCharDevEnum +*/ +static WERROR dcesrv_srvsvc_NetCharDevEnum(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetCharDevEnum *r) +{ + *r->out.totalentries = 0; + + switch (r->in.info_ctr->level) { + case 0: + r->out.info_ctr->ctr.ctr0 = talloc(mem_ctx, struct srvsvc_NetCharDevCtr0); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr0); + + r->out.info_ctr->ctr.ctr0->count = 0; + r->out.info_ctr->ctr.ctr0->array = NULL; + + return WERR_NOT_SUPPORTED; + + case 1: + r->out.info_ctr->ctr.ctr1 = talloc(mem_ctx, struct srvsvc_NetCharDevCtr1); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr1); + + r->out.info_ctr->ctr.ctr1->count = 0; + r->out.info_ctr->ctr.ctr1->array = NULL; + + return WERR_NOT_SUPPORTED; + + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetCharDevGetInfo +*/ +static WERROR dcesrv_srvsvc_NetCharDevGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetCharDevGetInfo *r) +{ + ZERO_STRUCTP(r->out.info); + + switch (r->in.level) { + case 0: + { + return WERR_NOT_SUPPORTED; + } + case 1: + { + return WERR_NOT_SUPPORTED; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetCharDevControl +*/ +static WERROR dcesrv_srvsvc_NetCharDevControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetCharDevControl *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetCharDevQEnum +*/ +static WERROR dcesrv_srvsvc_NetCharDevQEnum(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetCharDevQEnum *r) +{ + *r->out.totalentries = 0; + + switch (r->in.info_ctr->level) { + case 0: + { + r->out.info_ctr->ctr.ctr0 = talloc(mem_ctx, struct srvsvc_NetCharDevQCtr0); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr0); + + r->out.info_ctr->ctr.ctr0->count = 0; + r->out.info_ctr->ctr.ctr0->array = NULL; + + return WERR_NOT_SUPPORTED; + } + case 1: + { + r->out.info_ctr->ctr.ctr1 = talloc(mem_ctx, struct srvsvc_NetCharDevQCtr1); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr1); + + r->out.info_ctr->ctr.ctr1->count = 0; + r->out.info_ctr->ctr.ctr1->array = NULL; + + return WERR_NOT_SUPPORTED; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetCharDevQGetInfo +*/ +static WERROR dcesrv_srvsvc_NetCharDevQGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetCharDevQGetInfo *r) +{ + ZERO_STRUCTP(r->out.info); + + switch (r->in.level) { + case 0: + { + return WERR_NOT_SUPPORTED; + } + case 1: + { + return WERR_NOT_SUPPORTED; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetCharDevQSetInfo +*/ +static WERROR dcesrv_srvsvc_NetCharDevQSetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetCharDevQSetInfo *r) +{ + switch (r->in.level) { + case 0: + { + if (r->in.parm_error) { + r->out.parm_error = r->in.parm_error; + } + return WERR_NOT_SUPPORTED; + } + case 1: + { + if (r->in.parm_error) { + r->out.parm_error = r->in.parm_error; + } + return WERR_NOT_SUPPORTED; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetCharDevQPurge +*/ +static WERROR dcesrv_srvsvc_NetCharDevQPurge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetCharDevQPurge *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetCharDevQPurgeSelf +*/ +static WERROR dcesrv_srvsvc_NetCharDevQPurgeSelf(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetCharDevQPurgeSelf *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetConnEnum +*/ +static WERROR dcesrv_srvsvc_NetConnEnum(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetConnEnum *r) +{ + *r->out.totalentries = 0; + + switch (r->in.info_ctr->level) { + case 0: + { + r->out.info_ctr->ctr.ctr0 = talloc(mem_ctx, struct srvsvc_NetConnCtr0); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr0); + + r->out.info_ctr->ctr.ctr0->count = 0; + r->out.info_ctr->ctr.ctr0->array = NULL; + + return WERR_NOT_SUPPORTED; + } + case 1: + { + r->out.info_ctr->ctr.ctr1 = talloc(mem_ctx, struct srvsvc_NetConnCtr1); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr1); + + r->out.info_ctr->ctr.ctr1->count = 0; + r->out.info_ctr->ctr.ctr1->array = NULL; + + return WERR_NOT_SUPPORTED; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetFileEnum +*/ +static WERROR dcesrv_srvsvc_NetFileEnum(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetFileEnum *r) +{ + *r->out.totalentries = 0; + + switch (r->in.info_ctr->level) { + case 2: + { + r->out.info_ctr->ctr.ctr2 = talloc(mem_ctx, struct srvsvc_NetFileCtr2); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr2); + + r->out.info_ctr->ctr.ctr2->count = 0; + r->out.info_ctr->ctr.ctr2->array = NULL; + + return WERR_NOT_SUPPORTED; + } + case 3: + { + r->out.info_ctr->ctr.ctr3 = talloc(mem_ctx, struct srvsvc_NetFileCtr3); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr3); + + r->out.info_ctr->ctr.ctr3->count = 0; + r->out.info_ctr->ctr.ctr3->array = NULL; + + return WERR_NOT_SUPPORTED; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetFileGetInfo +*/ +static WERROR dcesrv_srvsvc_NetFileGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetFileGetInfo *r) +{ + ZERO_STRUCTP(r->out.info); + + switch (r->in.level) { + case 2: + { + return WERR_NOT_SUPPORTED; + } + case 3: + { + return WERR_NOT_SUPPORTED; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetFileClose +*/ +static WERROR dcesrv_srvsvc_NetFileClose(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetFileClose *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetSessEnum +*/ +static WERROR dcesrv_srvsvc_NetSessEnum(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetSessEnum *r) +{ + *r->out.totalentries = 0; + + switch (r->in.info_ctr->level) { + case 0: + { + r->out.info_ctr->ctr.ctr0 = talloc(mem_ctx, struct srvsvc_NetSessCtr0); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr0); + + r->out.info_ctr->ctr.ctr0->count = 0; + r->out.info_ctr->ctr.ctr0->array = NULL; + + return WERR_NOT_SUPPORTED; + } + case 1: + { + r->out.info_ctr->ctr.ctr1 = talloc(mem_ctx, struct srvsvc_NetSessCtr1); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr1); + + r->out.info_ctr->ctr.ctr1->count = 0; + r->out.info_ctr->ctr.ctr1->array = NULL; + + return WERR_NOT_SUPPORTED; + } + case 2: + { + r->out.info_ctr->ctr.ctr2 = talloc(mem_ctx, struct srvsvc_NetSessCtr2); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr2); + + r->out.info_ctr->ctr.ctr2->count = 0; + r->out.info_ctr->ctr.ctr2->array = NULL; + + return WERR_NOT_SUPPORTED; + } + case 10: + { + r->out.info_ctr->ctr.ctr10 = talloc(mem_ctx, struct srvsvc_NetSessCtr10); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr10); + + r->out.info_ctr->ctr.ctr10->count = 0; + r->out.info_ctr->ctr.ctr10->array = NULL; + + return WERR_NOT_SUPPORTED; + } + case 502: + { + r->out.info_ctr->ctr.ctr502 = talloc(mem_ctx, struct srvsvc_NetSessCtr502); + W_ERROR_HAVE_NO_MEMORY(r->out.info_ctr->ctr.ctr502); + + r->out.info_ctr->ctr.ctr502->count = 0; + r->out.info_ctr->ctr.ctr502->array = NULL; + + return WERR_NOT_SUPPORTED; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetSessDel +*/ +static WERROR dcesrv_srvsvc_NetSessDel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetSessDel *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetShareAdd +*/ +static WERROR dcesrv_srvsvc_NetShareAdd(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetShareAdd *r) +{ + switch (r->in.level) { + case 0: + { + if (r->in.parm_error) { + r->out.parm_error = r->in.parm_error; + } + return WERR_NOT_SUPPORTED; + } + case 1: + { + if (r->in.parm_error) { + r->out.parm_error = r->in.parm_error; + } + return WERR_NOT_SUPPORTED; + } + case 2: + { + NTSTATUS nterr; + struct share_info *info; + struct share_context *sctx; + unsigned int count = 8; + unsigned int i; + + nterr = share_get_context(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + /* there are no more than 8 options in struct srvsvc_NetShareInfo2 */ + info = talloc_array(mem_ctx, struct share_info, count); + W_ERROR_HAVE_NO_MEMORY(info); + + i = 0; + + info[i].name = SHARE_TYPE; + info[i].type = SHARE_INFO_STRING; + switch (r->in.info->info2->type) { + case STYPE_DISKTREE: + info[i].value = talloc_strdup(info, "DISK"); + break; + case STYPE_PRINTQ: + info[i].value = talloc_strdup(info, "PRINTER"); + break; + case STYPE_IPC: + info[i].value = talloc_strdup(info, "IPC"); + break; + default: + return WERR_INVALID_PARAMETER; + } + W_ERROR_HAVE_NO_MEMORY(info[i].value); + i++; + + if (r->in.info->info2->path && r->in.info->info2->path[0]) { + info[i].name = SHARE_PATH; + info[i].type = SHARE_INFO_STRING; + + /* Windows will send a path in a form of C:\example\path */ + if (r->in.info->info2->path[1] == ':') { + info[i].value = talloc_strdup(info, &r->in.info->info2->path[2]); + } else { + /* very strange let's try to set as is */ + info[i].value = talloc_strdup(info, r->in.info->info2->path); + } + W_ERROR_HAVE_NO_MEMORY(info[i].value); + all_string_sub((char *)info[i].value, "\\", "/", 0); + + i++; + } + + if (r->in.info->info2->comment && r->in.info->info2->comment[0]) { + info[i].name = SHARE_COMMENT; + info[i].type = SHARE_INFO_STRING; + info[i].value = talloc_strdup(info, r->in.info->info2->comment); + W_ERROR_HAVE_NO_MEMORY(info[i].value); + + i++; + } + + if (r->in.info->info2->password && r->in.info->info2->password[0]) { + info[i].name = SHARE_PASSWORD; + info[i].type = SHARE_INFO_STRING; + info[i].value = talloc_strdup(info, r->in.info->info2->password); + W_ERROR_HAVE_NO_MEMORY(info[i].value); + + i++; + } + + info[i].name = SHARE_MAX_CONNECTIONS; + info[i].type = SHARE_INFO_INT; + info[i].value = talloc(info, int); + *((int *)info[i].value) = r->in.info->info2->max_users; + i++; + + /* TODO: security descriptor */ + + nterr = share_create(sctx, r->in.info->info2->name, info, i); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + if (r->in.parm_error) { + r->out.parm_error = r->in.parm_error; + } + + return WERR_OK; + } + case 501: + { + if (r->in.parm_error) { + r->out.parm_error = r->in.parm_error; + } + return WERR_NOT_SUPPORTED; + } + case 502: + { + NTSTATUS nterr; + struct share_info *info; + struct share_context *sctx; + unsigned int count = 10; + unsigned int i; + + nterr = share_get_context(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + /* there are no more than 10 options in struct srvsvc_NetShareInfo502 */ + info = talloc_array(mem_ctx, struct share_info, count); + W_ERROR_HAVE_NO_MEMORY(info); + + i = 0; + + info[i].name = SHARE_TYPE; + info[i].type = SHARE_INFO_STRING; + switch (r->in.info->info502->type) { + case 0x00: + info[i].value = talloc_strdup(info, "DISK"); + break; + case 0x01: + info[i].value = talloc_strdup(info, "PRINTER"); + break; + case 0x03: + info[i].value = talloc_strdup(info, "IPC"); + break; + default: + return WERR_INVALID_PARAMETER; + } + W_ERROR_HAVE_NO_MEMORY(info[i].value); + i++; + + if (r->in.info->info502->path && r->in.info->info502->path[0]) { + info[i].name = SHARE_PATH; + info[i].type = SHARE_INFO_STRING; + + /* Windows will send a path in a form of C:\example\path */ + if (r->in.info->info502->path[1] == ':') { + info[i].value = talloc_strdup(info, &r->in.info->info502->path[2]); + } else { + /* very strange let's try to set as is */ + info[i].value = talloc_strdup(info, r->in.info->info502->path); + } + W_ERROR_HAVE_NO_MEMORY(info[i].value); + all_string_sub((char *)info[i].value, "\\", "/", 0); + + i++; + } + + if (r->in.info->info502->comment && r->in.info->info502->comment[0]) { + info[i].name = SHARE_COMMENT; + info[i].type = SHARE_INFO_STRING; + info[i].value = talloc_strdup(info, r->in.info->info502->comment); + W_ERROR_HAVE_NO_MEMORY(info[i].value); + + i++; + } + + if (r->in.info->info502->password && r->in.info->info502->password[0]) { + info[i].name = SHARE_PASSWORD; + info[i].type = SHARE_INFO_STRING; + info[i].value = talloc_strdup(info, r->in.info->info502->password); + W_ERROR_HAVE_NO_MEMORY(info[i].value); + + i++; + } + + info[i].name = SHARE_MAX_CONNECTIONS; + info[i].type = SHARE_INFO_INT; + info[i].value = talloc(info, int); + *((int *)info[i].value) = r->in.info->info502->max_users; + i++; + + /* TODO: security descriptor */ + + nterr = share_create(sctx, r->in.info->info502->name, info, i); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + if (r->in.parm_error) { + r->out.parm_error = r->in.parm_error; + } + + return WERR_OK; + } + default: + return WERR_INVALID_LEVEL; + } +} + +static WERROR dcesrv_srvsvc_fiel_ShareInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct share_config *scfg, uint32_t level, + union srvsvc_NetShareInfo *info) +{ + struct dcesrv_context *dce_ctx = dce_call->conn->dce_ctx; + + switch (level) { + case 0: + { + info->info0->name = talloc_strdup(mem_ctx, scfg->name); + W_ERROR_HAVE_NO_MEMORY(info->info0->name); + + return WERR_OK; + } + case 1: + { + info->info1->name = talloc_strdup(mem_ctx, scfg->name); + W_ERROR_HAVE_NO_MEMORY(info->info1->name); + info->info1->type = dcesrv_common_get_share_type(mem_ctx, dce_ctx, scfg); + info->info1->comment = share_string_option(mem_ctx, scfg, SHARE_COMMENT, ""); + W_ERROR_HAVE_NO_MEMORY(info->info1->comment); + + return WERR_OK; + } + case 2: + { + info->info2->name = talloc_strdup(mem_ctx, scfg->name); + W_ERROR_HAVE_NO_MEMORY(info->info2->name); + info->info2->type = dcesrv_common_get_share_type(mem_ctx, dce_ctx, scfg); + info->info2->comment = share_string_option(mem_ctx, scfg, SHARE_COMMENT, ""); + W_ERROR_HAVE_NO_MEMORY(info->info2->comment); + info->info2->permissions = dcesrv_common_get_share_permissions(mem_ctx, dce_ctx, scfg); + info->info2->max_users = share_int_option(scfg, SHARE_MAX_CONNECTIONS, SHARE_MAX_CONNECTIONS_DEFAULT); + info->info2->current_users = dcesrv_common_get_share_current_users(mem_ctx, dce_ctx, scfg); + info->info2->path = dcesrv_common_get_share_path(mem_ctx, dce_ctx, scfg); + W_ERROR_HAVE_NO_MEMORY(info->info2->path); + info->info2->password = share_string_option(mem_ctx, scfg, SHARE_PASSWORD, NULL); + + return WERR_OK; + } + case 501: + { + info->info501->name = talloc_strdup(mem_ctx, scfg->name); + W_ERROR_HAVE_NO_MEMORY(info->info501->name); + info->info501->type = dcesrv_common_get_share_type(mem_ctx, dce_ctx, scfg); + info->info501->comment = share_string_option(mem_ctx, scfg, SHARE_COMMENT, ""); + W_ERROR_HAVE_NO_MEMORY(info->info501->comment); + info->info501->csc_policy = share_int_option(scfg, SHARE_CSC_POLICY, SHARE_CSC_POLICY_DEFAULT); + + return WERR_OK; + } + case 502: + { + info->info502->name = talloc_strdup(mem_ctx, scfg->name); + W_ERROR_HAVE_NO_MEMORY(info->info502->name); + info->info502->type = dcesrv_common_get_share_type(mem_ctx, dce_ctx, scfg); + info->info502->comment = share_string_option(mem_ctx, scfg, SHARE_COMMENT, ""); + W_ERROR_HAVE_NO_MEMORY(info->info502->comment); + info->info502->permissions = dcesrv_common_get_share_permissions(mem_ctx, dce_ctx, scfg); + info->info502->max_users = share_int_option(scfg, SHARE_MAX_CONNECTIONS, SHARE_MAX_CONNECTIONS_DEFAULT); + info->info502->current_users = dcesrv_common_get_share_current_users(mem_ctx, dce_ctx, scfg); + info->info502->path = dcesrv_common_get_share_path(mem_ctx, dce_ctx, scfg); + W_ERROR_HAVE_NO_MEMORY(info->info502->path); + info->info502->password = share_string_option(mem_ctx, scfg, SHARE_PASSWORD, NULL); + info->info502->sd_buf.sd = dcesrv_common_get_security_descriptor(mem_ctx, dce_ctx, scfg); + + return WERR_OK; + } + case 1005: + { + info->info1005->dfs_flags = dcesrv_common_get_share_dfs_flags(mem_ctx, dce_ctx, scfg); + + return WERR_OK; + } + default: + return WERR_INVALID_LEVEL; + } +} + +/* + srvsvc_NetShareEnumAll +*/ +static WERROR dcesrv_srvsvc_NetShareEnumAll(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetShareEnumAll *r) +{ + NTSTATUS nterr; + int numshares = 0; + const char **snames; + struct share_context *sctx; + struct share_config *scfg; + + *r->out.totalentries = 0; + + /* TODO: - paging of results + */ + + nterr = share_get_context(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + nterr = share_list_all(mem_ctx, sctx, &numshares, &snames); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + switch (r->in.info_ctr->level) { + case 0: + { + unsigned int i; + struct srvsvc_NetShareCtr0 *ctr0; + + ctr0 = talloc(mem_ctx, struct srvsvc_NetShareCtr0); + W_ERROR_HAVE_NO_MEMORY(ctr0); + + ctr0->count = numshares; + ctr0->array = NULL; + + if (ctr0->count == 0) { + r->out.info_ctr->ctr.ctr0 = ctr0; + return WERR_OK; + } + + ctr0->array = talloc_array(mem_ctx, struct srvsvc_NetShareInfo0, ctr0->count); + W_ERROR_HAVE_NO_MEMORY(ctr0->array); + + for (i = 0; i < ctr0->count; i++) { + WERROR status; + union srvsvc_NetShareInfo info; + + nterr = share_get_config(mem_ctx, sctx, snames[i], &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + DEBUG(1, ("ERROR: Service [%s] disappeared after enumeration", snames[i])); + return WERR_GEN_FAILURE; + } + info.info0 = &ctr0->array[i]; + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.info_ctr->level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + talloc_free(scfg); + } + talloc_free(snames); + + r->out.info_ctr->ctr.ctr0 = ctr0; + *r->out.totalentries = r->out.info_ctr->ctr.ctr0->count; + return WERR_OK; + } + case 1: + { + unsigned int i; + struct srvsvc_NetShareCtr1 *ctr1; + + ctr1 = talloc(mem_ctx, struct srvsvc_NetShareCtr1); + W_ERROR_HAVE_NO_MEMORY(ctr1); + + ctr1->count = numshares; + ctr1->array = NULL; + + if (ctr1->count == 0) { + r->out.info_ctr->ctr.ctr1 = ctr1; + return WERR_OK; + } + + ctr1->array = talloc_array(mem_ctx, struct srvsvc_NetShareInfo1, ctr1->count); + W_ERROR_HAVE_NO_MEMORY(ctr1->array); + + for (i=0; i < ctr1->count; i++) { + WERROR status; + union srvsvc_NetShareInfo info; + + nterr = share_get_config(mem_ctx, sctx, snames[i], &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + DEBUG(1, ("ERROR: Service [%s] disappeared after enumeration", snames[i])); + return WERR_GEN_FAILURE; + } + info.info1 = &ctr1->array[i]; + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.info_ctr->level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + talloc_free(scfg); + } + talloc_free(snames); + + r->out.info_ctr->ctr.ctr1 = ctr1; + *r->out.totalentries = r->out.info_ctr->ctr.ctr1->count; + + return WERR_OK; + } + case 2: + { + unsigned int i; + struct srvsvc_NetShareCtr2 *ctr2; + + SRVSVC_CHECK_ADMIN_ACCESS; + + ctr2 = talloc(mem_ctx, struct srvsvc_NetShareCtr2); + W_ERROR_HAVE_NO_MEMORY(ctr2); + + ctr2->count = numshares; + ctr2->array = NULL; + + if (ctr2->count == 0) { + r->out.info_ctr->ctr.ctr2 = ctr2; + return WERR_OK; + } + + ctr2->array = talloc_array(mem_ctx, struct srvsvc_NetShareInfo2, ctr2->count); + W_ERROR_HAVE_NO_MEMORY(ctr2->array); + + for (i=0; i < ctr2->count; i++) { + WERROR status; + union srvsvc_NetShareInfo info; + + nterr = share_get_config(mem_ctx, sctx, snames[i], &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + DEBUG(1, ("ERROR: Service [%s] disappeared after enumeration", snames[i])); + return WERR_GEN_FAILURE; + } + info.info2 = &ctr2->array[i]; + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.info_ctr->level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + talloc_free(scfg); + } + talloc_free(snames); + + r->out.info_ctr->ctr.ctr2 = ctr2; + *r->out.totalentries = r->out.info_ctr->ctr.ctr2->count; + + return WERR_OK; + } + case 501: + { + unsigned int i; + struct srvsvc_NetShareCtr501 *ctr501; + + SRVSVC_CHECK_ADMIN_ACCESS; + + ctr501 = talloc(mem_ctx, struct srvsvc_NetShareCtr501); + W_ERROR_HAVE_NO_MEMORY(ctr501); + + ctr501->count = numshares; + ctr501->array = NULL; + + if (ctr501->count == 0) { + r->out.info_ctr->ctr.ctr501 = ctr501; + return WERR_OK; + } + + ctr501->array = talloc_array(mem_ctx, struct srvsvc_NetShareInfo501, ctr501->count); + W_ERROR_HAVE_NO_MEMORY(ctr501->array); + + for (i=0; i < ctr501->count; i++) { + WERROR status; + union srvsvc_NetShareInfo info; + + nterr = share_get_config(mem_ctx, sctx, snames[i], &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + DEBUG(1, ("ERROR: Service [%s] disappeared after enumeration", snames[i])); + return WERR_GEN_FAILURE; + } + info.info501 = &ctr501->array[i]; + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.info_ctr->level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + talloc_free(scfg); + } + talloc_free(snames); + + r->out.info_ctr->ctr.ctr501 = ctr501; + *r->out.totalentries = r->out.info_ctr->ctr.ctr501->count; + + return WERR_OK; + } + case 502: + { + unsigned int i; + struct srvsvc_NetShareCtr502 *ctr502; + + SRVSVC_CHECK_ADMIN_ACCESS; + + ctr502 = talloc(mem_ctx, struct srvsvc_NetShareCtr502); + W_ERROR_HAVE_NO_MEMORY(ctr502); + + ctr502->count = numshares; + ctr502->array = NULL; + + if (ctr502->count == 0) { + r->out.info_ctr->ctr.ctr502 = ctr502; + return WERR_OK; + } + + ctr502->array = talloc_array(mem_ctx, struct srvsvc_NetShareInfo502, ctr502->count); + W_ERROR_HAVE_NO_MEMORY(ctr502->array); + + for (i=0; i < ctr502->count; i++) { + WERROR status; + union srvsvc_NetShareInfo info; + + nterr = share_get_config(mem_ctx, sctx, snames[i], &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + DEBUG(1, ("ERROR: Service [%s] disappeared after enumeration", snames[i])); + return WERR_GEN_FAILURE; + } + info.info502 = &ctr502->array[i]; + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.info_ctr->level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + talloc_free(scfg); + } + talloc_free(snames); + + r->out.info_ctr->ctr.ctr502 = ctr502; + *r->out.totalentries = r->out.info_ctr->ctr.ctr502->count; + + return WERR_OK; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetShareGetInfo +*/ +static WERROR dcesrv_srvsvc_NetShareGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetShareGetInfo *r) +{ + NTSTATUS nterr; + struct share_context *sctx = NULL; + struct share_config *scfg = NULL; + + ZERO_STRUCTP(r->out.info); + + /* TODO: - access check + */ + + if (strcmp("", r->in.share_name) == 0) { + return WERR_INVALID_PARAMETER; + } + + nterr = share_get_context(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + nterr = share_get_config(mem_ctx, sctx, r->in.share_name, &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + switch (r->in.level) { + case 0: + { + WERROR status; + union srvsvc_NetShareInfo info; + + info.info0 = talloc(mem_ctx, struct srvsvc_NetShareInfo0); + W_ERROR_HAVE_NO_MEMORY(info.info0); + + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + + r->out.info->info0 = info.info0; + return WERR_OK; + } + case 1: + { + WERROR status; + union srvsvc_NetShareInfo info; + + info.info1 = talloc(mem_ctx, struct srvsvc_NetShareInfo1); + W_ERROR_HAVE_NO_MEMORY(info.info1); + + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + + r->out.info->info1 = info.info1; + return WERR_OK; + } + case 2: + { + WERROR status; + union srvsvc_NetShareInfo info; + + SRVSVC_CHECK_ADMIN_ACCESS; + + info.info2 = talloc(mem_ctx, struct srvsvc_NetShareInfo2); + W_ERROR_HAVE_NO_MEMORY(info.info2); + + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + + r->out.info->info2 = info.info2; + return WERR_OK; + } + case 501: + { + WERROR status; + union srvsvc_NetShareInfo info; + + info.info501 = talloc(mem_ctx, struct srvsvc_NetShareInfo501); + W_ERROR_HAVE_NO_MEMORY(info.info501); + + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + + r->out.info->info501 = info.info501; + return WERR_OK; + } + case 502: + { + WERROR status; + union srvsvc_NetShareInfo info; + + SRVSVC_CHECK_ADMIN_ACCESS; + + info.info502 = talloc(mem_ctx, struct srvsvc_NetShareInfo502); + W_ERROR_HAVE_NO_MEMORY(info.info502); + + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + + r->out.info->info502 = info.info502; + return WERR_OK; + } + case 1005: + { + WERROR status; + union srvsvc_NetShareInfo info; + + info.info1005 = talloc(mem_ctx, struct srvsvc_NetShareInfo1005); + W_ERROR_HAVE_NO_MEMORY(info.info1005); + + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.level, &info); + if (!W_ERROR_IS_OK(status)) { + return status; + } + + r->out.info->info1005 = info.info1005; + return WERR_OK; + } + default: + return WERR_INVALID_LEVEL; + } +} + +static WERROR dcesrv_srvsvc_fill_share_info(struct share_info *info, int *count, + const char *share_name, int level, + const char *name, + const char *path, + const char *comment, + const char *password, + enum srvsvc_ShareType type, + int32_t max_users, + uint32_t csc_policy, + struct security_descriptor *sd) +{ + unsigned int i = 0; + + if (level == 501) { + info[i].name = SHARE_CSC_POLICY; + info[i].type = SHARE_INFO_INT; + info[i].value = talloc(info, int); + *((int *)info[i].value) = csc_policy; + i++; + } + + switch(level) { + + case 502: + /* TODO: check if unknown is csc_policy */ + + /* TODO: security descriptor */ + + case 2: + if (path && path[0]) { + info[i].name = SHARE_PATH; + info[i].type = SHARE_INFO_STRING; + + /* Windows will send a path in a form of C:\example\path */ + if (path[1] == ':') { + info[i].value = talloc_strdup(info, &path[2]); + } else { + /* very strange let's try to set as is */ + info[i].value = talloc_strdup(info, path); + } + W_ERROR_HAVE_NO_MEMORY(info[i].value); + all_string_sub((char *)info[i].value, "\\", "/", 0); + + i++; + } + + if (password && password[0]) { + info[i].name = SHARE_PASSWORD; + info[i].type = SHARE_INFO_STRING; + info[i].value = talloc_strdup(info, password); + W_ERROR_HAVE_NO_MEMORY(info[i].value); + + i++; + } + + info[i].name = SHARE_MAX_CONNECTIONS; + info[i].type = SHARE_INFO_INT; + info[i].value = talloc(info, int); + *((int *)info[i].value) = max_users; + i++; + + FALL_THROUGH; + case 501: + case 1: + info[i].name = SHARE_TYPE; + info[i].type = SHARE_INFO_STRING; + switch (type) { + case 0x00: + info[i].value = talloc_strdup(info, "DISK"); + break; + case 0x01: + info[i].value = talloc_strdup(info, "PRINTER"); + break; + case 0x03: + info[i].value = talloc_strdup(info, "IPC"); + break; + default: + return WERR_INVALID_PARAMETER; + } + W_ERROR_HAVE_NO_MEMORY(info[i].value); + i++; + + FALL_THROUGH; + case 1004: + if (comment) { + info[i].name = SHARE_COMMENT; + info[i].type = SHARE_INFO_STRING; + info[i].value = talloc_strdup(info, comment); + W_ERROR_HAVE_NO_MEMORY(info[i].value); + + i++; + } + + FALL_THROUGH; + case 0: + if (name && + strcasecmp(share_name, name) != 0) { + info[i].name = SHARE_NAME; + info[i].type = SHARE_INFO_STRING; + info[i].value = talloc_strdup(info, name); + W_ERROR_HAVE_NO_MEMORY(info[i].value); + i++; + } + + break; + + default: + return WERR_INVALID_LEVEL; + } + + *count = i; + + return WERR_OK; +} + +/* + srvsvc_NetShareSetInfo +*/ +static WERROR dcesrv_srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetShareSetInfo *r) +{ + NTSTATUS nterr; + WERROR status; + struct share_context *sctx = NULL; + struct share_info *info; + int count; + + /* TODO: - access check + */ + + /* there are no more than 10 options in all struct srvsvc_NetShareInfoXXX */ + info = talloc_array(mem_ctx, struct share_info, 10); + W_ERROR_HAVE_NO_MEMORY(info); + + if (strcmp("", r->in.share_name) == 0) { + return WERR_INVALID_PARAMETER; + } + + nterr = share_get_context(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + switch (r->in.level) { + case 0: + { + status = dcesrv_srvsvc_fill_share_info(info, &count, + r->in.share_name, r->in.level, + r->in.info->info0->name, + NULL, + NULL, + NULL, + 0, + 0, + 0, + NULL); + if (!W_ERROR_EQUAL(status, WERR_OK)) { + return status; + } + break; + } + case 1: + { + status = dcesrv_srvsvc_fill_share_info(info, &count, + r->in.share_name, r->in.level, + r->in.info->info1->name, + NULL, + r->in.info->info1->comment, + NULL, + r->in.info->info1->type, + 0, + 0, + NULL); + if (!W_ERROR_EQUAL(status, WERR_OK)) { + return status; + } + break; + } + case 2: + { + status = dcesrv_srvsvc_fill_share_info(info, &count, + r->in.share_name, r->in.level, + r->in.info->info2->name, + r->in.info->info2->path, + r->in.info->info2->comment, + r->in.info->info2->password, + r->in.info->info2->type, + r->in.info->info2->max_users, + 0, + NULL); + if (!W_ERROR_EQUAL(status, WERR_OK)) { + return status; + } + break; + } + case 501: + { + status = dcesrv_srvsvc_fill_share_info(info, &count, + r->in.share_name, r->in.level, + r->in.info->info501->name, + NULL, + r->in.info->info501->comment, + NULL, + r->in.info->info501->type, + 0, + r->in.info->info501->csc_policy, + NULL); + if (!W_ERROR_EQUAL(status, WERR_OK)) { + return status; + } + break; + } + case 502: + { + status = dcesrv_srvsvc_fill_share_info(info, &count, + r->in.share_name, r->in.level, + r->in.info->info502->name, + r->in.info->info502->path, + r->in.info->info502->comment, + r->in.info->info502->password, + r->in.info->info502->type, + r->in.info->info502->max_users, + 0, + r->in.info->info502->sd_buf.sd); + if (!W_ERROR_EQUAL(status, WERR_OK)) { + return status; + } + break; + } + case 1004: + { + status = dcesrv_srvsvc_fill_share_info(info, &count, + r->in.share_name, r->in.level, + NULL, + NULL, + r->in.info->info1004->comment, + NULL, + 0, + 0, + 0, + NULL); + if (!W_ERROR_EQUAL(status, WERR_OK)) { + return status; + } + break; + } + case 1005: + { + /* r->in.info.dfs_flags; */ + + if (r->in.parm_error) { + r->out.parm_error = r->in.parm_error; + } + + return WERR_OK; + } + default: + return WERR_INVALID_LEVEL; + } + + nterr = share_set(sctx, r->in.share_name, info, count); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + if (r->in.parm_error) { + r->out.parm_error = r->in.parm_error; + } + + return WERR_OK; +} + + +/* + srvsvc_NetShareDelSticky +*/ +static WERROR dcesrv_srvsvc_NetShareDelSticky(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetShareDelSticky *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetShareCheck +*/ +static WERROR dcesrv_srvsvc_NetShareCheck(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetShareCheck *r) +{ + NTSTATUS nterr; + struct share_context *sctx = NULL; + struct share_config *scfg = NULL; + char *device; + const char **names; + int count; + int i; + + *r->out.type = 0; + + /* TODO: - access check + */ + + if (strcmp("", r->in.device_name) == 0) { + *r->out.type = STYPE_IPC; + return WERR_OK; + } + + /* copy the path skipping C:\ */ + if (strncasecmp(r->in.device_name, "C:", 2) == 0) { + device = talloc_strdup(mem_ctx, &r->in.device_name[2]); + } else { + /* no chance we have a share that doesn't start with C:\ */ + return WERR_NERR_DEVICENOTSHARED; + } + all_string_sub(device, "\\", "/", 0); + + nterr = share_get_context(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + nterr = share_list_all(mem_ctx, sctx, &count, &names); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + for (i = 0; i < count; i++) { + const char *path; + const char *type; + + nterr = share_get_config(mem_ctx, sctx, names[i], &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + path = share_string_option(mem_ctx, scfg, SHARE_PATH, NULL); + if (!path) continue; + + if (strcmp(device, path) == 0) { + type = share_string_option(mem_ctx, scfg, SHARE_TYPE, NULL); + if (!type) continue; + + if (strcmp(type, "DISK") == 0) { + *r->out.type = STYPE_DISKTREE; + return WERR_OK; + } + + if (strcmp(type, "IPC") == 0) { + *r->out.type = STYPE_IPC; + return WERR_OK; + } + + if (strcmp(type, "PRINTER") == 0) { + *r->out.type = STYPE_PRINTQ; + return WERR_OK; + } + } + } + + return WERR_NERR_DEVICENOTSHARED; +} + + +/* + srvsvc_NetSrvGetInfo +*/ +static WERROR dcesrv_srvsvc_NetSrvGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetSrvGetInfo *r) +{ + struct dcesrv_context *dce_ctx = dce_call->conn->dce_ctx; + struct dcerpc_server_info *server_info = lpcfg_dcerpc_server_info(mem_ctx, dce_ctx->lp_ctx); + const struct loadparm_substitution *lp_sub = + lpcfg_noop_substitution(); + + ZERO_STRUCTP(r->out.info); + + switch (r->in.level) { + case 100: + { + struct srvsvc_NetSrvInfo100 *info100; + + info100 = talloc(mem_ctx, struct srvsvc_NetSrvInfo100); + W_ERROR_HAVE_NO_MEMORY(info100); + + info100->platform_id = dcesrv_common_get_platform_id(mem_ctx, dce_ctx); + info100->server_name = dcesrv_common_get_server_name(mem_ctx, dce_ctx, r->in.server_unc); + W_ERROR_HAVE_NO_MEMORY(info100->server_name); + + r->out.info->info100 = info100; + return WERR_OK; + } + case 101: + { + struct srvsvc_NetSrvInfo101 *info101; + + info101 = talloc(mem_ctx, struct srvsvc_NetSrvInfo101); + W_ERROR_HAVE_NO_MEMORY(info101); + + info101->platform_id = dcesrv_common_get_platform_id(mem_ctx, dce_ctx); + info101->server_name = dcesrv_common_get_server_name(mem_ctx, dce_ctx, r->in.server_unc); + W_ERROR_HAVE_NO_MEMORY(info101->server_name); + + info101->version_major = server_info->version_major; + info101->version_minor = server_info->version_minor; + info101->server_type = dcesrv_common_get_server_type(mem_ctx, dce_call->event_ctx, dce_ctx); + info101->comment = lpcfg_server_string(dce_ctx->lp_ctx, lp_sub, mem_ctx); + W_ERROR_HAVE_NO_MEMORY(info101->comment); + + r->out.info->info101 = info101; + return WERR_OK; + } + case 102: + { + struct srvsvc_NetSrvInfo102 *info102; + + info102 = talloc(mem_ctx, struct srvsvc_NetSrvInfo102); + W_ERROR_HAVE_NO_MEMORY(info102); + + info102->platform_id = dcesrv_common_get_platform_id(mem_ctx, dce_ctx); + info102->server_name = dcesrv_common_get_server_name(mem_ctx, dce_ctx, r->in.server_unc); + W_ERROR_HAVE_NO_MEMORY(info102->server_name); + + info102->version_major = server_info->version_major; + info102->version_minor = server_info->version_minor; + info102->server_type = dcesrv_common_get_server_type(mem_ctx, dce_call->event_ctx, dce_ctx); + info102->comment = lpcfg_server_string(dce_ctx->lp_ctx, lp_sub, mem_ctx); + W_ERROR_HAVE_NO_MEMORY(info102->comment); + + info102->users = dcesrv_common_get_users(mem_ctx, dce_ctx); + info102->disc = dcesrv_common_get_disc(mem_ctx, dce_ctx); + info102->hidden = dcesrv_common_get_hidden(mem_ctx, dce_ctx); + info102->announce = dcesrv_common_get_announce(mem_ctx, dce_ctx); + info102->anndelta = dcesrv_common_get_anndelta(mem_ctx, dce_ctx); + info102->licenses = dcesrv_common_get_licenses(mem_ctx, dce_ctx); + info102->userpath = dcesrv_common_get_userpath(mem_ctx, dce_ctx); + W_ERROR_HAVE_NO_MEMORY(info102->userpath); + + r->out.info->info102 = info102; + return WERR_OK; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetSrvSetInfo +*/ +static WERROR dcesrv_srvsvc_NetSrvSetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetSrvSetInfo *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetDiskEnum +*/ +static WERROR dcesrv_srvsvc_NetDiskEnum(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetDiskEnum *r) +{ + r->out.info->disks = NULL; + r->out.info->count = 0; + *r->out.totalentries = 0; + + switch (r->in.level) { + case 0: + { + /* we can safely hardcode the reply and report we have only one disk (C:) */ + /* for some reason Windows wants 2 entries with the second being empty */ + r->out.info->disks = talloc_array(mem_ctx, struct srvsvc_NetDiskInfo0, 2); + W_ERROR_HAVE_NO_MEMORY(r->out.info->disks); + r->out.info->count = 2; + + r->out.info->disks[0].disk = talloc_strdup(mem_ctx, "C:"); + W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[0].disk); + + r->out.info->disks[1].disk = talloc_strdup(mem_ctx, ""); + W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[1].disk); + + *r->out.totalentries = 1; + r->out.resume_handle = r->in.resume_handle; + + return WERR_OK; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetServerStatisticsGet +*/ +static WERROR dcesrv_srvsvc_NetServerStatisticsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetServerStatisticsGet *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetTransportAdd +*/ +static WERROR dcesrv_srvsvc_NetTransportAdd(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetTransportAdd *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetTransportEnum +*/ +static WERROR dcesrv_srvsvc_NetTransportEnum(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetTransportEnum *r) +{ + r->out.transports->level = r->in.transports->level; + *r->out.totalentries = 0; + if (r->out.resume_handle) { + *r->out.resume_handle = 0; + } + + switch (r->in.transports->level) { + case 0: + { + r->out.transports->ctr.ctr0 = talloc(mem_ctx, struct srvsvc_NetTransportCtr0); + W_ERROR_HAVE_NO_MEMORY(r->out.transports->ctr.ctr0); + + r->out.transports->ctr.ctr0->count = 0; + r->out.transports->ctr.ctr0->array = NULL; + + return WERR_NOT_SUPPORTED; + } + case 1: + { + r->out.transports->ctr.ctr1 = talloc(mem_ctx, struct srvsvc_NetTransportCtr1); + W_ERROR_HAVE_NO_MEMORY(r->out.transports->ctr.ctr1); + + r->out.transports->ctr.ctr1->count = 0; + r->out.transports->ctr.ctr1->array = NULL; + + return WERR_NOT_SUPPORTED; + } + case 2: + { + r->out.transports->ctr.ctr2 = talloc(mem_ctx, struct srvsvc_NetTransportCtr2); + W_ERROR_HAVE_NO_MEMORY(r->out.transports->ctr.ctr2); + + r->out.transports->ctr.ctr2->count = 0; + r->out.transports->ctr.ctr2->array = NULL; + + return WERR_NOT_SUPPORTED; + } + case 3: + { + r->out.transports->ctr.ctr3 = talloc(mem_ctx, struct srvsvc_NetTransportCtr3); + W_ERROR_HAVE_NO_MEMORY(r->out.transports->ctr.ctr3); + + r->out.transports->ctr.ctr3->count = 0; + r->out.transports->ctr.ctr3->array = NULL; + + return WERR_NOT_SUPPORTED; + } + default: + return WERR_INVALID_LEVEL; + } +} + +/* + srvsvc_NetTransportDel +*/ +static WERROR dcesrv_srvsvc_NetTransportDel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetTransportDel *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetRemoteTOD +*/ +static WERROR dcesrv_srvsvc_NetRemoteTOD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetRemoteTOD *r) +{ + struct timeval tval; + time_t t; + struct tm tm; + struct srvsvc_NetRemoteTODInfo *info; + + info = talloc(mem_ctx, struct srvsvc_NetRemoteTODInfo); + W_ERROR_HAVE_NO_MEMORY(info); + + GetTimeOfDay(&tval); + t = tval.tv_sec; + + gmtime_r(&t, &tm); + + info->elapsed = t; + /* TODO: fake the uptime: just return the milliseconds till 0:00:00 today */ + info->msecs = (tm.tm_hour*60*60*1000) + + (tm.tm_min*60*1000) + + (tm.tm_sec*1000) + + (tval.tv_usec/1000); + info->hours = tm.tm_hour; + info->mins = tm.tm_min; + info->secs = tm.tm_sec; + info->hunds = tval.tv_usec/10000; + info->timezone = get_time_zone(t)/60; + info->tinterval = 310; /* just return the same as windows */ + info->day = tm.tm_mday; + info->month = tm.tm_mon + 1; + info->year = tm.tm_year + 1900; + info->weekday = tm.tm_wday; + + *r->out.info = info; + + return WERR_OK; +} + +/* + srvsvc_NetPathType +*/ +static WERROR dcesrv_srvsvc_NetPathType(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetPathType *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetPathCanonicalize +*/ +static WERROR dcesrv_srvsvc_NetPathCanonicalize(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetPathCanonicalize *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetPathCompare +*/ +static WERROR dcesrv_srvsvc_NetPathCompare(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetPathCompare *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetNameValidate +*/ +static WERROR dcesrv_srvsvc_NetNameValidate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetNameValidate *r) +{ + int len; + + if ((r->in.flags != 0x0) && (r->in.flags != 0x80000000)) { + return WERR_INVALID_NAME; + } + + switch (r->in.name_type) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + return WERR_NOT_SUPPORTED; + + case 9: /* validate share name */ + + len = strlen_m(r->in.name); + if ((r->in.flags == 0x0) && (len > 81)) { + return WERR_INVALID_NAME; + } + if ((r->in.flags == 0x80000000) && (len > 13)) { + return WERR_INVALID_NAME; + } + if (! dcesrv_common_validate_share_name(mem_ctx, r->in.name)) { + return WERR_INVALID_NAME; + } + return WERR_OK; + + case 10: + case 11: + case 12: + case 13: + return WERR_NOT_SUPPORTED; + default: + return WERR_INVALID_PARAMETER; + } +} + + +/* + srvsvc_NetPRNameCompare +*/ +static WERROR dcesrv_srvsvc_NetPRNameCompare(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetPRNameCompare *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetShareEnum +*/ +static WERROR dcesrv_srvsvc_NetShareEnum(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetShareEnum *r) +{ + NTSTATUS nterr; + int numshares = 0; + const char **snames; + struct share_context *sctx; + struct share_config *scfg; + struct dcesrv_context *dce_ctx = dce_call->conn->dce_ctx; + + *r->out.totalentries = 0; + + /* TODO: - paging of results + */ + + nterr = share_get_context(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + nterr = share_list_all(mem_ctx, sctx, &numshares, &snames); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + switch (r->in.info_ctr->level) { + case 0: + { + unsigned int i, y = 0; + unsigned int count; + struct srvsvc_NetShareCtr0 *ctr0; + + ctr0 = talloc(mem_ctx, struct srvsvc_NetShareCtr0); + W_ERROR_HAVE_NO_MEMORY(ctr0); + + count = numshares; + ctr0->count = count; + ctr0->array = NULL; + + if (ctr0->count == 0) { + r->out.info_ctr->ctr.ctr0 = ctr0; + return WERR_OK; + } + + ctr0->array = talloc_array(mem_ctx, struct srvsvc_NetShareInfo0, count); + W_ERROR_HAVE_NO_MEMORY(ctr0->array); + + for (i=0; i < count; i++) { + WERROR status; + union srvsvc_NetShareInfo info; + enum srvsvc_ShareType type; + + nterr = share_get_config(mem_ctx, sctx, snames[i], &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + DEBUG(1, ("ERROR: Service [%s] disappeared after enumeration", snames[i])); + return WERR_GEN_FAILURE; + } + + type = dcesrv_common_get_share_type(mem_ctx, dce_ctx, scfg); + if (type & STYPE_HIDDEN) { + ctr0->count--; + talloc_free(scfg); + continue; + } + + info.info0 = &ctr0->array[y]; + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.info_ctr->level, &info); + W_ERROR_NOT_OK_RETURN(status); + talloc_free(scfg); + y++; + } + talloc_free(snames); + + r->out.info_ctr->ctr.ctr0 = ctr0; + *r->out.totalentries = r->out.info_ctr->ctr.ctr0->count; + + return WERR_OK; + } + case 1: + { + unsigned int i, y = 0; + unsigned int count; + struct srvsvc_NetShareCtr1 *ctr1; + + ctr1 = talloc(mem_ctx, struct srvsvc_NetShareCtr1); + W_ERROR_HAVE_NO_MEMORY(ctr1); + + count = numshares; + ctr1->count = count; + ctr1->array = NULL; + + if (ctr1->count == 0) { + r->out.info_ctr->ctr.ctr1 = ctr1; + return WERR_OK; + } + + ctr1->array = talloc_array(mem_ctx, struct srvsvc_NetShareInfo1, count); + W_ERROR_HAVE_NO_MEMORY(ctr1->array); + + for (i=0; i < count; i++) { + WERROR status; + union srvsvc_NetShareInfo info; + enum srvsvc_ShareType type; + + nterr = share_get_config(mem_ctx, sctx, snames[i], &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + DEBUG(1, ("ERROR: Service [%s] disappeared after enumeration", snames[i])); + return WERR_GEN_FAILURE; + } + + type = dcesrv_common_get_share_type(mem_ctx, dce_ctx, scfg); + if (type & STYPE_HIDDEN) { + ctr1->count--; + talloc_free(scfg); + continue; + } + + info.info1 = &ctr1->array[y]; + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.info_ctr->level, &info); + W_ERROR_NOT_OK_RETURN(status); + talloc_free(scfg); + y++; + } + talloc_free(snames); + + r->out.info_ctr->ctr.ctr1 = ctr1; + *r->out.totalentries = r->out.info_ctr->ctr.ctr1->count; + + return WERR_OK; + } + case 2: + { + unsigned int i, y = 0; + unsigned int count; + struct srvsvc_NetShareCtr2 *ctr2; + + SRVSVC_CHECK_ADMIN_ACCESS; + + ctr2 = talloc(mem_ctx, struct srvsvc_NetShareCtr2); + W_ERROR_HAVE_NO_MEMORY(ctr2); + + count = numshares; + ctr2->count = count; + ctr2->array = NULL; + + if (ctr2->count == 0) { + r->out.info_ctr->ctr.ctr2 = ctr2; + return WERR_OK; + } + + ctr2->array = talloc_array(mem_ctx, struct srvsvc_NetShareInfo2, count); + W_ERROR_HAVE_NO_MEMORY(ctr2->array); + + for (i=0; i < count; i++) { + WERROR status; + union srvsvc_NetShareInfo info; + enum srvsvc_ShareType type; + + nterr = share_get_config(mem_ctx, sctx, snames[i], &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + DEBUG(1, ("ERROR: Service [%s] disappeared after enumeration", snames[i])); + return WERR_GEN_FAILURE; + } + + type = dcesrv_common_get_share_type(mem_ctx, dce_ctx, scfg); + if (type & STYPE_HIDDEN) { + ctr2->count--; + talloc_free(scfg); + continue; + } + + info.info2 = &ctr2->array[y]; + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.info_ctr->level, &info); + W_ERROR_NOT_OK_RETURN(status); + talloc_free(scfg); + y++; + } + talloc_free(snames); + + r->out.info_ctr->ctr.ctr2 = ctr2; + *r->out.totalentries = r->out.info_ctr->ctr.ctr2->count; + + return WERR_OK; + } + case 502: + { + unsigned int i, y = 0; + unsigned int count; + struct srvsvc_NetShareCtr502 *ctr502; + + SRVSVC_CHECK_ADMIN_ACCESS; + + ctr502 = talloc(mem_ctx, struct srvsvc_NetShareCtr502); + W_ERROR_HAVE_NO_MEMORY(ctr502); + + count = numshares; + ctr502->count = count; + ctr502->array = NULL; + + if (ctr502->count == 0) { + r->out.info_ctr->ctr.ctr502 = ctr502; + return WERR_OK; + } + + ctr502->array = talloc_array(mem_ctx, struct srvsvc_NetShareInfo502, count); + W_ERROR_HAVE_NO_MEMORY(ctr502->array); + + for (i=0; i < count; i++) { + WERROR status; + union srvsvc_NetShareInfo info; + enum srvsvc_ShareType type; + + nterr = share_get_config(mem_ctx, sctx, snames[i], &scfg); + if (!NT_STATUS_IS_OK(nterr)) { + DEBUG(1, ("ERROR: Service [%s] disappeared after enumeration", snames[i])); + return WERR_GEN_FAILURE; + } + + type = dcesrv_common_get_share_type(mem_ctx, dce_ctx, scfg); + if (type & STYPE_HIDDEN) { + ctr502->count--; + talloc_free(scfg); + continue; + } + + info.info502 = &ctr502->array[y]; + status = dcesrv_srvsvc_fiel_ShareInfo(dce_call, mem_ctx, scfg, r->in.info_ctr->level, &info); + W_ERROR_NOT_OK_RETURN(status); + talloc_free(scfg); + y++; + } + talloc_free(snames); + + r->out.info_ctr->ctr.ctr502 = ctr502; + *r->out.totalentries = r->out.info_ctr->ctr.ctr502->count; + + return WERR_OK; + } + default: + return WERR_INVALID_LEVEL; + } +} + + +/* + srvsvc_NetShareDelStart +*/ +static WERROR dcesrv_srvsvc_NetShareDelStart(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetShareDelStart *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetShareDelCommit +*/ +static WERROR dcesrv_srvsvc_NetShareDelCommit(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetShareDelCommit *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetGetFileSecurity +*/ +static WERROR dcesrv_srvsvc_NetGetFileSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetGetFileSecurity *r) +{ + struct auth_session_info *session_info = + dcesrv_call_session_info(dce_call); + struct sec_desc_buf *sd_buf; + struct ntvfs_context *ntvfs_ctx = NULL; + struct ntvfs_request *ntvfs_req; + union smb_fileinfo *io; + NTSTATUS nt_status; + + nt_status = srvsvc_create_ntvfs_context(dce_call, mem_ctx, r->in.share, &ntvfs_ctx); + if (!NT_STATUS_IS_OK(nt_status)) return ntstatus_to_werror(nt_status); + + ntvfs_req = ntvfs_request_create(ntvfs_ctx, mem_ctx, + session_info, + 0, + dce_call->time, + NULL, NULL, 0); + W_ERROR_HAVE_NO_MEMORY(ntvfs_req); + + sd_buf = talloc(mem_ctx, struct sec_desc_buf); + W_ERROR_HAVE_NO_MEMORY(sd_buf); + + io = talloc(mem_ctx, union smb_fileinfo); + W_ERROR_HAVE_NO_MEMORY(io); + + io->query_secdesc.level = RAW_FILEINFO_SEC_DESC; + io->query_secdesc.in.file.path = r->in.file; + io->query_secdesc.in.secinfo_flags = r->in.securityinformation; + + nt_status = ntvfs_qpathinfo(ntvfs_req, io); + if (!NT_STATUS_IS_OK(nt_status)) return ntstatus_to_werror(nt_status); + + sd_buf->sd = io->query_secdesc.out.sd; + + *r->out.sd_buf = sd_buf; + return WERR_OK; +} + + +/* + srvsvc_NetSetFileSecurity +*/ +static WERROR dcesrv_srvsvc_NetSetFileSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetSetFileSecurity *r) +{ + struct auth_session_info *session_info = + dcesrv_call_session_info(dce_call); + struct ntvfs_context *ntvfs_ctx; + struct ntvfs_request *ntvfs_req; + union smb_setfileinfo *io; + NTSTATUS nt_status; + + nt_status = srvsvc_create_ntvfs_context(dce_call, mem_ctx, r->in.share, &ntvfs_ctx); + if (!NT_STATUS_IS_OK(nt_status)) return ntstatus_to_werror(nt_status); + + ntvfs_req = ntvfs_request_create(ntvfs_ctx, mem_ctx, + session_info, + 0, + dce_call->time, + NULL, NULL, 0); + W_ERROR_HAVE_NO_MEMORY(ntvfs_req); + + io = talloc(mem_ctx, union smb_setfileinfo); + W_ERROR_HAVE_NO_MEMORY(io); + + io->set_secdesc.level = RAW_SFILEINFO_SEC_DESC; + io->set_secdesc.in.file.path = r->in.file; + io->set_secdesc.in.secinfo_flags = r->in.securityinformation; + io->set_secdesc.in.sd = r->in.sd_buf->sd; + + nt_status = ntvfs_setpathinfo(ntvfs_req, io); + if (!NT_STATUS_IS_OK(nt_status)) return ntstatus_to_werror(nt_status); + + return WERR_OK; +} + + +/* + srvsvc_NetServerTransportAddEx +*/ +static WERROR dcesrv_srvsvc_NetServerTransportAddEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetServerTransportAddEx *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NetServerSetServiceBitsEx +*/ +static WERROR dcesrv_srvsvc_NetServerSetServiceBitsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetServerSetServiceBitsEx *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRDFSGETVERSION +*/ +static WERROR dcesrv_srvsvc_NETRDFSGETVERSION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRDFSGETVERSION *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRDFSCREATELOCALPARTITION +*/ +static WERROR dcesrv_srvsvc_NETRDFSCREATELOCALPARTITION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRDFSCREATELOCALPARTITION *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRDFSDELETELOCALPARTITION +*/ +static WERROR dcesrv_srvsvc_NETRDFSDELETELOCALPARTITION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRDFSDELETELOCALPARTITION *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRDFSSETLOCALVOLUMESTATE +*/ +static WERROR dcesrv_srvsvc_NETRDFSSETLOCALVOLUMESTATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRDFSSETSERVERINFO +*/ +static WERROR dcesrv_srvsvc_NETRDFSSETSERVERINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRDFSSETSERVERINFO *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRDFSCREATEEXITPOINT +*/ +static WERROR dcesrv_srvsvc_NETRDFSCREATEEXITPOINT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRDFSCREATEEXITPOINT *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRDFSDELETEEXITPOINT +*/ +static WERROR dcesrv_srvsvc_NETRDFSDELETEEXITPOINT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRDFSDELETEEXITPOINT *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRDFSMODIFYPREFIX +*/ +static WERROR dcesrv_srvsvc_NETRDFSMODIFYPREFIX(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRDFSMODIFYPREFIX *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRDFSFIXLOCALVOLUME +*/ +static WERROR dcesrv_srvsvc_NETRDFSFIXLOCALVOLUME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRDFSFIXLOCALVOLUME *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRDFSMANAGERREPORTSITEINFO +*/ +static WERROR dcesrv_srvsvc_NETRDFSMANAGERREPORTSITEINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + + +/* + srvsvc_NETRSERVERTRANSPORTDELEX +*/ +static WERROR dcesrv_srvsvc_NETRSERVERTRANSPORTDELEX(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRSERVERTRANSPORTDELEX *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + +/* + srvsvc_NetShareDel +*/ +static WERROR dcesrv_srvsvc_NetShareDel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetShareDel *r) +{ + NTSTATUS nterr; + struct share_context *sctx; + + nterr = share_get_context(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + nterr = share_remove(sctx, r->in.share_name); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + return WERR_OK; +} + +/* + srvsvc_NetSetServiceBits +*/ +static WERROR dcesrv_srvsvc_NetSetServiceBits(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NetSetServiceBits *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + +/* + srvsvc_NETRPRNAMECANONICALIZE +*/ +static WERROR dcesrv_srvsvc_NETRPRNAMECANONICALIZE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct srvsvc_NETRPRNAMECANONICALIZE *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + +/* include the generated boilerplate */ +#include "librpc/gen_ndr/ndr_srvsvc_s.c" diff --git a/source4/rpc_server/srvsvc/srvsvc_ntvfs.c b/source4/rpc_server/srvsvc/srvsvc_ntvfs.c new file mode 100644 index 0000000..cbd0eb3 --- /dev/null +++ b/source4/rpc_server/srvsvc/srvsvc_ntvfs.c @@ -0,0 +1,139 @@ +/* + Unix SMB/CIFS implementation. + + srvsvc pipe ntvfs helper functions + + Copyright (C) Stefan (metze) Metzmacher 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include "includes.h" +#include "ntvfs/ntvfs.h" +#include "rpc_server/dcerpc_server.h" +#include "param/param.h" +#include "rpc_server/srvsvc/proto.h" + +struct srvsvc_ntvfs_ctx { + struct ntvfs_context *ntvfs; +}; + +static int srvsvc_ntvfs_ctx_destructor(struct srvsvc_ntvfs_ctx *c) +{ + ntvfs_disconnect(c->ntvfs); + return 0; +} + +NTSTATUS srvsvc_create_ntvfs_context(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + const char *share, + struct ntvfs_context **_ntvfs) +{ + struct auth_session_info *session_info = + dcesrv_call_session_info(dce_call); + struct imessaging_context *imsg_ctx = + dcesrv_imessaging_context(dce_call->conn); + struct server_id server_id = dcesrv_server_id(dce_call->conn); + NTSTATUS status; + struct srvsvc_ntvfs_ctx *c; + struct ntvfs_request *ntvfs_req; + enum ntvfs_type type; + struct share_context *sctx; + struct share_config *scfg; + char *sharetype; + union smb_tcon tcon; + const struct tsocket_address *local_address; + const struct tsocket_address *remote_address; + + status = share_get_context(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = share_get_config(mem_ctx, sctx, share, &scfg); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("srvsvc_create_ntvfs_context: couldn't find service %s\n", share)); + return status; + } + +#if 0 /* TODO: fix access cecking */ + if (!socket_check_access(dce_call->connection->socket, + scfg->name, + share_string_list_option(scfg, SHARE_HOSTS_ALLOW), + share_string_list_option(scfg, SHARE_HOSTS_DENY))) { + return NT_STATUS_ACCESS_DENIED; + } +#endif + + /* work out what sort of connection this is */ + sharetype = share_string_option(mem_ctx, scfg, SHARE_TYPE, SHARE_TYPE_DEFAULT); + if (sharetype && strcmp(sharetype, "IPC") == 0) { + type = NTVFS_IPC; + } else if (sharetype && strcmp(sharetype, "PRINTER")) { + type = NTVFS_PRINT; + } else { + type = NTVFS_DISK; + } + + TALLOC_FREE(sharetype); + + c = talloc(mem_ctx, struct srvsvc_ntvfs_ctx); + NT_STATUS_HAVE_NO_MEMORY(c); + + /* init ntvfs function pointers */ + status = ntvfs_init_connection(c, scfg, type, + PROTOCOL_NT1, + 0,/* ntvfs_client_caps */ + dce_call->event_ctx, + imsg_ctx, + dce_call->conn->dce_ctx->lp_ctx, + server_id, + &c->ntvfs); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("srvsvc_create_ntvfs_context: ntvfs_init_connection failed for service %s\n", + scfg->name)); + return status; + } + talloc_set_destructor(c, srvsvc_ntvfs_ctx_destructor); + + /* + * NOTE: we only set the addr callbacks as we're not interesseted in oplocks or in getting file handles + */ + local_address = dcesrv_connection_get_local_address(dce_call->conn); + remote_address = dcesrv_connection_get_remote_address(dce_call->conn); + status = ntvfs_set_addresses(c->ntvfs, local_address, remote_address); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("srvsvc_create_ntvfs_context: NTVFS failed to set the addr callbacks!\n")); + return status; + } + + ntvfs_req = ntvfs_request_create(c->ntvfs, mem_ctx, + session_info, + 0, /* TODO: fill in PID */ + dce_call->time, + NULL, NULL, 0); + NT_STATUS_HAVE_NO_MEMORY(ntvfs_req); + + /* Invoke NTVFS connection hook */ + tcon.tcon.level = RAW_TCON_TCON; + ZERO_STRUCT(tcon.tcon.in); + tcon.tcon.in.service = scfg->name; + status = ntvfs_connect(ntvfs_req, &tcon); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("srvsvc_create_ntvfs_context: NTVFS ntvfs_connect() failed!\n")); + return status; + } + + *_ntvfs = c->ntvfs; + return NT_STATUS_OK; +} |