added file and segment lengths to checksum.c
This commit is contained in:
@@ -44,12 +44,16 @@ int main(int argc, char* argv[])
|
|||||||
printf("#include <library.h>\n");
|
printf("#include <library.h>\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("integrity_checksum_t checksums[] = {\n");
|
printf("integrity_checksum_t checksums[] = {\n");
|
||||||
|
fprintf(stderr, "integrity test data:\n");
|
||||||
|
fprintf(stderr, "module name, file size / checksum segment size / checksum\n");
|
||||||
for (i = 1; i < argc; i++)
|
for (i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
char *name, *path, *sname = NULL;
|
char *name, *path, *sname = NULL;
|
||||||
void *handle, *symbol;
|
void *handle, *symbol;
|
||||||
u_int32_t fsum, ssum;
|
u_int32_t fsum, ssum;
|
||||||
|
size_t fsize = 0;
|
||||||
|
size_t ssize = 0;
|
||||||
|
|
||||||
path = argv[i];
|
path = argv[i];
|
||||||
|
|
||||||
if ((name = strstr(path, "libstrongswan-")))
|
if ((name = strstr(path, "libstrongswan-")))
|
||||||
@@ -79,7 +83,7 @@ int main(int argc, char* argv[])
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsum = integrity->build_file(integrity, path);
|
fsum = integrity->build_file(integrity, path, &fsize);
|
||||||
ssum = 0;
|
ssum = 0;
|
||||||
if (sname)
|
if (sname)
|
||||||
{
|
{
|
||||||
@@ -89,7 +93,7 @@ int main(int argc, char* argv[])
|
|||||||
symbol = dlsym(handle, sname);
|
symbol = dlsym(handle, sname);
|
||||||
if (symbol)
|
if (symbol)
|
||||||
{
|
{
|
||||||
ssum = integrity->build_segment(integrity, symbol);
|
ssum = integrity->build_segment(integrity, symbol, &ssize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -102,7 +106,10 @@ int main(int argc, char* argv[])
|
|||||||
fprintf(stderr, "dlopen failed: %s\n", dlerror());
|
fprintf(stderr, "dlopen failed: %s\n", dlerror());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\t{\"%-20s0x%08x, 0x%08x},\n", name, fsum, ssum);
|
printf("\t{\"%-20s%7u, 0x%08x, %6u, 0x%08x},\n",
|
||||||
|
name, fsize, fsum, ssize, ssum);
|
||||||
|
fprintf(stderr, "\"%-20s%7u / 0x%08x %6u / 0x%08x\n",
|
||||||
|
name, fsize, fsum, ssize, ssum);
|
||||||
free(name);
|
free(name);
|
||||||
}
|
}
|
||||||
printf("};\n");
|
printf("};\n");
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ struct private_integrity_checker_t {
|
|||||||
/**
|
/**
|
||||||
* Implementation of integrity_checker_t.build_file
|
* Implementation of integrity_checker_t.build_file
|
||||||
*/
|
*/
|
||||||
static u_int32_t build_file(private_integrity_checker_t *this, char *file)
|
static u_int32_t build_file(private_integrity_checker_t *this, char *file,
|
||||||
|
size_t *len)
|
||||||
{
|
{
|
||||||
u_int32_t checksum;
|
u_int32_t checksum;
|
||||||
chunk_t contents;
|
chunk_t contents;
|
||||||
@@ -71,13 +72,13 @@ static u_int32_t build_file(private_integrity_checker_t *this, char *file)
|
|||||||
fd = open(file, O_RDONLY);
|
fd = open(file, O_RDONLY);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
DBG1("opening '%s' failed: %s", file, strerror(errno));
|
DBG1(" opening '%s' failed: %s", file, strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstat(fd, &sb) == -1)
|
if (fstat(fd, &sb) == -1)
|
||||||
{
|
{
|
||||||
DBG1("getting file size of '%s' failed: %s", file, strerror(errno));
|
DBG1(" getting file size of '%s' failed: %s", file, strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -85,11 +86,12 @@ static u_int32_t build_file(private_integrity_checker_t *this, char *file)
|
|||||||
addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
if (addr == MAP_FAILED)
|
if (addr == MAP_FAILED)
|
||||||
{
|
{
|
||||||
DBG1("mapping '%s' failed: %s", file, strerror(errno));
|
DBG1(" mapping '%s' failed: %s", file, strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*len = sb.st_size;
|
||||||
contents = chunk_create(addr, sb.st_size);
|
contents = chunk_create(addr, sb.st_size);
|
||||||
checksum = chunk_hash(contents);
|
checksum = chunk_hash(contents);
|
||||||
|
|
||||||
@@ -136,24 +138,26 @@ static int callback(struct dl_phdr_info *dlpi, size_t size, Dl_info *dli)
|
|||||||
/**
|
/**
|
||||||
* Implementation of integrity_checker_t.build_segment
|
* Implementation of integrity_checker_t.build_segment
|
||||||
*/
|
*/
|
||||||
static u_int32_t build_segment(private_integrity_checker_t *this, void *sym)
|
static u_int32_t build_segment(private_integrity_checker_t *this, void *sym,
|
||||||
|
size_t *len)
|
||||||
{
|
{
|
||||||
chunk_t segment;
|
chunk_t segment;
|
||||||
Dl_info dli;
|
Dl_info dli;
|
||||||
|
|
||||||
if (dladdr(sym, &dli) == 0)
|
if (dladdr(sym, &dli) == 0)
|
||||||
{
|
{
|
||||||
DBG1("unable to locate symbol: %s", dlerror());
|
DBG1(" unable to locate symbol: %s", dlerror());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* we reuse the Dl_info struct as in/out parameter */
|
/* we reuse the Dl_info struct as in/out parameter */
|
||||||
if (!dl_iterate_phdr((void*)callback, &dli))
|
if (!dl_iterate_phdr((void*)callback, &dli))
|
||||||
{
|
{
|
||||||
DBG1("executable section not found");
|
DBG1(" executable section not found");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
segment = chunk_create(dli.dli_fbase, dli.dli_saddr - dli.dli_fbase);
|
segment = chunk_create(dli.dli_fbase, dli.dli_saddr - dli.dli_fbase);
|
||||||
|
*len = segment.len;
|
||||||
return chunk_hash(segment);
|
return chunk_hash(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,6 +187,7 @@ static bool check_file(private_integrity_checker_t *this,
|
|||||||
{
|
{
|
||||||
integrity_checksum_t *cs;
|
integrity_checksum_t *cs;
|
||||||
u_int32_t sum;
|
u_int32_t sum;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
cs = find_checksum(this, name);
|
cs = find_checksum(this, name);
|
||||||
if (!cs)
|
if (!cs)
|
||||||
@@ -190,8 +195,18 @@ static bool check_file(private_integrity_checker_t *this,
|
|||||||
DBG1(" '%s' file checksum not found", name);
|
DBG1(" '%s' file checksum not found", name);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
sum = build_file(this, file);
|
sum = build_file(this, file, &len);
|
||||||
if (!sum || cs->file != sum)
|
if (!sum)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (cs->file_len != len)
|
||||||
|
{
|
||||||
|
DBG1(" invalid '%s' file size: %u bytes, expected %u bytes",
|
||||||
|
name, len, cs->file_len);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (cs->file != sum)
|
||||||
{
|
{
|
||||||
DBG1(" invalid '%s' file checksum: %08x, expected %08x",
|
DBG1(" invalid '%s' file checksum: %08x, expected %08x",
|
||||||
name, sum, cs->file);
|
name, sum, cs->file);
|
||||||
@@ -209,6 +224,7 @@ static bool check_segment(private_integrity_checker_t *this,
|
|||||||
{
|
{
|
||||||
integrity_checksum_t *cs;
|
integrity_checksum_t *cs;
|
||||||
u_int32_t sum;
|
u_int32_t sum;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
cs = find_checksum(this, name);
|
cs = find_checksum(this, name);
|
||||||
if (!cs)
|
if (!cs)
|
||||||
@@ -216,8 +232,18 @@ static bool check_segment(private_integrity_checker_t *this,
|
|||||||
DBG1(" '%s' segment checksum not found", name);
|
DBG1(" '%s' segment checksum not found", name);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
sum = build_segment(this, sym);
|
sum = build_segment(this, sym, &len);
|
||||||
if (!sum || cs->segment != sum)
|
if (!sum)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (cs->segment_len != len)
|
||||||
|
{
|
||||||
|
DBG1(" invalid '%s' segment size: %u bytes, expected %u bytes",
|
||||||
|
name, len, cs->segment_len);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (cs->segment != sum)
|
||||||
{
|
{
|
||||||
DBG1(" invalid '%s' segment checksum: %08x, expected %08x",
|
DBG1(" invalid '%s' segment checksum: %08x, expected %08x",
|
||||||
name, sum, cs->segment);
|
name, sum, cs->segment);
|
||||||
@@ -270,9 +296,9 @@ integrity_checker_t *integrity_checker_create(char *checksum_library)
|
|||||||
private_integrity_checker_t *this = malloc_thing(private_integrity_checker_t);
|
private_integrity_checker_t *this = malloc_thing(private_integrity_checker_t);
|
||||||
|
|
||||||
this->public.check_file = (bool(*)(integrity_checker_t*, char *name, char *file))check_file;
|
this->public.check_file = (bool(*)(integrity_checker_t*, char *name, char *file))check_file;
|
||||||
this->public.build_file = (u_int32_t(*)(integrity_checker_t*, char *file))build_file;
|
this->public.build_file = (u_int32_t(*)(integrity_checker_t*, char *file, size_t *len))build_file;
|
||||||
this->public.check_segment = (bool(*)(integrity_checker_t*, char *name, void *sym))check_segment;
|
this->public.check_segment = (bool(*)(integrity_checker_t*, char *name, void *sym))check_segment;
|
||||||
this->public.build_segment = (u_int32_t(*)(integrity_checker_t*, void *sym))build_segment;
|
this->public.build_segment = (u_int32_t(*)(integrity_checker_t*, void *sym, size_t *len))build_segment;
|
||||||
this->public.check = (bool(*)(integrity_checker_t*, char *name, void *sym))check;
|
this->public.check = (bool(*)(integrity_checker_t*, char *name, void *sym))check;
|
||||||
this->public.destroy = (void(*)(integrity_checker_t*))destroy;
|
this->public.destroy = (void(*)(integrity_checker_t*))destroy;
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,12 @@ typedef struct integrity_checksum_t integrity_checksum_t;
|
|||||||
struct integrity_checksum_t {
|
struct integrity_checksum_t {
|
||||||
/* name of the checksum */
|
/* name of the checksum */
|
||||||
char *name;
|
char *name;
|
||||||
|
/* size in bytes of the file on disk */
|
||||||
|
size_t file_len;
|
||||||
/* checksum of the file on disk */
|
/* checksum of the file on disk */
|
||||||
u_int32_t file;
|
u_int32_t file;
|
||||||
|
/* size in bytes of executable segment in memory */
|
||||||
|
size_t segment_len;
|
||||||
/* checksum of the executable segment in memory */
|
/* checksum of the executable segment in memory */
|
||||||
u_int32_t segment;
|
u_int32_t segment;
|
||||||
};
|
};
|
||||||
@@ -60,9 +64,10 @@ struct integrity_checker_t {
|
|||||||
* Build the integrity checksum of a file on disk.
|
* Build the integrity checksum of a file on disk.
|
||||||
*
|
*
|
||||||
* @param file path to file
|
* @param file path to file
|
||||||
|
* @param len return length in bytes of file
|
||||||
* @return checksum, 0 on error
|
* @return checksum, 0 on error
|
||||||
*/
|
*/
|
||||||
u_int32_t (*build_file)(integrity_checker_t *this, char *file);
|
u_int32_t (*build_file)(integrity_checker_t *this, char *file, size_t *len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the integrity of the code segment in memory.
|
* Check the integrity of the code segment in memory.
|
||||||
@@ -72,14 +77,14 @@ struct integrity_checker_t {
|
|||||||
* @return TRUE if integrity tested successfully
|
* @return TRUE if integrity tested successfully
|
||||||
*/
|
*/
|
||||||
bool (*check_segment)(integrity_checker_t *this, char *name, void *sym);
|
bool (*check_segment)(integrity_checker_t *this, char *name, void *sym);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the integrity checksum of a code segment in memory.
|
* Build the integrity checksum of a code segment in memory.
|
||||||
*
|
*
|
||||||
* @param sym a symbol in the segment to check
|
* @param sym a symbol in the segment to check
|
||||||
|
* @param len return length in bytes of code segment in memory
|
||||||
* @return checksum, 0 on error
|
* @return checksum, 0 on error
|
||||||
*/
|
*/
|
||||||
u_int32_t (*build_segment)(integrity_checker_t *this, void *sym);
|
u_int32_t (*build_segment)(integrity_checker_t *this, void *sym, size_t *len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check both, on disk file integrity and loaded segment.
|
* Check both, on disk file integrity and loaded segment.
|
||||||
|
|||||||
Reference in New Issue
Block a user