/* 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; }
/* 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; }
/* Open up the notify.tdb database. You should close it down using talloc_free(). We need the imessaging_ctx to allow for notifications via internal messages */ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, struct imessaging_context *imessaging_ctx, struct loadparm_context *lp_ctx, struct tevent_context *ev, struct share_config *scfg) { struct notify_context *notify; if (share_bool_option(scfg, NOTIFY_ENABLE, NOTIFY_ENABLE_DEFAULT) != true) { return NULL; } if (ev == NULL) { return NULL; } notify = talloc(mem_ctx, struct notify_context); if (notify == NULL) { return NULL; } notify->w = cluster_tdb_tmp_open(notify, lp_ctx, "notify.tdb", TDB_SEQNUM); if (notify->w == NULL) { talloc_free(notify); return NULL; } notify->server = server; notify->imessaging_ctx = imessaging_ctx; notify->list = NULL; notify->array = NULL; notify->seqnum = tdb_get_seqnum(notify->w->tdb); talloc_set_destructor(notify, notify_destructor); /* register with the messaging subsystem for the notify message type */ imessaging_register(notify->imessaging_ctx, notify, MSG_PVFS_NOTIFY, notify_handler); notify->sys_notify_ctx = sys_notify_context_create(scfg, notify, ev); return notify; }
/* backend for tree connect call */ NTSTATUS smbsrv_tcon_backend(struct smbsrv_request *req, union smb_tcon *con) { NTSTATUS status; if (con->generic.level == RAW_TCON_TCON) { DATA_BLOB password; password = data_blob_string_const(con->tcon.in.password); status = make_connection(req, con->tcon.in.service, password, con->tcon.in.dev); if (!NT_STATUS_IS_OK(status)) { return status; } con->tcon.out.max_xmit = req->smb_conn->negotiate.max_recv; con->tcon.out.tid = req->tcon->tid; return status; } /* TODO: take a look at tconx.in.flags! */ status = make_connection(req, con->tconx.in.path, con->tconx.in.password, con->tconx.in.device); if (!NT_STATUS_IS_OK(status)) { return status; } con->tconx.out.tid = req->tcon->tid; con->tconx.out.dev_type = talloc_strdup(req, req->tcon->ntvfs->dev_type); con->tconx.out.fs_type = talloc_strdup(req, req->tcon->ntvfs->fs_type); con->tconx.out.options = SMB_SUPPORT_SEARCH_BITS | (share_int_option(req->tcon->ntvfs->config, SHARE_CSC_POLICY, SHARE_CSC_POLICY_DEFAULT) << 2); if (share_bool_option(req->tcon->ntvfs->config, SHARE_MSDFS_ROOT, SHARE_MSDFS_ROOT_DEFAULT) && lp_host_msdfs(req->smb_conn->lp_ctx)) { con->tconx.out.options |= SMB_SHARE_IN_DFS; } return status; }
/* open a file */ static NTSTATUS svfs_open(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_open *io) { struct svfs_private *p = ntvfs->private_data; char *unix_path; struct stat st; int fd, flags; struct svfs_file *f; int create_flags, rdwr_flags; bool readonly; NTSTATUS status; struct ntvfs_handle *handle; if (io->generic.level != RAW_OPEN_GENERIC) { return ntvfs_map_open(ntvfs, req, io); } readonly = share_bool_option(ntvfs->ctx->config, SHARE_READONLY, SHARE_READONLY_DEFAULT); if (readonly) { create_flags = 0; rdwr_flags = O_RDONLY; } else { create_flags = O_CREAT; rdwr_flags = O_RDWR; } unix_path = svfs_unix_path(ntvfs, req, io->ntcreatex.in.fname); switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_SUPERSEDE: case NTCREATEX_DISP_OVERWRITE_IF: flags = create_flags | O_TRUNC; break; case NTCREATEX_DISP_OPEN: case NTCREATEX_DISP_OVERWRITE: flags = 0; break; case NTCREATEX_DISP_CREATE: flags = create_flags | O_EXCL; break; case NTCREATEX_DISP_OPEN_IF: flags = create_flags; break; default: flags = 0; break; } flags |= rdwr_flags; if (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) { flags = O_RDONLY | O_DIRECTORY; if (readonly) { goto do_open; } switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_CREATE: if (mkdir(unix_path, 0755) == -1) { DEBUG(9,("svfs_open: mkdir %s errno=%d\n", unix_path, errno)); return map_nt_error_from_unix(errno); } break; case NTCREATEX_DISP_OPEN_IF: if (mkdir(unix_path, 0755) == -1 && errno != EEXIST) { DEBUG(9,("svfs_open: mkdir %s errno=%d\n", unix_path, errno)); return map_nt_error_from_unix(errno); } break; } } do_open: fd = open(unix_path, flags, 0644); if (fd == -1) { return map_nt_error_from_unix(errno); } if (fstat(fd, &st) == -1) { DEBUG(9,("svfs_open: fstat errno=%d\n", errno)); close(fd); return map_nt_error_from_unix(errno); } status = ntvfs_handle_new(ntvfs, req, &handle); NT_STATUS_NOT_OK_RETURN(status); f = talloc(handle, struct svfs_file); NT_STATUS_HAVE_NO_MEMORY(f); f->fd = fd; f->name = talloc_strdup(f, unix_path); NT_STATUS_HAVE_NO_MEMORY(f->name); DLIST_ADD(p->open_files, f); status = ntvfs_handle_set_backend_data(handle, ntvfs, f); NT_STATUS_NOT_OK_RETURN(status); ZERO_STRUCT(io->generic.out); unix_to_nt_time(&io->generic.out.create_time, st.st_ctime); unix_to_nt_time(&io->generic.out.access_time, st.st_atime); unix_to_nt_time(&io->generic.out.write_time, st.st_mtime); unix_to_nt_time(&io->generic.out.change_time, st.st_mtime); io->generic.out.file.ntvfs = handle; io->generic.out.alloc_size = st.st_size; io->generic.out.size = st.st_size; io->generic.out.attrib = svfs_unix_to_dos_attrib(st.st_mode); io->generic.out.is_directory = S_ISDIR(st.st_mode) ? 1 : 0; return NT_STATUS_OK; }
/* 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; }
/* 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")); }
/* 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")); }
/* 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; }