mirror of
https://github.com/mdbtools/mdbtools.git
synced 2026-03-10 00:20:54 +08:00
Simplify header-reading logic and support JET3 code pages
Using the notes and RC4 key provided in the HACKING file, decrypt the database definition page all at once instead of decrypting individual fields with ad-hoc keys. Use the newly decrypted header to access the database code page at offset 0x3C, and use this numeric value to initialize the iconv converter with an appropriate charset name for popular windows code pages. More encodings can be added later, with the eventual goal of getting rid of the MDB_JET3_CHARSET environment variable. Note that individual columns can have their own code pages but this issue is not addressed. An extra field is added to the MdbFile structure - because this struct is allocated internally, this should not break the public ABI. Finally, only set the db_passwd field if it's a JET3 database (see #144)
This commit is contained in:
@@ -168,9 +168,6 @@ static char *mdb_find_file(const char *file_name)
|
||||
* Return value: The handle on success, NULL on failure
|
||||
*/
|
||||
static MdbHandle *mdb_handle_from_stream(FILE *stream, MdbFileFlags flags) {
|
||||
int key[] = {0x86, 0xfb, 0xec, 0x37, 0x5d, 0x44, 0x9c, 0xfa, 0xc6, 0x5e, 0x28, 0xe6, 0x13, 0xb6};
|
||||
int j, pos;
|
||||
|
||||
MdbHandle *mdb = (MdbHandle *) g_malloc0(sizeof(MdbHandle));
|
||||
mdb_set_default_backend(mdb, "access");
|
||||
mdb_set_date_fmt(mdb, "%x %X");
|
||||
@@ -216,27 +213,22 @@ static MdbHandle *mdb_handle_from_stream(FILE *stream, MdbFileFlags flags) {
|
||||
mdb_close(mdb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RC4_KEY rc4_key;
|
||||
unsigned int tmp_key = 0x6b39dac7;
|
||||
RC4_set_key(&rc4_key, 4, (unsigned char *)&tmp_key);
|
||||
RC4(&rc4_key, mdb->f->jet_version == MDB_VER_JET3 ? 126 : 128, mdb->pg_buf + 0x18);
|
||||
|
||||
mdb->f->code_page = mdb_get_int16(mdb->pg_buf, 0x3c);
|
||||
mdb->f->db_key = mdb_get_int32(mdb->pg_buf, 0x3e);
|
||||
/* I don't know if this value is valid for some versions?
|
||||
* it doesn't seem to be valid for the databases I have
|
||||
*
|
||||
* f->db_key ^= 0xe15e01b9;
|
||||
*/
|
||||
mdb->f->db_key ^= 0x4ebc8afb;
|
||||
/* fprintf(stderr, "Encrypted file, RC4 key seed= %d\n", mdb->f->db_key); */
|
||||
if (mdb->f->jet_version == MDB_VER_JET3) {
|
||||
/* JET4 needs additional masking with the DB creation date, currently unsupported */
|
||||
/* Bug - JET3 supports 20 byte passwords, this is currently just 14 bytes */
|
||||
memcpy(mdb->f->db_passwd, mdb->pg_buf + 0x42, sizeof(mdb->f->db_passwd));
|
||||
}
|
||||
/* write is not supported for encrypted files yet */
|
||||
mdb->f->writable = mdb->f->writable && !mdb->f->db_key;
|
||||
|
||||
/* get the db password located at 0x42 bytes into the file */
|
||||
for (pos=0;pos<14;pos++) {
|
||||
j = mdb_get_int32(mdb->pg_buf, 0x42+pos);
|
||||
j ^= key[pos];
|
||||
if ( j != 0)
|
||||
mdb->f->db_passwd[pos] = j;
|
||||
else
|
||||
mdb->f->db_passwd[pos] = '\0';
|
||||
}
|
||||
|
||||
mdb_iconv_init(mdb);
|
||||
|
||||
return mdb;
|
||||
|
||||
Reference in New Issue
Block a user