2
* Unix SMB/CIFS implementation.
3
* Eventlog utility routines
4
* Copyright (C) Marcin Krzysztof Porwit 2005,
5
* Copyright (C) Brian Moran 2005.
6
* Copyright (C) Gerald (Jerry) Carter 2005.
7
* Copyright (C) Guenther Deschner 2009.
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 3 of the License, or
12
* (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, see <http://www.gnu.org/licenses/>.
25
/* maintain a list of open eventlog tdbs with reference counts */
27
static ELOG_TDB *open_elog_list;
29
/********************************************************************
30
Init an Eventlog TDB, and return it. If null, something bad
32
********************************************************************/
34
TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
38
DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
41
tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT,
42
O_RDWR|O_CREAT|O_TRUNC, 0660 );
45
DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
49
/* initialize with defaults, copy real values in here from registry */
51
tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 );
52
tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 );
53
tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 );
54
tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 );
56
tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
61
/********************************************************************
62
make the tdb file name for an event log, given destination buffer
63
and size. Caller must free memory.
64
********************************************************************/
66
char *elog_tdbname(TALLOC_CTX *ctx, const char *name )
68
char *path = talloc_asprintf(ctx, "%s/%s.tdb",
69
state_path("eventlog"),
79
/********************************************************************
80
this function is used to count up the number of bytes in a
82
********************************************************************/
84
struct trav_size_struct {
89
static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
92
struct trav_size_struct *tsize = (struct trav_size_struct *)state;
94
tsize->size += data.dsize;
100
/********************************************************************
101
returns the size of the eventlog, and if MaxSize is a non-null
102
ptr, puts the MaxSize there. This is purely a way not to have yet
103
another function that solely reads the maxsize of the eventlog.
105
********************************************************************/
107
int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
109
struct trav_size_struct tsize;
114
ZERO_STRUCT( tsize );
116
tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
118
if ( MaxSize != NULL ) {
119
*MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
122
if ( Retention != NULL ) {
123
*Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
127
( "eventlog size: [%d] for [%d] records\n", tsize.size,
132
/********************************************************************
133
Discard early event logs until we have enough for 'needed' bytes...
134
NO checking done beforehand to see that we actually need to do
135
this, and it's going to pluck records one-by-one. So, it's best
136
to determine that this needs to be done before doing it.
138
Setting whack_by_date to True indicates that eventlogs falling
139
outside of the retention range need to go...
141
return True if we made enough room to accommodate needed bytes
142
********************************************************************/
144
static bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32_t needed,
147
int32_t start_record, i, new_start;
149
int32_t reclen, tresv1, trecnum, timegen, timewr;
150
int nbytes, len, Retention, MaxSize;
152
time_t current_time, exp_time;
154
/* discard some eventlogs */
156
/* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
157
although records not necessarily guaranteed to have successive times */
161
tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
163
end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
164
start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
165
Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
166
MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
168
time( ¤t_time );
171
exp_time = current_time - Retention; /* discard older than exp_time */
173
/* todo - check for sanity in next_record */
177
( "MaxSize [%d] Retention [%d] Current Time [%u] exp_time [%u]\n",
178
MaxSize, Retention, (unsigned int)current_time, (unsigned int)exp_time ) );
180
( "Start Record [%u] End Record [%u]\n",
181
(unsigned int)start_record,
182
(unsigned int)end_record ));
184
for ( i = start_record; i < end_record; i++ ) {
185
/* read a record, add the amt to nbytes */
186
key.dsize = sizeof(int32_t);
187
key.dptr = (unsigned char *)&i;
188
ret = tdb_fetch( the_tdb, key );
189
if ( ret.dsize == 0 ) {
191
( "Can't find a record for the key, record [%d]\n",
193
tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
196
nbytes += ret.dsize; /* note this includes overhead */
198
len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
199
&tresv1, &trecnum, &timegen, &timewr );
201
DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
202
tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
203
SAFE_FREE( ret.dptr );
208
( "read record %u, record size is [%d], total so far [%d]\n",
209
(unsigned int)i, reclen, nbytes ) );
211
SAFE_FREE( ret.dptr );
213
/* note that other servers may just stop writing records when the size limit
214
is reached, and there are no records older than 'retention'. This doesn't
215
like a very useful thing to do, so instead we whack (as in sleeps with the
216
fishes) just enough records to fit the what we need. This behavior could
217
be changed to 'match', if the need arises. */
219
if ( !whack_by_date && ( nbytes >= needed ) )
221
if ( whack_by_date && ( timegen >= exp_time ) )
226
( "nbytes [%d] needed [%d] start_record is [%u], should be set to [%u]\n",
227
nbytes, needed, (unsigned int)start_record, (unsigned int)i ) );
228
/* todo - remove eventlog entries here and set starting record to start_record... */
230
if ( start_record != new_start ) {
231
for ( i = start_record; i < new_start; i++ ) {
232
key.dsize = sizeof(int32_t);
233
key.dptr = (unsigned char *)&i;
234
tdb_delete( the_tdb, key );
237
tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
239
tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
243
/********************************************************************
244
some hygiene for an eventlog - see how big it is, and then
245
calculate how many bytes we need to remove
246
********************************************************************/
248
bool prune_eventlog( TDB_CONTEXT * tdb )
250
int MaxSize, Retention, CalcdSize;
253
DEBUG( 4, ( "No eventlog tdb handle\n" ) );
257
CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
259
( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
262
if ( CalcdSize > MaxSize ) {
263
return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
267
return make_way_for_eventlogs( tdb, 0, True );
270
/********************************************************************
271
********************************************************************/
273
static bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed )
276
int MaxSize, Retention;
278
/* see if we can write to the eventlog -- do a policy enforcement */
280
return False; /* tdb is null, so we can't write to it */
288
calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
290
if ( calcd_size <= MaxSize )
291
return True; /* you betcha */
292
if ( calcd_size + needed < MaxSize )
295
if ( Retention == 0xffffffff ) {
296
return False; /* see msdn - we can't write no room, discard */
299
note don't have to test, but always good to show intent, in case changes needed
303
if ( Retention == 0x00000000 ) {
304
/* discard record(s) */
305
/* todo - decide when to remove a bunch vs. just what we need... */
306
return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
310
return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
313
/*******************************************************************
314
*******************************************************************/
316
ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only )
318
TDB_CONTEXT *tdb = NULL;
321
char *tdbpath = NULL;
322
ELOG_TDB *tdb_node = NULL;
324
TALLOC_CTX *ctx = talloc_tos();
326
/* check for invalid options */
328
if (force_clear && read_only) {
329
DEBUG(1,("elog_open_tdb: Invalid flags\n"));
333
/* first see if we have an open context */
335
for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
336
if ( strequal( ptr->name, logname ) ) {
339
/* trick to alow clearing of the eventlog tdb.
340
The force_clear flag should imply that someone
341
has done a force close. So make sure the tdb
342
is NULL. If this is a normal open, then just
343
return the existing reference */
346
SMB_ASSERT( ptr->tdb == NULL );
354
/* make sure that the eventlog dir exists */
356
eventlogdir = state_path( "eventlog" );
357
if ( !directory_exist( eventlogdir ) )
358
mkdir( eventlogdir, 0755 );
360
/* get the path on disk */
362
tdbpath = elog_tdbname(ctx, logname);
367
DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
368
tdbpath, force_clear?"True":"False" ));
370
/* the tdb wasn't already open or this is a forced clear open */
372
if ( !force_clear ) {
374
tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, read_only ? O_RDONLY : O_RDWR , 0 );
376
vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
378
if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
379
DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
382
tdb = elog_init_tdb( tdbpath );
388
tdb = elog_init_tdb( tdbpath );
390
/* if we got a valid context, then add it to the list */
393
/* on a forced clear, just reset the tdb context if we already
394
have an open entry in the list */
401
if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
402
DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
407
tdb_node->name = talloc_strdup( tdb_node, logname );
409
tdb_node->ref_count = 1;
411
DLIST_ADD( open_elog_list, tdb_node );
417
/*******************************************************************
418
Wrapper to handle reference counts to the tdb
419
*******************************************************************/
421
int elog_close_tdb( ELOG_TDB *etdb, bool force_close )
430
SMB_ASSERT( etdb->ref_count >= 0 );
432
if ( etdb->ref_count == 0 ) {
434
DLIST_REMOVE( open_elog_list, etdb );
436
return tdb_close( tdb );
442
return tdb_close( tdb );
448
/********************************************************************
449
Note that it's a pretty good idea to initialize the Eventlog_entry
450
structure to zero's before calling parse_logentry on an batch of
451
lines that may resolve to a record. ALSO, it's a good idea to
452
remove any linefeeds (that's EOL to you and me) on the lines
454
********************************************************************/
456
bool parse_logentry( TALLOC_CTX *mem_ctx, char *line, struct eventlog_Record_tdb *entry, bool * eor )
458
char *start = NULL, *stop = NULL;
462
/* empty line signyfiying record delimeter, or we're at the end of the buffer */
463
if ( start == NULL || strlen( start ) == 0 ) {
465
( "parse_logentry: found end-of-record indicator.\n" ) );
469
if ( !( stop = strchr( line, ':' ) ) ) {
473
DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
475
if ( 0 == strncmp( start, "LEN", stop - start ) ) {
476
/* This will get recomputed later anyway -- probably not necessary */
477
entry->size = atoi( stop + 1 );
478
} else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
479
/* For now all these reserved entries seem to have the same value,
480
which can be hardcoded to int(1699505740) for now */
481
entry->reserved = talloc_strdup(mem_ctx, "eLfL");
482
} else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
483
entry->record_number = atoi( stop + 1 );
484
} else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
485
entry->time_generated = atoi( stop + 1 );
486
} else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
487
entry->time_written = atoi( stop + 1 );
488
} else if ( 0 == strncmp( start, "EID", stop - start ) ) {
489
entry->event_id = atoi( stop + 1 );
490
} else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
491
if ( strstr( start, "ERROR" ) ) {
492
entry->event_type = EVENTLOG_ERROR_TYPE;
493
} else if ( strstr( start, "WARNING" ) ) {
494
entry->event_type = EVENTLOG_WARNING_TYPE;
495
} else if ( strstr( start, "INFO" ) ) {
496
entry->event_type = EVENTLOG_INFORMATION_TYPE;
497
} else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
498
entry->event_type = EVENTLOG_AUDIT_SUCCESS;
499
} else if ( strstr( start, "AUDIT_FAILURE" ) ) {
500
entry->event_type = EVENTLOG_AUDIT_FAILURE;
501
} else if ( strstr( start, "SUCCESS" ) ) {
502
entry->event_type = EVENTLOG_SUCCESS;
504
/* some other eventlog type -- currently not defined in MSDN docs, so error out */
510
else if(0 == strncmp(start, "NST", stop - start))
512
entry->num_of_strings = atoi(stop + 1);
515
else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
516
entry->event_category = atoi( stop + 1 );
517
} else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
518
entry->reserved_flags = atoi( stop + 1 );
519
} else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
520
entry->closing_record_number = atoi( stop + 1 );
521
} else if ( 0 == strncmp( start, "USL", stop - start ) ) {
522
entry->sid_length = atoi( stop + 1 );
523
} else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
525
while ( isspace( stop[0] ) ) {
528
entry->source_name_len = strlen_m_term(stop);
529
entry->source_name = talloc_strdup(mem_ctx, stop);
530
if (entry->source_name_len == (uint32_t)-1 ||
531
entry->source_name == NULL) {
534
} else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
536
while ( isspace( stop[0] ) ) {
539
entry->computer_name_len = strlen_m_term(stop);
540
entry->computer_name = talloc_strdup(mem_ctx, stop);
541
if (entry->computer_name_len == (uint32_t)-1 ||
542
entry->computer_name == NULL) {
545
} else if ( 0 == strncmp( start, "SID", stop - start ) ) {
546
smb_ucs2_t *dummy = NULL;
548
while ( isspace( stop[0] ) ) {
551
entry->sid_length = rpcstr_push_talloc(mem_ctx,
554
if (entry->sid_length == (uint32_t)-1) {
557
entry->sid = data_blob_talloc(mem_ctx, dummy, entry->sid_length);
558
if (entry->sid.data == NULL) {
561
} else if ( 0 == strncmp( start, "STR", stop - start ) ) {
564
/* skip past initial ":" */
566
/* now skip any other leading whitespace */
567
while ( isspace(stop[0])) {
570
tmp_len = strlen_m_term(stop);
571
if (tmp_len == (size_t)-1) {
574
num_of_strings = entry->num_of_strings;
575
if (!add_string_to_array(mem_ctx, stop, &entry->strings,
579
if (num_of_strings > 0xffff) {
582
entry->num_of_strings = num_of_strings;
583
entry->strings_len += tmp_len;
584
} else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
585
/* skip past initial ":" */
587
/* now skip any other leading whitespace */
588
while ( isspace( stop[0] ) ) {
591
entry->data_length = strlen_m(stop);
592
entry->data = data_blob_talloc(mem_ctx, stop, entry->data_length);
593
if (!entry->data.data) {
597
/* some other eventlog entry -- not implemented, so dropping on the floor */
598
DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
599
/* For now return true so that we can keep on parsing this mess. Eventually
600
we will return False here. */
606
/*******************************************************************
607
calculate the correct fields etc for an eventlog entry
608
*******************************************************************/
610
size_t fixup_eventlog_record_tdb(struct eventlog_Record_tdb *r)
612
size_t size = 56; /* static size of integers before buffers start */
614
r->source_name_len = strlen_m_term(r->source_name) * 2;
615
r->computer_name_len = strlen_m_term(r->computer_name) * 2;
616
r->strings_len = ndr_size_string_array(r->strings,
617
r->num_of_strings, LIBNDR_FLAG_STR_NULLTERM) * 2;
619
/* fix up the eventlog entry structure as necessary */
620
r->sid_padding = ( ( 4 - ( ( r->source_name_len + r->computer_name_len ) % 4 ) ) % 4 );
621
r->padding = ( 4 - ( ( r->strings_len + r->data_length ) % 4 ) ) % 4;
623
if (r->sid_length == 0) {
624
/* Should not pad to a DWORD boundary for writing out the sid if there is
625
no SID, so just propagate the padding to pad the data */
626
r->padding += r->sid_padding;
630
size += r->source_name_len;
631
size += r->computer_name_len;
632
size += r->sid_padding;
633
size += r->sid_length;
634
size += r->strings_len;
635
size += r->data_length;
637
/* need another copy of length at the end of the data */
638
size += sizeof(r->size);
646
/********************************************************************
647
********************************************************************/
649
struct eventlog_Record_tdb *evlog_pull_record_tdb(TALLOC_CTX *mem_ctx,
651
uint32_t record_number)
653
struct eventlog_Record_tdb *r;
657
enum ndr_err_code ndr_err;
660
srecno = record_number;
661
key.dptr = (unsigned char *)&srecno;
662
key.dsize = sizeof(int32_t);
664
data = tdb_fetch(tdb, key);
665
if (data.dsize == 0) {
666
DEBUG(8,("evlog_pull_record_tdb: "
667
"Can't find a record for the key, record %d\n",
672
r = talloc_zero(mem_ctx, struct eventlog_Record_tdb);
677
blob = data_blob_const(data.dptr, data.dsize);
679
ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, r,
680
(ndr_pull_flags_fn_t)ndr_pull_eventlog_Record_tdb);
682
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
683
DEBUG(10,("evlog_pull_record_tdb: failed to decode record %d\n",
689
if (DEBUGLEVEL >= 10) {
690
NDR_PRINT_DEBUG(eventlog_Record_tdb, r);
693
DEBUG(10,("evlog_pull_record_tdb: retrieved entry for record %d\n",
696
SAFE_FREE(data.dptr);
701
/********************************************************************
702
********************************************************************/
704
struct EVENTLOGRECORD *evlog_pull_record(TALLOC_CTX *mem_ctx,
706
uint32_t record_number)
708
struct eventlog_Record_tdb *t;
709
struct EVENTLOGRECORD *r;
712
r = talloc_zero(mem_ctx, struct EVENTLOGRECORD);
717
t = evlog_pull_record_tdb(r, tdb, record_number);
723
status = evlog_tdb_entry_to_evt_entry(r, t, r);
724
if (!NT_STATUS_IS_OK(status)) {
729
r->Length = r->Length2 = ndr_size_EVENTLOGRECORD(r, NULL, 0);
734
/********************************************************************
735
write an eventlog entry. Note that we have to lock, read next
736
eventlog, increment, write, write the record, unlock
738
coming into this, ee has the eventlog record, and the auxilliary date
739
(computer name, etc.) filled into the other structure. Before packing
740
into a record, this routine will calc the appropriate padding, etc.,
741
and then blast out the record in a form that can be read back in
742
********************************************************************/
744
NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx,
746
struct eventlog_Record_tdb *r,
747
uint32_t *record_number)
751
enum ndr_err_code ndr_err;
755
return NT_STATUS_INVALID_PARAMETER;
758
if (!can_write_to_eventlog(tdb, r->size)) {
759
return NT_STATUS_EVENTLOG_CANT_START;
762
/* need to read the record number and insert it into the entry here */
765
ret = tdb_lock_bystring_with_timeout(tdb, EVT_NEXT_RECORD, 1);
767
return NT_STATUS_LOCK_NOT_GRANTED;
771
r->record_number = tdb_fetch_int32(tdb, EVT_NEXT_RECORD);
773
ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, r,
774
(ndr_push_flags_fn_t)ndr_push_eventlog_Record_tdb);
775
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
776
tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
777
return ndr_map_error2ntstatus(ndr_err);
780
/* increment the record count */
782
kbuf.dsize = sizeof(int32_t);
783
kbuf.dptr = (uint8_t *)&r->record_number;
785
ebuf.dsize = blob.length;
786
ebuf.dptr = blob.data;
788
ret = tdb_store(tdb, kbuf, ebuf, 0);
790
tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
791
return NT_STATUS_EVENTLOG_FILE_CORRUPT;
794
ret = tdb_store_int32(tdb, EVT_NEXT_RECORD, r->record_number + 1);
796
tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
797
return NT_STATUS_EVENTLOG_FILE_CORRUPT;
799
tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
802
*record_number = r->record_number;
808
/********************************************************************
809
********************************************************************/
811
NTSTATUS evlog_push_record(TALLOC_CTX *mem_ctx,
813
struct EVENTLOGRECORD *r,
814
uint32_t *record_number)
816
struct eventlog_Record_tdb *t;
819
t = talloc_zero(mem_ctx, struct eventlog_Record_tdb);
821
return NT_STATUS_NO_MEMORY;
824
status = evlog_evt_entry_to_tdb_entry(t, r, t);
825
if (!NT_STATUS_IS_OK(status)) {
830
status = evlog_push_record_tdb(mem_ctx, tdb, t, record_number);
836
/********************************************************************
837
********************************************************************/
839
NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx,
840
const struct EVENTLOGRECORD *e,
841
struct eventlog_Record_tdb *t)
848
t->reserved = e->Reserved;
849
t->record_number = e->RecordNumber;
850
t->time_generated = e->TimeGenerated;
851
t->time_written = e->TimeWritten;
852
t->event_id = e->EventID;
853
t->event_type = e->EventType;
854
t->num_of_strings = e->NumStrings;
855
t->event_category = e->EventCategory;
856
t->reserved_flags = e->ReservedFlags;
857
t->closing_record_number = e->ClosingRecordNumber;
859
t->stringoffset = e->StringOffset;
860
t->sid_length = e->UserSidLength;
861
t->sid_offset = e->UserSidOffset;
862
t->data_length = e->DataLength;
863
t->data_offset = e->DataOffset;
865
t->source_name_len = 2 * strlen_m_term(e->SourceName);
866
t->source_name = talloc_strdup(mem_ctx, e->SourceName);
867
NT_STATUS_HAVE_NO_MEMORY(t->source_name);
869
t->computer_name_len = 2 * strlen_m_term(e->Computername);
870
t->computer_name = talloc_strdup(mem_ctx, e->Computername);
871
NT_STATUS_HAVE_NO_MEMORY(t->computer_name);
873
/* t->sid_padding; */
874
if (e->UserSidLength > 0) {
875
const char *sid_str = NULL;
876
smb_ucs2_t *dummy = NULL;
877
sid_str = sid_string_talloc(mem_ctx, &e->UserSid);
878
t->sid_length = rpcstr_push_talloc(mem_ctx, &dummy, sid_str);
879
if (t->sid_length == -1) {
880
return NT_STATUS_NO_MEMORY;
882
t->sid = data_blob_talloc(mem_ctx, (uint8_t *)dummy, t->sid_length);
883
NT_STATUS_HAVE_NO_MEMORY(t->sid.data);
886
t->strings = talloc_array(mem_ctx, const char *, e->NumStrings);
887
for (i=0; i < e->NumStrings; i++) {
888
t->strings[i] = talloc_strdup(t->strings, e->Strings[i]);
889
NT_STATUS_HAVE_NO_MEMORY(t->strings[i]);
892
t->strings_len = 2 * ndr_size_string_array(t->strings, t->num_of_strings, LIBNDR_FLAG_STR_NULLTERM);
893
t->data = data_blob_talloc(mem_ctx, e->Data, e->DataLength);
894
/* t->padding = r->Pad; */
899
/********************************************************************
900
********************************************************************/
902
NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx,
903
const struct eventlog_Record_tdb *t,
904
struct EVENTLOGRECORD *e)
911
e->Reserved = t->reserved;
912
e->RecordNumber = t->record_number;
913
e->TimeGenerated = t->time_generated;
914
e->TimeWritten = t->time_written;
915
e->EventID = t->event_id;
916
e->EventType = t->event_type;
917
e->NumStrings = t->num_of_strings;
918
e->EventCategory = t->event_category;
919
e->ReservedFlags = t->reserved_flags;
920
e->ClosingRecordNumber = t->closing_record_number;
922
e->StringOffset = t->stringoffset;
923
e->UserSidLength = t->sid_length;
924
e->UserSidOffset = t->sid_offset;
925
e->DataLength = t->data_length;
926
e->DataOffset = t->data_offset;
928
e->SourceName = talloc_strdup(mem_ctx, t->source_name);
929
NT_STATUS_HAVE_NO_MEMORY(e->SourceName);
931
e->Computername = talloc_strdup(mem_ctx, t->computer_name);
932
NT_STATUS_HAVE_NO_MEMORY(e->Computername);
934
if (t->sid_length > 0) {
935
const char *sid_str = NULL;
937
if (!convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
938
t->sid.data, t->sid.length,
939
(void **)&sid_str, &len, false)) {
940
return NT_STATUS_INVALID_SID;
943
e->UserSid = *string_sid_talloc(mem_ctx, sid_str);
947
e->Strings = talloc_array(mem_ctx, const char *, t->num_of_strings);
948
for (i=0; i < t->num_of_strings; i++) {
949
e->Strings[i] = talloc_strdup(e->Strings, t->strings[i]);
950
NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]);
953
e->Data = (uint8_t *)talloc_memdup(mem_ctx, t->data.data, t->data_length);
954
e->Pad = talloc_strdup(mem_ctx, "");
955
NT_STATUS_HAVE_NO_MEMORY(e->Pad);
957
e->Length2 = t->size;
962
/********************************************************************
963
********************************************************************/
965
NTSTATUS evlog_convert_tdb_to_evt(TALLOC_CTX *mem_ctx,
968
uint32_t *num_records_p)
970
NTSTATUS status = NT_STATUS_OK;
971
enum ndr_err_code ndr_err;
973
uint32_t num_records = 0;
974
struct EVENTLOG_EVT_FILE evt;
976
size_t endoffset = 0;
982
struct eventlog_Record_tdb *r;
983
struct EVENTLOGRECORD e;
985
r = evlog_pull_record_tdb(mem_ctx, etdb->tdb, count);
990
status = evlog_tdb_entry_to_evt_entry(mem_ctx, r, &e);
991
if (!NT_STATUS_IS_OK(status)) {
995
endoffset += ndr_size_EVENTLOGRECORD(&e, NULL, 0);
997
ADD_TO_ARRAY(mem_ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records);
1001
evt.hdr.StartOffset = 0x30;
1002
evt.hdr.EndOffset = evt.hdr.StartOffset + endoffset;
1003
evt.hdr.CurrentRecordNumber = count;
1004
evt.hdr.OldestRecordNumber = 1;
1005
evt.hdr.MaxSize = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE);
1007
evt.hdr.Retention = tdb_fetch_int32(etdb->tdb, EVT_RETENTION);
1009
if (DEBUGLEVEL >= 10) {
1010
NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr);
1013
evt.eof.BeginRecord = 0x30;
1014
evt.eof.EndRecord = evt.hdr.StartOffset + endoffset;
1015
evt.eof.CurrentRecordNumber = evt.hdr.CurrentRecordNumber;
1016
evt.eof.OldestRecordNumber = evt.hdr.OldestRecordNumber;
1018
if (DEBUGLEVEL >= 10) {
1019
NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof);
1022
ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &evt,
1023
(ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE);
1024
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1025
status = ndr_map_error2ntstatus(ndr_err);
1030
*num_records_p = num_records;