Пример #1
0
/* This hardcoded value should go into a ldb database! */
enum srvsvc_ShareType dcesrv_common_get_share_type(TALLOC_CTX *mem_ctx, struct dcesrv_context *dce_ctx, struct share_config *scfg)
{
	/* for disk share	0x00000000
	 * for print share	0x00000001
	 * for IPC$ share	0x00000003 
	 *
	 * administrative shares:
	 * ADMIN$, IPC$, C$, D$, E$ ...  are type |= 0x80000000
	 * this ones are hidden in NetShareEnum, but shown in NetShareEnumAll
	 */
	enum srvsvc_ShareType share_type = 0;
	const char *sharetype;

	if (!share_bool_option(scfg, SHARE_BROWSEABLE, SHARE_BROWSEABLE_DEFAULT)) {
		share_type |= STYPE_HIDDEN;
	}

	sharetype = share_string_option(scfg, SHARE_TYPE, SHARE_TYPE_DEFAULT);
	if (sharetype && strcasecmp(sharetype, "IPC") == 0) {
		share_type |= STYPE_IPC;
		return share_type;
	}

	if (sharetype && strcasecmp(sharetype, "PRINTER") == 0) {
		share_type |= STYPE_PRINTQ;
		return share_type;
	}

	share_type |= STYPE_DISKTREE;

	return share_type;
}
Пример #2
0
/*
  connect to a share - used when a tree_connect operation comes
  in. For a disk based backend we needs to ensure that the base
  directory exists (tho it doesn't need to be accessible by the user,
  that comes later)
*/
static NTSTATUS svfs_connect(struct ntvfs_module_context *ntvfs,
			     struct ntvfs_request *req, const char *sharename)
{
	struct stat st;
	struct svfs_private *p;
	struct share_config *scfg = ntvfs->ctx->config;

	p = talloc(ntvfs, struct svfs_private);
	NT_STATUS_HAVE_NO_MEMORY(p);
	p->ntvfs = ntvfs;
	p->next_search_handle = 0;
	p->connectpath = talloc_strdup(p, share_string_option(scfg, SHARE_PATH, ""));
	p->open_files = NULL;
	p->search = NULL;

	/* the directory must exist */
	if (stat(p->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
		DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", 
			 p->connectpath, sharename));
		return NT_STATUS_BAD_NETWORK_NAME;
	}

	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);

	ntvfs->private_data = p;

	return NT_STATUS_OK;
}
Пример #3
0
/*
  connect to a share - used when a tree_connect operation comes
  in. For a disk based backend we needs to ensure that the base
  directory exists (tho it doesn't need to be accessible by the user,
  that comes later)
*/
static NTSTATUS svfs_connect(struct ntvfs_module_context *ntvfs,
			     struct ntvfs_request *req,
			     union smb_tcon* tcon)
{
	struct stat st;
	struct svfs_private *p;
	struct share_config *scfg = ntvfs->ctx->config;
	const char *sharename;

	switch (tcon->generic.level) {
	case RAW_TCON_TCON:
		sharename = tcon->tcon.in.service;
		break;
	case RAW_TCON_TCONX:
		sharename = tcon->tconx.in.path;
		break;
	case RAW_TCON_SMB2:
		sharename = tcon->smb2.in.path;
		break;
	default:
		return NT_STATUS_INVALID_LEVEL;
	}

	if (strncmp(sharename, "\\\\", 2) == 0) {
		char *p2 = strchr(sharename+2, '\\');
		if (p2) {
			sharename = p2 + 1;
		}
	}

	p = talloc(ntvfs, struct svfs_private);
	NT_STATUS_HAVE_NO_MEMORY(p);
	p->ntvfs = ntvfs;
	p->next_search_handle = 0;
	p->connectpath = talloc_strdup(p, share_string_option(scfg, SHARE_PATH, ""));
	p->open_files = NULL;
	p->search = NULL;

	/* the directory must exist */
	if (stat(p->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
		DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", 
			 p->connectpath, sharename));
		return NT_STATUS_BAD_NETWORK_NAME;
	}

	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);

	if (tcon->generic.level == RAW_TCON_TCONX) {
		tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
		tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
	}

	ntvfs->private_data = p;

	return NT_STATUS_OK;
}
Пример #4
0
/*
  initialise a system change notify backend
*/
_PUBLIC_ struct sys_notify_context *sys_notify_context_create(struct share_config *scfg,
        TALLOC_CTX *mem_ctx,
        struct tevent_context *ev)
{
    struct sys_notify_context *ctx;
    const char *bname;
    int i;

    if (num_backends == 0) {
        return NULL;
    }

    if (ev == NULL) {
        return NULL;
    }

    ctx = talloc_zero(mem_ctx, struct sys_notify_context);
    if (ctx == NULL) {
        return NULL;
    }

    ctx->ev = ev;

    bname = share_string_option(scfg, NOTIFY_BACKEND, NULL);
    if (!bname) {
        if (num_backends) {
            bname = backends[0].name;
        } else {
            bname = "__unknown__";
        }
    }

    for (i=0; i<num_backends; i++) {
        char *enable_opt_name;
        bool enabled;

        enable_opt_name = talloc_asprintf(mem_ctx, "notify:%s",
                                          backends[i].name);
        enabled = share_bool_option(scfg, enable_opt_name, true);
        talloc_free(enable_opt_name);

        if (!enabled)
            continue;

        if (strcasecmp(backends[i].name, bname) == 0) {
            bname = backends[i].name;
            break;
        }
    }

    ctx->name = bname;
    ctx->notify_watch = NULL;

    if (i < num_backends) {
        ctx->notify_watch = backends[i].notify_watch;
    }

