Split mmap_file implementation.

Also add some useful definitions.
This commit is contained in:
Érico Rolim 2020-09-14 00:28:00 -03:00
parent 52f7829b48
commit 06eb9d4222
7 changed files with 149 additions and 129 deletions

View File

@ -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;

103
files.c
View File

@ -3,15 +3,8 @@
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#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";

View File

@ -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)

106
mmap_file.c Normal file
View File

@ -0,0 +1,106 @@
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#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;
}

33
mmap_file.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef __MMAP_FILE_H_
#define __MMAP_FILE_H_
#include <stdint.h>
#include <sys/mman.h>
#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_

3
purr.c
View File

@ -9,6 +9,7 @@
#include <s6-networking/sbearssl.h>
#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);

18
purr.h
View File

@ -4,7 +4,6 @@
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <sys/mman.h>
#include <bearssl.h>
@ -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_