1 /* 2 * Copyright (C) 2013-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 3 * Copyright (C) 2013 Sourcefire, Inc. 4 * 5 * Authors: David Raynor <draynor@sourcefire.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 * MA 02110-1301, USA. 20 */ 21 22 #ifndef __HFSPLUS_H 23 #define __HFSPLUS_H 24 25 #if HAVE_CONFIG_H 26 #include "clamav-config.h" 27 #endif 28 29 #include "clamav-types.h" 30 31 /* Structures based on Apple Technote 1150 */ 32 33 /* volume attributes that may affect reading */ 34 enum hfsVolAttributes { 35 /* hfsVolumeHardwareLockBit = 7, */ 36 hfsVolumeUnmountedBit = 8, 37 hfsVolumeSparedBlocksBit = 9, 38 /* hfsVolumeNoCacheRequiredBit = 10, */ 39 hfsBootVolumeInconsistentBit = 11, 40 hfsCatalogNodeIDsReusedBit = 12, 41 hfsVolumeJournaledBit = 13 42 /* hfsVolumeSoftwareLockBit = 15 */ 43 }; 44 45 /* reserved CatalogNodeID values */ 46 enum { 47 hfsRootParentID = 1, 48 hfsRootFolderID = 2, 49 hfsExtentsFileID = 3, 50 hfsCatalogFileID = 4, 51 hfsBadBlockFileID = 5, 52 hfsAllocationFileID = 6, 53 hfsStartupFileID = 7, 54 hfsAttributesFileID = 8, 55 hfsRepairCatalogFileID = 14, 56 hfsBogusExtentFileID = 15, 57 hfsFirstUserCatalogNodeID = 16 58 }; 59 60 #ifndef HAVE_ATTRIB_PACKED 61 #define __attribute__(x) 62 #endif 63 64 #ifdef HAVE_PRAGMA_PACK 65 #pragma pack(2) 66 #endif 67 68 #ifdef HAVE_PRAGMA_PACK_HPPA 69 #pragma pack 2 70 #endif 71 72 /* Basic HFS+ structures */ 73 struct hfsUniStr255 { 74 uint16_t length; 75 uint16_t unicode[255]; 76 } __attribute__((__packed__)); 77 typedef struct hfsUniStr255 hfsUniStr255; 78 79 struct hfsPlusExtentDescriptor { 80 uint32_t startBlock; 81 uint32_t blockCount; 82 } __attribute__((__packed__)); 83 typedef struct hfsPlusExtentDescriptor hfsPlusExtentDescriptor; 84 typedef hfsPlusExtentDescriptor hfsPlusExtentRecord[8]; 85 86 struct hfsPlusForkData { 87 uint64_t logicalSize; 88 uint32_t clumpSize; 89 uint32_t totalBlocks; 90 hfsPlusExtentRecord extents; 91 } __attribute__((__packed__)); 92 typedef struct hfsPlusForkData hfsPlusForkData; 93 94 /* HFS+ Volume Header (512 bytes) */ 95 struct hfsPlusVolumeHeader { 96 uint16_t signature; /* H+ for HFS+, HX for HFSX */ 97 uint16_t version; 98 uint32_t attributes; 99 uint32_t lastMountedVersion; 100 uint32_t journalInfoBlock; 101 102 uint32_t createDate; 103 uint32_t modifyDate; 104 uint32_t backupDate; 105 uint32_t checkedDate; 106 107 uint32_t fileCount; 108 uint32_t folderCount; 109 110 uint32_t blockSize; 111 uint32_t totalBlocks; 112 uint32_t freeBlocks; 113 114 uint32_t nextAllocation; 115 uint32_t rsrcClumpSize; 116 uint32_t dataClumpSize; 117 uint32_t nextCatalogID; /* Next unused catalog ID */ 118 119 uint32_t writeCount; 120 uint64_t encodingsBitmap; 121 122 uint32_t finderInfo[8]; /* for Finder */ 123 124 hfsPlusForkData allocationFile; 125 hfsPlusForkData extentsFile; 126 hfsPlusForkData catalogFile; 127 hfsPlusForkData attributesFile; 128 hfsPlusForkData startupFile; 129 } __attribute__((__packed__)); 130 typedef struct hfsPlusVolumeHeader hfsPlusVolumeHeader; 131 132 #define HFS_FILETREE_ALLOCATION 1 133 #define HFS_FILETREE_EXTENTS 2 134 #define HFS_FILETREE_CATALOG 3 135 #define HFS_FILETREE_ATTRIBUTES 4 136 #define HFS_FILETREE_STARTUP 5 137 138 /* BSD object info (16 bytes) */ 139 /* important parts for scanning are fileMode and the special part */ 140 struct hfsPlusBSDInfo { 141 uint32_t ownerID; 142 uint32_t groupID; 143 uint8_t adminFlags; 144 uint8_t ownerFlags; 145 uint16_t fileMode; 146 union { 147 uint32_t iNodeNum; 148 uint32_t linkCount; 149 uint32_t rawDevice; 150 } special; 151 } __attribute__((__packed__)); 152 typedef struct hfsPlusBSDInfo hfsPlusBSDInfo; 153 154 #define HFS_MODE_TYPEMASK 0170000 155 #define HFS_MODE_DIRECTORY 0040000 156 #define HFS_MODE_FILE 0100000 157 #define HFS_MODE_SOFTLINK 0120000 158 159 /******************************/ 160 /* Node and tree structures */ 161 /******************************/ 162 163 /* B-tree node descriptor (14 bytes) */ 164 struct hfsNodeDescriptor { 165 uint32_t fLink; 166 uint32_t bLink; 167 int8_t kind; 168 uint8_t height; 169 uint16_t numRecords; 170 uint16_t reserved; 171 } __attribute__((__packed__)); 172 typedef struct hfsNodeDescriptor hfsNodeDescriptor; 173 174 /* Node kinds are int8_t */ 175 #define HFS_NODEKIND_LEAF -1 176 #define HFS_NODEKIND_INDEX 0 177 #define HFS_NODEKIND_HEADER 1 178 #define HFS_NODEKIND_MAP 2 179 180 /* B-tree header record (106 bytes) */ 181 struct hfsHeaderRecord { 182 uint16_t treeDepth; 183 uint32_t rootNode; 184 uint32_t leafRecords; 185 uint32_t firstLeafNode; 186 uint32_t lastLeafNode; 187 uint16_t nodeSize; 188 uint16_t maxKeyLength; 189 uint32_t totalNodes; 190 uint32_t freeNodes; 191 uint16_t reserved1; 192 uint32_t clumpSize; 193 uint8_t btreeType; 194 uint8_t keyCompareType; 195 uint32_t attributes; 196 uint32_t reserved3[16]; 197 } __attribute__((__packed__)); 198 typedef struct hfsHeaderRecord hfsHeaderRecord; 199 200 #define HFS_HEADERATTR_MASK 0x00000006 201 #define HFS_HEADERATTR_BIGKEYS 0x00000002 202 #define HFS_HEADERATTR_VARKEYS 0x00000004 203 204 struct hfsPlusCatalogKey { 205 uint16_t keyLength; 206 uint32_t parentID; /* CNID */ 207 hfsUniStr255 nodeName; 208 } __attribute__((__packed__)); 209 typedef struct hfsPlusCatalogKey hfsPlusCatalogKey; 210 211 struct hfsPlusCatalogFolder { 212 int16_t recordType; 213 uint16_t flags; 214 uint32_t valence; 215 uint32_t folderID; /* CNID */ 216 uint32_t dates[5]; 217 hfsPlusBSDInfo permissions; 218 uint16_t userInfo[8]; /* FolderInfo */ 219 uint16_t finderInfo[8]; /* ExtendedFolderInfo */ 220 uint32_t textEncoding; 221 uint32_t reserved; 222 } __attribute__((__packed__)); 223 typedef struct hfsPlusCatalogFolder hfsPlusCatalogFolder; 224 225 struct hfsPlusCatalogFile { 226 int16_t recordType; 227 uint16_t flags; 228 uint32_t reserved1; 229 uint32_t fileID; /* CNID */ 230 uint32_t dates[5]; 231 hfsPlusBSDInfo permissions; 232 uint16_t userInfo[8]; /* FileInfo */ 233 uint16_t finderInfo[8]; /* ExtendedFileInfo */ 234 uint32_t textEncoding; 235 uint32_t reserved2; 236 hfsPlusForkData dataFork; 237 hfsPlusForkData resourceFork; 238 }; 239 typedef struct hfsPlusCatalogFile hfsPlusCatalogFile; 240 241 struct hfsPlusCatalogThread { 242 int16_t recordType; 243 int16_t reserved; 244 uint32_t parentID; /* CNID */ 245 hfsUniStr255 nodeName; 246 } __attribute__((__packed__)); 247 typedef struct hfsPlusCatalogThread hfsPlusCatalogThread; 248 249 #define HFSPLUS_RECTYPE_FOLDER 0x0001 250 #define HFSPLUS_RECTYPE_FILE 0x0002 251 #define HFSPLUS_RECTYPE_FOLDERTHREAD 0x0003 252 #define HFSPLUS_RECTYPE_FILETHREAD 0x0004 253 #define HFSPLUS_RECTYPE_INLINE_DATA_ATTRIBUTE 0x0010 254 /* HFS types are similar 255 #define HFS_RECTYPE_FOLDER 0x0100 256 #define HFS_RECTYPE_FILE 0x0200 257 #define HFS_RECTYPE_FOLDERTHREAD 0x0300 258 #define HFS_RECTYPE_FILETHREAD 0x0400 259 */ 260 261 #define HFS_HARD_LINK_FILE_TYPE 0x686C6E6B /* hlnk */ 262 263 /* Extents structures */ 264 struct hfsPlusExtentKey { 265 uint16_t keyLength; 266 uint8_t forkType; 267 uint8_t pad; 268 uint32_t fileID; /* CNID */ 269 uint32_t startBlock; 270 } __attribute__((__packed__)); 271 typedef struct hfsPlusExtentKey hfsPlusExtentKey; 272 273 #define HFSPLUS_FORKTYPE_DATA 0x00 274 #define HFSPLUS_FORKTYPE_RSRC 0xFF 275 276 /* Attribute structures */ 277 struct hfsPlusAttributeKey { 278 uint16_t keyLength; 279 uint16_t pad; 280 uint32_t cnid; 281 uint32_t startBlock; 282 uint16_t nameLength; 283 } __attribute__((__packed__)); 284 typedef struct hfsPlusAttributeKey hfsPlusAttributeKey; 285 286 struct hfsPlusAttributeRecord { 287 uint32_t recordType; 288 uint32_t reserved1; 289 uint32_t reserved2; 290 uint32_t attributeSize; 291 } __attribute__((__packed__)); 292 typedef struct hfsPlusAttributeRecord hfsPlusAttributeRecord; 293 294 struct hfsPlusCompressionHeader { 295 uint32_t magic; 296 uint32_t compressionType; 297 uint64_t fileSize; 298 } __attribute__((__packed__)); 299 typedef struct hfsPlusCompressionHeader hfsPlusCompressionHeader; 300 301 /* Resource structures */ 302 struct hfsPlusResourceHeader { 303 uint32_t dataOffset; 304 uint32_t mapOffset; 305 uint32_t dataLength; 306 uint32_t mapLength; 307 } __attribute__((__packed__)); 308 typedef struct hfsPlusResourceHeader hfsPlusResourceHeader; 309 310 struct hfsPlusResourceMap { 311 uint8_t reserved1[16]; 312 uint32_t reserved2; 313 uint16_t reserved3; 314 uint16_t resourceForkAttributes; 315 uint16_t typeListOffset; 316 uint16_t nameListOffset; 317 int16_t typeCount; 318 } __attribute__((__packed__)); 319 typedef struct hfsPlusResourceMap hfsPlusResourceMap; 320 321 struct hfsPlusResourceType { 322 char type[4]; 323 uint16_t instanceCount; 324 uint16_t referenceListOffset; 325 } __attribute__((__packed__)); 326 typedef struct hfsPlusResourceType hfsPlusResourceType; 327 328 struct hfsPlusReferenceEntry { 329 uint16_t resourceId; 330 int16_t resourceNameOffset; 331 uint8_t resourceAttributes; 332 uint8_t resourceDataOffset[3]; 333 uint32_t reserved1; 334 } __attribute__((__packed__)); 335 typedef struct hfsPlusReferenceEntry hfsPlusReferenceEntry; 336 337 struct hfsPlusResourceBlockTable { 338 uint32_t offset; 339 uint32_t length; 340 } __attribute__((__packed__)); 341 typedef struct hfsPlusResourceBlockTable hfsPlusResourceBlockTable; 342 343 #define HFSPLUS_COMPRESSION_INLINE 0x03 344 #define HFSPLUS_COMPRESSION_RESOURCE 0x04 345 346 #ifdef HAVE_PRAGMA_PACK 347 #pragma pack() 348 #endif 349 350 #ifdef HAVE_PRAGMA_PACK_HPPA 351 #pragma pack 352 #endif 353 354 #define HFS_VOL_INCONSISTENT(hdr) \ 355 ((hdr->attributes & (1 << hfsBootVolumeInconsistentBit)) || !(hdr->attributes & (1 << hfsVolumeUnmountedBit))) 356 357 /* Maximum number of catalog leaf nodes to scan for records */ 358 #define HFSPLUS_NODE_LIMIT 1000 359 360 cl_error_t cli_scanhfsplus(cli_ctx *ctx); 361 362 #endif 363