    return ctx;
}
Пример #5
0
/*
  initialise a system change notify backend
*/
_PUBLIC_ struct sys_lease_context *sys_lease_context_create(struct share_config *scfg,
							    TALLOC_CTX *mem_ctx,
							    struct tevent_context *ev,
							    struct messaging_context *msg,
							    sys_lease_send_break_fn break_send)
{
	struct sys_lease_context *ctx;
	const char *bname;
	int i;
	NTSTATUS status;

	if (num_backends == 0) {
		return NULL;
	}

	if (ev == NULL) {
		return NULL;
	}

	ctx = talloc_zero(mem_ctx, struct sys_lease_context);
	if (ctx == NULL) {
		return NULL;
	}

	ctx->event_ctx = ev;
	ctx->msg_ctx = msg;
	ctx->break_send = break_send;

	bname = share_string_option(scfg, LEASE_BACKEND, NULL);
	if (!bname) {
		talloc_free(ctx);
		return NULL;
	}

	for (i=0;i<num_backends;i++) {
		if (strcasecmp(backends[i].name, bname) == 0) {
			ctx->ops = &backends[i];
			break;
		}
	}

	if (!ctx->ops) {
		talloc_free(ctx);
		return NULL;
	}

	status = ctx->ops->init(ctx);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(ctx);
		return NULL;
	}

	return ctx;
}
Пример #6
0
/****************************************************************************
 Make a connection to a service.
 *
 * @param service 
****************************************************************************/
static NTSTATUS make_connection(struct smbsrv_request *req,
				const char *service, DATA_BLOB password, 
				const char *dev)
{
	NTSTATUS status;
	enum ntvfs_type type;
	const char *type_str;
	struct share_config *scfg;
	const char *sharetype;

	/* the service might be of the form \\SERVER\SHARE. Should we put
	   the server name we get from this somewhere? */
	if (strncmp(service, "\\\\", 2) == 0) {
		char *p = strchr(service+2, '\\');
		if (p) {
			service = p + 1;
		}
	}

	status = share_get_config(req, req->smb_conn->share_context, service, &scfg);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("make_connection: couldn't find service %s\n", service));
		return NT_STATUS_BAD_NETWORK_NAME;
	}

	/* TODO: check the password, when it's share level security! */

	if (!socket_check_access(req->smb_conn->connection->socket, 
				 scfg->name, 
				 share_string_list_option(req, scfg, SHARE_HOSTS_ALLOW), 
				 share_string_list_option(req, scfg, SHARE_HOSTS_DENY))) {
		return NT_STATUS_ACCESS_DENIED;
	}

	/* work out what sort of connection this is */
	sharetype = share_string_option(scfg, "type", "DISK");
	if (sharetype && strcmp(sharetype, "IPC") == 0) {
		type = NTVFS_IPC;
		type_str = "IPC";
	} else if (sharetype && strcmp(sharetype, "PRINTER") == 0) {
		type = NTVFS_PRINT;
		type_str = "LPT:";
	} else {
		type = NTVFS_DISK;
		type_str = "A:";
	}

	if (strcmp(dev, "?????") != 0 && strcasecmp(type_str, dev) != 0) {
		/* the client gave us the wrong device type */
		return NT_STATUS_BAD_DEVICE_TYPE;
	}

	return make_connection_scfg(req, scfg, type, password, dev);
}
Пример #7
0
/* This hardcoded value should go into a ldb database! */
const char *dcesrv_common_get_share_path(TALLOC_CTX *mem_ctx, struct dcesrv_context *dce_ctx, struct share_config *scfg)
{
	const char *sharetype;
	char *p;
	
	sharetype = share_string_option(scfg, SHARE_TYPE, SHARE_TYPE_DEFAULT);
	
	if (sharetype && strcasecmp(sharetype, "IPC") == 0) {
		return talloc_strdup(mem_ctx, "");
	}

	p = talloc_strdup(mem_ctx, share_string_option(scfg, SHARE_PATH, ""));
	if (!p) {
		return NULL;
	}
	if (p[0] == '\0') {
		return p;
	}
	all_string_sub(p, "/", "\\", 0);
	
	return talloc_asprintf(mem_ctx, "C:%s", p);
}
Пример #8
0
/*
  initialise a system change notify backend
*/
_PUBLIC_ struct sys_notify_context *sys_notify_context_create(struct share_config *scfg,
        TALLOC_CTX *mem_ctx,
        struct event_context *ev)
{
    struct sys_notify_context *ctx;
    const char *bname;
    int i;

    if (num_backends == 0) {
        return NULL;
    }

    if (ev == NULL) {
        ev = event_context_find(mem_ctx);
    }

    ctx = talloc_zero(mem_ctx, struct sys_notify_context);
    if (ctx == NULL) {
        return NULL;
    }

    ctx->ev = ev;

    bname = share_string_option(scfg, NOTIFY_BACKEND, NULL);
    if (!bname) {
        if (num_backends) {
            bname = backends[0].name;
        } else {
            bname = "__unknown__";
        }
    }

    for (i=0; i<num_backends; i++) {
        if (strcasecmp(backends[i].name, bname) == 0) {
            bname = backends[i].name;
            break;
        }
    }

    ctx->name = bname;
    ctx->notify_watch = NULL;

    if (i < num_backends) {
        ctx->notify_watch = backends[i].notify_watch;
    }

    return ctx;
}
Пример #9
0
NTSTATUS rap_netshareenum(TALLOC_CTX *mem_ctx,
			  struct tevent_context *event_ctx,
			  struct loadparm_context *lp_ctx,
			  struct rap_NetShareEnum *r)
{
	NTSTATUS nterr;
	const char **snames;
	struct share_context *sctx;
	struct share_config *scfg;
	int i, j, count;

	r->out.status = 0;
	r->out.available = 0;
	r->out.info = NULL;

	nterr = share_get_context_by_name(mem_ctx, lp_share_backend(lp_ctx), event_ctx, lp_ctx, &sctx);
	if (!NT_STATUS_IS_OK(nterr)) {
		return nterr;
	}

