static int set_reparse_index(ntfs_inode *ni, ntfs_index_context *xr, le32 reparse_tag) { struct REPARSE_INDEX indx; u64 file_id_cpu; le64 file_id; le16 seqn; seqn = ni->mrec->sequence_number; file_id_cpu = MK_MREF(ni->mft_no,le16_to_cpu(seqn)); file_id = cpu_to_le64(file_id_cpu); indx.header.data_offset = const_cpu_to_le16( sizeof(INDEX_ENTRY_HEADER) + sizeof(REPARSE_INDEX_KEY)); indx.header.data_length = const_cpu_to_le16(0); indx.header.reservedV = const_cpu_to_le32(0); indx.header.length = const_cpu_to_le16( sizeof(struct REPARSE_INDEX)); indx.header.key_length = const_cpu_to_le16( sizeof(REPARSE_INDEX_KEY)); indx.header.flags = const_cpu_to_le16(0); indx.header.reserved = const_cpu_to_le16(0); indx.key.reparse_tag = reparse_tag; /* danger on processors which require proper alignment ! */ memcpy(&indx.key.file_id, &file_id, 8); indx.filling = const_cpu_to_le32(0); ntfs_index_ctx_reinit(xr); return (ntfs_ie_add(xr,(INDEX_ENTRY*)&indx)); }
static int set_object_id_index(ntfs_inode *ni, ntfs_index_context *xo, const OBJECT_ID_ATTR *object_id) { struct OBJECT_ID_INDEX indx; u64 file_id_cpu; le64 file_id; le16 seqn; seqn = ni->mrec->sequence_number; file_id_cpu = MK_MREF(ni->mft_no,le16_to_cpu(seqn)); file_id = cpu_to_le64(file_id_cpu); indx.header.data_offset = const_cpu_to_le16( sizeof(INDEX_ENTRY_HEADER) + sizeof(OBJECT_ID_INDEX_KEY)); indx.header.data_length = const_cpu_to_le16( sizeof(OBJECT_ID_INDEX_DATA)); indx.header.reservedV = const_cpu_to_le32(0); indx.header.length = const_cpu_to_le16( sizeof(struct OBJECT_ID_INDEX)); indx.header.key_length = const_cpu_to_le16( sizeof(OBJECT_ID_INDEX_KEY)); indx.header.flags = const_cpu_to_le16(0); indx.header.reserved = const_cpu_to_le16(0); memcpy(&indx.key.object_id,object_id,sizeof(GUID)); indx.data.file_id = file_id; memcpy(&indx.data.birth_volume_id, &object_id->birth_volume_id,sizeof(GUID)); memcpy(&indx.data.birth_object_id, &object_id->birth_object_id,sizeof(GUID)); memcpy(&indx.data.domain_id, &object_id->domain_id,sizeof(GUID)); ntfs_index_ctx_reinit(xo); return (ntfs_ie_add(xo,(INDEX_ENTRY*)&indx)); }
int ntfs_fuse_listxattr_common(ntfs_inode *ni, ntfs_attr_search_ctx *actx, char *list, size_t size, BOOL prefixing) { int ret = 0; char *to = list; #ifdef XATTR_MAPPINGS BOOL accepted; const struct XATTRMAPPING *item; #endif /* XATTR_MAPPINGS */ /* first list the regular user attributes (ADS) */ while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE, 0, NULL, 0, actx)) { char *tmp_name = NULL; int tmp_name_len; if (!actx->attr->name_length) continue; tmp_name_len = ntfs_ucstombs( (ntfschar *)((u8*)actx->attr + le16_to_cpu(actx->attr->name_offset)), actx->attr->name_length, &tmp_name, 0); if (tmp_name_len < 0) { ret = -errno; goto exit; } /* * When using name spaces, do not return * security, trusted or system attributes * (filtered elsewhere anyway) * otherwise insert "user." prefix */ if (prefixing) { if ((strlen(tmp_name) > sizeof(xattr_ntfs_3g)) && !strncmp(tmp_name,xattr_ntfs_3g, sizeof(xattr_ntfs_3g)-1)) tmp_name_len = 0; else ret += tmp_name_len + nf_ns_user_prefix_len + 1; } else ret += tmp_name_len + 1; if (size && tmp_name_len) { if ((size_t)ret <= size) { if (prefixing) { strcpy(to, nf_ns_user_prefix); to += nf_ns_user_prefix_len; } strncpy(to, tmp_name, tmp_name_len); to += tmp_name_len; *to = 0; to++; } else { free(tmp_name); ret = -ERANGE; goto exit; } } free(tmp_name); } #ifdef XATTR_MAPPINGS /* now append the system attributes mapped to user space */ for (item=ni->vol->xattr_mapping; item; item=item->next) { switch (item->xattr) { case XATTR_NTFS_EFSINFO : accepted = ni->vol->efs_raw && (ni->flags & FILE_ATTR_ENCRYPTED); break; case XATTR_NTFS_REPARSE_DATA : accepted = (ni->flags & FILE_ATTR_REPARSE_POINT) != const_cpu_to_le32(0); break; // TODO : we are supposed to only return xattrs which are set // this is more complex for OBJECT_ID and DOS_NAME default : accepted = TRUE; break; } if (accepted) { ret += strlen(item->name) + 1; if (size) { if ((size_t)ret <= size) { strcpy(to, item->name); to += strlen(item->name); *to++ = 0; } else { ret = -ERANGE; goto exit; } } #else /* XATTR_MAPPINGS */ /* List efs info xattr for encrypted files */ if (ni->vol->efs_raw && (ni->flags & FILE_ATTR_ENCRYPTED)) { ret += sizeof(nf_ns_alt_xattr_efsinfo); if ((size_t)ret <= size) { memcpy(to, nf_ns_alt_xattr_efsinfo, sizeof(nf_ns_alt_xattr_efsinfo)); to += sizeof(nf_ns_alt_xattr_efsinfo); #endif /* XATTR_MAPPINGS */ } } exit : return (ret); }
/** * init_secure_sds - * * NTFS 3.1 - System files security decriptors * =========================================== * Create the security descriptor entries in $SDS data stream like they * are in a partition, newly formatted with windows 2003 */ void init_secure_sds(char *sd_val) { SECURITY_DESCRIPTOR_HEADER *sds; SECURITY_DESCRIPTOR_RELATIVE *sd; ACL *acl; ACCESS_ALLOWED_ACE *ace; SID *sid; /* * security descriptor #1 */ //header sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val); sds->hash = const_cpu_to_le32(0xF80312F0); sds->security_id = const_cpu_to_le32(0x0100); sds->offset = const_cpu_to_le64(0x00); sds->length = const_cpu_to_le32(0x7C); //security descriptor relative sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds + sizeof(SECURITY_DESCRIPTOR_HEADER)); sd->revision = 0x01; sd->alignment = 0x00; sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT; sd->owner = const_cpu_to_le32(0x48); sd->group = const_cpu_to_le32(0x58); sd->sacl = const_cpu_to_le32(0x00); sd->dacl = const_cpu_to_le32(0x14); //acl acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); acl->revision = 0x02; acl->alignment1 = 0x00; acl->size = const_cpu_to_le16(0x34); acl->ace_count = const_cpu_to_le16(0x02); acl->alignment2 = 0x00; //ace1 ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL)); ace->type = 0x00; ace->flags = 0x00; ace->size = const_cpu_to_le16(0x14); ace->mask = const_cpu_to_le32(0x120089); ace->sid.revision = 0x01; ace->sid.sub_authority_count = 0x01; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); //ace2 ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size)); ace->type = 0x00; ace->flags = 0x00; ace->size = const_cpu_to_le16(0x18); ace->mask = const_cpu_to_le32(0x120089); ace->sid.revision = 0x01; ace->sid.sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); //owner sid sid = (SID*)((char*)sd + le32_to_cpu(sd->owner)); sid->revision = 0x01; sid->sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); //group sid sid = (SID*)((char*)sd + le32_to_cpu(sd->group)); sid->revision = 0x01; sid->sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); /* * security descriptor #2 */ //header sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val + 0x80); sds->hash = const_cpu_to_le32(0xB32451); sds->security_id = const_cpu_to_le32(0x0101); sds->offset = const_cpu_to_le64(0x80); sds->length = const_cpu_to_le32(0x7C); //security descriptor relative sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds + sizeof(SECURITY_DESCRIPTOR_HEADER)); sd->revision = 0x01; sd->alignment = 0x00; sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT; sd->owner = const_cpu_to_le32(0x48); sd->group = const_cpu_to_le32(0x58); sd->sacl = const_cpu_to_le32(0x00); sd->dacl = const_cpu_to_le32(0x14); //acl acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); acl->revision = 0x02; acl->alignment1 = 0x00; acl->size = const_cpu_to_le16(0x34); acl->ace_count = const_cpu_to_le16(0x02); acl->alignment2 = 0x00; //ace1 ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL)); ace->type = 0x00; ace->flags = 0x00; ace->size = const_cpu_to_le16(0x14); ace->mask = const_cpu_to_le32(0x12019F); ace->sid.revision = 0x01; ace->sid.sub_authority_count = 0x01; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); //ace2 ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size)); ace->type = 0x00; ace->flags = 0x00; ace->size = const_cpu_to_le16(0x18); ace->mask = const_cpu_to_le32(0x12019F); ace->sid.revision = 0x01; ace->sid.sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); //owner sid sid = (SID*)((char*)sd + le32_to_cpu(sd->owner)); sid->revision = 0x01; sid->sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); //group sid sid = (SID*)((char*)sd + le32_to_cpu(sd->group)); sid->revision = 0x01; sid->sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); return; }
/** * init_system_file_sd - * * NTFS 3.1 - System files security decriptors * ===================================================== * * Create the security descriptor for system file number @sys_file_no and * return a pointer to the descriptor. * * Note the root directory system file (".") is very different and handled by a * different function. * * The sd is returned in *@sd_val and has length *@sd_val_len. * * Do NOT free *@sd_val as it is static memory. This also means that you can * only use *@sd_val until the next call to this function. */ void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len) { static u8 sd_array[0x68]; SECURITY_DESCRIPTOR_RELATIVE *sd; ACL *acl; ACCESS_ALLOWED_ACE *aa_ace; SID *sid; le32 *sub_authorities; if (sys_file_no < 0) { *sd_val = NULL; *sd_val_len = 0; return; } *sd_val = sd_array; sd = (SECURITY_DESCRIPTOR_RELATIVE*)&sd_array; sd->revision = 1; sd->alignment = 0; sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT; *sd_val_len = 0x64; sd->owner = const_cpu_to_le32(0x48); sd->group = const_cpu_to_le32(0x54); sd->sacl = const_cpu_to_le32(0); sd->dacl = const_cpu_to_le32(0x14); /* * Now at offset 0x14, as specified in the security descriptor, we have * the DACL. */ acl = (ACL*)((char*)sd + le32_to_cpu(sd->dacl)); acl->revision = 2; acl->alignment1 = 0; acl->size = const_cpu_to_le16(0x34); acl->ace_count = const_cpu_to_le16(2); acl->alignment2 = const_cpu_to_le16(0); /* * Now at offset 0x1c, just after the DACL's ACL, we have the first * ACE of the DACL. The type of the ACE is access allowed. */ aa_ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL)); aa_ace->type = ACCESS_ALLOWED_ACE_TYPE; aa_ace->flags = 0; aa_ace->size = const_cpu_to_le16(0x14); switch (sys_file_no) { case FILE_AttrDef: case FILE_Boot: aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA; break; default: aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_WRITE | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA | FILE_READ_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA; break; } aa_ace->sid.revision = 1; aa_ace->sid.sub_authority_count = 1; aa_ace->sid.identifier_authority.value[0] = 0; aa_ace->sid.identifier_authority.value[1] = 0; aa_ace->sid.identifier_authority.value[2] = 0; aa_ace->sid.identifier_authority.value[3] = 0; aa_ace->sid.identifier_authority.value[4] = 0; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ aa_ace->sid.identifier_authority.value[5] = 5; aa_ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); /* * Now at offset 0x30 within security descriptor, just after the first * ACE of the DACL. All system files, except the root directory, have * a second ACE. */ /* The second ACE of the DACL. Type is access allowed. */ aa_ace = (ACCESS_ALLOWED_ACE*)((char*)aa_ace + le16_to_cpu(aa_ace->size)); aa_ace->type = ACCESS_ALLOWED_ACE_TYPE; aa_ace->flags = 0; aa_ace->size = const_cpu_to_le16(0x18); /* Only $AttrDef and $Boot behave differently to everything else. */ switch (sys_file_no) { case FILE_AttrDef: case FILE_Boot: aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA; break; default: aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA | FILE_READ_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA; break; } aa_ace->sid.revision = 1; aa_ace->sid.sub_authority_count = 2; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ aa_ace->sid.identifier_authority.value[0] = 0; aa_ace->sid.identifier_authority.value[1] = 0; aa_ace->sid.identifier_authority.value[2] = 0; aa_ace->sid.identifier_authority.value[3] = 0; aa_ace->sid.identifier_authority.value[4] = 0; aa_ace->sid.identifier_authority.value[5] = 5; sub_authorities = aa_ace->sid.sub_authority; *sub_authorities++ = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); *sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); /* * Now at offset 0x48 into the security descriptor, as specified in the * security descriptor, we now have the owner SID. */ sid = (SID*)((char*)sd + le32_to_cpu(sd->owner)); sid->revision = 1; sid->sub_authority_count = 1; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); /* * Now at offset 0x54 into the security descriptor, as specified in the * security descriptor, we have the group SID. */ sid = (SID*)((char*)sd + le32_to_cpu(sd->group)); sid->revision = 1; sid->sub_authority_count = 2; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sub_authorities = sid->sub_authority; *sub_authorities++ = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); *sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); }
/** * init_root_sd - * * Creates the security_descriptor for the root folder on ntfs 3.1 as created * by Windows Vista (when the format is done from the disk management MMC * snap-in, note this is different from the format done from the disk * properties in Windows Explorer). */ void init_root_sd(u8 **sd_val, int *sd_val_len) { SECURITY_DESCRIPTOR_RELATIVE *sd; ACL *acl; ACCESS_ALLOWED_ACE *ace; SID *sid; le32 *sub_authorities; static char sd_array[0x102c]; *sd_val_len = 0x102c; *sd_val = (u8*)&sd_array; //security descriptor relative sd = (SECURITY_DESCRIPTOR_RELATIVE*)sd_array; sd->revision = SECURITY_DESCRIPTOR_REVISION; sd->alignment = 0; sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT; sd->owner = const_cpu_to_le32(0x1014); sd->group = const_cpu_to_le32(0x1020); sd->sacl = 0; sd->dacl = const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)); //acl acl = (ACL*)((u8*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); acl->revision = ACL_REVISION; acl->alignment1 = 0; acl->size = const_cpu_to_le16(0x1000); acl->ace_count = const_cpu_to_le16(0x08); acl->alignment2 = 0; //ace1 ace = (ACCESS_ALLOWED_ACE*)((u8*)acl + sizeof(ACL)); ace->type = ACCESS_ALLOWED_ACE_TYPE; ace->flags = 0; ace->size = const_cpu_to_le16(0x18); ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_WRITE_DATA | FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA | FILE_TRAVERSE | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES; ace->sid.revision = SID_REVISION; ace->sid.sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; sub_authorities = ace->sid.sub_authority; *sub_authorities++ = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); *sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); //ace2 ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); ace->type = ACCESS_ALLOWED_ACE_TYPE; ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; ace->size = const_cpu_to_le16(0x18); ace->mask = GENERIC_ALL; ace->sid.revision = SID_REVISION; ace->sid.sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; sub_authorities = ace->sid.sub_authority; *sub_authorities++ = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); *sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); //ace3 ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); ace->type = ACCESS_ALLOWED_ACE_TYPE; ace->flags = 0; ace->size = const_cpu_to_le16(0x14); ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_WRITE_DATA | FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA | FILE_TRAVERSE | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES; ace->sid.revision = SID_REVISION; ace->sid.sub_authority_count = 0x01; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); //ace4 ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); ace->type = ACCESS_ALLOWED_ACE_TYPE; ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; ace->size = const_cpu_to_le16(0x14); ace->mask = GENERIC_ALL; ace->sid.revision = SID_REVISION; ace->sid.sub_authority_count = 0x01; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); //ace5 ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size)); ace->type = ACCESS_ALLOWED_ACE_TYPE; ace->flags = 0; ace->size = const_cpu_to_le16(0x14); ace->mask = SYNCHRONIZE | READ_CONTROL | DELETE | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | FILE_WRITE_EA | FILE_READ_EA | FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE | FILE_LIST_DIRECTORY; ace->sid.revision = SID_REVISION; ace->sid.sub_authority_count = 0x01; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_AUTHENTICATED_USER_RID); //ace6 ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); ace->type = ACCESS_ALLOWED_ACE_TYPE; ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; ace->size = const_cpu_to_le16(0x14); ace->mask = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE; ace->sid.revision = SID_REVISION; ace->sid.sub_authority_count = 0x01; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_AUTHENTICATED_USER_RID); //ace7 ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); ace->type = ACCESS_ALLOWED_ACE_TYPE; ace->flags = 0; ace->size = const_cpu_to_le16(0x18); ace->mask = SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | FILE_READ_EA | FILE_LIST_DIRECTORY; ace->sid.revision = SID_REVISION; ace->sid.sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; sub_authorities = ace->sid.sub_authority; *sub_authorities++ = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); *sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS); //ace8 ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); ace->type = ACCESS_ALLOWED_ACE_TYPE; ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; ace->size = const_cpu_to_le16(0x18); ace->mask = GENERIC_READ | GENERIC_EXECUTE; ace->sid.revision = SID_REVISION; ace->sid.sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; sub_authorities = ace->sid.sub_authority; *sub_authorities++ = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); *sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS); //owner sid sid = (SID*)((char*)sd + le32_to_cpu(sd->owner)); sid->revision = 0x01; sid->sub_authority_count = 0x01; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); //group sid sid = (SID*)((char*)sd + le32_to_cpu(sd->group)); sid->revision = 0x01; sid->sub_authority_count = 0x01; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); }
/** * enum NTFS_CRYPTO_ALGORITHMS - List of crypto algorithms used by EFS (32 bit) * * To choose which one is used in Windows, create or set the REG_DWORD registry * key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\EFS\ * AlgorithmID to the value of your chosen crypto algorithm, e.g. to use DesX, * set AlgorithmID to 0x6604. * * Note that the Windows versions I have tried so far (all are high crypto * enabled) ignore the AlgorithmID value if it is not one of CALG_3DES, * CALG_DESX, or CALG_AES_256, i.e. you cannot select CALG_DES at all using * this registry key. It would be interesting to check out encryption on one * of the "crippled" crypto Windows versions... */ typedef enum { CALG_DES = const_cpu_to_le32(0x6601), /* If not one of the below three, fall back to standard Des. */ CALG_3DES = const_cpu_to_le32(0x6603), CALG_DESX = const_cpu_to_le32(0x6604), CALG_AES_256 = const_cpu_to_le32(0x6610), } NTFS_CRYPTO_ALGORITHMS; typedef struct { u64 in_whitening, out_whitening; u8 des_key[8]; } ntfs_desx_ctx; /** * struct ntfs_fek - Decrypted, in-memory file encryption key. */
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include "types.h" #include "layout.h" #include "attrib.h" #include "security.h" #include "misc.h" #include "bitmap.h" /* * The zero GUID. */ static const GUID __zero_guid = { const_cpu_to_le32(0), const_cpu_to_le16(0), const_cpu_to_le16(0), { 0, 0, 0, 0, 0, 0, 0, 0 } }; const GUID *const zero_guid = &__zero_guid; /** * ntfs_guid_is_zero - check if a GUID is zero * @guid: [IN] guid to check * * Return TRUE if @guid is a valid pointer to a GUID and it is the zero GUID * and FALSE otherwise. */ BOOL ntfs_guid_is_zero(const GUID *guid) { return (memcmp(guid, zero_guid, sizeof(*zero_guid))); }
/** * ntfs_inode_open - open an inode ready for access * @vol: volume to get the inode from * @mref: inode number / mft record number to open * * Allocate an ntfs_inode structure and initialize it for the given inode * specified by @mref. @mref specifies the inode number / mft record to read, * including the sequence number, which can be 0 if no sequence number checking * is to be performed. * * Then, allocate a buffer for the mft record, read the mft record from the * volume @vol, and attach it to the ntfs_inode structure (->mrec). The * mft record is mst deprotected and sanity checked for validity and we abort * if deprotection or checks fail. * * Finally, search for an attribute list attribute in the mft record and if one * is found, load the attribute list attribute value and attach it to the * ntfs_inode structure (->attr_list). Also set the NI_AttrList bit to indicate * this. * * Return a pointer to the ntfs_inode structure on success or NULL on error, * with errno set to the error code. */ static ntfs_inode *ntfs_inode_real_open(ntfs_volume *vol, const MFT_REF mref) { s64 l; ntfs_inode *ni = NULL; ntfs_attr_search_ctx *ctx; STANDARD_INFORMATION *std_info; le32 lthle; int olderrno; ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref)); if (!vol) { errno = EINVAL; goto out; } ni = __ntfs_inode_allocate(vol); if (!ni) goto out; if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL)) goto err_out; if (!(ni->mrec->flags & MFT_RECORD_IN_USE)) { errno = ENOENT; goto err_out; } ni->mft_no = MREF(mref); ctx = ntfs_attr_get_search_ctx(ni, NULL); if (!ctx) goto err_out; /* Receive some basic information about inode. */ if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { if (!ni->mrec->base_mft_record) ntfs_log_perror("No STANDARD_INFORMATION in base record" " %lld", (long long)MREF(mref)); goto put_err_out; } std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + le16_to_cpu(ctx->attr->value_offset)); ni->flags = std_info->file_attributes; ni->creation_time = std_info->creation_time; ni->last_data_change_time = std_info->last_data_change_time; ni->last_mft_change_time = std_info->last_mft_change_time; ni->last_access_time = std_info->last_access_time; /* JPA insert v3 extensions if present */ /* length may be seen as 72 (v1.x) or 96 (v3.x) */ lthle = ctx->attr->length; if (le32_to_cpu(lthle) > sizeof(STANDARD_INFORMATION)) { set_nino_flag(ni, v3_Extensions); ni->owner_id = std_info->owner_id; ni->security_id = std_info->security_id; ni->quota_charged = std_info->quota_charged; ni->usn = std_info->usn; } else { clear_nino_flag(ni, v3_Extensions); ni->owner_id = const_cpu_to_le32(0); ni->security_id = const_cpu_to_le32(0); } /* Set attribute list information. */ olderrno = errno; if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { if (errno != ENOENT) goto put_err_out; /* Attribute list attribute does not present. */ /* restore previous errno to avoid misinterpretation */ errno = olderrno; goto get_size; } NInoSetAttrList(ni); l = ntfs_get_attribute_value_length(ctx->attr); if (!l) goto put_err_out; if (l > 0x40000) { errno = EIO; ntfs_log_perror("Too large attrlist attribute (%lld), inode " "%lld", (long long)l, (long long)MREF(mref)); goto put_err_out; } ni->attr_list_size = l; ni->attr_list = ntfs_malloc(ni->attr_list_size); if (!ni->attr_list) goto put_err_out; l = ntfs_get_attribute_value(vol, ctx->attr, ni->attr_list); if (!l) goto put_err_out; if (l != ni->attr_list_size) { errno = EIO; ntfs_log_perror("Unexpected attrlist size (%lld <> %u), inode " "%lld", (long long)l, ni->attr_list_size, (long long)MREF(mref)); goto put_err_out; } get_size: olderrno = errno; if (ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { if (errno != ENOENT) goto put_err_out; /* Directory or special file. */ /* restore previous errno to avoid misinterpretation */ errno = olderrno; ni->data_size = ni->allocated_size = 0; } else { if (ctx->attr->non_resident) { ni->data_size = sle64_to_cpu(ctx->attr->data_size); if (ctx->attr->flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ni->allocated_size = sle64_to_cpu( ctx->attr->compressed_size); else ni->allocated_size = sle64_to_cpu( ctx->attr->allocated_size); } else { ni->data_size = le32_to_cpu(ctx->attr->value_length); ni->allocated_size = (ni->data_size + 7) & ~7; } set_nino_flag(ni,KnownSize); } ntfs_attr_put_search_ctx(ctx); out: ntfs_log_leave("\n"); return ni; put_err_out: ntfs_attr_put_search_ctx(ctx); err_out: __ntfs_inode_release(ni); ni = NULL; goto out; }
char *ntfs_make_symlink(ntfs_inode *ni, const char *mnt_point, int *pattr_size) { s64 attr_size = 0; char *target; unsigned int offs; unsigned int lth; ntfs_volume *vol; REPARSE_POINT *reparse_attr; struct MOUNT_POINT_REPARSE_DATA *mount_point_data; struct SYMLINK_REPARSE_DATA *symlink_data; enum { FULL_TARGET, ABS_TARGET, REL_TARGET } kind; ntfschar *p; BOOL bad; BOOL isdir; target = (char*)NULL; bad = TRUE; isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); vol = ni->vol; reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni, AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size); if (reparse_attr && attr_size && valid_reparse_data(ni, reparse_attr, attr_size)) { switch (reparse_attr->reparse_tag) { case IO_REPARSE_TAG_MOUNT_POINT : mount_point_data = (struct MOUNT_POINT_REPARSE_DATA*) reparse_attr->reparse_data; offs = le16_to_cpu(mount_point_data->subst_name_offset); lth = le16_to_cpu(mount_point_data->subst_name_length); /* reparse data consistency has been checked */ target = ntfs_get_fulllink(vol, (ntfschar*)&mount_point_data->path_buffer[offs], lth/2, mnt_point, isdir); if (target) bad = FALSE; break; case IO_REPARSE_TAG_SYMLINK : symlink_data = (struct SYMLINK_REPARSE_DATA*) reparse_attr->reparse_data; offs = le16_to_cpu(symlink_data->subst_name_offset); lth = le16_to_cpu(symlink_data->subst_name_length); p = (ntfschar*)&symlink_data->path_buffer[offs]; /* * Predetermine the kind of target, * the called function has to make a full check */ if (*p++ == const_cpu_to_le16('\\')) { if ((*p == const_cpu_to_le16('?')) || (*p == const_cpu_to_le16('\\'))) kind = FULL_TARGET; else kind = ABS_TARGET; } else if (*p == const_cpu_to_le16(':')) kind = ABS_TARGET; else kind = REL_TARGET; p--; /* reparse data consistency has been checked */ switch (kind) { case FULL_TARGET : if (!(symlink_data->flags & const_cpu_to_le32(1))) { target = ntfs_get_fulllink(vol, p, lth/2, mnt_point, isdir); if (target) bad = FALSE; } break; case ABS_TARGET : if (symlink_data->flags & const_cpu_to_le32(1)) { target = ntfs_get_abslink(vol, p, lth/2, mnt_point, isdir); if (target) bad = FALSE; } break; case REL_TARGET : if (symlink_data->flags & const_cpu_to_le32(1)) { target = ntfs_get_rellink(ni, p, lth/2); if (target) bad = FALSE; } break; } break; } free(reparse_attr); } *pattr_size = attr_size; if (bad) errno = EOPNOTSUPP; return (target); }