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
;