diff --git a/include/mdbprivate.h b/include/mdbprivate.h index 88c625d..5e6c84c 100644 --- a/include/mdbprivate.h +++ b/include/mdbprivate.h @@ -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 diff --git a/src/libmdb/Makefile.am b/src/libmdb/Makefile.am index 29436fd..ec6cc23 100644 --- a/src/libmdb/Makefile.am +++ b/src/libmdb/Makefile.am @@ -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 diff --git a/src/libmdb/file.c b/src/libmdb/file.c index bffd71c..b4cb5cc 100644 --- a/src/libmdb/file.c +++ b/src/libmdb/file.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 - */ - -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; diff --git a/src/libmdb/rc4.c b/src/libmdb/rc4.c new file mode 100644 index 0000000..5596736 --- /dev/null +++ b/src/libmdb/rc4.c @@ -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 + */ +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); +} \ No newline at end of file diff --git a/src/libmdb/write.c b/src/libmdb/write.c index 891b121..6ae073a 100644 --- a/src/libmdb/write.c +++ b/src/libmdb/write.c @@ -18,7 +18,7 @@ #include #include -#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;