ClamAV is an open source (GPLv2) anti-virus toolkit.
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.
 
 
 
 
 
 
clamav/libclamav/udf.h

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_ */