ÜberWall

UWfirmforce

/* $Id: iso9660.c,v 1.1 2009/02/21 21:25:18 khorben Exp $ */
/*
* ISO filesystem by (suzanne) vega.
* driven by tomato luv.
*/
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include "plugin.h"
/* types */
/* some structure and macros were stolen from NetBSD <isofs/cd9660/iso.h> includes */
#define ISODCL(from, to) (to - from + 1)
#pragma pack(1)
struct iso_volume_descriptor {
u_char type[ISODCL(1,1)]; /* 711 */
char id[ISODCL(2,6)];
char version[ISODCL(7,7)];
char data[ISODCL(8,2048)];
};
#pragma pack()
/* volume descriptor types */
#define ISO_VD_BOOTSECT 0
#define ISO_VD_PRIMARY 1
#define ISO_VD_SUPPLEMENTARY 2
#define ISO_VD_PARTITION 3
#define ISO_VD_END 255
#define ISO_STANDARD_ID "CD001"
#define ISO_ECMA_ID "CDW01"
#define ISO_EMPTY ""
struct iso_primary_descriptor {
char type [ISODCL ( 1, 1)]; /* 711 */
char id [ISODCL ( 2, 6)];
char version [ISODCL ( 7, 7)]; /* 711 */
char unused1 [ISODCL ( 8, 8)];
char system_id [ISODCL ( 9, 40)]; /* achars */
char volume_id [ISODCL ( 41, 72)]; /* dchars */
char unused2 [ISODCL ( 73, 80)];
char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
char unused3 [ISODCL ( 89, 120)];
char volume_set_size [ISODCL (121, 124)]; /* 723 */
char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
char logical_block_size [ISODCL (129, 132)]; /* 723 */
char path_table_size [ISODCL (133, 140)]; /* 733 */
char type_l_path_table [ISODCL (141, 144)]; /* 731 */
char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
char type_m_path_table [ISODCL (149, 152)]; /* 732 */
char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
char volume_set_id [ISODCL (191, 318)]; /* dchars */
char publisher_id [ISODCL (319, 446)]; /* achars */
char preparer_id [ISODCL (447, 574)]; /* achars */
char application_id [ISODCL (575, 702)]; /* achars */
char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
char file_structure_version [ISODCL (882, 882)]; /* 711 */
char unused4 [ISODCL (883, 883)];
char application_data [ISODCL (884, 1395)];
char unused5 [ISODCL (1396, 2048)];
};
#define ISO_DEFAULT_BLOCK_SIZE 2048
struct iso_supplementary_descriptor {
char type [ISODCL ( 1, 1)]; /* 711 */
char id [ISODCL ( 2, 6)];
char version [ISODCL ( 7, 7)]; /* 711 */
char flags [ISODCL ( 8, 8)]; /* 711? */
char system_id [ISODCL ( 9, 40)]; /* achars */
char volume_id [ISODCL ( 41, 72)]; /* dchars */
char unused2 [ISODCL ( 73, 80)];
char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
char escape [ISODCL ( 89, 120)];
char volume_set_size [ISODCL (121, 124)]; /* 723 */
char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
char logical_block_size [ISODCL (129, 132)]; /* 723 */
char path_table_size [ISODCL (133, 140)]; /* 733 */
char type_l_path_table [ISODCL (141, 144)]; /* 731 */
char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
char type_m_path_table [ISODCL (149, 152)]; /* 732 */
char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
char volume_set_id [ISODCL (191, 318)]; /* dchars */
char publisher_id [ISODCL (319, 446)]; /* achars */
char preparer_id [ISODCL (447, 574)]; /* achars */
char application_id [ISODCL (575, 702)]; /* achars */
char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
char file_structure_version [ISODCL (882, 882)]; /* 711 */
char unused4 [ISODCL (883, 883)];
char application_data [ISODCL (884, 1395)];
char unused5 [ISODCL (1396, 2048)];
};
/* variables */
static char a_char_lazy[] = " !\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
static char a_char_strict[] = " !\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
static char d_char_lazy[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static char d_char_strict[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
typedef enum typechar {
TYPE_LAZY_A_CHARS,
TYPE_LAZY_D_CHARS,
TYPE_STRICT_A_CHARS,
TYPE_STRICT_D_CHARS
} ctype_t;
static __inline int isonum_711(u_char *) __attribute__ ((unused));
/* 7.1.1: unsigned char */
static __inline int
isonum_711(u_char *p)
{
return *p;
}
/* 7.2.3: unsigned both-endian (little, then big) 16-bit value */
static __inline uint16_t
isonum_723(u_char *p)
{
#if defined(UNALIGNED_ACCESS) && \
((BYTE_ORDER == LITTLE_ENDIAN) || (BYTE_ORDER == BIG_ENDIAN))
#if BYTE_ORDER == LITTLE_ENDIAN
return *(uint16_t *)p;
#else
return *(uint16_t *)(p + 2);
#endif
#else /* !UNALIGNED_ACCESS or weird byte order */
return *p|(p[1] << 8);
#endif
}
/* 7.3.3: unsigned both-endian (little, then big) 32-bit value */
static __inline uint32_t
isonum_733(u_char *p)
{
#if defined(UNALIGNED_ACCESS) && \
((BYTE_ORDER == LITTLE_ENDIAN) || (BYTE_ORDER == BIG_ENDIAN))
#if BYTE_ORDER == LITTLE_ENDIAN
return *(uint32_t *)p;
#else
return *(uint32_t *)(p + 4);
#endif
#else /* !UNALIGNED_ACCESS or weird byte order */
return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
#endif
}
/* signatures */
static unsigned char sig1[] = ISO_STANDARD_ID;
static unsigned char sig2[] = ISO_ECMA_ID;
static unsigned char sig3[] = ISO_EMPTY;
/* plugin */
static PluginMagic iso9660_magic[] =
{
{ (2*sizeof(struct iso_volume_descriptor)), 0, sig1, sizeof(sig1)-1 },
{ (2*sizeof(struct iso_volume_descriptor)), 0, sig2, sizeof(sig2)-1 },
{ 0, 0, NULL, 0 }
};
static int iso9660_callback(PluginHelper * ph, int signature, FILE * fp);
Plugin plugin =
{
PT_ARCHIVE | PT_EXECUTABLE,
"ISO9660",
iso9660_magic,
iso9660_callback
};
#define ISO_FLAGS_VDBOOT 0x00000001
#define ISO_FLAGS_VDPRIM 0x00000002
#define ISO_FLAGS_VDSUPP 0x00000004
#define ISO_FLAGS_VDPART 0x00000010
#define ISO_FLAGS_VDEND 0x00000020
/* plugin_callback */
int _plugin_check_isovdprimary(struct iso_primary_descriptor * i );
static int iso9660_callback(PluginHelper * ph, int signature, FILE * fp) {
fpos_t pos;
int rc = 0, score = 0;
int iso_flag = 0x00000000;
char buffer[2048];
struct iso_volume_descriptor * isovd;
struct iso_primary_descriptor * isopri;
fpos_t fpos;
//ph->printf(ph, "callback called!\n");
//fprintf(stderr,"prout prout prout we are in plugin callback!!!\n");
//fprintf(stderr, "isovd: %d isopri: %d\n", sizeof(struct iso_volume_descriptor), sizeof(struct iso_primary_descriptor));
reread:
memset(buffer, 0, sizeof(buffer));
//while ( !feof(fp) ) {
//rc = fread((void *)buffer, sizeof(struct iso_volume_descriptor), 1, fp);
rc = fread((void *)buffer, sizeof(char), 2048, fp);
//rc = read(fileno(fp), buffer, sizeof(struct iso_volume_descriptor));
//fprintf(stderr, "fread() rc: %d\n", rc);
/* cast type */
isovd = (struct iso_volume_descriptor *) buffer;
isopri = (struct iso_primary_descriptor *) buffer;
fgetpos(fp, &fpos);
//fprintf(stderr, "sizeof(): %u\n", sizeof(fpos_t));
//fprintf(stderr, "fread(@%08x) rc: %d bytes (isovd sz: %d bytes)\n", (int)fpos, rc, sizeof(struct iso_volume_descriptor));
/*
if (fpos == 0x8000) {
fprintf(stderr, "BUFFER[0]: %02x\n",buffer[0]);
fprintf(stderr, "BUFFER[1]: %02x\n",buffer[1]);
fprintf(stderr, "BUFFER[2]: %02x\n",buffer[2]);
fprintf(stderr, "BUFFER[3]: %02x\n",buffer[3]);
fprintf(stderr, "BUFFER[4]: %02x\n",buffer[4]);
}
*/
if ((rc*sizeof(struct iso_volume_descriptor)) < sizeof(struct iso_volume_descriptor))
return score;
switch (isonum_711(isovd->type)) {
case ISO_VD_BOOTSECT:
//fprintf(stderr, "VD BOOT!\n");
iso_flag |= ISO_FLAGS_VDBOOT;
break;
case ISO_VD_PRIMARY:
fprintf(stderr, "VD PRIM!\n");
iso_flag |= ISO_FLAGS_VDPRIM;
//fprintf(stderr, "file structure version: %d\n", isonum_711(isopri->file_structure_version));
rc = _plugin_check_isovdprimary(isopri);
//fprintf(stderr, "plugin_check_rc: %d\n", rc);
fgetpos(fp, &fpos);
#ifdef DEBUG
fprintf(stderr, "rc: %d fread(@%08x)\n", rc, (int)fpos);
#endif
if (rc < 0)
return -1;
else
score += rc;
#ifdef DEBUG
fprintf(stderr, "flag: %08x type: %02x\n", iso_flag, isonum_711(isovd->type));
fprintf(stderr, "BUFFER[0]: %02x\n",buffer[0]);
fprintf(stderr, "BUFFER[1]: %02x\n",buffer[1]);
fprintf(stderr, "BUFFER[2]: %02x\n",buffer[2]);
fprintf(stderr, "BUFFER[3]: %02x\n",buffer[3]);
fprintf(stderr, "BUFFER[4]: %02x\n",buffer[4]);
#endif
score += 10;
goto reread;
break;
case ISO_VD_SUPPLEMENTARY:
#ifdef DEBUG
fprintf(stderr, "VD SUP!\n");
#endif
iso_flag |= ISO_FLAGS_VDSUPP;
if (iso_flag & ISO_FLAGS_VDPRIM)
score += 10;
break;
case ISO_VD_PARTITION:
iso_flag |= ISO_FLAGS_VDPART;
if (iso_flag & ISO_FLAGS_VDPRIM)
score += 10;
break;
case ISO_VD_END:
iso_flag |= ISO_FLAGS_VDEND;
score += 10;
if (iso_flag & ISO_FLAGS_VDPRIM)
score += 30;
return score;
break;
default:
return -1;
}
memset(buffer, 0, sizeof(buffer));
//}
/*
printf("pos: %d\n", pos);
pos = 0;
printf("callback @ %d\n", pos);
*/
return -1;
}
/*
* add PluginHelper for printf() functions control (verbosity)
*/
int _plugin_check_isXchar(ctype_t type, char * buf, size_t buflen) {
char * ptr = NULL;
size_t rc = 0;
/*
fprintf(stderr, "buf: '%s' buflen: %d bytes\n", buf, buflen);
fprintf(stderr, "buf[8]: %02x\n", buf[8]);
*/
if (buflen > 0) {
ptr = (char *) calloc (buflen+1, sizeof(char));
if (!ptr)
return -1;
memcpy(ptr, buf, buflen);
switch (type) {
case TYPE_LAZY_A_CHARS:
rc = strspn(ptr, a_char_lazy);
break;
case TYPE_LAZY_D_CHARS:
rc = strspn(ptr, d_char_lazy);
break;
case TYPE_STRICT_A_CHARS:
rc = strspn(ptr, a_char_strict);
break;
case TYPE_STRICT_D_CHARS:
rc = strspn(ptr, d_char_strict);
break;
}
if (rc == buflen) {
free(ptr);
return rc;
}
}
free(ptr);
return 0;
}
/*
* return 1 if STANDARD ID
* return 2 if ECMA ID
* return -1 otherwise
* TODO: simplify
*/
int _plugin_check_isisoid(char * buf, size_t buflen) {
int score = 0;
char * id_standard = ISO_STANDARD_ID;
char * id_ecma = ISO_ECMA_ID;
/* test standard id */
if ( memcmp(buf, id_standard, buflen) == 0x0 ) {
score += 15;
return score;
}
/* test ecma id */
if ( memcmp(buf, id_ecma, buflen) == 0x0 ) {
score += 10;
return score;
}
return score;
}
/*
* lame, very lame and simple ISO9660 primary
* volume descriptor conformance check, more later...
*
* max score is 55
*/
int _plugin_check_isovdprimary(struct iso_primary_descriptor * i ) {
int score = 0;
size_t j;
int rc;
rc = _plugin_check_isisoid(i->id, sizeof(i->id));
if (rc > 0)
score += rc;
else
return -1;
/* isprint(first check system ID) - a_chars */
rc = _plugin_check_isXchar(TYPE_LAZY_A_CHARS, i->system_id, sizeof(i->system_id));
if (rc > 0)
score += 10;
/* isprint(then check volume ID) - d_chars */
rc = _plugin_check_isXchar(TYPE_LAZY_D_CHARS, i->volume_id, sizeof(i->volume_id));
if (rc > 0)
score += 10;
/* isprint(then check file structure version) */
if (i->unused1 != '\0')
return 0;
rc = 0;
for (j = 0, rc = 0 ; j < sizeof(i->unused2) ; j++) {
if (i->unused2[j] == '\0')
rc++;
}
if (rc < (signed)sizeof(i->unused2))
return -1;
score += 10;
rc = 0;
for (j = 0, rc = 0 ; j < sizeof(i->unused3) ; j++) {
if (i->unused3[j] == '\0')
rc++;
}
if (rc < (signed)sizeof(i->unused3))
return -1;
score += 10;
return score;
}