mirror of
https://github.com/mdbtools/mdbtools.git
synced 2026-03-10 00:20:54 +08:00
Merge pull request #305 from filmor/write-encrypted-pages
Write encrypted pages
This commit is contained in:
@@ -16,16 +16,28 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _mdbprivate_h_
|
||||
#define _mdbprivate_h_
|
||||
#ifndef MDBPRIVATE_H
|
||||
#define MDBPRIVATE_H
|
||||
|
||||
#include "mdbtools.h"
|
||||
|
||||
/*
|
||||
* This header is for stuff lacking a MDB_ or mdb_ something, so they won't be
|
||||
* exported to calling programs.
|
||||
* This header is for stuff lacking a MDB_ or mdb_ something, or functions only
|
||||
* used within mdbtools so they won't be exported to calling programs.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_G_MEMDUP2
|
||||
#define g_memdup2 g_memdup
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void mdbi_rc4(unsigned char *key, guint32 key_len, unsigned char *buf, guint32 buf_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
lib_LTLIBRARIES = libmdb.la
|
||||
libmdb_la_SOURCES= catalog.c file.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c map.c props.c worktable.c options.c iconv.c version.c
|
||||
libmdb_la_SOURCES= catalog.c file.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c map.c props.c worktable.c options.c iconv.c version.c rc4.c
|
||||
libmdb_la_LDFLAGS = -version-info $(VERSION_INFO)
|
||||
if FAKE_GLIB
|
||||
libmdb_la_SOURCES += fakeglib.c
|
||||
|
||||
@@ -66,69 +66,8 @@ MdbFormatConstants MdbJet3Constants = {
|
||||
.tab_row_col_num_offset = 5
|
||||
};
|
||||
|
||||
typedef struct _RC4_KEY
|
||||
{
|
||||
unsigned char state[256];
|
||||
unsigned char x;
|
||||
unsigned char y;
|
||||
} RC4_KEY;
|
||||
|
||||
#define swap_byte(x,y) t = *(x); *(x) = *(y); *(y) = t
|
||||
|
||||
static ssize_t _mdb_read_pg(MdbHandle *mdb, void *pg_buf, unsigned long pg);
|
||||
|
||||
static void RC4_set_key(RC4_KEY *key, int key_data_len, unsigned char *key_data_ptr)
|
||||
{
|
||||
unsigned char t;
|
||||
unsigned char index1;
|
||||
unsigned char index2;
|
||||
unsigned char* state;
|
||||
short counter;
|
||||
|
||||
state = &key->state[0];
|
||||
for(counter = 0; counter < 256; counter++)
|
||||
state[counter] = counter;
|
||||
key->x = 0;
|
||||
key->y = 0;
|
||||
index1 = 0;
|
||||
index2 = 0;
|
||||
for(counter = 0; counter < 256; counter++) {
|
||||
index2 = (key_data_ptr[index1] + state[counter] + index2) % 256;
|
||||
swap_byte(&state[counter], &state[index2]);
|
||||
index1 = (index1 + 1) % key_data_len;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* this algorithm does 'encrypt in place' instead of inbuff/outbuff
|
||||
* note also: encryption and decryption use same routine
|
||||
* implementation supplied by (Adam Back) at <adam at cypherspace dot org>
|
||||
*/
|
||||
|
||||
static void RC4(RC4_KEY *key, int buffer_len, unsigned char * buff)
|
||||
{
|
||||
unsigned char t;
|
||||
unsigned char x;
|
||||
unsigned char y;
|
||||
unsigned char* state;
|
||||
unsigned char xorIndex;
|
||||
short counter;
|
||||
|
||||
x = key->x;
|
||||
y = key->y;
|
||||
state = &key->state[0];
|
||||
for(counter = 0; counter < buffer_len; counter++) {
|
||||
x = (x + 1) % 256;
|
||||
y = (state[x] + y) % 256;
|
||||
swap_byte(&state[x], &state[y]);
|
||||
xorIndex = (state[x] + state[y]) % 256;
|
||||
buff[counter] ^= state[xorIndex];
|
||||
}
|
||||
key->x = x;
|
||||
key->y = y;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mdb_find_file:
|
||||
* @filename: path to MDB (database) file
|
||||
@@ -232,10 +171,13 @@ static MdbHandle *mdb_handle_from_stream(FILE *stream, MdbFileFlags flags) {
|
||||
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);
|
||||
guint32 tmp_key = 0x6b39dac7;
|
||||
mdbi_rc4(
|
||||
(unsigned char *)&tmp_key,
|
||||
4,
|
||||
mdb->pg_buf + 0x18,
|
||||
mdb->f->jet_version == MDB_VER_JET3 ? 126 : 128
|
||||
);
|
||||
|
||||
if (mdb->f->jet_version == MDB_VER_JET3) {
|
||||
mdb->f->lang_id = mdb_get_int16(mdb->pg_buf, 0x3a);
|
||||
@@ -249,8 +191,6 @@ static MdbHandle *mdb_handle_from_stream(FILE *stream, MdbFileFlags flags) {
|
||||
/* 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;
|
||||
|
||||
mdb_iconv_init(mdb);
|
||||
|
||||
@@ -436,10 +376,8 @@ static ssize_t _mdb_read_pg(MdbHandle *mdb, void *pg_buf, unsigned long pg)
|
||||
*/
|
||||
if (pg != 0 && mdb->f->db_key != 0)
|
||||
{
|
||||
RC4_KEY rc4_key;
|
||||
unsigned int tmp_key = mdb->f->db_key ^ pg;
|
||||
RC4_set_key(&rc4_key, 4, (unsigned char *)&tmp_key);
|
||||
RC4(&rc4_key, mdb->fmt->pg_size, pg_buf);
|
||||
mdbi_rc4((unsigned char*)&tmp_key, 4, pg_buf, mdb->fmt->pg_size);
|
||||
}
|
||||
|
||||
return mdb->fmt->pg_size;
|
||||
|
||||
85
src/libmdb/rc4.c
Normal file
85
src/libmdb/rc4.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/* MDB Tools - A library for reading MS Access database files
|
||||
* Copyright (C) 2000 Brian Bruns
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mdbprivate.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char state[256];
|
||||
unsigned char x;
|
||||
unsigned char y;
|
||||
} RC4_KEY;
|
||||
|
||||
#define swap_byte(x,y) t = *(x); *(x) = *(y); *(y) = t
|
||||
|
||||
|
||||
static void RC4_set_key(RC4_KEY *key, int key_data_len, unsigned char *key_data_ptr)
|
||||
{
|
||||
unsigned char t;
|
||||
unsigned char index1;
|
||||
unsigned char index2;
|
||||
unsigned char* state;
|
||||
short counter;
|
||||
|
||||
state = &key->state[0];
|
||||
for(counter = 0; counter < 256; counter++)
|
||||
state[counter] = counter;
|
||||
key->x = 0;
|
||||
key->y = 0;
|
||||
index1 = 0;
|
||||
index2 = 0;
|
||||
for(counter = 0; counter < 256; counter++) {
|
||||
index2 = (key_data_ptr[index1] + state[counter] + index2) % 256;
|
||||
swap_byte(&state[counter], &state[index2]);
|
||||
index1 = (index1 + 1) % key_data_len;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* this algorithm does 'encrypt in place' instead of inbuff/outbuff
|
||||
* note also: encryption and decryption use same routine
|
||||
* implementation supplied by (Adam Back) at <adam at cypherspace dot org>
|
||||
*/
|
||||
static void RC4(RC4_KEY *key, int buffer_len, unsigned char * buff)
|
||||
{
|
||||
unsigned char t;
|
||||
unsigned char x;
|
||||
unsigned char y;
|
||||
unsigned char* state;
|
||||
unsigned char xorIndex;
|
||||
short counter;
|
||||
|
||||
x = key->x;
|
||||
y = key->y;
|
||||
state = &key->state[0];
|
||||
for(counter = 0; counter < buffer_len; counter++) {
|
||||
x = (x + 1) % 256;
|
||||
y = (state[x] + y) % 256;
|
||||
swap_byte(&state[x], &state[y]);
|
||||
xorIndex = (state[x] + state[y]) % 256;
|
||||
buff[counter] ^= state[xorIndex];
|
||||
}
|
||||
key->x = x;
|
||||
key->y = y;
|
||||
}
|
||||
|
||||
void mdbi_rc4(unsigned char *key, guint32 key_len, unsigned char *buf, guint32 buf_len) {
|
||||
RC4_KEY rc4_key;
|
||||
RC4_set_key(&rc4_key, key_len, key);
|
||||
RC4(&rc4_key, buf_len, buf);
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
#include "mdbtools.h"
|
||||
#include "mdbprivate.h"
|
||||
|
||||
//static int mdb_copy_index_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg);
|
||||
static int mdb_add_row_to_leaf_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg, MdbField *idx_fields, guint32 pgnum, guint16 rownum);
|
||||
@@ -70,6 +70,7 @@ mdb_write_pg(MdbHandle *mdb, unsigned long pg)
|
||||
{
|
||||
ssize_t len;
|
||||
off_t offset = pg * mdb->fmt->pg_size;
|
||||
unsigned char *buf = mdb->pg_buf;
|
||||
|
||||
fseeko(mdb->f->stream, 0, SEEK_END);
|
||||
/* is page beyond current size + 1 ? */
|
||||
@@ -78,7 +79,20 @@ mdb_write_pg(MdbHandle *mdb, unsigned long pg)
|
||||
return 0;
|
||||
}
|
||||
fseeko(mdb->f->stream, offset, SEEK_SET);
|
||||
len = fwrite(mdb->pg_buf, 1, mdb->fmt->pg_size, mdb->f->stream);
|
||||
|
||||
if (pg != 0 && mdb->f->db_key != 0)
|
||||
{
|
||||
buf = g_memdup2(mdb->pg_buf, mdb->fmt->pg_size);
|
||||
unsigned int tmp_key = mdb->f->db_key ^ pg;
|
||||
mdbi_rc4((unsigned char*)&tmp_key, 4, buf, mdb->fmt->pg_size);
|
||||
}
|
||||
|
||||
len = fwrite(buf, 1, mdb->fmt->pg_size, mdb->f->stream);
|
||||
|
||||
if (buf != mdb->pg_buf) {
|
||||
g_free(buf);
|
||||
}
|
||||
|
||||
if (ferror(mdb->f->stream)) {
|
||||
perror("write");
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user