	nterr = share_list_all(mem_ctx, sctx, &count, &snames);
	if (!NT_STATUS_IS_OK(nterr)) {
		return nterr;
	}

	r->out.available = count;
	r->out.info = talloc_array(mem_ctx,
				   union rap_shareenum_info, r->out.available);

	for (i = 0, j = 0; i < r->out.available; i++) {
		if (!NT_STATUS_IS_OK(share_get_config(mem_ctx, sctx, snames[i], &scfg))) {
			DEBUG(3, ("WARNING: Service [%s] disappeared after enumeration!\n", snames[i]));
			continue;
		}
		strncpy(r->out.info[j].info1.name,
			snames[i],
			sizeof(r->out.info[0].info1.name));
		r->out.info[i].info1.pad = 0;
		r->out.info[i].info1.type = dcesrv_common_get_share_type(mem_ctx, NULL, scfg);
		r->out.info[i].info1.comment = talloc_strdup(mem_ctx, share_string_option(scfg, SHARE_COMMENT, ""));
		talloc_free(scfg);
		j++;
	}
	r->out.available = j;
	
	return NT_STATUS_OK;
}
Пример #10
0
/*
  connect to a share - used when a tree_connect operation comes in.
*/
static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, 
			     struct ntvfs_request *req,
			     union smb_tcon *tcon)
{
	NTSTATUS status;
	struct cvfs_private *p;
	const char *host, *user, *pass, *domain, *remote_share;
	struct smb_composite_connect io;
	struct composite_context *creq;
	struct share_config *scfg = ntvfs->ctx->config;

	struct cli_credentials *credentials;
	bool machine_account;
	bool s4u2proxy;
	const char* sharename;

	switch (tcon->generic.level) {
	case RAW_TCON_TCON:
		sharename = tcon->tcon.in.service;
		break;
	case RAW_TCON_TCONX:
		sharename = tcon->tconx.in.path;
		break;
	case RAW_TCON_SMB2:
		sharename = tcon->smb2.in.path;
		break;
	default:
		return NT_STATUS_INVALID_LEVEL;
	}

	if (strncmp(sharename, "\\\\", 2) == 0) {
		char *str = strchr(sharename+2, '\\');
		if (str) {
			sharename = str + 1;
		}
	}

	/* Here we need to determine which server to connect to.
	 * For now we use parametric options, type cifs.
	 * Later we will use security=server and auth_server.c.
	 */
	host = share_string_option(scfg, CIFS_SERVER, NULL);
	user = share_string_option(scfg, CIFS_USER, NULL);
	pass = share_string_option(scfg, CIFS_PASSWORD, NULL);
	domain = share_string_option(scfg, CIFS_DOMAIN, NULL);
	remote_share = share_string_option(scfg, CIFS_SHARE, NULL);
	if (!remote_share) {
		remote_share = sharename;
	}

	machine_account = share_bool_option(scfg, CIFS_USE_MACHINE_ACCT, CIFS_USE_MACHINE_ACCT_DEFAULT);
	s4u2proxy = share_bool_option(scfg, CIFS_USE_S4U2PROXY, CIFS_USE_S4U2PROXY_DEFAULT);

	p = talloc_zero(ntvfs, struct cvfs_private);
	if (!p) {
		return NT_STATUS_NO_MEMORY;
	}

	ntvfs->private_data = p;

	if (!host) {
		DEBUG(1,("CIFS backend: You must supply server\n"));
		return NT_STATUS_INVALID_PARAMETER;
	} 
	
	if (user && pass) {
		DEBUG(5, ("CIFS backend: Using specified password\n"));
		credentials = cli_credentials_init(p);
		if (!credentials) {
			return NT_STATUS_NO_MEMORY;
		}
		cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
		cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		cli_credentials_set_password(credentials, pass, CRED_SPECIFIED);
	} else if (machine_account) {
		DEBUG(5, ("CIFS backend: Using machine account\n"));
		credentials = cli_credentials_init(p);
		cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
	} else if (req->session_info->credentials) {
		DEBUG(5, ("CIFS backend: Using delegated credentials\n"));
		credentials = req->session_info->credentials;
	} else if (s4u2proxy) {
		struct ccache_container *ccc = NULL;
		const char *err_str = NULL;
		int ret;
		char *impersonate_principal;
		char *self_service;
		char *target_service;

		impersonate_principal = talloc_asprintf(req, "%s@%s",
						req->session_info->info->account_name,
						req->session_info->info->domain_name);

		self_service = talloc_asprintf(req, "cifs/%s",
					       lpcfg_netbios_name(ntvfs->ctx->lp_ctx));

		target_service = talloc_asprintf(req, "cifs/%s", host);

		DEBUG(5, ("CIFS backend: Using S4U2Proxy credentials\n"));

		credentials = cli_credentials_init(p);
		cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
		cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
		cli_credentials_set_impersonate_principal(credentials,
							  impersonate_principal,
							  self_service);
		cli_credentials_set_target_service(credentials, target_service);
		ret = cli_credentials_get_ccache(credentials,
						 ntvfs->ctx->event_ctx,
						 ntvfs->ctx->lp_ctx,
						 &ccc,
						 &err_str);
		if (ret != 0) {
			status = NT_STATUS_CROSSREALM_DELEGATION_FAILURE;
			DEBUG(1,("S4U2Proxy: cli_credentials_get_ccache() gave: ret[%d] str[%s] - %s\n",
				ret, err_str, nt_errstr(status)));
			return status;
		}

	} else {
		DEBUG(1,("CIFS backend: NO delegated credentials found: You must supply server, user and password or the client must supply delegated credentials\n"));
		return NT_STATUS_INTERNAL_ERROR;
	}

