From 06eb9d422265a5c28a19da42f118b3e02cc2b32d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Rolim?= Date: Mon, 14 Sep 2020 00:28:00 -0300 Subject: [PATCH] Split mmap_file implementation. Also add some useful definitions. --- encrypt.c | 10 ++--- files.c | 103 +------------------------------------------------- makefile | 5 ++- mmap_file.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mmap_file.h | 33 ++++++++++++++++ purr.c | 3 +- purr.h | 18 --------- 7 files changed, 149 insertions(+), 129 deletions(-) create mode 100644 mmap_file.c create mode 100644 mmap_file.h diff --git a/encrypt.c b/encrypt.c index 668cbb2..ef3fe4a 100644 --- a/encrypt.c +++ b/encrypt.c @@ -11,6 +11,7 @@ #include "libbaseencode/baseencode.h" #include "purr.h" +#include "mmap_file.h" /* * This function takes an mmap_file struct, and creates an encrypted buffer from it. @@ -27,8 +28,7 @@ struct mmap_file encrypt_mmap(struct mmap_file file, uint8_t **keyp, uint8_t **i if (blocks * br_aes_big_BLOCK_SIZE < file_size) blocks++; file_size = blocks * br_aes_big_BLOCK_SIZE; - struct mmap_file rv = - {.size = file_size, .prot = PROT_WRITE | PROT_READ, .flags = MAP_ANONYMOUS | MAP_PRIVATE}; + struct mmap_file rv = {.size = file_size, .prot = PROT_MEM, .flags = MAP_MEM}; uint8_t *key = calloc(KEY_LEN, 1); uint8_t *iv = calloc(IV_LEN, 1); @@ -80,8 +80,7 @@ struct mmap_file encrypt_mmap(struct mmap_file file, uint8_t **keyp, uint8_t **i return rv; } size_t len = strlen(data); - struct mmap_file rv_64 = - {.size = len, .prot = PROT_WRITE | PROT_READ, .flags = MAP_ANONYMOUS | MAP_PRIVATE}; + struct mmap_file rv_64 = {.size = len, .prot = PROT_MEM, .flags = MAP_MEM}; rv_64.data = mmap(NULL, rv_64.size, rv_64.prot, rv_64.flags, -1, 0); if (ERROR_MMAP(rv_64)) { perror("mmap()"); @@ -106,8 +105,7 @@ struct mmap_file encrypt_mmap(struct mmap_file file, uint8_t **keyp, uint8_t **i struct mmap_file decrypt_mmap(struct mmap_file file, const uint8_t *key, const uint8_t *iv) { - struct mmap_file rv = - {.size = file.size, .prot = PROT_WRITE | PROT_READ, .flags = MAP_ANONYMOUS | MAP_PRIVATE}; + struct mmap_file rv = {.size = file.size, .prot = PROT_MEM, .flags = MAP_MEM}; #ifdef DECODE_BASE_64 baseencode_error_t berr; diff --git a/files.c b/files.c index 7003e61..5cf1189 100644 --- a/files.c +++ b/files.c @@ -3,15 +3,8 @@ #include #include -#include -#include -#include -#include - #include "purr.h" - -// 128KiB -#define OUTPUT_FILE_SIZE (128 * 1024) +#include "mmap_file.h" struct strip_header_info { struct mmap_file *output; @@ -21,100 +14,6 @@ struct strip_header_info { bool no_strip, debug; }; -struct mmap_file create_mmap_from_file(const char *name, int prot) -{ - struct mmap_file rv = {.prot = prot}; - int fd; - if (prot == PROT_READ) { - fd = open(name, O_RDONLY); - rv.flags = MAP_PRIVATE; - - if (fd == -1) { - return rv; - } - - struct stat st; - if (fstat(fd, &st) == -1) { - perror("fstat()"); - return rv; - } - rv.size = st.st_size; - } else if (prot == PROT_WRITE) { - fd = open(name, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); - rv.flags = MAP_PRIVATE; - - if (fd == -1) { - return rv; - } - - // ftruncate is good enough for now - // TODO: we can truncate again once we know the content-size, - // otherwise this will leave the file with the wrong size - if (0 && ftruncate(fd, OUTPUT_FILE_SIZE) == -1) { - return rv; - } - rv.size = OUTPUT_FILE_SIZE; - } else if (name == NULL && prot == (PROT_WRITE | PROT_READ)) { - fd = -1; - rv.flags = MAP_ANONYMOUS | MAP_PRIVATE; - rv.size = OUTPUT_FILE_SIZE; - } else { - fputs("unsupported prot flags\n", stderr); - errno = 0; - return rv; - } - - rv.data = mmap(NULL, rv.size, rv.prot, rv.flags, fd, 0); - close(fd); - - return rv; -} - -int read_from_mmap(struct mmap_file *file, int n) -{ - assert(file->prot & PROT_READ); - - if (file->size == file->offset) { - // can't read any more - return 0; - } - - ssize_t max = file->size - file->offset; - file->cursor = file->data + file->offset; - if (n < max) { - // can fit the read - file->offset += n; - } else { - // can read less than n - file->offset = file->size; - n = max; - } - - return n; -} - -int write_into_mmap(struct mmap_file *file, const uint8_t *buffer, int n) -{ - assert(file->prot & PROT_WRITE); - - if (file->size == file->offset) { - return -1; - } - - ssize_t max = file->size - file->offset; - file->cursor = file->data + file->offset; - if (n < max) { - file->offset += n; - } else { - file->offset = file->size; - n = max; - } - - memcpy(file->cursor, buffer, n); - - return n; -} - static size_t fwrite_strip(const uint8_t *buf, int rlen, struct strip_header_info *st) { const char *separator = "\r\n\r\n"; diff --git a/makefile b/makefile index d4b0858..9d42ef3 100644 --- a/makefile +++ b/makefile @@ -11,7 +11,8 @@ LIBS = $(BASEENCODE) LIBSOBJS = $(BASEENCODEOBJS) FINAL = purr -OBJS = purr.o socket.o urls.o files.o comm.o formats.o encrypt.o +HEADERS = purr.h mmap_file.h +OBJS = purr.o socket.o urls.o files.o comm.o formats.o encrypt.o mmap_file.o TEST = tests TOBJS = tests.o formats.o urls.o @@ -21,7 +22,7 @@ all: $(FINAL) check: $(TEST) ./tests -$(OBJS): purr.h +$(OBJS): $(HEADERS) $(OBJS): CFLAGS += $(WARN) $(INC) purr: $(OBJS) $(LIBS) tests: $(TOBJS) $(LIBS) diff --git a/mmap_file.c b/mmap_file.c new file mode 100644 index 0000000..af1d183 --- /dev/null +++ b/mmap_file.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mmap_file.h" + +struct mmap_file create_mmap_from_file(const char *name, int prot) +{ + struct mmap_file rv = {.prot = prot}; + int fd; + if (prot == PROT_READ) { + fd = open(name, O_RDONLY); + rv.flags = MAP_PRIVATE; + + if (fd == -1) { + return rv; + } + + struct stat st; + if (fstat(fd, &st) == -1) { + perror("fstat()"); + return rv; + } + rv.size = st.st_size; + } else if (prot == PROT_WRITE) { + fd = open(name, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + rv.flags = MAP_PRIVATE; + + if (fd == -1) { + return rv; + } + + // ftruncate is good enough for now + // TODO: we can truncate again once we know the content-size, + // otherwise this will leave the file with the wrong size + if (0 && ftruncate(fd, OUTPUT_FILE_SIZE) == -1) { + return rv; + } + rv.size = OUTPUT_FILE_SIZE; + } else if (name == NULL && prot == PROT_MEM) { + fd = -1; + rv.flags = MAP_ANONYMOUS | MAP_PRIVATE; + rv.size = OUTPUT_FILE_SIZE; + } else { + fputs("unsupported prot flags\n", stderr); + errno = 0; + return rv; + } + + rv.data = mmap(NULL, rv.size, rv.prot, rv.flags, fd, 0); + close(fd); + + return rv; +} + +int read_from_mmap(struct mmap_file *file, int n) +{ + assert(file->prot & PROT_READ); + + if (file->size == file->offset) { + // can't read any more + return 0; + } + + ssize_t max = file->size - file->offset; + file->cursor = file->data + file->offset; + if (n < max) { + // can fit the read + file->offset += n; + } else { + // can read less than n + file->offset = file->size; + n = max; + } + + return n; +} + +int write_into_mmap(struct mmap_file *file, const uint8_t *buffer, int n) +{ + assert(file->prot & PROT_WRITE); + + if (file->size == file->offset) { + return -1; + } + + ssize_t max = file->size - file->offset; + file->cursor = file->data + file->offset; + if (n < max) { + file->offset += n; + } else { + file->offset = file->size; + n = max; + } + + memcpy(file->cursor, buffer, n); + + return n; +} diff --git a/mmap_file.h b/mmap_file.h new file mode 100644 index 0000000..c725d76 --- /dev/null +++ b/mmap_file.h @@ -0,0 +1,33 @@ +#ifndef __MMAP_FILE_H_ +#define __MMAP_FILE_H_ + +#include +#include + +#define RESET_MMAP(file) do{(file).offset = 0; (file).cursor = 0}while(0); +#define ERROR_MMAP(file) ((file).data == MAP_FAILED || (file).data == NULL) +#define CLOSE_MMAP(file) do{if((file).data != MAP_FAILED && (file).data != NULL) munmap((file).data, (file).size);}while(0); + +// definitions for memory backed mappings +#define PROT_MEM (PROT_WRITE | PROT_READ) +#define MAP_MEM (MAP_ANONYMOUS | MAP_PRIVATE) + +// 128KiB +#define OUTPUT_FILE_SIZE (128 * 1024) + +struct mmap_file { + uint8_t *data, *cursor; + off_t size, offset; + int prot, flags; +}; + +/* mmap_file.c */ +struct mmap_file create_mmap_from_file(const char *, int); +int read_from_mmap(struct mmap_file *, int); +int write_into_mmap(struct mmap_file *, const uint8_t *, int); + +/* encrypt.c */ +struct mmap_file encrypt_mmap(struct mmap_file, uint8_t **, uint8_t **); +struct mmap_file decrypt_mmap(struct mmap_file, const uint8_t *, const uint8_t *); + +#endif // __MMAP_FILE_H_ diff --git a/purr.c b/purr.c index b559f59..c0aceb6 100644 --- a/purr.c +++ b/purr.c @@ -9,6 +9,7 @@ #include #include "purr.h" +#include "mmap_file.h" __attribute__ ((noreturn)) static void usage(bool fail) @@ -89,7 +90,7 @@ int main (int argc, char **argv) } struct mmap_file input; - struct mmap_file output = create_mmap_from_file(NULL, PROT_WRITE | PROT_READ); + struct mmap_file output = create_mmap_from_file(NULL, PROT_MEM); if (ERROR_MMAP(output)) { perror("couldn't open output file"); exit(EXIT_FAILURE); diff --git a/purr.h b/purr.h index cf0024e..5c71728 100644 --- a/purr.h +++ b/purr.h @@ -4,7 +4,6 @@ #include #include #include -#include #include @@ -22,10 +21,6 @@ #define ENCODE_BASE_64 #define DECODE_BASE_64 -#define RESET_MMAP(file) do{(file).offset = 0; (file).cursor = 0}while(0); -#define ERROR_MMAP(file) ((file).data == MAP_FAILED || (file).data == NULL) -#define CLOSE_MMAP(file) do{if((file).data != MAP_FAILED && (file).data != NULL) munmap((file).data, (file).size);}while(0); - struct connection_information { br_sslio_context *ioc; br_ssl_client_context *sc; @@ -44,12 +39,6 @@ struct transmission_information { bool no_strip, debug, ssl; }; -struct mmap_file { - uint8_t *data, *cursor; - off_t size, offset; - int prot, flags; -}; - /* sockets.c */ int socket_read(void *, uint8_t *, size_t); int socket_write(void *, const uint8_t *, size_t); @@ -60,9 +49,6 @@ int get_encryption_params(char *, uint8_t **, uint8_t **); int host_connect(const char *, const char *, bool); /* files.c */ -struct mmap_file create_mmap_from_file(const char *, int); -int read_from_mmap(struct mmap_file *, int); -int write_into_mmap(struct mmap_file *, const uint8_t *, int); size_t ssl_to_mmap(struct transmission_information); size_t mmap_to_ssl(struct transmission_information); @@ -73,8 +59,4 @@ int send_and_receive(struct connection_information *); char *print_hex(const uint8_t *, int, bool); int decode_hex(const char *, uint8_t *, int); -/* encrypt.c */ -struct mmap_file encrypt_mmap(struct mmap_file, uint8_t **, uint8_t **); -struct mmap_file decrypt_mmap(struct mmap_file, const uint8_t *, const uint8_t *); - #endif // __PURR_H_