/* * Test creating a file with a NULL DACL. */ static bool test_create_null_dacl(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; struct smb2_create io; const char *fname = "nulldacl.txt"; bool ret = true; struct smb2_handle handle; union smb_fileinfo q; union smb_setfileinfo s; struct security_descriptor *sd = security_descriptor_initialise(tctx); struct security_acl dacl; torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n"); smb2_util_unlink(tree, fname); ZERO_STRUCT(io); io.level = RAW_OPEN_SMB2; io.in.create_flags = 0; io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC | SEC_STD_WRITE_OWNER; io.in.create_options = 0; io.in.file_attributes = FILE_ATTRIBUTE_NORMAL; io.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; io.in.alloc_size = 0; io.in.create_disposition = NTCREATEX_DISP_CREATE; io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS; io.in.security_flags = 0; io.in.fname = fname; io.in.sec_desc = sd; /* XXX create_options ? */ io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY | NTCREATEX_OPTIONS_ASYNC_ALERT | NTCREATEX_OPTIONS_NON_DIRECTORY_FILE | 0x00200000; torture_comment(tctx, "creating a file with a empty sd\n"); status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); handle = io.out.file.handle; torture_comment(tctx, "get the original sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* * Testing the created DACL, * the server should add the inherited DACL * when SEC_DESC_DACL_PRESENT isn't specified */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl == NULL) { ret = false; torture_fail_goto(tctx, done, "no DACL has been created on the server!\n"); } torture_comment(tctx, "set NULL DACL\n"); sd->type |= SEC_DESC_DACL_PRESENT; s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; s.set_secdesc.in.file.handle = handle; s.set_secdesc.in.secinfo_flags = SECINFO_DACL; s.set_secdesc.in.sd = sd; status = smb2_setinfo_file(tree, &s); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "get the sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* Testing the modified DACL */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl != NULL) { ret = false; torture_fail_goto(tctx, done, "DACL has been created on the server!\n"); } io.in.create_disposition = NTCREATEX_DISP_OPEN; torture_comment(tctx, "try open for read control\n"); io.in.desired_access = SEC_STD_READ_CONTROL; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_STD_READ_CONTROL); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for write\n"); io.in.desired_access = SEC_FILE_WRITE_DATA; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_FILE_WRITE_DATA); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for read\n"); io.in.desired_access = SEC_FILE_READ_DATA; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_FILE_READ_DATA); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for generic write\n"); io.in.desired_access = SEC_GENERIC_WRITE; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_RIGHTS_FILE_WRITE); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for generic read\n"); io.in.desired_access = SEC_GENERIC_READ; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_RIGHTS_FILE_READ); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "set DACL with 0 aces\n"); ZERO_STRUCT(dacl); dacl.revision = SECURITY_ACL_REVISION_NT4; dacl.num_aces = 0; sd->dacl = &dacl; s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; s.set_secdesc.in.file.handle = handle; s.set_secdesc.in.secinfo_flags = SECINFO_DACL; s.set_secdesc.in.sd = sd; status = smb2_setinfo_file(tree, &s); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "get the sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* Testing the modified DACL */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl == NULL) { ret = false; torture_fail_goto(tctx, done, "no DACL has been created on the server!\n"); } if (q.query_secdesc.out.sd->dacl->num_aces != 0) { torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n", q.query_secdesc.out.sd->dacl->num_aces); ret = false; goto done; } torture_comment(tctx, "try open for read control\n"); io.in.desired_access = SEC_STD_READ_CONTROL; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_STD_READ_CONTROL); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for write => access_denied\n"); io.in.desired_access = SEC_FILE_WRITE_DATA; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "try open for read => access_denied\n"); io.in.desired_access = SEC_FILE_READ_DATA; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "try open for generic write => access_denied\n"); io.in.desired_access = SEC_GENERIC_WRITE; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "try open for generic read => access_denied\n"); io.in.desired_access = SEC_GENERIC_READ; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "set empty sd\n"); sd->type &= ~SEC_DESC_DACL_PRESENT; sd->dacl = NULL; s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; s.set_secdesc.in.file.handle = handle; s.set_secdesc.in.secinfo_flags = SECINFO_DACL; s.set_secdesc.in.sd = sd; status = smb2_setinfo_file(tree, &s); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "get the sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* Testing the modified DACL */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl != NULL) { ret = false; torture_fail_goto(tctx, done, "DACL has been created on the server!\n"); } done: smb2_util_close(tree, handle); smb2_util_unlink(tree, fname); smb2_tdis(tree); smb2_logoff(tree->session); return ret; }
/* load the current ACL from system.nfs4acl */ static NTSTATUS pvfs_acl_load_nfs4(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd, TALLOC_CTX *mem_ctx, struct security_descriptor **psd) { NTSTATUS status; struct nfs4acl *acl; struct security_descriptor *sd; int i, num_ids; struct id_map *ids; acl = talloc_zero(mem_ctx, struct nfs4acl); NT_STATUS_HAVE_NO_MEMORY(acl); status = pvfs_xattr_ndr_load(pvfs, mem_ctx, name->full_name, fd, NFS4ACL_XATTR_NAME, acl, (void *) ndr_pull_nfs4acl); if (!NT_STATUS_IS_OK(status)) { talloc_free(acl); return status; } *psd = security_descriptor_initialise(mem_ctx); NT_STATUS_HAVE_NO_MEMORY(*psd); sd = *psd; sd->type |= acl->a_flags; /* the number of ids to map is the acl count plus uid and gid */ num_ids = acl->a_count +2; ids = talloc_array(sd, struct id_map, num_ids); NT_STATUS_HAVE_NO_MEMORY(ids); ids[0].xid.id = name->st.st_uid; ids[0].xid.type = ID_TYPE_UID; ids[0].sid = NULL; ids[0].status = ID_UNKNOWN; ids[1].xid.id = name->st.st_gid; ids[1].xid.type = ID_TYPE_GID; ids[1].sid = NULL; ids[1].status = ID_UNKNOWN; for (i=0;i<acl->a_count;i++) { struct nfs4ace *a = &acl->ace[i]; ids[i+2].xid.id = a->e_id; if (a->e_flags & ACE4_IDENTIFIER_GROUP) { ids[i+2].xid.type = ID_TYPE_GID; } else { ids[i+2].xid.type = ID_TYPE_UID; } ids[i+2].sid = NULL; ids[i+2].status = ID_UNKNOWN; } /* Allocate memory for the sids from the security descriptor to be on * the safe side. */ status = wbc_xids_to_sids(ids, num_ids); NT_STATUS_NOT_OK_RETURN(status); sd->owner_sid = talloc_steal(sd, ids[0].sid); sd->group_sid = talloc_steal(sd, ids[1].sid); for (i=0;i<acl->a_count;i++) { struct nfs4ace *a = &acl->ace[i]; struct security_ace ace; ace.type = a->e_type; ace.flags = a->e_flags; ace.access_mask = a->e_mask; ace.trustee = *ids[i+2].sid; security_descriptor_dacl_add(sd, &ace); } return NT_STATUS_OK; }
/* test setfileacl */ static bool test_appendacl(struct smbcli_state *cli, struct torture_context *tctx) { struct smb_composite_appendacl **io; struct smb_composite_appendacl **io_orig; struct composite_context **c; struct tevent_context *event_ctx; struct security_descriptor *test_sd; struct security_ace *ace; struct dom_sid *test_sid; const int num_ops = 50; int *count = talloc_zero(tctx, int); struct smb_composite_savefile io1; NTSTATUS status; int i; io_orig = talloc_array(tctx, struct smb_composite_appendacl *, num_ops); printf ("creating %d empty files and getting their acls with appendacl\n", num_ops); for (i = 0; i < num_ops; i++) { io1.in.fname = talloc_asprintf(io_orig, BASEDIR "\\test%d.txt", i); io1.in.data = NULL; io1.in.size = 0; status = smb_composite_savefile(cli->tree, &io1); if (!NT_STATUS_IS_OK(status)) { printf("(%s) savefile failed: %s\n", __location__, nt_errstr(status)); return false; } io_orig[i] = talloc (io_orig, struct smb_composite_appendacl); io_orig[i]->in.fname = talloc_steal(io_orig[i], io1.in.fname); io_orig[i]->in.sd = security_descriptor_initialise(io_orig[i]); status = smb_composite_appendacl(cli->tree, io_orig[i], io_orig[i]); if (!NT_STATUS_IS_OK(status)) { printf("(%s) appendacl failed: %s\n", __location__, nt_errstr(status)); return false; } } /* fill Security Descriptor with aces to be added */ test_sd = security_descriptor_initialise(tctx); test_sid = dom_sid_parse_talloc (tctx, "S-1-5-32-1234-5432"); ace = talloc_zero(tctx, struct security_ace); ace->type = SEC_ACE_TYPE_ACCESS_ALLOWED; ace->flags = 0; ace->access_mask = SEC_STD_ALL; ace->trustee = *test_sid; status = security_descriptor_dacl_add(test_sd, ace); if (!NT_STATUS_IS_OK(status)) { printf("(%s) appendacl failed: %s\n", __location__, nt_errstr(status)); return false; } /* set parameters for appendacl async call */ printf("testing parallel appendacl with %d ops\n", num_ops); c = talloc_array(tctx, struct composite_context *, num_ops); io = talloc_array(tctx, struct smb_composite_appendacl *, num_ops); for (i=0; i < num_ops; i++) { io[i] = talloc (io, struct smb_composite_appendacl); io[i]->in.sd = test_sd; io[i]->in.fname = talloc_asprintf(io[i], BASEDIR "\\test%d.txt", i); c[i] = smb_composite_appendacl_send(cli->tree, io[i]); c[i]->async.fn = loadfile_complete; c[i]->async.private_data = count; } event_ctx = tctx->ev; printf("waiting for completion\n"); while (*count != num_ops) { event_loop_once(event_ctx); if (torture_setting_bool(tctx, "progress", true)) { printf("(%s) count=%d\r", __location__, *count); fflush(stdout); } } printf("count=%d\n", *count); for (i=0; i < num_ops; i++) { status = smb_composite_appendacl_recv(c[i], io[i]); if (!NT_STATUS_IS_OK(status)) { printf("(%s) appendacl[%d] failed - %s\n", __location__, i, nt_errstr(status)); return false; } security_descriptor_dacl_add(io_orig[i]->out.sd, ace); if (!security_acl_equal(io_orig[i]->out.sd->dacl, io[i]->out.sd->dacl)) { printf("(%s) appendacl[%d] failed - needed acl isn't set\n", __location__, i); return false; } } talloc_free (ace); talloc_free (test_sid); talloc_free (test_sd); return true; }