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 "system/filesys.h"
25 #include "lib/eventlog/eventlog.h"
26 #include "../libcli/security/security.h"
28 /* maintain a list of open eventlog tdbs with reference counts */
30 static ELOG_TDB *open_elog_list;
32 /********************************************************************
33 Init an Eventlog TDB, and return it. If null, something bad
35 ********************************************************************/
37 TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
41 DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
44 tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT,
45 O_RDWR|O_CREAT|O_TRUNC, 0660 );
48 DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
52 /* initialize with defaults, copy real values in here from registry */
54 tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 );
55 tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 );
56 tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 );
57 tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 );
59 tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
64 /********************************************************************
65 make the tdb file name for an event log, given destination buffer
66 and size. Caller must free memory.
67 ********************************************************************/
69 char *elog_tdbname(TALLOC_CTX *ctx, const char *name )
75 path = talloc_strdup(ctx, state_path("eventlog"));
80 file = talloc_asprintf_strlower_m(path, "%s.tdb", name);
86 tdbname = talloc_asprintf(path, "%s/%s", state_path("eventlog"), file);
96 /********************************************************************
97 this function is used to count up the number of bytes in a
99 ********************************************************************/
101 struct trav_size_struct {
106 static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
109 struct trav_size_struct *tsize = (struct trav_size_struct *)state;
111 tsize->size += data.dsize;
117 /********************************************************************
118 returns the size of the eventlog, and if MaxSize is a non-null
119 ptr, puts the MaxSize there. This is purely a way not to have yet
120 another function that solely reads the maxsize of the eventlog.
122 ********************************************************************/
124 int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
126 struct trav_size_struct tsize;
131 ZERO_STRUCT( tsize );
133 tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
135 if ( MaxSize != NULL ) {
136 *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
139 if ( Retention != NULL ) {
140 *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
144 ( "eventlog size: [%d] for [%d] records\n", tsize.size,
149 /********************************************************************
150 Discard early event logs until we have enough for 'needed' bytes...
151 NO checking done beforehand to see that we actually need to do
152 this, and it's going to pluck records one-by-one. So, it's best
153 to determine that this needs to be done before doing it.
155 Setting whack_by_date to True indicates that eventlogs falling
156 outside of the retention range need to go...
158 return True if we made enough room to accommodate needed bytes
159 ********************************************************************/
161 static bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32_t needed,
164 int32_t start_record, i, new_start;
166 int32_t reclen, tresv1, trecnum, timegen, timewr;
167 int nbytes, len, Retention, MaxSize;
169 time_t current_time, exp_time;
171 /* discard some eventlogs */
173 /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
174 although records not necessarily guaranteed to have successive times */
178 tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
180 end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
181 start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
182 Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
183 MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
185 time( ¤t_time );
188 exp_time = current_time - Retention; /* discard older than exp_time */
190 /* todo - check for sanity in next_record */
194 ( "MaxSize [%d] Retention [%d] Current Time [%u] exp_time [%u]\n",
195 MaxSize, Retention, (unsigned int)current_time, (unsigned int)exp_time ) );
197 ( "Start Record [%u] End Record [%u]\n",
198 (unsigned int)start_record,
199 (unsigned int)end_record ));
201 for ( i = start_record; i < end_record; i++ ) {
202 /* read a record, add the amt to nbytes */
203 key.dsize = sizeof(int32_t);
204 key.dptr = (unsigned char *)&i;
205 ret = tdb_fetch( the_tdb, key );
206 if ( ret.dsize == 0 ) {
208 ( "Can't find a record for the key, record [%d]\n",
210 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
213 nbytes += ret.dsize; /* note this includes overhead */
215 len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
216 &tresv1, &trecnum, &timegen, &timewr );
218 DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
219 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
220 SAFE_FREE( ret.dptr );
225 ( "read record %u, record size is [%d], total so far [%d]\n",
226 (unsigned int)i, reclen, nbytes ) );
228 SAFE_FREE( ret.dptr );
230 /* note that other servers may just stop writing records when the size limit
231 is reached, and there are no records older than 'retention'. This doesn't
232 like a very useful thing to do, so instead we whack (as in sleeps with the
233 fishes) just enough records to fit the what we need. This behavior could
234 be changed to 'match', if the need arises. */
236 if ( !whack_by_date && ( nbytes >= needed ) )
238 if ( whack_by_date && ( timegen >= exp_time ) )
243 ( "nbytes [%d] needed [%d] start_record is [%u], should be set to [%u]\n",
244 nbytes, needed, (unsigned int)start_record, (unsigned int)i ) );
245 /* todo - remove eventlog entries here and set starting record to start_record... */
247 if ( start_record != new_start ) {
248 for ( i = start_record; i < new_start; i++ ) {
249 key.dsize = sizeof(int32_t);
250 key.dptr = (unsigned char *)&i;
251 tdb_delete( the_tdb, key );
254 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
256 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
260 /********************************************************************
261 some hygiene for an eventlog - see how big it is, and then
262 calculate how many bytes we need to remove
263 ********************************************************************/
265 bool prune_eventlog( TDB_CONTEXT * tdb )
267 int MaxSize, Retention, CalcdSize;
270 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
274 CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
276 ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
279 if ( CalcdSize > MaxSize ) {
280 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
284 return make_way_for_eventlogs( tdb, 0, True );
287 /********************************************************************
288 ********************************************************************/
290 static bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed )
293 int MaxSize, Retention;
295 /* see if we can write to the eventlog -- do a policy enforcement */
297 return False; /* tdb is null, so we can't write to it */
305 calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
307 if ( calcd_size <= MaxSize )
308 return True; /* you betcha */
309 if ( calcd_size + needed < MaxSize )
312 if ( Retention == 0xffffffff ) {
313 return False; /* see msdn - we can't write no room, discard */
316 note don't have to test, but always good to show intent, in case changes needed
320 if ( Retention == 0x00000000 ) {
321 /* discard record(s) */
322 /* todo - decide when to remove a bunch vs. just what we need... */
323 return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
327 return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
330 /*******************************************************************
331 *******************************************************************/
333 ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only )
335 TDB_CONTEXT *tdb = NULL;
338 char *tdbpath = NULL;
339 ELOG_TDB *tdb_node = NULL;
341 TALLOC_CTX *ctx = talloc_tos();
343 /* check for invalid options */
345 if (force_clear && read_only) {
346 DEBUG(1,("elog_open_tdb: Invalid flags\n"));
350 /* first see if we have an open context */
352 for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
353 if ( strequal( ptr->name, logname ) ) {
356 /* trick to alow clearing of the eventlog tdb.
357 The force_clear flag should imply that someone
358 has done a force close. So make sure the tdb
359 is NULL. If this is a normal open, then just
360 return the existing reference */
363 SMB_ASSERT( ptr->tdb == NULL );
371 /* make sure that the eventlog dir exists */
373 eventlogdir = state_path( "eventlog" );
374 if ( !directory_exist( eventlogdir ) )
375 mkdir( eventlogdir, 0755 );
377 /* get the path on disk */
379 tdbpath = elog_tdbname(ctx, logname);
384 DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
385 tdbpath, force_clear?"True":"False" ));
387 /* the tdb wasn't already open or this is a forced clear open */
389 if ( !force_clear ) {
391 tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, read_only ? O_RDONLY : O_RDWR , 0 );
393 vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
395 if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
396 DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
399 tdb = elog_init_tdb( tdbpath );
405 tdb = elog_init_tdb( tdbpath );
407 /* if we got a valid context, then add it to the list */
410 /* on a forced clear, just reset the tdb context if we already
411 have an open entry in the list */
418 if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
419 DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
424 tdb_node->name = talloc_strdup( tdb_node, logname );
426 tdb_node->ref_count = 1;
428 DLIST_ADD( open_elog_list, tdb_node );
434 /*******************************************************************
435 Wrapper to handle reference counts to the tdb
436 *******************************************************************/
438 int elog_close_tdb( ELOG_TDB *etdb, bool force_close )
447 SMB_ASSERT( etdb->ref_count >= 0 );
449 if ( etdb->ref_count == 0 ) {
451 DLIST_REMOVE( open_elog_list, etdb );
453 return tdb_close( tdb );
459 return tdb_close( tdb );
465 /********************************************************************
466 Note that it's a pretty good idea to initialize the Eventlog_entry
467 structure to zero's before calling parse_logentry on an batch of
468 lines that may resolve to a record. ALSO, it's a good idea to
469 remove any linefeeds (that's EOL to you and me) on the lines
471 ********************************************************************/
473 bool parse_logentry( TALLOC_CTX *mem_ctx, char *line, struct eventlog_Record_tdb *entry, bool * eor )
475 char *start = NULL, *stop = NULL;
479 /* empty line signyfiying record delimeter, or we're at the end of the buffer */
480 if ( start == NULL || strlen( start ) == 0 ) {
482 ( "parse_logentry: found end-of-record indicator.\n" ) );
486 if ( !( stop = strchr( line, ':' ) ) ) {
490 DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
492 if ( 0 == strncmp( start, "LEN", stop - start ) ) {
493 /* This will get recomputed later anyway -- probably not necessary */
494 entry->size = atoi( stop + 1 );
495 } else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
496 /* For now all these reserved entries seem to have the same value,
497 which can be hardcoded to int(1699505740) for now */
498 entry->reserved = talloc_strdup(mem_ctx, "eLfL");
499 } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
500 entry->record_number = atoi( stop + 1 );
501 } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
502 entry->time_generated = atoi( stop + 1 );
503 } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
504 entry->time_written = atoi( stop + 1 );
505 } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
506 entry->event_id = atoi( stop + 1 );
507 } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
508 if ( strstr( start, "ERROR" ) ) {
509 entry->event_type = EVENTLOG_ERROR_TYPE;
510 } else if ( strstr( start, "WARNING" ) ) {
511 entry->event_type = EVENTLOG_WARNING_TYPE;
512 } else if ( strstr( start, "INFO" ) ) {
513 entry->event_type = EVENTLOG_INFORMATION_TYPE;
514 } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
515 entry->event_type = EVENTLOG_AUDIT_SUCCESS;
516 } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
517 entry->event_type = EVENTLOG_AUDIT_FAILURE;
518 } else if ( strstr( start, "SUCCESS" ) ) {
519 entry->event_type = EVENTLOG_SUCCESS;
521 /* some other eventlog type -- currently not defined in MSDN docs, so error out */
527 else if(0 == strncmp(start, "NST", stop - start))
529 entry->num_of_strings = atoi(stop + 1);
532 else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
533 entry->event_category = atoi( stop + 1 );
534 } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
535 entry->reserved_flags = atoi( stop + 1 );
536 } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
537 entry->closing_record_number = atoi( stop + 1 );
538 } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
539 entry->sid_length = atoi( stop + 1 );
540 } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
542 while ( isspace( stop[0] ) ) {
545 entry->source_name_len = strlen_m_term(stop);
546 entry->source_name = talloc_strdup(mem_ctx, stop);
547 if (entry->source_name_len == (uint32_t)-1 ||
548 entry->source_name == NULL) {
551 } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
553 while ( isspace( stop[0] ) ) {
556 entry->computer_name_len = strlen_m_term(stop);
557 entry->computer_name = talloc_strdup(mem_ctx, stop);
558 if (entry->computer_name_len == (uint32_t)-1 ||
559 entry->computer_name == NULL) {
562 } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
563 smb_ucs2_t *dummy = NULL;
565 while ( isspace( stop[0] ) ) {
568 entry->sid_length = rpcstr_push_talloc(mem_ctx,
571 if (entry->sid_length == (uint32_t)-1) {
574 entry->sid = data_blob_talloc(mem_ctx, dummy, entry->sid_length);
575 if (entry->sid.data == NULL) {
578 } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
581 /* skip past initial ":" */
583 /* now skip any other leading whitespace */
584 while ( isspace(stop[0])) {
587 tmp_len = strlen_m_term(stop);
588 if (tmp_len == (size_t)-1) {
591 num_of_strings = entry->num_of_strings;
592 if (!add_string_to_array(mem_ctx, stop, &entry->strings,
596 if (num_of_strings > 0xffff) {
599 entry->num_of_strings = num_of_strings;
600 entry->strings_len += tmp_len;
601 } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
602 /* skip past initial ":" */
604 /* now skip any other leading whitespace */
605 while ( isspace( stop[0] ) ) {
608 entry->data_length = strlen_m(stop);
609 entry->data = data_blob_talloc(mem_ctx, stop, entry->data_length);
610 if (!entry->data.data) {
614 /* some other eventlog entry -- not implemented, so dropping on the floor */
615 DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
616 /* For now return true so that we can keep on parsing this mess. Eventually
617 we will return False here. */
623 /*******************************************************************
624 calculate the correct fields etc for an eventlog entry
625 *******************************************************************/
627 size_t fixup_eventlog_record_tdb(struct eventlog_Record_tdb *r)
629 size_t size = 56; /* static size of integers before buffers start */
631 r->source_name_len = strlen_m_term(r->source_name) * 2;
632 r->computer_name_len = strlen_m_term(r->computer_name) * 2;
633 r->strings_len = ndr_size_string_array(r->strings,
634 r->num_of_strings, LIBNDR_FLAG_STR_NULLTERM) * 2;
636 /* fix up the eventlog entry structure as necessary */
637 r->sid_padding = ( ( 4 - ( ( r->source_name_len + r->computer_name_len ) % 4 ) ) % 4 );
638 r->padding = ( 4 - ( ( r->strings_len + r->data_length ) % 4 ) ) % 4;
640 if (r->sid_length == 0) {
641 /* Should not pad to a DWORD boundary for writing out the sid if there is
642 no SID, so just propagate the padding to pad the data */
643 r->padding += r->sid_padding;
647 size += r->source_name_len;
648 size += r->computer_name_len;
649 size += r->sid_padding;
650 size += r->sid_length;
651 size += r->strings_len;
652 size += r->data_length;
654 /* need another copy of length at the end of the data */
655 size += sizeof(r->size);
663 /********************************************************************
664 ********************************************************************/
666 struct eventlog_Record_tdb *evlog_pull_record_tdb(TALLOC_CTX *mem_ctx,
668 uint32_t record_number)
670 struct eventlog_Record_tdb *r;
674 enum ndr_err_code ndr_err;
677 srecno = record_number;
678 key.dptr = (unsigned char *)&srecno;
679 key.dsize = sizeof(int32_t);
681 data = tdb_fetch(tdb, key);
682 if (data.dsize == 0) {
683 DEBUG(8,("evlog_pull_record_tdb: "
684 "Can't find a record for the key, record %d\n",
689 r = talloc_zero(mem_ctx, struct eventlog_Record_tdb);
694 blob = data_blob_const(data.dptr, data.dsize);
696 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, r,
697 (ndr_pull_flags_fn_t)ndr_pull_eventlog_Record_tdb);
699 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
700 DEBUG(10,("evlog_pull_record_tdb: failed to decode record %d\n",
706 if (DEBUGLEVEL >= 10) {
707 NDR_PRINT_DEBUG(eventlog_Record_tdb, r);
710 DEBUG(10,("evlog_pull_record_tdb: retrieved entry for record %d\n",
713 SAFE_FREE(data.dptr);
718 /********************************************************************
719 ********************************************************************/
721 struct EVENTLOGRECORD *evlog_pull_record(TALLOC_CTX *mem_ctx,
723 uint32_t record_number)
725 struct eventlog_Record_tdb *t;
726 struct EVENTLOGRECORD *r;
729 r = talloc_zero(mem_ctx, struct EVENTLOGRECORD);
734 t = evlog_pull_record_tdb(r, tdb, record_number);
740 status = evlog_tdb_entry_to_evt_entry(r, t, r);
741 if (!NT_STATUS_IS_OK(status)) {
746 r->Length = r->Length2 = ndr_size_EVENTLOGRECORD(r, 0);
751 /********************************************************************
752 write an eventlog entry. Note that we have to lock, read next
753 eventlog, increment, write, write the record, unlock
755 coming into this, ee has the eventlog record, and the auxilliary date
756 (computer name, etc.) filled into the other structure. Before packing
757 into a record, this routine will calc the appropriate padding, etc.,
758 and then blast out the record in a form that can be read back in
759 ********************************************************************/
761 NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx,
763 struct eventlog_Record_tdb *r,
764 uint32_t *record_number)
768 enum ndr_err_code ndr_err;
772 return NT_STATUS_INVALID_PARAMETER;
775 if (!can_write_to_eventlog(tdb, r->size)) {
776 return NT_STATUS_EVENTLOG_CANT_START;
779 /* need to read the record number and insert it into the entry here */
782 ret = tdb_lock_bystring_with_timeout(tdb, EVT_NEXT_RECORD, 1);
784 return NT_STATUS_LOCK_NOT_GRANTED;
788 r->record_number = tdb_fetch_int32(tdb, EVT_NEXT_RECORD);
790 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, r,
791 (ndr_push_flags_fn_t)ndr_push_eventlog_Record_tdb);
792 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
793 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
794 return ndr_map_error2ntstatus(ndr_err);
797 /* increment the record count */
799 kbuf.dsize = sizeof(int32_t);
800 kbuf.dptr = (uint8_t *)&r->record_number;
802 ebuf.dsize = blob.length;
803 ebuf.dptr = blob.data;
805 ret = tdb_store(tdb, kbuf, ebuf, 0);
807 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
808 return NT_STATUS_EVENTLOG_FILE_CORRUPT;
811 ret = tdb_store_int32(tdb, EVT_NEXT_RECORD, r->record_number + 1);
813 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
814 return NT_STATUS_EVENTLOG_FILE_CORRUPT;
816 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
819 *record_number = r->record_number;
825 /********************************************************************
826 ********************************************************************/
828 NTSTATUS evlog_push_record(TALLOC_CTX *mem_ctx,
830 struct EVENTLOGRECORD *r,
831 uint32_t *record_number)
833 struct eventlog_Record_tdb *t;
836 t = talloc_zero(mem_ctx, struct eventlog_Record_tdb);
838 return NT_STATUS_NO_MEMORY;
841 status = evlog_evt_entry_to_tdb_entry(t, r, t);
842 if (!NT_STATUS_IS_OK(status)) {
847 status = evlog_push_record_tdb(mem_ctx, tdb, t, record_number);
853 /********************************************************************
854 ********************************************************************/
856 NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx,
857 const struct EVENTLOGRECORD *e,
858 struct eventlog_Record_tdb *t)
865 t->reserved = e->Reserved;
866 t->record_number = e->RecordNumber;
867 t->time_generated = e->TimeGenerated;
868 t->time_written = e->TimeWritten;
869 t->event_id = e->EventID;
870 t->event_type = e->EventType;
871 t->num_of_strings = e->NumStrings;
872 t->event_category = e->EventCategory;
873 t->reserved_flags = e->ReservedFlags;
874 t->closing_record_number = e->ClosingRecordNumber;
876 t->stringoffset = e->StringOffset;
877 t->sid_length = e->UserSidLength;
878 t->sid_offset = e->UserSidOffset;
879 t->data_length = e->DataLength;
880 t->data_offset = e->DataOffset;
882 t->source_name_len = 2 * strlen_m_term(e->SourceName);
883 t->source_name = talloc_strdup(mem_ctx, e->SourceName);
884 NT_STATUS_HAVE_NO_MEMORY(t->source_name);
886 t->computer_name_len = 2 * strlen_m_term(e->Computername);
887 t->computer_name = talloc_strdup(mem_ctx, e->Computername);
888 NT_STATUS_HAVE_NO_MEMORY(t->computer_name);
890 /* t->sid_padding; */
891 if (e->UserSidLength > 0) {
892 const char *sid_str = NULL;
893 smb_ucs2_t *dummy = NULL;
894 sid_str = sid_string_talloc(mem_ctx, &e->UserSid);
895 t->sid_length = rpcstr_push_talloc(mem_ctx, &dummy, sid_str);
896 if (t->sid_length == -1) {
897 return NT_STATUS_NO_MEMORY;
899 t->sid = data_blob_talloc(mem_ctx, (uint8_t *)dummy, t->sid_length);
900 NT_STATUS_HAVE_NO_MEMORY(t->sid.data);
903 t->strings = talloc_array(mem_ctx, const char *, e->NumStrings);
904 for (i=0; i < e->NumStrings; i++) {
905 t->strings[i] = talloc_strdup(t->strings, e->Strings[i]);
906 NT_STATUS_HAVE_NO_MEMORY(t->strings[i]);
909 t->strings_len = 2 * ndr_size_string_array(t->strings, t->num_of_strings, LIBNDR_FLAG_STR_NULLTERM);
910 t->data = data_blob_talloc(mem_ctx, e->Data, e->DataLength);
911 /* t->padding = r->Pad; */
916 /********************************************************************
917 ********************************************************************/
919 NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx,
920 const struct eventlog_Record_tdb *t,
921 struct EVENTLOGRECORD *e)
928 e->Reserved = t->reserved;
929 e->RecordNumber = t->record_number;
930 e->TimeGenerated = t->time_generated;
931 e->TimeWritten = t->time_written;
932 e->EventID = t->event_id;
933 e->EventType = t->event_type;
934 e->NumStrings = t->num_of_strings;
935 e->EventCategory = t->event_category;
936 e->ReservedFlags = t->reserved_flags;
937 e->ClosingRecordNumber = t->closing_record_number;
939 e->StringOffset = t->stringoffset;
940 e->UserSidLength = t->sid_length;
941 e->UserSidOffset = t->sid_offset;
942 e->DataLength = t->data_length;
943 e->DataOffset = t->data_offset;
945 e->SourceName = talloc_strdup(mem_ctx, t->source_name);
946 NT_STATUS_HAVE_NO_MEMORY(e->SourceName);
948 e->Computername = talloc_strdup(mem_ctx, t->computer_name);
949 NT_STATUS_HAVE_NO_MEMORY(e->Computername);
951 if (t->sid_length > 0) {
952 const char *sid_str = NULL;
954 if (!convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
955 t->sid.data, t->sid.length,
956 (void *)&sid_str, &len)) {
957 return NT_STATUS_INVALID_SID;
960 string_to_sid(&e->UserSid, sid_str);
964 e->Strings = talloc_array(mem_ctx, const char *, t->num_of_strings);
965 for (i=0; i < t->num_of_strings; i++) {
966 e->Strings[i] = talloc_strdup(e->Strings, t->strings[i]);
967 NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]);
970 e->Data = (uint8_t *)talloc_memdup(mem_ctx, t->data.data, t->data_length);
971 e->Pad = talloc_strdup(mem_ctx, "");
972 NT_STATUS_HAVE_NO_MEMORY(e->Pad);
974 e->Length2 = t->size;
979 /********************************************************************
980 ********************************************************************/
982 NTSTATUS evlog_convert_tdb_to_evt(TALLOC_CTX *mem_ctx,
985 uint32_t *num_records_p)
987 NTSTATUS status = NT_STATUS_OK;
988 enum ndr_err_code ndr_err;
990 uint32_t num_records = 0;
991 struct EVENTLOG_EVT_FILE evt;
993 size_t endoffset = 0;
999 struct eventlog_Record_tdb *r;
1000 struct EVENTLOGRECORD e;
1002 r = evlog_pull_record_tdb(mem_ctx, etdb->tdb, count);
1007 status = evlog_tdb_entry_to_evt_entry(mem_ctx, r, &e);
1008 if (!NT_STATUS_IS_OK(status)) {
1012 endoffset += ndr_size_EVENTLOGRECORD(&e, 0);
1014 ADD_TO_ARRAY(mem_ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records);
1018 evt.hdr.StartOffset = 0x30;
1019 evt.hdr.EndOffset = evt.hdr.StartOffset + endoffset;
1020 evt.hdr.CurrentRecordNumber = count;
1021 evt.hdr.OldestRecordNumber = 1;
1022 evt.hdr.MaxSize = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE);
1024 evt.hdr.Retention = tdb_fetch_int32(etdb->tdb, EVT_RETENTION);
1026 if (DEBUGLEVEL >= 10) {
1027 NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr);
1030 evt.eof.BeginRecord = 0x30;
1031 evt.eof.EndRecord = evt.hdr.StartOffset + endoffset;
1032 evt.eof.CurrentRecordNumber = evt.hdr.CurrentRecordNumber;
1033 evt.eof.OldestRecordNumber = evt.hdr.OldestRecordNumber;
1035 if (DEBUGLEVEL >= 10) {
1036 NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof);
1039 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &evt,
1040 (ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE);
1041 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1042 status = ndr_map_error2ntstatus(ndr_err);
1047 *num_records_p = num_records;