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"
25 #include "../libcli/security/security.h"
27 /* maintain a list of open eventlog tdbs with reference counts */
29 static ELOG_TDB *open_elog_list;
31 /********************************************************************
32 Init an Eventlog TDB, and return it. If null, something bad
34 ********************************************************************/
36 TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
40 DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
43 tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT,
44 O_RDWR|O_CREAT|O_TRUNC, 0660 );
47 DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
51 /* initialize with defaults, copy real values in here from registry */
53 tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 );
54 tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 );
55 tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 );
56 tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 );
58 tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
63 /********************************************************************
64 make the tdb file name for an event log, given destination buffer
65 and size. Caller must free memory.
66 ********************************************************************/
68 char *elog_tdbname(TALLOC_CTX *ctx, const char *name )
74 path = talloc_strdup(ctx, state_path("eventlog"));
79 file = talloc_asprintf_strlower_m(path, "%s.tdb", name);
85 tdbname = talloc_asprintf(path, "%s/%s", state_path("eventlog"), file);
95 /********************************************************************
96 this function is used to count up the number of bytes in a
98 ********************************************************************/
100 struct trav_size_struct {
105 static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
108 struct trav_size_struct *tsize = (struct trav_size_struct *)state;
110 tsize->size += data.dsize;
116 /********************************************************************
117 returns the size of the eventlog, and if MaxSize is a non-null
118 ptr, puts the MaxSize there. This is purely a way not to have yet
119 another function that solely reads the maxsize of the eventlog.
121 ********************************************************************/
123 int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
125 struct trav_size_struct tsize;
130 ZERO_STRUCT( tsize );
132 tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
134 if ( MaxSize != NULL ) {
135 *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
138 if ( Retention != NULL ) {
139 *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
143 ( "eventlog size: [%d] for [%d] records\n", tsize.size,
148 /********************************************************************
149 Discard early event logs until we have enough for 'needed' bytes...
150 NO checking done beforehand to see that we actually need to do
151 this, and it's going to pluck records one-by-one. So, it's best
152 to determine that this needs to be done before doing it.
154 Setting whack_by_date to True indicates that eventlogs falling
155 outside of the retention range need to go...
157 return True if we made enough room to accommodate needed bytes
158 ********************************************************************/
160 static bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32_t needed,
163 int32_t start_record, i, new_start;
165 int32_t reclen, tresv1, trecnum, timegen, timewr;
166 int nbytes, len, Retention, MaxSize;
168 time_t current_time, exp_time;
170 /* discard some eventlogs */
172 /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
173 although records not necessarily guaranteed to have successive times */
177 tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
179 end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
180 start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
181 Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
182 MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
184 time( ¤t_time );
187 exp_time = current_time - Retention; /* discard older than exp_time */
189 /* todo - check for sanity in next_record */
193 ( "MaxSize [%d] Retention [%d] Current Time [%u] exp_time [%u]\n",
194 MaxSize, Retention, (unsigned int)current_time, (unsigned int)exp_time ) );
196 ( "Start Record [%u] End Record [%u]\n",
197 (unsigned int)start_record,
198 (unsigned int)end_record ));
200 for ( i = start_record; i < end_record; i++ ) {
201 /* read a record, add the amt to nbytes */
202 key.dsize = sizeof(int32_t);
203 key.dptr = (unsigned char *)&i;
204 ret = tdb_fetch( the_tdb, key );
205 if ( ret.dsize == 0 ) {
207 ( "Can't find a record for the key, record [%d]\n",
209 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
212 nbytes += ret.dsize; /* note this includes overhead */
214 len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
215 &tresv1, &trecnum, &timegen, &timewr );
217 DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
218 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
219 SAFE_FREE( ret.dptr );
224 ( "read record %u, record size is [%d], total so far [%d]\n",
225 (unsigned int)i, reclen, nbytes ) );
227 SAFE_FREE( ret.dptr );
229 /* note that other servers may just stop writing records when the size limit
230 is reached, and there are no records older than 'retention'. This doesn't
231 like a very useful thing to do, so instead we whack (as in sleeps with the
232 fishes) just enough records to fit the what we need. This behavior could
233 be changed to 'match', if the need arises. */
235 if ( !whack_by_date && ( nbytes >= needed ) )
237 if ( whack_by_date && ( timegen >= exp_time ) )
242 ( "nbytes [%d] needed [%d] start_record is [%u], should be set to [%u]\n",
243 nbytes, needed, (unsigned int)start_record, (unsigned int)i ) );
244 /* todo - remove eventlog entries here and set starting record to start_record... */
246 if ( start_record != new_start ) {
247 for ( i = start_record; i < new_start; i++ ) {
248 key.dsize = sizeof(int32_t);
249 key.dptr = (unsigned char *)&i;
250 tdb_delete( the_tdb, key );
253 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
255 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
259 /********************************************************************
260 some hygiene for an eventlog - see how big it is, and then
261 calculate how many bytes we need to remove
262 ********************************************************************/
264 bool prune_eventlog( TDB_CONTEXT * tdb )
266 int MaxSize, Retention, CalcdSize;
269 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
273 CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
275 ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
278 if ( CalcdSize > MaxSize ) {
279 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
283 return make_way_for_eventlogs( tdb, 0, True );
286 /********************************************************************
287 ********************************************************************/
289 static bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed )
292 int MaxSize, Retention;
294 /* see if we can write to the eventlog -- do a policy enforcement */
296 return False; /* tdb is null, so we can't write to it */
304 calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
306 if ( calcd_size <= MaxSize )
307 return True; /* you betcha */
308 if ( calcd_size + needed < MaxSize )
311 if ( Retention == 0xffffffff ) {
312 return False; /* see msdn - we can't write no room, discard */
315 note don't have to test, but always good to show intent, in case changes needed
319 if ( Retention == 0x00000000 ) {
320 /* discard record(s) */
321 /* todo - decide when to remove a bunch vs. just what we need... */
322 return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
326 return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
329 /*******************************************************************
330 *******************************************************************/
332 ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only )
334 TDB_CONTEXT *tdb = NULL;
337 char *tdbpath = NULL;
338 ELOG_TDB *tdb_node = NULL;
340 TALLOC_CTX *ctx = talloc_tos();
342 /* check for invalid options */
344 if (force_clear && read_only) {
345 DEBUG(1,("elog_open_tdb: Invalid flags\n"));
349 /* first see if we have an open context */
351 for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
352 if ( strequal( ptr->name, logname ) ) {
355 /* trick to alow clearing of the eventlog tdb.
356 The force_clear flag should imply that someone
357 has done a force close. So make sure the tdb
358 is NULL. If this is a normal open, then just
359 return the existing reference */
362 SMB_ASSERT( ptr->tdb == NULL );
370 /* make sure that the eventlog dir exists */
372 eventlogdir = state_path( "eventlog" );
373 if ( !directory_exist( eventlogdir ) )
374 mkdir( eventlogdir, 0755 );
376 /* get the path on disk */
378 tdbpath = elog_tdbname(ctx, logname);
383 DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
384 tdbpath, force_clear?"True":"False" ));
386 /* the tdb wasn't already open or this is a forced clear open */
388 if ( !force_clear ) {
390 tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, read_only ? O_RDONLY : O_RDWR , 0 );
392 vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
394 if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
395 DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
398 tdb = elog_init_tdb( tdbpath );
404 tdb = elog_init_tdb( tdbpath );
406 /* if we got a valid context, then add it to the list */
409 /* on a forced clear, just reset the tdb context if we already
410 have an open entry in the list */
417 if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
418 DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
423 tdb_node->name = talloc_strdup( tdb_node, logname );
425 tdb_node->ref_count = 1;
427 DLIST_ADD( open_elog_list, tdb_node );
433 /*******************************************************************
434 Wrapper to handle reference counts to the tdb
435 *******************************************************************/
437 int elog_close_tdb( ELOG_TDB *etdb, bool force_close )
446 SMB_ASSERT( etdb->ref_count >= 0 );
448 if ( etdb->ref_count == 0 ) {
450 DLIST_REMOVE( open_elog_list, etdb );
452 return tdb_close( tdb );
458 return tdb_close( tdb );
464 /********************************************************************
465 Note that it's a pretty good idea to initialize the Eventlog_entry
466 structure to zero's before calling parse_logentry on an batch of
467 lines that may resolve to a record. ALSO, it's a good idea to
468 remove any linefeeds (that's EOL to you and me) on the lines
470 ********************************************************************/
472 bool parse_logentry( TALLOC_CTX *mem_ctx, char *line, struct eventlog_Record_tdb *entry, bool * eor )
474 char *start = NULL, *stop = NULL;
478 /* empty line signyfiying record delimeter, or we're at the end of the buffer */
479 if ( start == NULL || strlen( start ) == 0 ) {
481 ( "parse_logentry: found end-of-record indicator.\n" ) );
485 if ( !( stop = strchr( line, ':' ) ) ) {
489 DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
491 if ( 0 == strncmp( start, "LEN", stop - start ) ) {
492 /* This will get recomputed later anyway -- probably not necessary */
493 entry->size = atoi( stop + 1 );
494 } else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
495 /* For now all these reserved entries seem to have the same value,
496 which can be hardcoded to int(1699505740) for now */
497 entry->reserved = talloc_strdup(mem_ctx, "eLfL");
498 } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
499 entry->record_number = atoi( stop + 1 );
500 } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
501 entry->time_generated = atoi( stop + 1 );
502 } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
503 entry->time_written = atoi( stop + 1 );
504 } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
505 entry->event_id = atoi( stop + 1 );
506 } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
507 if ( strstr( start, "ERROR" ) ) {
508 entry->event_type = EVENTLOG_ERROR_TYPE;
509 } else if ( strstr( start, "WARNING" ) ) {
510 entry->event_type = EVENTLOG_WARNING_TYPE;
511 } else if ( strstr( start, "INFO" ) ) {
512 entry->event_type = EVENTLOG_INFORMATION_TYPE;
513 } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
514 entry->event_type = EVENTLOG_AUDIT_SUCCESS;
515 } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
516 entry->event_type = EVENTLOG_AUDIT_FAILURE;
517 } else if ( strstr( start, "SUCCESS" ) ) {
518 entry->event_type = EVENTLOG_SUCCESS;
520 /* some other eventlog type -- currently not defined in MSDN docs, so error out */
526 else if(0 == strncmp(start, "NST", stop - start))
528 entry->num_of_strings = atoi(stop + 1);
531 else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
532 entry->event_category = atoi( stop + 1 );
533 } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
534 entry->reserved_flags = atoi( stop + 1 );
535 } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
536 entry->closing_record_number = atoi( stop + 1 );
537 } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
538 entry->sid_length = atoi( stop + 1 );
539 } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
541 while ( isspace( stop[0] ) ) {
544 entry->source_name_len = strlen_m_term(stop);
545 entry->source_name = talloc_strdup(mem_ctx, stop);
546 if (entry->source_name_len == (uint32_t)-1 ||
547 entry->source_name == NULL) {
550 } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
552 while ( isspace( stop[0] ) ) {
555 entry->computer_name_len = strlen_m_term(stop);
556 entry->computer_name = talloc_strdup(mem_ctx, stop);
557 if (entry->computer_name_len == (uint32_t)-1 ||
558 entry->computer_name == NULL) {
561 } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
562 smb_ucs2_t *dummy = NULL;
564 while ( isspace( stop[0] ) ) {
567 entry->sid_length = rpcstr_push_talloc(mem_ctx,
570 if (entry->sid_length == (uint32_t)-1) {
573 entry->sid = data_blob_talloc(mem_ctx, dummy, entry->sid_length);
574 if (entry->sid.data == NULL) {
577 } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
580 /* skip past initial ":" */
582 /* now skip any other leading whitespace */
583 while ( isspace(stop[0])) {
586 tmp_len = strlen_m_term(stop);
587 if (tmp_len == (size_t)-1) {
590 num_of_strings = entry->num_of_strings;
591 if (!add_string_to_array(mem_ctx, stop, &entry->strings,
595 if (num_of_strings > 0xffff) {
598 entry->num_of_strings = num_of_strings;
599 entry->strings_len += tmp_len;
600 } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
601 /* skip past initial ":" */
603 /* now skip any other leading whitespace */
604 while ( isspace( stop[0] ) ) {
607 entry->data_length = strlen_m(stop);
608 entry->data = data_blob_talloc(mem_ctx, stop, entry->data_length);
609 if (!entry->data.data) {
613 /* some other eventlog entry -- not implemented, so dropping on the floor */
614 DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
615 /* For now return true so that we can keep on parsing this mess. Eventually
616 we will return False here. */
622 /*******************************************************************
623 calculate the correct fields etc for an eventlog entry
624 *******************************************************************/
626 size_t fixup_eventlog_record_tdb(struct eventlog_Record_tdb *r)
628 size_t size = 56; /* static size of integers before buffers start */
630 r->source_name_len = strlen_m_term(r->source_name) * 2;
631 r->computer_name_len = strlen_m_term(r->computer_name) * 2;
632 r->strings_len = ndr_size_string_array(r->strings,
633 r->num_of_strings, LIBNDR_FLAG_STR_NULLTERM) * 2;
635 /* fix up the eventlog entry structure as necessary */
636 r->sid_padding = ( ( 4 - ( ( r->source_name_len + r->computer_name_len ) % 4 ) ) % 4 );
637 r->padding = ( 4 - ( ( r->strings_len + r->data_length ) % 4 ) ) % 4;
639 if (r->sid_length == 0) {
640 /* Should not pad to a DWORD boundary for writing out the sid if there is
641 no SID, so just propagate the padding to pad the data */
642 r->padding += r->sid_padding;
646 size += r->source_name_len;
647 size += r->computer_name_len;
648 size += r->sid_padding;
649 size += r->sid_length;
650 size += r->strings_len;
651 size += r->data_length;
653 /* need another copy of length at the end of the data */
654 size += sizeof(r->size);
662 /********************************************************************
663 ********************************************************************/
665 struct eventlog_Record_tdb *evlog_pull_record_tdb(TALLOC_CTX *mem_ctx,
667 uint32_t record_number)
669 struct eventlog_Record_tdb *r;
673 enum ndr_err_code ndr_err;
676 srecno = record_number;
677 key.dptr = (unsigned char *)&srecno;
678 key.dsize = sizeof(int32_t);
680 data = tdb_fetch(tdb, key);
681 if (data.dsize == 0) {
682 DEBUG(8,("evlog_pull_record_tdb: "
683 "Can't find a record for the key, record %d\n",
688 r = talloc_zero(mem_ctx, struct eventlog_Record_tdb);
693 blob = data_blob_const(data.dptr, data.dsize);
695 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, r,
696 (ndr_pull_flags_fn_t)ndr_pull_eventlog_Record_tdb);
698 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
699 DEBUG(10,("evlog_pull_record_tdb: failed to decode record %d\n",
705 if (DEBUGLEVEL >= 10) {
706 NDR_PRINT_DEBUG(eventlog_Record_tdb, r);
709 DEBUG(10,("evlog_pull_record_tdb: retrieved entry for record %d\n",
712 SAFE_FREE(data.dptr);
717 /********************************************************************
718 ********************************************************************/
720 struct EVENTLOGRECORD *evlog_pull_record(TALLOC_CTX *mem_ctx,
722 uint32_t record_number)
724 struct eventlog_Record_tdb *t;
725 struct EVENTLOGRECORD *r;
728 r = talloc_zero(mem_ctx, struct EVENTLOGRECORD);
733 t = evlog_pull_record_tdb(r, tdb, record_number);
739 status = evlog_tdb_entry_to_evt_entry(r, t, r);
740 if (!NT_STATUS_IS_OK(status)) {
745 r->Length = r->Length2 = ndr_size_EVENTLOGRECORD(r, 0);
750 /********************************************************************
751 write an eventlog entry. Note that we have to lock, read next
752 eventlog, increment, write, write the record, unlock
754 coming into this, ee has the eventlog record, and the auxilliary date
755 (computer name, etc.) filled into the other structure. Before packing
756 into a record, this routine will calc the appropriate padding, etc.,
757 and then blast out the record in a form that can be read back in
758 ********************************************************************/
760 NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx,
762 struct eventlog_Record_tdb *r,
763 uint32_t *record_number)
767 enum ndr_err_code ndr_err;
771 return NT_STATUS_INVALID_PARAMETER;
774 if (!can_write_to_eventlog(tdb, r->size)) {
775 return NT_STATUS_EVENTLOG_CANT_START;
778 /* need to read the record number and insert it into the entry here */
781 ret = tdb_lock_bystring_with_timeout(tdb, EVT_NEXT_RECORD, 1);
783 return NT_STATUS_LOCK_NOT_GRANTED;
787 r->record_number = tdb_fetch_int32(tdb, EVT_NEXT_RECORD);
789 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, r,
790 (ndr_push_flags_fn_t)ndr_push_eventlog_Record_tdb);
791 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
792 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
793 return ndr_map_error2ntstatus(ndr_err);
796 /* increment the record count */
798 kbuf.dsize = sizeof(int32_t);
799 kbuf.dptr = (uint8_t *)&r->record_number;
801 ebuf.dsize = blob.length;
802 ebuf.dptr = blob.data;
804 ret = tdb_store(tdb, kbuf, ebuf, 0);
806 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
807 return NT_STATUS_EVENTLOG_FILE_CORRUPT;
810 ret = tdb_store_int32(tdb, EVT_NEXT_RECORD, r->record_number + 1);
812 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
813 return NT_STATUS_EVENTLOG_FILE_CORRUPT;
815 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
818 *record_number = r->record_number;
824 /********************************************************************
825 ********************************************************************/
827 NTSTATUS evlog_push_record(TALLOC_CTX *mem_ctx,
829 struct EVENTLOGRECORD *r,
830 uint32_t *record_number)
832 struct eventlog_Record_tdb *t;
835 t = talloc_zero(mem_ctx, struct eventlog_Record_tdb);
837 return NT_STATUS_NO_MEMORY;
840 status = evlog_evt_entry_to_tdb_entry(t, r, t);
841 if (!NT_STATUS_IS_OK(status)) {
846 status = evlog_push_record_tdb(mem_ctx, tdb, t, record_number);
852 /********************************************************************
853 ********************************************************************/
855 NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx,
856 const struct EVENTLOGRECORD *e,
857 struct eventlog_Record_tdb *t)
864 t->reserved = e->Reserved;
865 t->record_number = e->RecordNumber;
866 t->time_generated = e->TimeGenerated;
867 t->time_written = e->TimeWritten;
868 t->event_id = e->EventID;
869 t->event_type = e->EventType;
870 t->num_of_strings = e->NumStrings;
871 t->event_category = e->EventCategory;
872 t->reserved_flags = e->ReservedFlags;
873 t->closing_record_number = e->ClosingRecordNumber;
875 t->stringoffset = e->StringOffset;
876 t->sid_length = e->UserSidLength;
877 t->sid_offset = e->UserSidOffset;
878 t->data_length = e->DataLength;
879 t->data_offset = e->DataOffset;
881 t->source_name_len = 2 * strlen_m_term(e->SourceName);
882 t->source_name = talloc_strdup(mem_ctx, e->SourceName);
883 NT_STATUS_HAVE_NO_MEMORY(t->source_name);
885 t->computer_name_len = 2 * strlen_m_term(e->Computername);
886 t->computer_name = talloc_strdup(mem_ctx, e->Computername);
887 NT_STATUS_HAVE_NO_MEMORY(t->computer_name);
889 /* t->sid_padding; */
890 if (e->UserSidLength > 0) {
891 const char *sid_str = NULL;
892 smb_ucs2_t *dummy = NULL;
893 sid_str = sid_string_talloc(mem_ctx, &e->UserSid);
894 t->sid_length = rpcstr_push_talloc(mem_ctx, &dummy, sid_str);
895 if (t->sid_length == -1) {
896 return NT_STATUS_NO_MEMORY;
898 t->sid = data_blob_talloc(mem_ctx, (uint8_t *)dummy, t->sid_length);
899 NT_STATUS_HAVE_NO_MEMORY(t->sid.data);
902 t->strings = talloc_array(mem_ctx, const char *, e->NumStrings);
903 for (i=0; i < e->NumStrings; i++) {
904 t->strings[i] = talloc_strdup(t->strings, e->Strings[i]);
905 NT_STATUS_HAVE_NO_MEMORY(t->strings[i]);
908 t->strings_len = 2 * ndr_size_string_array(t->strings, t->num_of_strings, LIBNDR_FLAG_STR_NULLTERM);
909 t->data = data_blob_talloc(mem_ctx, e->Data, e->DataLength);
910 /* t->padding = r->Pad; */
915 /********************************************************************
916 ********************************************************************/
918 NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx,
919 const struct eventlog_Record_tdb *t,
920 struct EVENTLOGRECORD *e)
927 e->Reserved = t->reserved;
928 e->RecordNumber = t->record_number;
929 e->TimeGenerated = t->time_generated;
930 e->TimeWritten = t->time_written;
931 e->EventID = t->event_id;
932 e->EventType = t->event_type;
933 e->NumStrings = t->num_of_strings;
934 e->EventCategory = t->event_category;
935 e->ReservedFlags = t->reserved_flags;
936 e->ClosingRecordNumber = t->closing_record_number;
938 e->StringOffset = t->stringoffset;
939 e->UserSidLength = t->sid_length;
940 e->UserSidOffset = t->sid_offset;
941 e->DataLength = t->data_length;
942 e->DataOffset = t->data_offset;
944 e->SourceName = talloc_strdup(mem_ctx, t->source_name);
945 NT_STATUS_HAVE_NO_MEMORY(e->SourceName);
947 e->Computername = talloc_strdup(mem_ctx, t->computer_name);
948 NT_STATUS_HAVE_NO_MEMORY(e->Computername);
950 if (t->sid_length > 0) {
951 const char *sid_str = NULL;
953 if (!convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
954 t->sid.data, t->sid.length,
955 (void *)&sid_str, &len)) {
956 return NT_STATUS_INVALID_SID;
959 string_to_sid(&e->UserSid, sid_str);
963 e->Strings = talloc_array(mem_ctx, const char *, t->num_of_strings);
964 for (i=0; i < t->num_of_strings; i++) {
965 e->Strings[i] = talloc_strdup(e->Strings, t->strings[i]);
966 NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]);
969 e->Data = (uint8_t *)talloc_memdup(mem_ctx, t->data.data, t->data_length);
970 e->Pad = talloc_strdup(mem_ctx, "");
971 NT_STATUS_HAVE_NO_MEMORY(e->Pad);
973 e->Length2 = t->size;
978 /********************************************************************
979 ********************************************************************/
981 NTSTATUS evlog_convert_tdb_to_evt(TALLOC_CTX *mem_ctx,
984 uint32_t *num_records_p)
986 NTSTATUS status = NT_STATUS_OK;
987 enum ndr_err_code ndr_err;
989 uint32_t num_records = 0;
990 struct EVENTLOG_EVT_FILE evt;
992 size_t endoffset = 0;
998 struct eventlog_Record_tdb *r;
999 struct EVENTLOGRECORD e;
1001 r = evlog_pull_record_tdb(mem_ctx, etdb->tdb, count);
1006 status = evlog_tdb_entry_to_evt_entry(mem_ctx, r, &e);
1007 if (!NT_STATUS_IS_OK(status)) {
1011 endoffset += ndr_size_EVENTLOGRECORD(&e, 0);
1013 ADD_TO_ARRAY(mem_ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records);
1017 evt.hdr.StartOffset = 0x30;
1018 evt.hdr.EndOffset = evt.hdr.StartOffset + endoffset;
1019 evt.hdr.CurrentRecordNumber = count;
1020 evt.hdr.OldestRecordNumber = 1;
1021 evt.hdr.MaxSize = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE);
1023 evt.hdr.Retention = tdb_fetch_int32(etdb->tdb, EVT_RETENTION);
1025 if (DEBUGLEVEL >= 10) {
1026 NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr);
1029 evt.eof.BeginRecord = 0x30;
1030 evt.eof.EndRecord = evt.hdr.StartOffset + endoffset;
1031 evt.eof.CurrentRecordNumber = evt.hdr.CurrentRecordNumber;
1032 evt.eof.OldestRecordNumber = evt.hdr.OldestRecordNumber;
1034 if (DEBUGLEVEL >= 10) {
1035 NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof);
1038 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &evt,
1039 (ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE);
1040 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1041 status = ndr_map_error2ntstatus(ndr_err);
1046 *num_records_p = num_records;