mirror of https://github.com/Cisco-Talos/clamav
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
537 lines
12 KiB
537 lines
12 KiB
/*
|
|
* Copyright (C) 2023-2025 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
|
|
*
|
|
* Authors: Cisco
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifndef _UDF_H_
|
|
#define _UDF_H_
|
|
|
|
#include "others.h"
|
|
|
|
#define UDF_EMPTY_LEN 32768
|
|
|
|
// All Volume Descriptors are the same size.
|
|
#define VOLUME_DESCRIPTOR_SIZE 0x800
|
|
|
|
#ifndef HAVE_ATTRIB_PACKED
|
|
#define __attribute__(x)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK_HPPA
|
|
#pragma pack 1
|
|
#endif
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
uint16_t typeTimeZone; /*
|
|
0 Coordinated UTC
|
|
1 Local Time
|
|
2 Up to agreement between originator and recipient
|
|
3 - 15 Reserved
|
|
*/
|
|
uint16_t year;
|
|
uint8_t month;
|
|
uint8_t day;
|
|
uint8_t hour;
|
|
uint8_t minute;
|
|
uint8_t second;
|
|
uint8_t centiseconds;
|
|
uint8_t hundredsMicroSeconds;
|
|
uint8_t microseconds;
|
|
} timestamp;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
|
|
uint32_t blockNumber;
|
|
|
|
uint16_t partitionReferenceNumber;
|
|
|
|
} lb_addr;
|
|
|
|
// Long allocation descriptor
|
|
typedef struct __attribute__((packed)) {
|
|
uint32_t length; // 4/14.14.1.1
|
|
/*30 least significant bits are length in bytes.
|
|
*
|
|
* 2 most significant bits are described in figure 4/42
|
|
*
|
|
* 0 extent recorded and allocated
|
|
* 1 extent NOT recorded but allocated
|
|
* 2 extent NOT recorded and NOT allocated
|
|
* 3 the extent is the next extent of allocation descriptors.
|
|
* */
|
|
|
|
lb_addr extentLocation; // logical block number. (CAN be zero)
|
|
|
|
uint8_t implementationUse[6];
|
|
|
|
} long_ad;
|
|
|
|
/*
|
|
* https://www.ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf
|
|
* section 3/7.2 */
|
|
typedef struct __attribute__((packed)) {
|
|
uint16_t tagId;
|
|
uint16_t descriptorVersion;
|
|
uint8_t checksum;
|
|
uint8_t reserved;
|
|
uint16_t serialNumber;
|
|
uint16_t descriptorCRC;
|
|
uint16_t descriptorCRCLength;
|
|
uint32_t tagLocation;
|
|
} DescriptorTag;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
uint8_t flags;
|
|
/*
|
|
* 1/7.4
|
|
* characteristics
|
|
* bit 0 dirty: If regid has been modified and might not be valid, set to * 1. Otherwise, 0
|
|
* bit 1 protected: If 1, this regid cannot be modified
|
|
* bit 2-7 reserved
|
|
*/
|
|
uint8_t identifier[23];
|
|
/*
|
|
* If first byte is 0x2b, then this is covered by ECMA-168 (this spec)
|
|
* If first byte is 0x2d, then this is not registered
|
|
*/
|
|
uint8_t identifierSuffix[8];
|
|
} regid;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
DescriptorTag tag;
|
|
uint32_t volumeDescriptorSequenceNumber;
|
|
uint32_t primaryVolumeDescriptorNumber;
|
|
uint8_t volumeIdentifier[32];
|
|
uint16_t volumeSequenceNumber;
|
|
uint16_t interchangeLevel;
|
|
uint16_t maxInterchangeLevel;
|
|
uint32_t charSetList;
|
|
uint8_t volumeSetIdentifier[128];
|
|
uint8_t descriptorCharSet[64];
|
|
uint8_t explanatoryCharSet[64];
|
|
uint64_t volumeAbstract;
|
|
uint64_t volumeCopyrightNotice;
|
|
uint8_t applicationIdentifier[32];
|
|
uint8_t recordingDateTime[12];
|
|
uint8_t implementationIdentifier[32];
|
|
uint8_t implementationUse[64];
|
|
uint32_t predVolumeDescSequenceLocation;
|
|
uint16_t flags;
|
|
uint8_t reserved[22];
|
|
|
|
} PrimaryVolumeDescriptor;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
DescriptorTag tag;
|
|
uint32_t volumeDescriptorSequenceNumber;
|
|
|
|
regid implementationIdentifier;
|
|
uint8_t implementationUse[460];
|
|
|
|
} ImplementationUseVolumeDescriptor;
|
|
|
|
/* https://www.ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf */
|
|
/* 4/3 */
|
|
typedef struct __attribute__((packed)) {
|
|
uint32_t logicalBlockNumber;
|
|
|
|
uint16_t partitionReferenceNumber;
|
|
} LBAddr;
|
|
|
|
// https://www.ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf
|
|
// section 4/23
|
|
typedef struct __attribute__((packed)) {
|
|
uint32_t priorRecordedNumberOfDirectEntries;
|
|
uint16_t strategyType;
|
|
uint8_t strategyParameter[2]; /*described as 'bytes' in docs, so don't want to worry about byte order.*/
|
|
uint16_t maxEntries;
|
|
uint8_t reserved_must_be_zero;
|
|
|
|
uint8_t fileType;
|
|
|
|
LBAddr parentICBLocation;
|
|
|
|
uint16_t flags;
|
|
} ICBTag;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
|
|
DescriptorTag tag;
|
|
|
|
uint16_t versionNumber;
|
|
|
|
uint8_t characteristics;
|
|
|
|
uint8_t fileIdentifierLength;
|
|
|
|
long_ad icb;
|
|
|
|
/*L_IU specified in 1/7.1.3 */
|
|
uint16_t implementationLength;
|
|
|
|
uint8_t rest[1];
|
|
|
|
} FileIdentifierDescriptor;
|
|
|
|
#define FILE_IDENTIFIER_DESCRIPTOR_SIZE_KNOWN (sizeof(FileIdentifierDescriptor) - 1)
|
|
|
|
/*Section 14.4.9 of https:... */
|
|
static uint32_t getFileIdentifierDescriptorPaddingLength(const FileIdentifierDescriptor* const fid)
|
|
{
|
|
uint32_t ret = 0;
|
|
uint32_t tmp = le16_to_host(fid->implementationLength) + fid->fileIdentifierLength + 38;
|
|
ret = tmp + 3;
|
|
ret = ret / 4;
|
|
|
|
ret = ret * 4;
|
|
ret = ret - tmp;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline size_t getFileIdentifierDescriptorSize(const FileIdentifierDescriptor* fid)
|
|
{
|
|
return FILE_IDENTIFIER_DESCRIPTOR_SIZE_KNOWN + le16_to_host(fid->implementationLength) + fid->fileIdentifierLength + getFileIdentifierDescriptorPaddingLength(fid);
|
|
}
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
DescriptorTag tag;
|
|
|
|
ICBTag icbTag;
|
|
|
|
uint32_t uid;
|
|
|
|
uint32_t gid;
|
|
|
|
uint32_t permissions;
|
|
|
|
uint16_t fileLinkCnt;
|
|
|
|
uint8_t recordFormat;
|
|
uint8_t recordDisplayAttributes;
|
|
|
|
uint32_t recordLength;
|
|
|
|
uint64_t infoLength;
|
|
|
|
uint64_t logicalBlocksRecorded;
|
|
|
|
timestamp accessDateTime;
|
|
|
|
timestamp modificationDateTime;
|
|
|
|
timestamp attributeDateTime;
|
|
|
|
uint32_t checkpoint;
|
|
|
|
long_ad extendedAttrICB;
|
|
|
|
regid implementationId;
|
|
|
|
uint64_t uniqueId;
|
|
|
|
uint32_t extendedAttrLen;
|
|
|
|
uint32_t allocationDescLen;
|
|
|
|
/* Variable length stuff here, need to handle;
|
|
*/
|
|
uint8_t rest[1];
|
|
|
|
} FileEntryDescriptor;
|
|
|
|
#define FILE_ENTRY_DESCRIPTOR_SIZE_KNOWN (sizeof(FileEntryDescriptor) - 1)
|
|
static inline size_t getFileEntryDescriptorSize(const FileEntryDescriptor* fed)
|
|
{
|
|
return FILE_ENTRY_DESCRIPTOR_SIZE_KNOWN + le32_to_host(fed->extendedAttrLen) + le32_to_host(fed->allocationDescLen);
|
|
}
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
DescriptorTag tag;
|
|
|
|
ICBTag icbTag;
|
|
|
|
uint32_t uid;
|
|
|
|
uint32_t gid;
|
|
|
|
uint32_t permissions;
|
|
|
|
uint16_t fileLinkCnt;
|
|
|
|
uint8_t recordFormat;
|
|
|
|
uint8_t recordDisplayAttributes;
|
|
|
|
uint32_t recordLength;
|
|
|
|
uint64_t infoLength;
|
|
|
|
uint64_t objectSize; // different
|
|
|
|
uint64_t logicalBlocksRecorded;
|
|
|
|
timestamp accessDateTime;
|
|
|
|
timestamp modificationDateTime;
|
|
|
|
timestamp creationDateTime; // different
|
|
|
|
timestamp attributeDateTime;
|
|
|
|
uint32_t checkpoint;
|
|
|
|
uint32_t reserved; // different
|
|
|
|
long_ad extendedAttrICB;
|
|
|
|
long_ad streamDirectoryICB; // different
|
|
|
|
regid implementationId;
|
|
|
|
uint64_t uniqueId;
|
|
|
|
uint32_t extendedAttrLen;
|
|
|
|
uint32_t allocationDescLen;
|
|
|
|
/* Variable length stuff here, need to handle;
|
|
*/
|
|
|
|
} ExtendedFileEntryDescriptor;
|
|
|
|
// Short allocation descriptor
|
|
typedef struct __attribute__((packed)) {
|
|
|
|
uint32_t length;
|
|
|
|
uint32_t position;
|
|
|
|
} short_ad;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
uint32_t extentLen;
|
|
uint32_t recordedLen;
|
|
|
|
uint32_t infoLen;
|
|
|
|
lb_addr extentLocation;
|
|
|
|
uint8_t implementationUse[2];
|
|
} ext_ad;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
uint32_t extentLength;
|
|
|
|
uint32_t extentLocation;
|
|
|
|
} extent_ad;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
|
|
DescriptorTag tag;
|
|
|
|
uint32_t volumeDescriptorSequenceNumber;
|
|
|
|
uint16_t partitionFlags;
|
|
|
|
uint16_t partitionNumber;
|
|
|
|
regid partitionContents;
|
|
|
|
uint8_t partitionContentsUse[128];
|
|
|
|
uint32_t accessType;
|
|
|
|
uint32_t partitionStartingLocation;
|
|
|
|
uint32_t partitionLength;
|
|
|
|
regid implementationIdentifier;
|
|
|
|
uint8_t implementationUse[128];
|
|
|
|
uint8_t reserved[156];
|
|
|
|
} PartitionDescriptor;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
DescriptorTag tag;
|
|
|
|
uint32_t volumeDescriptorSequenceNumber;
|
|
|
|
uint32_t numAllocationDescriptors;
|
|
|
|
uint8_t rest[1]; /*reset is 'numAllocationDescriptors' * sizeof (extent_ad),
|
|
and padded out to VOLUME_DESCRIPTOR_SIZE with zeros. */
|
|
|
|
} UnallocatedSpaceDescriptor;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
DescriptorTag tag;
|
|
|
|
uint8_t padding[496];
|
|
} TerminatingDescriptor;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
DescriptorTag tag;
|
|
|
|
timestamp recordingDateTime;
|
|
|
|
uint32_t integrityType;
|
|
|
|
extent_ad nextIntegrityExtent;
|
|
|
|
uint8_t logicalVolumeContents[32];
|
|
|
|
uint32_t numPartitions;
|
|
|
|
uint32_t lenImplementationUse;
|
|
|
|
uint32_t freeSpaceTable;
|
|
|
|
uint32_t sizeTable;
|
|
|
|
uint8_t rest[1];
|
|
|
|
} LogicalVolumeIntegrityDescriptor;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
DescriptorTag tag;
|
|
|
|
extent_ad mainVolumeDescriptorSequence;
|
|
|
|
extent_ad reserveVolumeDescriptorSequence;
|
|
|
|
uint8_t reserved[480];
|
|
|
|
} AnchorVolumeDescriptorPointer;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
DescriptorTag tag;
|
|
|
|
uint32_t volumeDescriptorSequenceNumber;
|
|
|
|
extent_ad nextVolumeDescriptorSequence;
|
|
|
|
uint8_t reserved[484];
|
|
|
|
} VolumeDescriptorPointer;
|
|
|
|
/*
|
|
* charsetType can be
|
|
0 The CS0 coded character set (1/7.2.2).
|
|
1 The CS1 coded character set (1/7.2.3).
|
|
2 The CS2 coded character set (1/7.2.4).
|
|
3 The CS3 coded character set (1/7.2.5).
|
|
4 The CS4 coded character set (1/7.2.6).
|
|
5 The CS5 coded character set (1/7.2.7).
|
|
6 The CS6 coded character set (1/7.2.8).
|
|
7 The CS7 coded character set (1/7.2.9).
|
|
8 The CS8 coded character set (1/7.2.10).
|
|
9-255 Reserved for future standardisation.
|
|
*
|
|
*/
|
|
typedef struct __attribute__((packed)) {
|
|
uint8_t charSetType;
|
|
|
|
uint8_t charSetInfo[63];
|
|
} charspec;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
|
|
DescriptorTag tag;
|
|
|
|
uint32_t volumeDescriptorSequenceNumber;
|
|
|
|
charspec descriptorCharSet;
|
|
|
|
uint8_t logicalVolumeIdentifier[128]; // TODO: handle dstring
|
|
|
|
uint32_t logicalBlockSize;
|
|
|
|
regid domainIdentifier;
|
|
|
|
uint8_t logicalVolumeContentsUse[16];
|
|
|
|
uint32_t mapTableLength;
|
|
|
|
uint32_t numPartitionMaps;
|
|
|
|
regid implementationIdentifier;
|
|
|
|
uint8_t implementationUse[128];
|
|
|
|
ext_ad integritySequenceExtent;
|
|
|
|
uint8_t partitionMaps[1]; // actual length of mapTableLength above;
|
|
|
|
} LogicalVolumeDescriptor;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
DescriptorTag tag;
|
|
timestamp recordingDateTime;
|
|
|
|
uint16_t interchangeLevel;
|
|
|
|
uint16_t maxInterchangeLevel;
|
|
uint32_t characterSetList;
|
|
uint32_t maxCharacterSetList;
|
|
|
|
uint32_t fileSetNumber;
|
|
uint32_t fileSetDescriptorNumber;
|
|
|
|
charspec logicalVolumeIdentifierCharSet;
|
|
uint8_t logicalVolumeIdentifier[128];
|
|
charspec fileSetCharSet;
|
|
uint8_t fileSetIdentifier[32];
|
|
|
|
uint8_t copyrightIdentifier[32];
|
|
uint8_t abstractIdentifier[32];
|
|
long_ad rootDirectoryICB;
|
|
|
|
regid domainIdentifier;
|
|
|
|
long_ad nextExtent;
|
|
long_ad systemStreamDirectoryICB;
|
|
uint8_t reserved[32];
|
|
|
|
} FileSetDescriptor;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
uint8_t structType;
|
|
char standardIdentifier[5];
|
|
uint8_t structVersion;
|
|
uint8_t rest[2041];
|
|
} GenericVolumeStructureDescriptor;
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack()
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK_HPPA
|
|
#pragma pack
|
|
#endif
|
|
|
|
cl_error_t cli_scanudf(cli_ctx* ctx, size_t offset);
|
|
|
|
#endif /* _UDF_H_ */
|
|
|