2012-08-16 03:51:54 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd .
Copyright 2012 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
( at your option ) any later version .
systemd 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
# include <stdio.h>
# include <unistd.h>
# include <fcntl.h>
# include "util.h"
# include "log.h"
# include "journal-file.h"
# include "journal-verify.h"
2012-08-18 02:40:03 +04:00
# include "journal-authenticate.h"
2012-08-16 03:51:54 +04:00
# define N_ENTRIES 6000
# define RANDOM_RANGE 77
2012-08-18 02:40:03 +04:00
static void bit_toggle ( const char * fn , uint64_t p ) {
uint8_t b ;
ssize_t r ;
int fd ;
fd = open ( fn , O_RDWR | O_CLOEXEC ) ;
assert ( fd > = 0 ) ;
r = pread ( fd , & b , 1 , p / 8 ) ;
assert ( r = = 1 ) ;
b ^ = 1 < < ( p % 8 ) ;
r = pwrite ( fd , & b , 1 , p / 8 ) ;
assert ( r = = 1 ) ;
close_nointr_nofail ( fd ) ;
}
static int raw_verify ( const char * fn , const char * verification_key ) {
JournalFile * f ;
int r ;
r = journal_file_open ( fn , O_RDONLY , 0666 , true , true , NULL , NULL , NULL , & f ) ;
if ( r < 0 )
return r ;
r = journal_file_verify ( f , verification_key , NULL , NULL , NULL , false ) ;
journal_file_close ( f ) ;
return r ;
}
2012-08-16 03:51:54 +04:00
int main ( int argc , char * argv [ ] ) {
char t [ ] = " /tmp/journal-XXXXXX " ;
unsigned n ;
JournalFile * f ;
2012-08-17 01:58:14 +04:00
const char * verification_key = argv [ 1 ] ;
2012-08-18 02:40:03 +04:00
usec_t from = 0 , to = 0 , total = 0 ;
2012-08-17 05:30:22 +04:00
char a [ FORMAT_TIMESTAMP_MAX ] ;
char b [ FORMAT_TIMESTAMP_MAX ] ;
char c [ FORMAT_TIMESPAN_MAX ] ;
2012-08-18 02:40:03 +04:00
struct stat st ;
uint64_t p ;
2012-08-16 03:51:54 +04:00
log_set_max_level ( LOG_DEBUG ) ;
assert_se ( mkdtemp ( t ) ) ;
assert_se ( chdir ( t ) > = 0 ) ;
log_info ( " Generating... " ) ;
2012-08-17 01:58:14 +04:00
assert_se ( journal_file_open ( " test.journal " , O_RDWR | O_CREAT , 0666 , true , ! ! verification_key , NULL , NULL , NULL , & f ) = = 0 ) ;
2012-08-16 03:51:54 +04:00
for ( n = 0 ; n < N_ENTRIES ; n + + ) {
struct iovec iovec ;
struct dual_timestamp ts ;
char * test ;
dual_timestamp_get ( & ts ) ;
assert_se ( asprintf ( & test , " RANDOM=%lu " , random ( ) % RANDOM_RANGE ) ) ;
iovec . iov_base = ( void * ) test ;
iovec . iov_len = strlen ( test ) ;
assert_se ( journal_file_append_entry ( f , & ts , & iovec , 1 , NULL , NULL , NULL ) = = 0 ) ;
free ( test ) ;
}
journal_file_close ( f ) ;
log_info ( " Verifying... " ) ;
2012-08-18 02:40:03 +04:00
assert_se ( journal_file_open ( " test.journal " , O_RDONLY , 0666 , true , true , NULL , NULL , NULL , & f ) = = 0 ) ;
2012-08-20 17:59:33 +04:00
/* journal_file_print_header(f); */
journal_file_dump ( f ) ;
2012-08-17 04:29:20 +04:00
2012-08-18 02:40:03 +04:00
assert_se ( journal_file_verify ( f , verification_key , & from , & to , & total , true ) > = 0 ) ;
2012-08-17 05:30:22 +04:00
2012-08-18 02:40:03 +04:00
if ( verification_key & & journal_file_fss_enabled ( f ) ) {
log_info ( " => Validated from %s to %s, %s missing " ,
format_timestamp ( a , sizeof ( a ) , from ) ,
format_timestamp ( b , sizeof ( b ) , to ) ,
format_timespan ( c , sizeof ( c ) , total > to ? total - to : 0 ) ) ;
}
2012-08-16 03:51:54 +04:00
journal_file_close ( f ) ;
2012-08-20 17:59:33 +04:00
if ( verification_key ) {
log_info ( " Toggling bits... " ) ;
2012-08-18 02:40:03 +04:00
2012-08-20 17:59:33 +04:00
assert_se ( stat ( " test.journal " , & st ) > = 0 ) ;
2012-08-18 02:40:03 +04:00
2012-08-20 17:59:33 +04:00
for ( p = 38448 * 8 + 0 ; p < ( ( uint64_t ) st . st_size * 8 ) ; p + + ) {
bit_toggle ( " test.journal " , p ) ;
2012-08-18 02:40:03 +04:00
2012-08-20 17:59:33 +04:00
log_info ( " [ %llu+%llu] " , ( unsigned long long ) p / 8 , ( unsigned long long ) p % 8 ) ;
2012-08-18 02:40:03 +04:00
2012-08-20 17:59:33 +04:00
if ( raw_verify ( " test.journal " , verification_key ) > = 0 )
log_notice ( ANSI_HIGHLIGHT_RED_ON " >>>> %llu (bit %llu) can be toggled without detection. " ANSI_HIGHLIGHT_OFF , ( unsigned long long ) p / 8 , ( unsigned long long ) p % 8 ) ;
2012-08-18 02:40:03 +04:00
2012-08-20 17:59:33 +04:00
bit_toggle ( " test.journal " , p ) ;
}
2012-08-18 02:40:03 +04:00
}
2012-08-16 03:51:54 +04:00
log_info ( " Exiting... " ) ;
assert_se ( rm_rf_dangerous ( t , false , true , false ) > = 0 ) ;
return 0 ;
}