fix buffer overflow

This commit is contained in:
olszomal 2021-04-21 12:41:23 +02:00 committed by Michał Trojnara
parent b01a2f5cd7
commit a161efdb25
3 changed files with 16 additions and 15 deletions

25
msi.c
View File

@ -154,9 +154,10 @@ int msi_file_read(MSI_FILE *msi, MSI_ENTRY *entry, size_t offset, char *buffer,
/* Parse MSI_FILE_HDR struct */ /* Parse MSI_FILE_HDR struct */
static MSI_FILE_HDR *parse_header(char *data) static MSI_FILE_HDR *parse_header(char *data)
{ {
MSI_FILE_HDR *header = (MSI_FILE_HDR *)OPENSSL_malloc(sizeof(MSI_FILE_HDR)); MSI_FILE_HDR *header = (MSI_FILE_HDR *)OPENSSL_malloc(HEADER_SIZE);
if (!data) { if (!data) {
memset(&header, 0, sizeof(MSI_FILE_HDR)); /* initialise 512 bytes */
memset(header, 0, sizeof(MSI_FILE_HDR));
} else { } else {
memcpy(header->signature, data + HEADER_SIGNATURE, sizeof(header->signature)); memcpy(header->signature, data + HEADER_SIGNATURE, sizeof(header->signature));
header->minorVersion = GET_UINT16_LE(data + HEADER_MINOR_VER); header->minorVersion = GET_UINT16_LE(data + HEADER_MINOR_VER);
@ -308,9 +309,9 @@ MSI_ENTRY *msi_signatures_get(MSI_DIRENT *dirent, MSI_ENTRY **dse)
for (i = 0; i < sk_MSI_DIRENT_num(dirent->children); i++) { for (i = 0; i < sk_MSI_DIRENT_num(dirent->children); i++) {
MSI_DIRENT *child = sk_MSI_DIRENT_value(dirent->children, i); MSI_DIRENT *child = sk_MSI_DIRENT_value(dirent->children, i);
if (!memcmp(child->name, digital_signature, sizeof(digital_signature))) { if (!memcmp(child->name, digital_signature, MIN(child->nameLen, sizeof(digital_signature)))) {
ds = child->entry; ds = child->entry;
} else if (dse && !memcmp(child->name, digital_signature_ex, sizeof(digital_signature_ex))) { } else if (dse && !memcmp(child->name, digital_signature_ex, MIN(child->nameLen, sizeof(digital_signature_ex)))) {
*dse = child->entry; *dse = child->entry;
} else { } else {
continue; continue;
@ -413,8 +414,8 @@ int msi_prehash_dir(MSI_DIRENT *dirent, BIO *hash, int is_root)
sk_MSI_DIRENT_sort(children); sk_MSI_DIRENT_sort(children);
for (i = 0; i < sk_MSI_DIRENT_num(children); i++) { for (i = 0; i < sk_MSI_DIRENT_num(children); i++) {
MSI_DIRENT *child = sk_MSI_DIRENT_value(children, i); MSI_DIRENT *child = sk_MSI_DIRENT_value(children, i);
if (is_root && (!memcmp(child->name, digital_signature, sizeof(digital_signature)) if (is_root && (!memcmp(child->name, digital_signature, MIN(child->nameLen, sizeof(digital_signature)))
|| !memcmp(child->name, digital_signature_ex, sizeof(digital_signature_ex)))) { || !memcmp(child->name, digital_signature_ex, MIN(child->nameLen, sizeof(digital_signature_ex))))) {
continue; continue;
} }
if (child->type == DIR_STREAM) { if (child->type == DIR_STREAM) {
@ -443,8 +444,8 @@ int msi_hash_dir(MSI_FILE *msi, MSI_DIRENT *dirent, BIO *hash, int is_root)
for (i = 0; i < sk_MSI_DIRENT_num(children); i++) { for (i = 0; i < sk_MSI_DIRENT_num(children); i++) {
MSI_DIRENT *child = sk_MSI_DIRENT_value(children, i); MSI_DIRENT *child = sk_MSI_DIRENT_value(children, i);
if (is_root && (!memcmp(child->name, digital_signature, sizeof(digital_signature)) if (is_root && (!memcmp(child->name, digital_signature, MIN(child->nameLen, sizeof(digital_signature)))
|| !memcmp(child->name, digital_signature_ex, sizeof(digital_signature_ex)))) { || !memcmp(child->name, digital_signature_ex, MIN(child->nameLen, sizeof(digital_signature_ex))))) {
continue; continue;
} }
if (child->type == DIR_STREAM) { if (child->type == DIR_STREAM) {
@ -536,13 +537,13 @@ static void fat_append(MSI_OUT *out, char *buf, int len)
out->fatLen += len; out->fatLen += len;
} }
int msi_dirent_delete(MSI_DIRENT *dirent, const u_char *name) int msi_dirent_delete(MSI_DIRENT *dirent, const u_char *name, uint16_t nameLen)
{ {
int i; int i;
for (i = 0; i < sk_MSI_DIRENT_num(dirent->children); i++) { for (i = 0; i < sk_MSI_DIRENT_num(dirent->children); i++) {
MSI_DIRENT *child = sk_MSI_DIRENT_value(dirent->children, i); MSI_DIRENT *child = sk_MSI_DIRENT_value(dirent->children, i);
if (memcmp(child->name, name, child->nameLen)) { if (memcmp(child->name, name, MIN(child->nameLen, nameLen))) {
continue; continue;
} }
if (child->type != DIR_STREAM) { if (child->type != DIR_STREAM) {
@ -587,7 +588,7 @@ static int dirent_insert(MSI_DIRENT *dirent, const u_char *name, uint16_t nameLe
{ {
MSI_DIRENT *new_dirent; MSI_DIRENT *new_dirent;
if (!msi_dirent_delete(dirent, name)) { if (!msi_dirent_delete(dirent, name, nameLen)) {
return 0; /* FAILED */ return 0; /* FAILED */
} }
/* create new dirent */ /* create new dirent */
@ -604,7 +605,7 @@ static int signature_insert(MSI_DIRENT *dirent, int len_msiex)
return 0; /* FAILED */ return 0; /* FAILED */
} }
} else { } else {
if (!msi_dirent_delete(dirent, digital_signature_ex)) { if (!msi_dirent_delete(dirent, digital_signature_ex, sizeof(digital_signature_ex))) {
return 0; /* FAILED */ return 0; /* FAILED */
} }
} }

2
msi.h
View File

@ -202,5 +202,5 @@ MSI_FILE_HDR *msi_header_get(MSI_FILE *msi);
int msi_prehash_dir(MSI_DIRENT *dirent, BIO *hash, int is_root); int msi_prehash_dir(MSI_DIRENT *dirent, BIO *hash, int is_root);
int msi_hash_dir(MSI_FILE *msi, MSI_DIRENT *dirent, BIO *hash, int is_root); int msi_hash_dir(MSI_FILE *msi, MSI_DIRENT *dirent, BIO *hash, int is_root);
void msi_calc_digest(char *indata, const EVP_MD *md, u_char *mdbuf, size_t fileend); void msi_calc_digest(char *indata, const EVP_MD *md, u_char *mdbuf, size_t fileend);
int msi_dirent_delete(MSI_DIRENT *dirent, const u_char *name); int msi_dirent_delete(MSI_DIRENT *dirent, const u_char *name, uint16_t nameLen);
int msi_file_write(MSI_FILE *msi, MSI_DIRENT *dirent, u_char *p, int len, u_char *p_msiex, int len_msiex, BIO *outdata); int msi_file_write(MSI_FILE *msi, MSI_DIRENT *dirent, u_char *p, int len, u_char *p_msiex, int len_msiex, BIO *outdata);

View File

@ -3076,10 +3076,10 @@ static int msi_extract_file(MSI_PARAMS *msiparams, BIO *outdata, int output_pkcs
static int msi_remove_file(MSI_PARAMS *msiparams, BIO *outdata) static int msi_remove_file(MSI_PARAMS *msiparams, BIO *outdata)
{ {
if (!msi_dirent_delete(msiparams->dirent, digital_signature_ex)) { if (!msi_dirent_delete(msiparams->dirent, digital_signature_ex, sizeof(digital_signature_ex))) {
return 1; /* FAILED */ return 1; /* FAILED */
} }
if (!msi_dirent_delete(msiparams->dirent, digital_signature)) { if (!msi_dirent_delete(msiparams->dirent, digital_signature, sizeof(digital_signature))) {
return 1; /* FAILED */ return 1; /* FAILED */
} }
if (!msi_file_write(msiparams->msi, msiparams->dirent, NULL, 0, NULL, 0, outdata)) { if (!msi_file_write(msiparams->msi, msiparams->dirent, NULL, 0, NULL, 0, outdata)) {