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/>.
24 #include "lib/eventlog/eventlog.h"
26 /* maintain a list of open eventlog tdbs with reference counts */
28 static ELOG_TDB *open_elog_list;
30 /********************************************************************
31 Init an Eventlog TDB, and return it. If null, something bad
33 ********************************************************************/
35 TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
39 DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
42 tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT,
43 O_RDWR|O_CREAT|O_TRUNC, 0660 );
46 DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
50 /* initialize with defaults, copy real values in here from registry */
52 tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 );
53 tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 );
54 tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 );
55 tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 );
57 tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
62 /********************************************************************
63 make the tdb file name for an event log, given destination buffer
64 and size. Caller must free memory.
65 ********************************************************************/
67 char *elog_tdbname(TALLOC_CTX *ctx, const char *name )
73 path = talloc_strdup(ctx, state_path("eventlog"));
78 file = talloc_asprintf_strlower_m(path, "%s.tdb", name);
84 tdbname = talloc_asprintf(path, "%s/%s", state_path("eventlog"), file);
94 /********************************************************************
95 this function is used to count up the number of bytes in a
97 ********************************************************************/
99 struct trav_size_struct {
104 static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
107 struct trav_size_struct *tsize = (struct trav_size_struct *)state;
109 tsize->size += data.dsize;
115 /********************************************************************
116 returns the size of the eventlog, and if MaxSize is a non-null
117 ptr, puts the MaxSize there. This is purely a way not to have yet
118 another function that solely reads the maxsize of the eventlog.
120 ********************************************************************/
122 int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
124 struct trav_size_struct tsize;
129 ZERO_STRUCT( tsize );
131 tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
133 if ( MaxSize != NULL ) {
134 *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
137 if ( Retention != NULL ) {
138 *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
142 ( "eventlog size: [%d] for [%d] records\n", tsize.size,
147 /********************************************************************
148 Discard early event logs until we have enough for 'needed' bytes...
149 NO checking done beforehand to see that we actually need to do
150 this, and it's going to pluck records one-by-one. So, it's best
151 to determine that this needs to be done before doing it.
153 Setting whack_by_date to True indicates that eventlogs falling
154 outside of the retention range need to go...
156 return True if we made enough room to accommodate needed bytes
157 ********************************************************************/
159 static bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32_t needed,
162 int32_t start_record, i, new_start;
164 int32_t reclen, tresv1, trecnum, timegen, timewr;
165 int nbytes, len, Retention, MaxSize;
167 time_t current_time, exp_time;
169 /* discard some eventlogs */
171 /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
172 although records not necessarily guaranteed to have successive times */
176 tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
178 end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
179 start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
180 Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
181 MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
183 time( ¤t_time );
186 exp_time = current_time - Retention; /* discard older than exp_time */
188 /* todo - check for sanity in next_record */
192 ( "MaxSize [%d] Retention [%d] Current Time [%u] exp_time [%u]\n",
193 MaxSize, Retention, (unsigned int)current_time, (unsigned int)exp_time ) );
195 ( "Start Record [%u] End Record [%u]\n",
196 (unsigned int)start_record,
197 (unsigned int)end_record ));
199 for ( i = start_record; i < end_record; i++ ) {
200 /* read a record, add the amt to nbytes */
201 key.dsize = sizeof(int32_t);
202 key.dptr = (unsigned char *)&i;
203 ret = tdb_fetch( the_tdb, key );
204 if ( ret.dsize == 0 ) {
206 ( "Can't find a record for the key, record [%d]\n",
208 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
211 nbytes += ret.dsize; /* note this includes overhead */
213 len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
214 &tresv1, &trecnum, &timegen, &timewr );
216 DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
217 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
218 SAFE_FREE( ret.dptr );
223 ( "read record %u, record size is [%d], total so far [%d]\n",
224 (unsigned int)i, reclen, nbytes ) );
226 SAFE_FREE( ret.dptr );
228 /* note that other servers may just stop writing records when the size limit
229 is reached, and there are no records older than 'retention'. This doesn't
230 like a very useful thing to do, so instead we whack (as in sleeps with the
231 fishes) just enough records to fit the what we need. This behavior could
232 be changed to 'match', if the need arises. */
234 if ( !whack_by_date && ( nbytes >= needed ) )
236 if ( whack_by_date && ( timegen >= exp_time ) )
241 ( "nbytes [%d] needed [%d] start_record is [%u], should be set to [%u]\n",
242 nbytes, needed, (unsigned int)start_record, (unsigned int)i ) );
243 /* todo - remove eventlog entries here and set starting record to start_record... */
245 if ( start_record != new_start ) {
246 for ( i = start_record; i < new_start; i++ ) {
247 key.dsize = sizeof(int32_t);
248 key.dptr = (unsigned char *)&i;
249 tdb_delete( the_tdb, key );
252 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
254 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
258 /********************************************************************
259 some hygiene for an eventlog - see how big it is, and then
260 calculate how many bytes we need to remove
261 ********************************************************************/
263 bool prune_eventlog( TDB_CONTEXT * tdb )
265 int MaxSize, Retention, CalcdSize;
268 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
272 CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
274 ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
277 if ( CalcdSize > MaxSize ) {
278 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
282 return make_way_for_eventlogs( tdb, 0, True );
285 /********************************************************************
286 ********************************************************************/
288 static bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed )
291 int MaxSize, Retention;
293 /* see if we can write to the eventlog -- do a policy enforcement */
295 return False; /* tdb is null, so we can't write to it */
303 calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
305 if ( calcd_size <= MaxSize )
306 return True; /* you betcha */
307 if ( calcd_size + needed < MaxSize )
310 if ( Retention == 0xffffffff ) {
311 return False; /* see msdn - we can't write no room, discard */
314 note don't have to test, but always good to show intent, in case changes needed
318 if ( Retention == 0x00000000 ) {
319 /* discard record(s) */
320 /* todo - decide when to remove a bunch vs. just what we need... */
321 return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
325 return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
328 /*******************************************************************
329 *******************************************************************/
331 ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only )
333 TDB_CONTEXT *tdb = NULL;
336 char *tdbpath = NULL;
337 ELOG_TDB *tdb_node = NULL;
339 TALLOC_CTX *ctx = talloc_tos();
341 /* check for invalid options */
343 if (force_clear && read_only) {
344 DEBUG(1,("elog_open_tdb: Invalid flags\n"));
348 /* first see if we have an open context */
350 for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
351 if ( strequal( ptr->name, logname ) ) {
354 /* trick to alow clearing of the eventlog tdb.
355 The force_clear flag should imply that someone
356 has done a force close. So make sure the tdb
357 is NULL. If this is a normal open, then just
358 return the existing reference */
361 SMB_ASSERT( ptr->tdb == NULL );
369 /* make sure that the eventlog dir exists */
371 eventlogdir = state_path( "eventlog" );
372 if ( !directory_exist( eventlogdir ) )
373 mkdir( eventlogdir, 0755 );
375 /* get the path on disk */
377 tdbpath = elog_tdbname(ctx, logname);
382 DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
383 tdbpath, force_clear?"True":"False" ));
385 /* the tdb wasn't already open or this is a forced clear open */
387 if ( !force_clear ) {
389 tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, read_only ? O_RDONLY : O_RDWR , 0 );
391 vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
393 if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
394 DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
397 tdb = elog_init_tdb( tdbpath );
403 tdb = elog_init_tdb( tdbpath );
405 /* if we got a valid context, then add it to the list */
408 /* on a forced clear, just reset the tdb context if we already
409 have an open entry in the list */
416 if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
417 DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
422 tdb_node->name = talloc_strdup( tdb_node, logname );
424 tdb_node->ref_count = 1;
426 DLIST_ADD( open_elog_list, tdb_node );
432 /*******************************************************************
433 Wrapper to handle reference counts to the tdb
434 *******************************************************************/
436 int elog_close_tdb( ELOG_TDB *etdb, bool force_close )
445 SMB_ASSERT( etdb->ref_count >= 0 );
447 if ( etdb->ref_count == 0 ) {
449 DLIST_REMOVE( open_elog_list, etdb );
451 return tdb_close( tdb );
457 return tdb_close( tdb );
463 /********************************************************************
464 Note that it's a pretty good idea to initialize the Eventlog_entry
465 structure to zero's before calling parse_logentry on an batch of
466 lines that may resolve to a record. ALSO, it's a good idea to
467 remove any linefeeds (that's EOL to you and me) on the lines
469 ********************************************************************/
471 bool parse_logentry( TALLOC_CTX *mem_ctx, char *line, struct eventlog_Record_tdb *entry, bool * eor )
473 char *start = NULL, *stop = NULL;
477 /* empty line signyfiying record delimeter, or we're at the end of the buffer */
478 if ( start == NULL || strlen( start ) == 0 ) {
480 ( "parse_logentry: found end-of-record indicator.\n" ) );
484 if ( !( stop = strchr( line, ':' ) ) ) {
488 DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
490 if ( 0 == strncmp( start, "LEN", stop - start ) ) {
491 /* This will get recomputed later anyway -- probably not necessary */
492 entry->size = atoi( stop + 1 );
493 } else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
494 /* For now all these reserved entries seem to have the same value,
495 which can be hardcoded to int(1699505740) for now */
496 entry->reserved = talloc_strdup(mem_ctx, "eLfL");
497 } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
498 entry->record_number = atoi( stop + 1 );
499 } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
500 entry->time_generated = atoi( stop + 1 );
501 } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
502 entry->time_written = atoi( stop + 1 );
503 } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
504 entry->event_id = atoi( stop + 1 );
505 } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
506 if ( strstr( start, "ERROR" ) ) {
507 entry->event_type = EVENTLOG_ERROR_TYPE;
508 } else if ( strstr( start, "WARNING" ) ) {
509 entry->event_type = EVENTLOG_WARNING_TYPE;
510 } else if ( strstr( start, "INFO" ) ) {
511 entry->event_type = EVENTLOG_INFORMATION_TYPE;
512 } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
513 entry->event_type = EVENTLOG_AUDIT_SUCCESS;
514 } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
515 entry->event_type = EVENTLOG_AUDIT_FAILURE;
516 } else if ( strstr( start, "SUCCESS" ) ) {
517 entry->event_type = EVENTLOG_SUCCESS;
519 /* some other eventlog type -- currently not defined in MSDN docs, so error out */
525 else if(0 == strncmp(start, "NST", stop - start))
527 entry->num_of_strings = atoi(stop + 1);
530 else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
531 entry->event_category = atoi( stop + 1 );
532 } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
533 entry->reserved_flags = atoi( stop + 1 );
534 } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
535 entry->closing_record_number = atoi( stop + 1 );
536 } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
537 entry->sid_length = atoi( stop + 1 );
538 } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
540 while ( isspace( stop[0] ) ) {
543 entry->source_name_len = strlen_m_term(stop);
544 entry->source_name = talloc_strdup(mem_ctx, stop);
545 if (entry->source_name_len == (uint32_t)-1 ||
546 entry->source_name == NULL) {
549 } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
551 while ( isspace( stop[0] ) ) {
554 entry->computer_name_len = strlen_m_term(stop);
555 entry->computer_name = talloc_strdup(mem_ctx, stop);
556 if (entry->computer_name_len == (uint32_t)-1 ||
557 entry->computer_name == NULL) {
560 } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
561 smb_ucs2_t *dummy = NULL;
563 while ( isspace( stop[0] ) ) {
566 entry->sid_length = rpcstr_push_talloc(mem_ctx,
569 if (entry->sid_length == (uint32_t)-1) {
572 entry->sid = data_blob_talloc(mem_ctx, dummy, entry->sid_length);
573 if (entry->sid.data == NULL) {
576 } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
579 /* skip past initial ":" */
581 /* now skip any other leading whitespace */
582 while ( isspace(stop[0])) {
585 tmp_len = strlen_m_term(stop);
586 if (tmp_len == (size_t)-1) {
589 num_of_strings = entry->num_of_strings;
590 if (!add_string_to_array(mem_ctx, stop, &entry->strings,
594 if (num_of_strings > 0xffff) {
597 entry->num_of_strings = num_of_strings;
598 entry->strings_len += tmp_len;
599 } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
600 /* skip past initial ":" */
602 /* now skip any other leading whitespace */
603 while ( isspace( stop[0] ) ) {
606 entry->data_length = strlen_m(stop);
607 entry->data = data_blob_talloc(mem_ctx, stop, entry->data_length);
608 if (!entry->data.data) {
612 /* some other eventlog entry -- not implemented, so dropping on the floor */
613 DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
614 /* For now return true so that we can keep on parsing this mess. Eventually
615 we will return False here. */
621 /*******************************************************************
622 calculate the correct fields etc for an eventlog entry
623 *******************************************************************/
625 size_t fixup_eventlog_record_tdb(struct eventlog_Record_tdb *r)
627 size_t size = 56; /* static size of integers before buffers start */
629 r->source_name_len = strlen_m_term(r->source_name) * 2;
630 r->computer_name_len = strlen_m_term(r->computer_name) * 2;
631 r->strings_len = ndr_size_string_array(r->strings,
632 r->num_of_strings, LIBNDR_FLAG_STR_NULLTERM) * 2;
634 /* fix up the eventlog entry structure as necessary */
635 r->sid_padding = ( ( 4 - ( ( r->source_name_len + r->computer_name_len ) % 4 ) ) % 4 );
636 r->padding = ( 4 - ( ( r->strings_len + r->data_length ) % 4 ) ) % 4;
638 if (r->sid_length == 0) {
639 /* Should not pad to a DWORD boundary for writing out the sid if there is
640 no SID, so just propagate the padding to pad the data */
641 r->padding += r->sid_padding;
645 size += r->source_name_len;
646 size += r->computer_name_len;
647 size += r->sid_padding;
648 size += r->sid_length;
649 size += r->strings_len;
650 size += r->data_length;
652 /* need another copy of length at the end of the data */
653 size += sizeof(r->size);
661 /********************************************************************
662 ********************************************************************/
664 struct eventlog_Record_tdb *evlog_pull_record_tdb(TALLOC_CTX *mem_ctx,
666 uint32_t record_number)
668 struct eventlog_Record_tdb *r;
672 enum ndr_err_code ndr_err;
675 srecno = record_number;
676 key.dptr = (unsigned char *)&srecno;
677 key.dsize = sizeof(int32_t);
679 data = tdb_fetch(tdb, key);
680 if (data.dsize == 0) {
681 DEBUG(8,("evlog_pull_record_tdb: "
682 "Can't find a record for the key, record %d\n",
687 r = talloc_zero(mem_ctx, struct eventlog_Record_tdb);
692 blob = data_blob_const(data.dptr, data.dsize);
694 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, r,
695 (ndr_pull_flags_fn_t)ndr_pull_eventlog_Record_tdb);
697 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
698 DEBUG(10,("evlog_pull_record_tdb: failed to decode record %d\n",
704 if (DEBUGLEVEL >= 10) {
705 NDR_PRINT_DEBUG(eventlog_Record_tdb, r);
708 DEBUG(10,("evlog_pull_record_tdb: retrieved entry for record %d\n",
711 SAFE_FREE(data.dptr);
716 /********************************************************************
717 ********************************************************************/
719 struct EVENTLOGRECORD *evlog_pull_record(TALLOC_CTX *mem_ctx,
721 uint32_t record_number)
723 struct eventlog_Record_tdb *t;
724 struct EVENTLOGRECORD *r;
727 r = talloc_zero(mem_ctx, struct EVENTLOGRECORD);
732 t = evlog_pull_record_tdb(r, tdb, record_number);
738 status = evlog_tdb_entry_to_evt_entry(r, t, r);
739 if (!NT_STATUS_IS_OK(status)) {
744 r->Length = r->Length2 = ndr_size_EVENTLOGRECORD(r, NULL, 0);
749 /********************************************************************
750 write an eventlog entry. Note that we have to lock, read next
751 eventlog, increment, write, write the record, unlock
753 coming into this, ee has the eventlog record, and the auxilliary date
754 (computer name, etc.) filled into the other structure. Before packing
755 into a record, this routine will calc the appropriate padding, etc.,
756 and then blast out the record in a form that can be read back in
757 ********************************************************************/
759 NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx,
761 struct eventlog_Record_tdb *r,
762 uint32_t *record_number)
766 enum ndr_err_code ndr_err;
770 return NT_STATUS_INVALID_PARAMETER;
773 if (!can_write_to_eventlog(tdb, r->size)) {
774 return NT_STATUS_EVENTLOG_CANT_START;
777 /* need to read the record number and insert it into the entry here */
780 ret = tdb_lock_bystring_with_timeout(tdb, EVT_NEXT_RECORD, 1);
782 return NT_STATUS_LOCK_NOT_GRANTED;
786 r->record_number = tdb_fetch_int32(tdb, EVT_NEXT_RECORD);
788 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, r,
789 (ndr_push_flags_fn_t)ndr_push_eventlog_Record_tdb);
790 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
791 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
792 return ndr_map_error2ntstatus(ndr_err);
795 /* increment the record count */
797 kbuf.dsize = sizeof(int32_t);
798 kbuf.dptr = (uint8_t *)&r->record_number;
800 ebuf.dsize = blob.length;
801 ebuf.dptr = blob.data;
803 ret = tdb_store(tdb, kbuf, ebuf, 0);
805 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
806 return NT_STATUS_EVENTLOG_FILE_CORRUPT;
809 ret = tdb_store_int32(tdb, EVT_NEXT_RECORD, r->record_number + 1);
811 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
812 return NT_STATUS_EVENTLOG_FILE_CORRUPT;
814 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
817 *record_number = r->record_number;
823 /********************************************************************
824 ********************************************************************/
826 NTSTATUS evlog_push_record(TALLOC_CTX *mem_ctx,
828 struct EVENTLOGRECORD *r,
829 uint32_t *record_number)
831 struct eventlog_Record_tdb *t;
834 t = talloc_zero(mem_ctx, struct eventlog_Record_tdb);
836 return NT_STATUS_NO_MEMORY;
839 status = evlog_evt_entry_to_tdb_entry(t, r, t);
840 if (!NT_STATUS_IS_OK(status)) {
845 status = evlog_push_record_tdb(mem_ctx, tdb, t, record_number);
851 /********************************************************************
852 ********************************************************************/
854 NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx,
855 const struct EVENTLOGRECORD *e,
856 struct eventlog_Record_tdb *t)
863 t->reserved = e->Reserved;
864 t->record_number = e->RecordNumber;
865 t->time_generated = e->TimeGenerated;
866 t->time_written = e->TimeWritten;
867 t->event_id = e->EventID;
868 t->event_type = e->EventType;
869 t->num_of_strings = e->NumStrings;
870 t->event_category = e->EventCategory;
871 t->reserved_flags = e->ReservedFlags;
872 t->closing_record_number = e->ClosingRecordNumber;
874 t->stringoffset = e->StringOffset;
875 t->sid_length = e->UserSidLength;
876 t->sid_offset = e->UserSidOffset;
877 t->data_length = e->DataLength;
878 t->data_offset = e->DataOffset;
880 t->source_name_len = 2 * strlen_m_term(e->SourceName);
881 t->source_name = talloc_strdup(mem_ctx, e->SourceName);
882 NT_STATUS_HAVE_NO_MEMORY(t->source_name);
884 t->computer_name_len = 2 * strlen_m_term(e->Computername);
885 t->computer_name = talloc_strdup(mem_ctx, e->Computername);
886 NT_STATUS_HAVE_NO_MEMORY(t->computer_name);
888 /* t->sid_padding; */
889 if (e->UserSidLength > 0) {
890 const char *sid_str = NULL;
891 smb_ucs2_t *dummy = NULL;
892 sid_str = sid_string_talloc(mem_ctx, &e->UserSid);
893 t->sid_length = rpcstr_push_talloc(mem_ctx, &dummy, sid_str);
894 if (t->sid_length == -1) {
895 return NT_STATUS_NO_MEMORY;
897 t->sid = data_blob_talloc(mem_ctx, (uint8_t *)dummy, t->sid_length);
898 NT_STATUS_HAVE_NO_MEMORY(t->sid.data);
901 t->strings = talloc_array(mem_ctx, const char *, e->NumStrings);
902 for (i=0; i < e->NumStrings; i++) {
903 t->strings[i] = talloc_strdup(t->strings, e->Strings[i]);
904 NT_STATUS_HAVE_NO_MEMORY(t->strings[i]);
907 t->strings_len = 2 * ndr_size_string_array(t->strings, t->num_of_strings, LIBNDR_FLAG_STR_NULLTERM);
908 t->data = data_blob_talloc(mem_ctx, e->Data, e->DataLength);
909 /* t->padding = r->Pad; */
914 /********************************************************************
915 ********************************************************************/
917 NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx,
918 const struct eventlog_Record_tdb *t,
919 struct EVENTLOGRECORD *e)
926 e->Reserved = t->reserved;
927 e->RecordNumber = t->record_number;
928 e->TimeGenerated = t->time_generated;
929 e->TimeWritten = t->time_written;
930 e->EventID = t->event_id;
931 e->EventType = t->event_type;
932 e->NumStrings = t->num_of_strings;
933 e->EventCategory = t->event_category;
934 e->ReservedFlags = t->reserved_flags;
935 e->ClosingRecordNumber = t->closing_record_number;
937 e->StringOffset = t->stringoffset;
938 e->UserSidLength = t->sid_length;
939 e->UserSidOffset = t->sid_offset;
940 e->DataLength = t->data_length;
941 e->DataOffset = t->data_offset;
943 e->SourceName = talloc_strdup(mem_ctx, t->source_name);
944 NT_STATUS_HAVE_NO_MEMORY(e->SourceName);
946 e->Computername = talloc_strdup(mem_ctx, t->computer_name);
947 NT_STATUS_HAVE_NO_MEMORY(e->Computername);
949 if (t->sid_length > 0) {
950 const char *sid_str = NULL;
952 if (!convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
953 t->sid.data, t->sid.length,
954 (void *)&sid_str, &len, false)) {
955 return NT_STATUS_INVALID_SID;
958 string_to_sid(&e->UserSid, sid_str);
962 e->Strings = talloc_array(mem_ctx, const char *, t->num_of_strings);
963 for (i=0; i < t->num_of_strings; i++) {
964 e->Strings[i] = talloc_strdup(e->Strings, t->strings[i]);
965 NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]);
968 e->Data = (uint8_t *)talloc_memdup(mem_ctx, t->data.data, t->data_length);
969 e->Pad = talloc_strdup(mem_ctx, "");
970 NT_STATUS_HAVE_NO_MEMORY(e->Pad);
972 e->Length2 = t->size;
977 /********************************************************************
978 ********************************************************************/
980 NTSTATUS evlog_convert_tdb_to_evt(TALLOC_CTX *mem_ctx,
983 uint32_t *num_records_p)
985 NTSTATUS status = NT_STATUS_OK;
986 enum ndr_err_code ndr_err;
988 uint32_t num_records = 0;
989 struct EVENTLOG_EVT_FILE evt;
991 size_t endoffset = 0;
997 struct eventlog_Record_tdb *r;
998 struct EVENTLOGRECORD e;
1000 r = evlog_pull_record_tdb(mem_ctx, etdb->tdb, count);
1005 status = evlog_tdb_entry_to_evt_entry(mem_ctx, r, &e);
1006 if (!NT_STATUS_IS_OK(status)) {
1010 endoffset += ndr_size_EVENTLOGRECORD(&e, NULL, 0);
1012 ADD_TO_ARRAY(mem_ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records);
1016 evt.hdr.StartOffset = 0x30;
1017 evt.hdr.EndOffset = evt.hdr.StartOffset + endoffset;
1018 evt.hdr.CurrentRecordNumber = count;
1019 evt.hdr.OldestRecordNumber = 1;
1020 evt.hdr.MaxSize = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE);
1022 evt.hdr.Retention = tdb_fetch_int32(etdb->tdb, EVT_RETENTION);
1024 if (DEBUGLEVEL >= 10) {
1025 NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr);
1028 evt.eof.BeginRecord = 0x30;
1029 evt.eof.EndRecord = evt.hdr.StartOffset + endoffset;
1030 evt.eof.CurrentRecordNumber = evt.hdr.CurrentRecordNumber;
1031 evt.eof.OldestRecordNumber = evt.hdr.OldestRecordNumber;
1033 if (DEBUGLEVEL >= 10) {
1034 NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof);
1037 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &evt,
1038 (ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE);
1039 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1040 status = ndr_map_error2ntstatus(ndr_err);
1045 *num_records_p = num_records;