static int atalk_unlink(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname) { int ret = 0, i; char *path = NULL; char *adbl_path = NULL; char *orig_path = NULL; SMB_STRUCT_STAT adbl_info; SMB_STRUCT_STAT orig_info; NTSTATUS status; ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname); status = get_full_smb_filename(talloc_tos(), smb_fname, &path); if (!NT_STATUS_IS_OK(status)) { return ret; } /* no .AppleDouble sync if veto or hide list is empty, * otherwise "Cannot find the specified file" error will be caused */ if (!handle->conn->veto_list) return ret; if (!handle->conn->hide_list) return ret; for (i = 0; handle->conn->veto_list[i].name; i ++) { if (strstr_m(handle->conn->veto_list[i].name, APPLEDOUBLE)) break; } if (!handle->conn->veto_list[i].name) { for (i = 0; handle->conn->hide_list[i].name; i ++) { if (strstr_m(handle->conn->hide_list[i].name, APPLEDOUBLE)) break; else { DEBUG(3, ("ATALK: %s is not hidden, skipped..\n", APPLEDOUBLE)); goto exit_unlink; } } } if (atalk_build_paths(talloc_tos(), handle->conn->cwd, path, &adbl_path, &orig_path, &adbl_info, &orig_info) != 0) goto exit_unlink; if (S_ISDIR(orig_info.st_ex_mode) || S_ISREG(orig_info.st_ex_mode)) { DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); goto exit_unlink; } atalk_unlink_file(adbl_path); exit_unlink: TALLOC_FREE(path); TALLOC_FREE(adbl_path); TALLOC_FREE(orig_path); return ret; }
static int tsmsm_set_offline(struct vfs_handle_struct *handle, const struct smb_filename *fname) { struct tsmsm_struct *tsmd = (struct tsmsm_struct *) handle->data; int result = 0; char *command; NTSTATUS status; char *path; if (tsmd->hsmscript == NULL) { /* no script enabled */ DEBUG(1, ("tsmsm_set_offline: No 'tsmsm:hsm script' configured\n")); return 0; } status = get_full_smb_filename(talloc_tos(), fname, &path); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); return false; } /* Now, call the script */ command = talloc_asprintf(tsmd, "%s offline \"%s\"", tsmd->hsmscript, path); if(!command) { DEBUG(1, ("tsmsm_set_offline: can't allocate memory to run hsm script")); return -1; } DEBUG(10, ("tsmsm_set_offline: Running [%s]\n", command)); if((result = smbrun(command, NULL)) != 0) { DEBUG(1,("tsmsm_set_offline: Running [%s] returned %d\n", command, result)); } TALLOC_FREE(command); return result; }
/** * Return a string using the talloc_tos() */ const char *smb_fname_str_dbg(const struct smb_filename *smb_fname) { char *fname = NULL; NTSTATUS status; if (smb_fname == NULL) { return ""; } status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); if (!NT_STATUS_IS_OK(status)) { return ""; } return fname; }
static int fake_acls_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { int ret = -1; ret = SMB_VFS_NEXT_STAT(handle, smb_fname); if (ret == 0) { TALLOC_CTX *frame = talloc_stackframe(); char *path; struct smb_filename smb_fname_base = { .base_name = smb_fname->base_name }; NTSTATUS status; /* * As we're calling getxattr directly here * we need to use only the base_name, not * the full name containing any stream name. */ status = get_full_smb_filename(frame, &smb_fname_base, &path); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); TALLOC_FREE(frame); return -1; } ret = fake_acls_uid(handle, path, &smb_fname->st.st_ex_uid); if (ret != 0) { TALLOC_FREE(frame); return ret; } ret = fake_acls_gid(handle, path, &smb_fname->st.st_ex_gid); if (ret != 0) { TALLOC_FREE(frame); return ret; } TALLOC_FREE(frame); } return ret; }
static int fake_acls_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { int ret = -1; ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); if (ret == 0) { TALLOC_CTX *frame = talloc_stackframe(); char *path; struct smb_filename smb_fname_base = { .base_name = smb_fname->base_name }; NTSTATUS status; /* * As we're calling getxattr directly here * we need to use only the base_name, not * the full name containing any stream name. */ status = get_full_smb_filename(frame, &smb_fname_base, &path); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); TALLOC_FREE(frame); return -1; } /* This isn't quite right (calling getxattr not * lgetxattr), but for the test purposes of this * module (fake NT ACLs from windows clients), it is * close enough. We removed the l*xattr functions * because linux doesn't support using them, but we * could fake them in xattr_tdb if we really wanted * to. We ignore errors because the link might not point anywhere */ fake_acls_uid(handle, path, &smb_fname->st.st_ex_uid); fake_acls_gid(handle, path, &smb_fname->st.st_ex_gid); TALLOC_FREE(frame); } return ret; }
static int atalk_rename(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname_src, const struct smb_filename *smb_fname_dst) { int ret = 0; char *oldname = NULL; char *adbl_path = NULL; char *orig_path = NULL; SMB_STRUCT_STAT adbl_info; SMB_STRUCT_STAT orig_info; NTSTATUS status; ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); status = get_full_smb_filename(talloc_tos(), smb_fname_src, &oldname); if (!NT_STATUS_IS_OK(status)) { return ret; } if (atalk_build_paths(talloc_tos(), handle->conn->cwd, oldname, &adbl_path, &orig_path, &adbl_info, &orig_info) != 0) goto exit_rename; if (S_ISDIR(orig_info.st_ex_mode) || S_ISREG(orig_info.st_ex_mode)) { DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); goto exit_rename; } atalk_unlink_file(adbl_path); exit_rename: TALLOC_FREE(oldname); TALLOC_FREE(adbl_path); TALLOC_FREE(orig_path); return ret; }
static bool tsmsm_is_offline(struct vfs_handle_struct *handle, const struct smb_filename *fname, SMB_STRUCT_STAT *stbuf) { struct tsmsm_struct *tsmd = (struct tsmsm_struct *) handle->data; const dm_sessid_t *dmsession_id; void *dmhandle = NULL; size_t dmhandle_len = 0; size_t rlen; dm_attrname_t dmname; int ret, lerrno; bool offline; char *buf = NULL; size_t buflen; NTSTATUS status; char *path; status = get_full_smb_filename(talloc_tos(), fname, &path); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); return false; } /* if the file has more than FILE_IS_ONLINE_RATIO of blocks available, then assume it is not offline (it may not be 100%, as it could be sparse) */ if (512 * stbuf->st_ex_blocks >= stbuf->st_ex_size * tsmd->online_ratio) { DEBUG(10,("%s not offline: st_blocks=%llu st_size=%llu " "online_ratio=%.2f\n", path, (unsigned long long)stbuf->st_ex_blocks, (unsigned long long)stbuf->st_ex_size, tsmd->online_ratio)); return false; } dmsession_id = dmapi_get_current_session(); if (dmsession_id == NULL) { DEBUG(2, ("tsmsm_is_offline: no DMAPI session available? " "Assume file is online.\n")); return false; } /* using POSIX capabilities does not work here. It's a slow path, so * become_root() is just as good anyway (tridge) */ /* Also, AIX has DMAPI but no POSIX capablities support. In this case, * we need to be root to do DMAPI manipulations. */ become_root(); /* go the slow DMAPI route */ if (dm_path_to_handle((char*)path, &dmhandle, &dmhandle_len) != 0) { DEBUG(2,("dm_path_to_handle failed - assuming offline (%s) - %s\n", path, strerror(errno))); offline = true; goto done; } memset(&dmname, 0, sizeof(dmname)); strlcpy((char *)&dmname.an_chars[0], tsmd->attrib_name, sizeof(dmname.an_chars)); if (tsmd->attrib_value != NULL) { buflen = strlen(tsmd->attrib_value); } else { buflen = 1; } buf = talloc_zero_size(tsmd, buflen); if (buf == NULL) { DEBUG(0,("out of memory in tsmsm_is_offline -- assuming online (%s)\n", path)); errno = ENOMEM; offline = false; goto done; } do { lerrno = 0; ret = dm_get_dmattr(*dmsession_id, dmhandle, dmhandle_len, DM_NO_TOKEN, &dmname, buflen, buf, &rlen); if (ret == -1 && errno == EINVAL) { DEBUG(0, ("Stale DMAPI session, re-creating it.\n")); lerrno = EINVAL; if (dmapi_new_session()) { dmsession_id = dmapi_get_current_session(); } else { DEBUG(0, ("Unable to re-create DMAPI session, assuming offline (%s) - %s\n", path, strerror(errno))); offline = true; dm_handle_free(dmhandle, dmhandle_len); goto done; } } } while (ret == -1 && lerrno == EINVAL); /* check if we need a specific attribute value */ if (tsmd->attrib_value != NULL) { offline = (ret == 0 && rlen == buflen && memcmp(buf, tsmd->attrib_value, buflen) == 0); } else { /* its offline if the specified DMAPI attribute exists */ offline = (ret == 0 || (ret == -1 && errno == E2BIG)); } DEBUG(10,("dm_get_dmattr %s ret=%d (%s)\n", path, ret, strerror(errno))); ret = 0; dm_handle_free(dmhandle, dmhandle_len); done: talloc_free(buf); unbecome_root(); return offline; }
static int open_acl_common(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) { uint32_t access_granted = 0; struct security_descriptor *pdesc = NULL; struct security_descriptor *parent_desc = NULL; bool file_existed = true; char *fname = NULL; NTSTATUS status; if (fsp->base_fsp) { /* Stream open. Base filename open already did the ACL check. */ DEBUG(10,("open_acl_common: stream open on %s\n", fsp_str_dbg(fsp) )); return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); } status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); if (!NT_STATUS_IS_OK(status)) { goto err; } status = get_nt_acl_internal(handle, NULL, fname, (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION), &pdesc); if (NT_STATUS_IS_OK(status)) { /* See if we can access it. */ status = smb1_file_se_access_check(handle->conn, pdesc, handle->conn->server_info->ptok, fsp->access_mask, &access_granted); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("open_acl_xattr: %s open " "refused with error %s\n", fsp_str_dbg(fsp), nt_errstr(status) )); goto err; } } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) { file_existed = false; /* * If O_CREAT is true then we're trying to create a file. * Check the parent directory ACL will allow this. */ if (flags & O_CREAT) { struct security_descriptor *psd = NULL; status = check_parent_acl_common(handle, fname, SEC_DIR_ADD_FILE, &parent_desc); if (!NT_STATUS_IS_OK(status)) { goto err; } /* Cache the parent security descriptor for * later use. We do have an fsp here, but to * keep the code consistent with the directory * case which doesn't, use the handle. */ /* Attach this to the conn, move from talloc_tos(). */ psd = (struct security_descriptor *)talloc_move(handle->conn, &parent_desc); if (!psd) { status = NT_STATUS_NO_MEMORY; goto err; } status = NT_STATUS_NO_MEMORY; SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common, struct security_descriptor *, goto err); status = NT_STATUS_OK; } } DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for " "%s returned %s\n", fsp_str_dbg(fsp), nt_errstr(status) )); fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); return fsp->fh->fd; err: errno = map_errno_from_nt_status(status); return -1; }