	/* connect to the server, using the smbd event context */
	io.in.dest_host = host;
	io.in.dest_ports = lpcfg_smb_ports(ntvfs->ctx->lp_ctx);
	io.in.socket_options = lpcfg_socket_options(ntvfs->ctx->lp_ctx);
	io.in.called_name = host;
	io.in.credentials = credentials;
	io.in.fallback_to_anonymous = false;
	io.in.workgroup = lpcfg_workgroup(ntvfs->ctx->lp_ctx);
	io.in.service = remote_share;
	io.in.service_type = "?????";
	io.in.gensec_settings = lpcfg_gensec_settings(p, ntvfs->ctx->lp_ctx);
	lpcfg_smbcli_options(ntvfs->ctx->lp_ctx, &io.in.options);
	lpcfg_smbcli_session_options(ntvfs->ctx->lp_ctx, &io.in.session_options);

	if (!(ntvfs->ctx->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS)) {
		io.in.options.use_level2_oplocks = false;
	}

	creq = smb_composite_connect_send(&io, p,
					  lpcfg_resolve_context(ntvfs->ctx->lp_ctx),
					  ntvfs->ctx->event_ctx);
	status = smb_composite_connect_recv(creq, p);
	NT_STATUS_NOT_OK_RETURN(status);

	p->tree = io.out.tree;

	p->transport = p->tree->session->transport;
	SETUP_PID;
	p->ntvfs = ntvfs;

	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);

	if (tcon->generic.level == RAW_TCON_TCONX) {
		tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
		tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
	}

	/* we need to receive oplock break requests from the server */
	smbcli_oplock_handler(p->transport, oplock_handler, p);

	p->map_generic = share_bool_option(scfg, CIFS_MAP_GENERIC, CIFS_MAP_GENERIC_DEFAULT);

	p->map_trans2 = share_bool_option(scfg, CIFS_MAP_TRANS2, CIFS_MAP_TRANS2_DEFAULT);

	return NT_STATUS_OK;
}
Пример #11
0
/*
  setup config options for a posix share
*/
static void pvfs_setup_options(struct pvfs_state *pvfs)
{
	struct share_config *scfg = pvfs->ntvfs->ctx->config;
	const char *eadb;
	bool def_perm_override = false;

	if (share_bool_option(scfg, SHARE_MAP_HIDDEN, SHARE_MAP_HIDDEN_DEFAULT))
		pvfs->flags |= PVFS_FLAG_MAP_HIDDEN;
	if (share_bool_option(scfg, SHARE_MAP_ARCHIVE, SHARE_MAP_ARCHIVE_DEFAULT))
		pvfs->flags |= PVFS_FLAG_MAP_ARCHIVE;
	if (share_bool_option(scfg, SHARE_MAP_SYSTEM, SHARE_MAP_SYSTEM_DEFAULT))
		pvfs->flags |= PVFS_FLAG_MAP_SYSTEM;
	if (share_bool_option(scfg, SHARE_READONLY, SHARE_READONLY_DEFAULT))
		pvfs->flags |= PVFS_FLAG_READONLY;
	if (share_bool_option(scfg, SHARE_STRICT_SYNC, SHARE_STRICT_SYNC_DEFAULT))
		pvfs->flags |= PVFS_FLAG_STRICT_SYNC;
	if (share_bool_option(scfg, SHARE_STRICT_LOCKING, SHARE_STRICT_LOCKING_DEFAULT))
		pvfs->flags |= PVFS_FLAG_STRICT_LOCKING;
	if (share_bool_option(scfg, SHARE_CI_FILESYSTEM, SHARE_CI_FILESYSTEM_DEFAULT))
		pvfs->flags |= PVFS_FLAG_CI_FILESYSTEM;
	if (share_bool_option(scfg, PVFS_FAKE_OPLOCKS, PVFS_FAKE_OPLOCKS_DEFAULT))
		pvfs->flags |= PVFS_FLAG_FAKE_OPLOCKS;
	if (share_bool_option(scfg, PVFS_AIO, false))
		pvfs->flags |= PVFS_FLAG_LINUX_AIO;

#if defined(O_DIRECTORY) && defined(O_NOFOLLOW)
	/* set PVFS_PERM_OVERRIDE by default only if the system
	 * supports the necessary capabilities to make it secure
	 */
	def_perm_override = true;
#endif
	if (share_bool_option(scfg, PVFS_PERM_OVERRIDE, def_perm_override))
		pvfs->flags |= PVFS_FLAG_PERM_OVERRIDE;

	/* file perm options */
	pvfs->options.create_mask       = share_int_option(scfg,
							   SHARE_CREATE_MASK,
							   SHARE_CREATE_MASK_DEFAULT);
	pvfs->options.dir_mask          = share_int_option(scfg,
							   SHARE_DIR_MASK,
							   SHARE_DIR_MASK_DEFAULT);
	pvfs->options.force_dir_mode    = share_int_option(scfg,
							   SHARE_FORCE_DIR_MODE,
							   SHARE_FORCE_DIR_MODE_DEFAULT);
	pvfs->options.force_create_mode = share_int_option(scfg,
							   SHARE_FORCE_CREATE_MODE,
							   SHARE_FORCE_CREATE_MODE_DEFAULT);
	/* this must be a power of 2 */
	pvfs->alloc_size_rounding = share_int_option(scfg,
							PVFS_ALLOCATION_ROUNDING,
							PVFS_ALLOCATION_ROUNDING_DEFAULT);

	pvfs->search.inactivity_time = share_int_option(scfg,
							PVFS_SEARCH_INACTIVITY,
							PVFS_SEARCH_INACTIVITY_DEFAULT);

#if HAVE_XATTR_SUPPORT
	if (share_bool_option(scfg, PVFS_XATTR, PVFS_XATTR_DEFAULT))
		pvfs->flags |= PVFS_FLAG_XATTR_ENABLE;
#endif

	pvfs->sharing_violation_delay = share_int_option(scfg,
							PVFS_SHARE_DELAY,
							PVFS_SHARE_DELAY_DEFAULT);

	pvfs->oplock_break_timeout = share_int_option(scfg,
						      PVFS_OPLOCK_TIMEOUT,
						      PVFS_OPLOCK_TIMEOUT_DEFAULT);

	pvfs->writetime_delay = share_int_option(scfg,
						 PVFS_WRITETIME_DELAY,
						 PVFS_WRITETIME_DELAY_DEFAULT);

	pvfs->share_name = talloc_strdup(pvfs, scfg->name);

	pvfs->fs_attribs = 
		FS_ATTR_CASE_SENSITIVE_SEARCH | 
		FS_ATTR_CASE_PRESERVED_NAMES |
		FS_ATTR_UNICODE_ON_DISK |
		FS_ATTR_SPARSE_FILES;

	/* allow xattrs to be stored in a external tdb */
	eadb = share_string_option(scfg, PVFS_EADB, NULL);
	if (eadb != NULL) {
		pvfs->ea_db = tdb_wrap_open(pvfs, eadb, 50000,  
					    TDB_DEFAULT, O_RDWR|O_CREAT, 0600, 
					    pvfs->ntvfs->ctx->lp_ctx);
		if (pvfs->ea_db != NULL) {
			pvfs->flags |= PVFS_FLAG_XATTR_ENABLE;
		} else {
			DEBUG(0,("Failed to open eadb '%s' - %s\n",
				 eadb, strerror(errno)));
			pvfs->flags &= ~PVFS_FLAG_XATTR_ENABLE;
		}
	}

	if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
		pvfs->fs_attribs |= FS_ATTR_NAMED_STREAMS;
	}
	if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
		pvfs->fs_attribs |= FS_ATTR_PERSISTANT_ACLS;
	}

	pvfs->sid_cache.creator_owner = dom_sid_parse_talloc(pvfs, SID_CREATOR_OWNER);
	pvfs->sid_cache.creator_group = dom_sid_parse_talloc(pvfs, SID_CREATOR_GROUP);

	/* check if the system really supports xattrs */
	if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
		pvfs_xattr_probe(pvfs);
	}

	/* enable an ACL backend */
	pvfs->acl_ops = pvfs_acl_backend_byname(share_string_option(scfg, PVFS_ACL, "xattr"));
}
Пример #12
0
/*
  connect to a share - used when a tree_connect operation comes
  in. For a disk based backend we needs to ensure that the base
  directory exists (tho it doesn't need to be accessible by the user,
  that comes later)
*/
static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
			     struct ntvfs_request *req,
			     union smb_tcon* tcon)
{
	struct pvfs_state *pvfs;
	struct stat st;
	char *base_directory;
	NTSTATUS status;
	const char *sharename;

