00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "includes.h"
00024
00025
00026
00027 static ELOG_TDB *open_elog_list;
00028
00029
00030
00031
00032
00033
00034 TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
00035 {
00036 TDB_CONTEXT *tdb;
00037
00038 DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
00039 tdbfilename));
00040
00041 tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT,
00042 O_RDWR|O_CREAT|O_TRUNC, 0660 );
00043
00044 if ( !tdb ) {
00045 DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
00046 return NULL;
00047 }
00048
00049
00050
00051 tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 );
00052 tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 );
00053 tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 );
00054 tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 );
00055
00056 tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
00057
00058 return tdb;
00059 }
00060
00061
00062
00063
00064
00065
00066 char *elog_tdbname( const char *name )
00067 {
00068 fstring path;
00069 char *tdb_fullpath;
00070 char *eventlogdir = lock_path( "eventlog" );
00071
00072 pstr_sprintf( path, "%s/%s.tdb", eventlogdir, name );
00073 strlower_m( path );
00074 tdb_fullpath = SMB_STRDUP( path );
00075
00076 return tdb_fullpath;
00077 }
00078
00079
00080
00081
00082
00083
00084
00085 struct trav_size_struct {
00086 int size;
00087 int rec_count;
00088 };
00089
00090 static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
00091 void *state )
00092 {
00093 struct trav_size_struct *tsize = state;
00094
00095 tsize->size += data.dsize;
00096 tsize->rec_count++;
00097
00098 return 0;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108 int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
00109 {
00110 struct trav_size_struct tsize;
00111
00112 if ( !tdb )
00113 return 0;
00114
00115 ZERO_STRUCT( tsize );
00116
00117 tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
00118
00119 if ( MaxSize != NULL ) {
00120 *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
00121 }
00122
00123 if ( Retention != NULL ) {
00124 *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
00125 }
00126
00127 DEBUG( 1,
00128 ( "eventlog size: [%d] for [%d] records\n", tsize.size,
00129 tsize.rec_count ) );
00130 return tsize.size;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
00146 BOOL whack_by_date )
00147 {
00148 int start_record, i, new_start;
00149 int end_record;
00150 int nbytes, reclen, len, Retention, MaxSize;
00151 int tresv1, trecnum, timegen, timewr;
00152 TDB_DATA key, ret;
00153 TALLOC_CTX *mem_ctx = NULL;
00154 time_t current_time, exp_time;
00155
00156
00157
00158
00159
00160
00161 mem_ctx = talloc_init( "make_way_for_eventlogs" );
00162
00163 if ( mem_ctx == NULL )
00164 return False;
00165
00166 tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
00167
00168 end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
00169 start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
00170 Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
00171 MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
00172
00173 time( ¤t_time );
00174
00175
00176 exp_time = current_time - Retention;
00177
00178
00179 nbytes = 0;
00180
00181 DEBUG( 3,
00182 ( "MaxSize [%d] Retention [%d] Current Time [%d] exp_time [%d]\n",
00183 MaxSize, Retention, (uint32)current_time, (uint32)exp_time ) );
00184 DEBUG( 3,
00185 ( "Start Record [%d] End Record [%d]\n", start_record,
00186 end_record ) );
00187
00188 for ( i = start_record; i < end_record; i++ ) {
00189
00190 key.dsize = sizeof( int32 );
00191 key.dptr = ( char * ) ( int32 * ) & i;
00192 ret = tdb_fetch( the_tdb, key );
00193 if ( ret.dsize == 0 ) {
00194 DEBUG( 8,
00195 ( "Can't find a record for the key, record [%d]\n",
00196 i ) );
00197 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
00198 return False;
00199 }
00200 nbytes += ret.dsize;
00201
00202 len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
00203 &tresv1, &trecnum, &timegen, &timewr );
00204 if (len == -1) {
00205 DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
00206 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
00207 return False;
00208 }
00209
00210 DEBUG( 8,
00211 ( "read record %d, record size is [%d], total so far [%d]\n",
00212 i, reclen, nbytes ) );
00213
00214 SAFE_FREE( ret.dptr );
00215
00216
00217
00218
00219
00220
00221
00222 if ( !whack_by_date && ( nbytes >= needed ) )
00223 break;
00224 if ( whack_by_date && ( timegen >= exp_time ) )
00225 break;
00226 }
00227
00228 DEBUG( 3,
00229 ( "nbytes [%d] needed [%d] start_record is [%d], should be set to [%d]\n",
00230 nbytes, needed, start_record, i ) );
00231
00232 new_start = i;
00233 if ( start_record != new_start ) {
00234 for ( i = start_record; i < new_start; i++ ) {
00235 key.dsize = sizeof( int32 );
00236 key.dptr = ( char * ) ( int32 * ) & i;
00237 tdb_delete( the_tdb, key );
00238 }
00239
00240 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
00241 }
00242 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
00243 return True;
00244 }
00245
00246
00247
00248
00249
00250
00251 BOOL prune_eventlog( TDB_CONTEXT * tdb )
00252 {
00253 int MaxSize, Retention, CalcdSize;
00254
00255 if ( !tdb ) {
00256 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
00257 return False;
00258 }
00259
00260 CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
00261 DEBUG( 3,
00262 ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
00263 MaxSize ) );
00264
00265 if ( CalcdSize > MaxSize ) {
00266 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
00267 False );
00268 }
00269
00270 return make_way_for_eventlogs( tdb, 0, True );
00271 }
00272
00273
00274
00275
00276 BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
00277 {
00278 int calcd_size;
00279 int MaxSize, Retention;
00280
00281
00282 if ( !tdb )
00283 return False;
00284
00285
00286 if ( needed < 0 )
00287 return False;
00288 MaxSize = 0;
00289 Retention = 0;
00290
00291 calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
00292
00293 if ( calcd_size <= MaxSize )
00294 return True;
00295 if ( calcd_size + needed < MaxSize )
00296 return True;
00297
00298 if ( Retention == 0xffffffff ) {
00299 return False;
00300 }
00301
00302
00303
00304
00305
00306 if ( Retention == 0x00000000 ) {
00307
00308
00309 return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
00310 True );
00311 }
00312
00313 return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
00314 }
00315
00316
00317
00318
00319 ELOG_TDB *elog_open_tdb( char *logname, BOOL force_clear )
00320 {
00321 TDB_CONTEXT *tdb = NULL;
00322 uint32 vers_id;
00323 ELOG_TDB *ptr;
00324 char *tdbfilename;
00325 pstring tdbpath;
00326 ELOG_TDB *tdb_node = NULL;
00327 char *eventlogdir;
00328
00329
00330
00331 for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
00332 if ( strequal( ptr->name, logname ) ) {
00333 ptr->ref_count++;
00334
00335
00336
00337
00338
00339
00340
00341 if ( force_clear ) {
00342 SMB_ASSERT( ptr->tdb == NULL );
00343 break;
00344 }
00345 else
00346 return ptr;
00347 }
00348 }
00349
00350
00351
00352 eventlogdir = lock_path( "eventlog" );
00353 if ( !directory_exist( eventlogdir, NULL ) )
00354 mkdir( eventlogdir, 0755 );
00355
00356
00357
00358 tdbfilename = elog_tdbname( logname );
00359 pstrcpy( tdbpath, tdbfilename );
00360 SAFE_FREE( tdbfilename );
00361
00362 DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
00363 tdbpath, force_clear?"True":"False" ));
00364
00365
00366
00367 if ( !force_clear ) {
00368
00369 tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 );
00370 if ( tdb ) {
00371 vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
00372
00373 if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
00374 DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
00375 vers_id, tdbpath));
00376 tdb_close( tdb );
00377 tdb = elog_init_tdb( tdbpath );
00378 }
00379 }
00380 }
00381
00382 if ( !tdb )
00383 tdb = elog_init_tdb( tdbpath );
00384
00385
00386
00387 if ( tdb ) {
00388
00389
00390
00391 if ( ptr ) {
00392 ptr->tdb = tdb;
00393 return ptr;
00394 }
00395
00396 if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
00397 DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
00398 tdb_close( tdb );
00399 return NULL;
00400 }
00401
00402 tdb_node->name = talloc_strdup( tdb_node, logname );
00403 tdb_node->tdb = tdb;
00404 tdb_node->ref_count = 1;
00405
00406 DLIST_ADD( open_elog_list, tdb_node );
00407 }
00408
00409 return tdb_node;
00410 }
00411
00412
00413
00414
00415
00416 int elog_close_tdb( ELOG_TDB *etdb, BOOL force_close )
00417 {
00418 TDB_CONTEXT *tdb;
00419
00420 if ( !etdb )
00421 return 0;
00422
00423 etdb->ref_count--;
00424
00425 SMB_ASSERT( etdb->ref_count >= 0 );
00426
00427 if ( etdb->ref_count == 0 ) {
00428 tdb = etdb->tdb;
00429 DLIST_REMOVE( open_elog_list, etdb );
00430 TALLOC_FREE( etdb );
00431 return tdb_close( tdb );
00432 }
00433
00434 if ( force_close ) {
00435 tdb = etdb->tdb;
00436 etdb->tdb = NULL;
00437 return tdb_close( tdb );
00438 }
00439
00440 return 0;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 #define MARGIN 512
00455
00456 int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
00457 {
00458 int32 next_record;
00459 uint8 *packed_ee;
00460 TALLOC_CTX *mem_ctx = NULL;
00461 TDB_DATA kbuf, ebuf;
00462 uint32 n_packed;
00463
00464 if ( !ee )
00465 return 0;
00466
00467 mem_ctx = talloc_init( "write_eventlog_tdb" );
00468
00469 if ( mem_ctx == NULL )
00470 return 0;
00471
00472 if ( !ee )
00473 return 0;
00474
00475 if ( ee->record.time_generated == 0 )
00476 return 0;
00477
00478
00479
00480 fixup_eventlog_entry( ee );
00481
00482 if ( !can_write_to_eventlog( the_tdb, ee->record.length ) ) {
00483 DEBUG( 3, ( "Can't write to Eventlog, no room \n" ) );
00484 talloc_destroy( mem_ctx );
00485 return 0;
00486 }
00487
00488
00489 packed_ee = (uint8 *)TALLOC( mem_ctx, ee->record.length + MARGIN );
00490 if ( !packed_ee ) {
00491 talloc_destroy( mem_ctx );
00492 return 0;
00493 }
00494
00495
00496
00497
00498 tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
00499
00500 next_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
00501
00502 n_packed =
00503 tdb_pack( (char *)packed_ee, ee->record.length + MARGIN,
00504 "ddddddwwwwddddddBBdBBBd", ee->record.length,
00505 ee->record.reserved1, next_record,
00506 ee->record.time_generated, ee->record.time_written,
00507 ee->record.event_id, ee->record.event_type,
00508 ee->record.num_strings, ee->record.event_category,
00509 ee->record.reserved2,
00510 ee->record.closing_record_number,
00511 ee->record.string_offset,
00512 ee->record.user_sid_length,
00513 ee->record.user_sid_offset, ee->record.data_length,
00514 ee->record.data_offset,
00515 ee->data_record.source_name_len,
00516 ee->data_record.source_name,
00517 ee->data_record.computer_name_len,
00518 ee->data_record.computer_name,
00519 ee->data_record.sid_padding,
00520 ee->record.user_sid_length, ee->data_record.sid,
00521 ee->data_record.strings_len,
00522 ee->data_record.strings,
00523 ee->data_record.user_data_len,
00524 ee->data_record.user_data,
00525 ee->data_record.data_padding );
00526
00527
00528
00529
00530
00531 kbuf.dsize = sizeof( int32 );
00532 kbuf.dptr = (char * ) & next_record;
00533
00534 ebuf.dsize = n_packed;
00535 ebuf.dptr = (char *)packed_ee;
00536
00537 if ( tdb_store( the_tdb, kbuf, ebuf, 0 ) ) {
00538
00539 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
00540 talloc_destroy( mem_ctx );
00541 return 0;
00542 }
00543 next_record++;
00544 tdb_store_int32( the_tdb, EVT_NEXT_RECORD, next_record );
00545 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
00546 talloc_destroy( mem_ctx );
00547 return ( next_record - 1 );
00548 }
00549
00550
00551
00552
00553
00554 void fixup_eventlog_entry( Eventlog_entry * ee )
00555 {
00556
00557
00558 ee->data_record.sid_padding =
00559 ( ( 4 -
00560 ( ( ee->data_record.source_name_len +
00561 ee->data_record.computer_name_len ) % 4 ) ) % 4 );
00562 ee->data_record.data_padding =
00563 ( 4 -
00564 ( ( ee->data_record.strings_len +
00565 ee->data_record.user_data_len ) % 4 ) ) % 4;
00566 ee->record.length = sizeof( Eventlog_record );
00567 ee->record.length += ee->data_record.source_name_len;
00568 ee->record.length += ee->data_record.computer_name_len;
00569 if ( ee->record.user_sid_length == 0 ) {
00570
00571
00572 ee->data_record.data_padding += ee->data_record.sid_padding;
00573 ee->data_record.sid_padding = 0;
00574 }
00575
00576
00577
00578 ee->record.length += ee->data_record.sid_padding;
00579 ee->record.length += ee->record.user_sid_length;
00580 ee->record.length += ee->data_record.strings_len;
00581 ee->record.length += ee->data_record.user_data_len;
00582 ee->record.length += ee->data_record.data_padding;
00583
00584 ee->record.length += sizeof( ee->record.length );
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 BOOL parse_logentry( char *line, Eventlog_entry * entry, BOOL * eor )
00596 {
00597 char *start = NULL, *stop = NULL;
00598 pstring temp;
00599 int temp_len = 0;
00600
00601 start = line;
00602
00603
00604 if ( start == NULL || strlen( start ) == 0 ) {
00605 DEBUG( 6,
00606 ( "parse_logentry: found end-of-record indicator.\n" ) );
00607 *eor = True;
00608 return True;
00609 }
00610 if ( !( stop = strchr( line, ':' ) ) ) {
00611 return False;
00612 }
00613
00614 DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
00615
00616 if ( 0 == strncmp( start, "LEN", stop - start ) ) {
00617
00618 entry->record.length = atoi( stop + 1 );
00619 } else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
00620
00621
00622 entry->record.reserved1 = atoi( stop + 1 );
00623 } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
00624 entry->record.record_number = atoi( stop + 1 );
00625 } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
00626 entry->record.time_generated = atoi( stop + 1 );
00627 } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
00628 entry->record.time_written = atoi( stop + 1 );
00629 } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
00630 entry->record.event_id = atoi( stop + 1 );
00631 } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
00632 if ( strstr( start, "ERROR" ) ) {
00633 entry->record.event_type = EVENTLOG_ERROR_TYPE;
00634 } else if ( strstr( start, "WARNING" ) ) {
00635 entry->record.event_type = EVENTLOG_WARNING_TYPE;
00636 } else if ( strstr( start, "INFO" ) ) {
00637 entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
00638 } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
00639 entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
00640 } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
00641 entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
00642 } else if ( strstr( start, "SUCCESS" ) ) {
00643 entry->record.event_type = EVENTLOG_SUCCESS;
00644 } else {
00645
00646 return False;
00647 }
00648 }
00649
00650
00651
00652
00653
00654
00655
00656 else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
00657 entry->record.event_category = atoi( stop + 1 );
00658 } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
00659 entry->record.reserved2 = atoi( stop + 1 );
00660 } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
00661 entry->record.closing_record_number = atoi( stop + 1 );
00662 } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
00663 entry->record.user_sid_length = atoi( stop + 1 );
00664 } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
00665 memset( temp, 0, sizeof( temp ) );
00666 stop++;
00667 while ( isspace( stop[0] ) ) {
00668 stop++;
00669 }
00670 temp_len = strlen( stop );
00671 strncpy( temp, stop, temp_len );
00672 rpcstr_push( ( void * ) ( entry->data_record.source_name ),
00673 temp, sizeof( entry->data_record.source_name ),
00674 STR_TERMINATE );
00675 entry->data_record.source_name_len =
00676 ( strlen_w( entry->data_record.source_name ) * 2 ) +
00677 2;
00678 } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
00679 memset( temp, 0, sizeof( temp ) );
00680 stop++;
00681 while ( isspace( stop[0] ) ) {
00682 stop++;
00683 }
00684 temp_len = strlen( stop );
00685 strncpy( temp, stop, temp_len );
00686 rpcstr_push( ( void * ) ( entry->data_record.computer_name ),
00687 temp, sizeof( entry->data_record.computer_name ),
00688 STR_TERMINATE );
00689 entry->data_record.computer_name_len =
00690 ( strlen_w( entry->data_record.computer_name ) * 2 ) +
00691 2;
00692 } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
00693 memset( temp, 0, sizeof( temp ) );
00694 stop++;
00695 while ( isspace( stop[0] ) ) {
00696 stop++;
00697 }
00698 temp_len = strlen( stop );
00699 strncpy( temp, stop, temp_len );
00700 rpcstr_push( ( void * ) ( entry->data_record.sid ), temp,
00701 sizeof( entry->data_record.sid ),
00702 STR_TERMINATE );
00703 entry->record.user_sid_length =
00704 ( strlen_w( entry->data_record.sid ) * 2 ) + 2;
00705 } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
00706
00707 stop++;
00708
00709 while ( isspace( stop[0] ) ) {
00710 stop++;
00711 }
00712 temp_len = strlen( stop );
00713 memset( temp, 0, sizeof( temp ) );
00714 strncpy( temp, stop, temp_len );
00715 rpcstr_push( ( void * ) ( entry->data_record.strings +
00716 ( entry->data_record.strings_len / 2 ) ),
00717 temp,
00718 sizeof( entry->data_record.strings ) -
00719 ( entry->data_record.strings_len / 2 ), STR_TERMINATE );
00720 entry->data_record.strings_len += ( temp_len * 2 ) + 2;
00721 entry->record.num_strings++;
00722 } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
00723
00724 stop++;
00725
00726 while ( isspace( stop[0] ) ) {
00727 stop++;
00728 }
00729 entry->data_record.user_data_len = strlen( stop );
00730 memset( entry->data_record.user_data, 0,
00731 sizeof( entry->data_record.user_data ) );
00732 if ( entry->data_record.user_data_len > 0 ) {
00733
00734 if ( entry->data_record.user_data_len >
00735 sizeof( entry->data_record.user_data ) )
00736 entry->data_record.user_data_len =
00737 sizeof( entry->data_record.
00738 user_data );
00739 memcpy( entry->data_record.user_data, stop,
00740 entry->data_record.user_data_len );
00741 }
00742 } else {
00743
00744 DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
00745
00746
00747 return True;
00748 }
00749 return True;
00750 }