	switch (tcon->generic.level) {
	case RAW_TCON_TCON:
		sharename = tcon->tcon.in.service;
		break;
	case RAW_TCON_TCONX:
		sharename = tcon->tconx.in.path;
		break;
	case RAW_TCON_SMB2:
		sharename = tcon->smb2.in.path;
		break;
	default:
		return NT_STATUS_INVALID_LEVEL;
	}

	if (strncmp(sharename, "\\\\", 2) == 0) {
		char *p = strchr(sharename+2, '\\');
		if (p) {
			sharename = p + 1;
		}
	}

	/*
	 * TODO: call this from ntvfs_posix_init()
	 *       but currently we don't have a lp_ctx there
	 */
	status = pvfs_acl_init();
	NT_STATUS_NOT_OK_RETURN(status);

	pvfs = talloc_zero(ntvfs, struct pvfs_state);
	NT_STATUS_HAVE_NO_MEMORY(pvfs);

	/* for simplicity of path construction, remove any trailing slash now */
	base_directory = talloc_strdup(pvfs, share_string_option(ntvfs->ctx->config, SHARE_PATH, ""));
	NT_STATUS_HAVE_NO_MEMORY(base_directory);
	if (strcmp(base_directory, "/") != 0) {
		trim_string(base_directory, NULL, "/");
	}

	pvfs->ntvfs = ntvfs;
	pvfs->base_directory = base_directory;

	/* the directory must exist. Note that we deliberately don't
	   check that it is readable */
	if (stat(pvfs->base_directory, &st) != 0 || !S_ISDIR(st.st_mode)) {
		DEBUG(0,("pvfs_connect: '%s' is not a directory, when connecting to [%s]\n", 
			 pvfs->base_directory, sharename));
		return NT_STATUS_BAD_NETWORK_NAME;
	}

	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);

	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);

	if (tcon->generic.level == RAW_TCON_TCONX) {
		tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
		tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
	}

	ntvfs->private_data = pvfs;

	pvfs->brl_context = brlock_init(pvfs, 
				     pvfs->ntvfs->ctx->server_id,
				     pvfs->ntvfs->ctx->lp_ctx,
				     pvfs->ntvfs->ctx->msg_ctx);
	if (pvfs->brl_context == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	pvfs->odb_context = odb_init(pvfs, pvfs->ntvfs->ctx);
	if (pvfs->odb_context == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* allow this to be NULL - we just disable change notify */
	pvfs->notify_context = notify_init(pvfs, 
					   pvfs->ntvfs->ctx->server_id,  
					   pvfs->ntvfs->ctx->msg_ctx, 
					   pvfs->ntvfs->ctx->lp_ctx,
					   pvfs->ntvfs->ctx->event_ctx,
					   pvfs->ntvfs->ctx->config);

	pvfs->wbc_ctx = wbc_init(pvfs,
				 pvfs->ntvfs->ctx->msg_ctx,
				 pvfs->ntvfs->ctx->event_ctx);
	if (pvfs->wbc_ctx == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* allocate the search handle -> ptr tree */
	pvfs->search.idtree = idr_init(pvfs);
	NT_STATUS_HAVE_NO_MEMORY(pvfs->search.idtree);

	status = pvfs_mangle_init(pvfs);
	NT_STATUS_NOT_OK_RETURN(status);

	pvfs_setup_options(pvfs);

	talloc_set_destructor(pvfs, pvfs_state_destructor);

#ifdef SIGXFSZ
	/* who had the stupid idea to generate a signal on a large
	   file write instead of just failing it!? */
	BlockSignals(true, SIGXFSZ);
#endif

	return NT_STATUS_OK;
}
Пример #13
0
/*
  setup config options for a posix share
*/
static void pvfs_setup_options(struct pvfs_state *pvfs)
{
	struct share_config *scfg = pvfs->ntvfs->ctx->config;
	const char *eadb;

	if (share_bool_option(scfg, SHARE_MAP_HIDDEN, SHARE_MAP_HIDDEN_DEFAULT))
		pvfs->flags |= PVFS_FLAG_MAP_HIDDEN;
	if (share_bool_option(scfg, SHARE_MAP_ARCHIVE, SHARE_MAP_ARCHIVE_DEFAULT))
		pvfs->flags |= PVFS_FLAG_MAP_ARCHIVE;
	if (share_bool_option(scfg, SHARE_MAP_SYSTEM, SHARE_MAP_SYSTEM_DEFAULT))
		pvfs->flags |= PVFS_FLAG_MAP_SYSTEM;
	if (share_bool_option(scfg, SHARE_READONLY, SHARE_READONLY_DEFAULT))
		pvfs->flags |= PVFS_FLAG_READONLY;
	if (share_bool_option(scfg, SHARE_STRICT_SYNC, SHARE_STRICT_SYNC_DEFAULT))
		pvfs->flags |= PVFS_FLAG_STRICT_SYNC;
	if (share_bool_option(scfg, SHARE_STRICT_LOCKING, SHARE_STRICT_LOCKING_DEFAULT))
		pvfs->flags |= PVFS_FLAG_STRICT_LOCKING;
	if (share_bool_option(scfg, SHARE_CI_FILESYSTEM, SHARE_CI_FILESYSTEM_DEFAULT))
		pvfs->flags |= PVFS_FLAG_CI_FILESYSTEM;
	if (share_bool_option(scfg, PVFS_FAKE_OPLOCKS, PVFS_FAKE_OPLOCKS_DEFAULT)) {
		pvfs->flags |= PVFS_FLAG_FAKE_OPLOCKS;
	}

	/* this must be a power of 2 */
	pvfs->alloc_size_rounding = share_int_option(scfg,
							PVFS_ALLOCATION_ROUNDING,
							PVFS_ALLOCATION_ROUNDING_DEFAULT);

	pvfs->search.inactivity_time = share_int_option(scfg,
							PVFS_SEARCH_INACTIVITY,
							PVFS_SEARCH_INACTIVITY_DEFAULT);

#if HAVE_XATTR_SUPPORT
	if (share_bool_option(scfg, PVFS_XATTR, PVFS_XATTR_DEFAULT))
		pvfs->flags |= PVFS_FLAG_XATTR_ENABLE;
#endif

	pvfs->sharing_violation_delay = share_int_option(scfg,
							PVFS_SHARE_DELAY,
							PVFS_SHARE_DELAY_DEFAULT);

	pvfs->share_name = talloc_strdup(pvfs, scfg->name);

	pvfs->fs_attribs = 
		FS_ATTR_CASE_SENSITIVE_SEARCH | 
		FS_ATTR_CASE_PRESERVED_NAMES |
		FS_ATTR_UNICODE_ON_DISK |
		FS_ATTR_SPARSE_FILES;

	/* allow xattrs to be stored in a external tdb */
	eadb = share_string_option(scfg, PVFS_EADB, NULL);
	if (eadb != NULL) {
		pvfs->ea_db = tdb_wrap_open(pvfs, eadb, 50000,  
					    TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
		if (pvfs->ea_db != NULL) {
			pvfs->flags |= PVFS_FLAG_XATTR_ENABLE;
		} else {
			DEBUG(0,("Failed to open eadb '%s' - %s\n",
				 eadb, strerror(errno)));
			pvfs->flags &= ~PVFS_FLAG_XATTR_ENABLE;
		}
	}

	if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
		pvfs->fs_attribs |= FS_ATTR_NAMED_STREAMS;
	}
	if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
		pvfs->fs_attribs |= FS_ATTR_PERSISTANT_ACLS;
	}

	pvfs->sid_cache.creator_owner = dom_sid_parse_talloc(pvfs, SID_CREATOR_OWNER);
	pvfs->sid_cache.creator_group = dom_sid_parse_talloc(pvfs, SID_CREATOR_GROUP);

	/* check if the system really supports xattrs */
	if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
		pvfs_xattr_probe(pvfs);
	}

	/* enable an ACL backend */
	pvfs->acl_ops = pvfs_acl_backend_byname(share_string_option(scfg, PVFS_ACL, "xattr"));
}
Пример #14
0
/*
  connect to a share - used when a tree_connect operation comes
  in. For a disk based backend we needs to ensure that the base
  directory exists (tho it doesn't need to be accessible by the user,
  that comes later)
*/
static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
			     struct ntvfs_request *req, const char *sharename)
{
	struct pvfs_state *pvfs;
	struct stat st;
	char *base_directory;
	NTSTATUS status;

	pvfs = talloc_zero(ntvfs, struct pvfs_state);
	NT_STATUS_HAVE_NO_MEMORY(pvfs);

	/* for simplicity of path construction, remove any trailing slash now */
	base_directory = talloc_strdup(pvfs, share_string_option(ntvfs->ctx->config, SHARE_PATH, ""));
	NT_STATUS_HAVE_NO_MEMORY(base_directory);
	if (strcmp(base_directory, "/") != 0) {
		trim_string(base_directory, NULL, "/");
	}

	pvfs->ntvfs = ntvfs;
	pvfs->base_directory = base_directory;

	/* the directory must exist. Note that we deliberately don't
	   check that it is readable */
	if (stat(pvfs->base_directory, &st) != 0 || !S_ISDIR(st.st_mode)) {
		DEBUG(0,("pvfs_connect: '%s' is not a directory, when connecting to [%s]\n", 
			 pvfs->base_directory, sharename));
		return NT_STATUS_BAD_NETWORK_NAME;
	}

	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);

	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);

	ntvfs->private_data = pvfs;

	pvfs->brl_context = brl_init(pvfs, 
				     pvfs->ntvfs->ctx->server_id,
				     pvfs->ntvfs->ctx->msg_ctx);
	if (pvfs->brl_context == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	pvfs->odb_context = odb_init(pvfs, pvfs->ntvfs->ctx);
	if (pvfs->odb_context == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* allow this to be NULL - we just disable change notify */
	pvfs->notify_context = notify_init(pvfs, 
					   pvfs->ntvfs->ctx->server_id,  
					   pvfs->ntvfs->ctx->msg_ctx, 
					   event_context_find(pvfs),
					   pvfs->ntvfs->ctx->config);

	pvfs->sidmap = sidmap_open(pvfs);
	if (pvfs->sidmap == NULL) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* allocate the search handle -> ptr tree */
	pvfs->search.idtree = idr_init(pvfs);
	NT_STATUS_HAVE_NO_MEMORY(pvfs->search.idtree);

	status = pvfs_mangle_init(pvfs);
	NT_STATUS_NOT_OK_RETURN(status);

	pvfs_setup_options(pvfs);

	talloc_set_destructor(pvfs, pvfs_state_destructor);

#ifdef SIGXFSZ
	/* who had the stupid idea to generate a signal on a large
	   file write instead of just failing it!? */
	BlockSignals(True, SIGXFSZ);
#endif

	return NT_STATUS_OK;
}
Пример #15
0
static NTSTATUS smb2srv_tcon_backend(struct smb2srv_request *req, union smb_tcon *io)
{
	struct smbsrv_tcon *tcon;
	NTSTATUS status;
	enum ntvfs_type type;
	uint16_t type_smb2;
	uint32_t unknown2;
	const char *service = io->smb2.in.path;
	struct share_config *scfg;
	const char *sharetype;

	if (strncmp(service, "\\\\", 2) == 0) {
		const char *p = strchr(service+2, '\\');
		if (p) {
			service = p + 1;
		}
	}

	status = share_get_config(req, req->smb_conn->share_context, service, &scfg);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("smb2srv_tcon_backend: couldn't find service %s\n", service));
		return NT_STATUS_BAD_NETWORK_NAME;
	}

	if (!socket_check_access(req->smb_conn->connection->socket, 
				 scfg->name, 
				 share_string_list_option(req, scfg, SHARE_HOSTS_ALLOW), 
				 share_string_list_option(req, scfg, SHARE_HOSTS_DENY))) {
		return NT_STATUS_ACCESS_DENIED;
	}

	/* work out what sort of connection this is */
	sharetype = share_string_option(scfg, SHARE_TYPE, "DISK");
	if (sharetype && strcmp(sharetype, "IPC") == 0) {
		type = NTVFS_IPC;
		type_smb2 = 0x0002;
		unknown2 = 0x00000030;
	} else if (sharetype && strcmp(sharetype, "PRINTER") == 0) {
		type = NTVFS_PRINT;
		type_smb2 = 0x0003;
		unknown2 = 0x00000000;
	} else {
		type = NTVFS_DISK;
		type_smb2 = 0x0001;
		unknown2 = 0x00000800;
	}

	tcon = smbsrv_smb2_tcon_new(req->session, scfg->name);
	if (!tcon) {
		DEBUG(0,("smb2srv_tcon_backend: Couldn't find free connection.\n"));
		return NT_STATUS_INSUFFICIENT_RESOURCES;
	}
	req->tcon = tcon;

	/* init ntvfs function pointers */
	status = ntvfs_init_connection(tcon, scfg, type,
				       req->smb_conn->negotiate.protocol,
				       req->smb_conn->connection->event.ctx,
				       req->smb_conn->connection->msg_ctx,
				       req->smb_conn->connection->server_id,
				       &tcon->ntvfs);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("smb2srv_tcon_backend: ntvfs_init_connection failed for service %s\n", 
			  scfg->name));
		goto failed;
	}

	status = ntvfs_set_oplock_handler(tcon->ntvfs, smb2srv_send_oplock_break, tcon);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("smb2srv_tcon_backend: NTVFS failed to set the oplock handler!\n"));
		goto failed;
	}

	status = ntvfs_set_addr_callbacks(tcon->ntvfs, smbsrv_get_my_addr, smbsrv_get_peer_addr, req->smb_conn);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("smb2srv_tcon_backend: NTVFS failed to set the addr callbacks!\n"));
		goto failed;
	}

	status = ntvfs_set_handle_callbacks(tcon->ntvfs,
					    smb2srv_handle_create_new,
					    smb2srv_handle_make_valid,
					    smb2srv_handle_destroy,
					    smb2srv_handle_search_by_wire_key,
					    smb2srv_handle_get_wire_key,
					    tcon);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("smb2srv_tcon_backend: NTVFS failed to set the handle callbacks!\n"));
		goto failed;
	}

	req->ntvfs = ntvfs_request_create(req->tcon->ntvfs, req,
					  req->session->session_info,
					  0, /* TODO: fill in PID */
					  req->request_time,
					  req, NULL, 0);
	if (!req->ntvfs) {
		status = NT_STATUS_NO_MEMORY;
		goto failed;
	}

	/* Invoke NTVFS connection hook */
	status = ntvfs_connect(req->ntvfs, scfg->name);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("smb2srv_tcon_backend: NTVFS ntvfs_connect() failed!\n"));
		goto failed;
	}

	io->smb2.out.unknown1	= type_smb2; /* 1 - DISK, 2 - Print, 3 - IPC */
	io->smb2.out.unknown2	= unknown2;
	io->smb2.out.unknown3	= 0x00000000;
	io->smb2.out.access_mask= SEC_RIGHTS_FILE_ALL;

	io->smb2.out.tid	= tcon->tid;

	return NT_STATUS_OK;

failed:
	req->tcon = NULL;
	talloc_free(tcon);
	return status;
}
Пример #16
0
/*
  connect to a share - used when a tree_connect operation comes in.
*/
static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, 
			     struct ntvfs_request *req,
			     union smb_tcon* tcon)
{
	NTSTATUS status;
	struct cvfs_private *p;
	const char *host, *user, *pass, *domain, *remote_share, *sharename;
	struct share_config *scfg = ntvfs->ctx->config;
	struct smb2_tree *tree;
	struct cli_credentials *credentials;
	bool machine_account;
	struct smbcli_options options;

	switch (tcon->generic.level) {
	case RAW_TCON_TCON:
		sharename = tcon->tcon.in.service;
		break;
	case RAW_TCON_TCONX:
		sharename = tcon->tconx.in.path;
		break;
	case RAW_TCON_SMB2:
		sharename = tcon->smb2.in.path;
		break;
	default:
		return NT_STATUS_INVALID_LEVEL;
	}

	if (strncmp(sharename, "\\\\", 2) == 0) {
		char *str = strchr(sharename+2, '\\');
		if (str) {
			sharename = str + 1;
		}
	}

	/* Here we need to determine which server to connect to.
	 * For now we use parametric options, type cifs.
	 */
	host = share_string_option(scfg, SMB2_SERVER, NULL);
	user = share_string_option(scfg, SMB2_USER, NULL);
	pass = share_string_option(scfg, SMB2_PASSWORD, NULL);
	domain = share_string_option(scfg, SMB2_DOMAIN, NULL);
	remote_share = share_string_option(scfg, SMB2_SHARE, NULL);
	if (!remote_share) {
		remote_share = sharename;
	}

	machine_account = share_bool_option(scfg, SMB2_USE_MACHINE_ACCT, SMB2_USE_MACHINE_ACCT_DEFAULT);

	p = talloc_zero(ntvfs, struct cvfs_private);
	if (!p) {
		return NT_STATUS_NO_MEMORY;
	}

	ntvfs->private_data = p;

	if (!host) {
		DEBUG(1,("CIFS backend: You must supply server\n"));
		return NT_STATUS_INVALID_PARAMETER;
	} 
	
	if (user && pass) {
		DEBUG(5, ("CIFS backend: Using specified password\n"));
		credentials = cli_credentials_init(p);
		if (!credentials) {
			return NT_STATUS_NO_MEMORY;
		}
		cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
		cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		cli_credentials_set_password(credentials, pass, CRED_SPECIFIED);
	} else if (machine_account) {
		DEBUG(5, ("CIFS backend: Using machine account\n"));
		credentials = cli_credentials_init(p);
		cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
	} else if (req->session_info->credentials) {
		DEBUG(5, ("CIFS backend: Using delegated credentials\n"));
		credentials = req->session_info->credentials;
	} else {
		DEBUG(1,("CIFS backend: NO delegated credentials found: You must supply server, user and password or the client must supply delegated credentials\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	lpcfg_smbcli_options(ntvfs->ctx->lp_ctx, &options);

	status = smb2_connect(p, host,
			lpcfg_parm_string_list(p, ntvfs->ctx->lp_ctx, NULL, "smb2", "ports", NULL),
			remote_share,
			lpcfg_resolve_context(ntvfs->ctx->lp_ctx),
			credentials,
			&tree,
			ntvfs->ctx->event_ctx, &options,
			lpcfg_socket_options(ntvfs->ctx->lp_ctx),
			lpcfg_gensec_settings(p, ntvfs->ctx->lp_ctx));
	NT_STATUS_NOT_OK_RETURN(status);

	status = smb2_get_roothandle(tree, &p->roothandle);
	NT_STATUS_NOT_OK_RETURN(status);

	p->tree = tree;
	p->transport = p->tree->session->transport;
	p->ntvfs = ntvfs;

	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);

	if (tcon->generic.level == RAW_TCON_TCONX) {
		tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
		tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
	}

	/* we need to receive oplock break requests from the server */
	/* TODO: enable oplocks 
	smbcli_oplock_handler(p->transport, oplock_handler, p);
	*/
	return NT_STATUS_OK;
}
Пример #17
0
NTSTATUS srvsvc_create_ntvfs_context(struct dcesrv_call_state *dce_call,
				     TALLOC_CTX *mem_ctx,
				     const char *share,
				     struct ntvfs_context **_ntvfs)
{
	NTSTATUS status;
	struct srvsvc_ntvfs_ctx	*c;
	struct ntvfs_request *ntvfs_req;
	enum ntvfs_type type;
	struct share_context *sctx;
	struct share_config *scfg;
	const char *sharetype;
	union smb_tcon tcon;
	const struct tsocket_address *local_address;
	const struct tsocket_address *remote_address;

	status = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_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(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;
	}

	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,
				       dce_call->conn->msg_ctx,
				       dce_call->conn->dce_ctx->lp_ctx,
				       dce_call->conn->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,
					 dce_call->conn->auth_state.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;
}