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"
29 /* maintain a list of open eventlog tdbs with reference counts */
31 static ELOG_TDB
*open_elog_list
;
33 /********************************************************************
34 Init an Eventlog TDB, and return it. If null, something bad
36 ********************************************************************/
38 TDB_CONTEXT
*elog_init_tdb( char *tdbfilename
)
42 DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
45 tdb
= tdb_open_log( tdbfilename
, 0, TDB_DEFAULT
,
46 O_RDWR
|O_CREAT
|O_TRUNC
, 0660 );
49 DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename
) );
53 /* initialize with defaults, copy real values in here from registry */
55 tdb_store_int32( tdb
, EVT_OLDEST_ENTRY
, 1 );
56 tdb_store_int32( tdb
, EVT_NEXT_RECORD
, 1 );
57 tdb_store_int32( tdb
, EVT_MAXSIZE
, 0x80000 );
58 tdb_store_int32( tdb
, EVT_RETENTION
, 0x93A80 );
60 tdb_store_int32( tdb
, EVT_VERSION
, EVENTLOG_DATABASE_VERSION_V1
);
65 /********************************************************************
66 make the tdb file name for an event log, given destination buffer
67 and size. Caller must free memory.
68 ********************************************************************/
70 char *elog_tdbname(TALLOC_CTX
*ctx
, const char *name
)
76 path
= state_path(talloc_tos(), "eventlog");
81 file
= talloc_asprintf_strlower_m(path
, "%s.tdb", name
);
87 tdbname
= talloc_asprintf(ctx
, "%s/%s", path
, file
);
98 /********************************************************************
99 this function is used to count up the number of bytes in a
101 ********************************************************************/
103 struct trav_size_struct
{
108 static int eventlog_tdb_size_fn( TDB_CONTEXT
* tdb
, TDB_DATA key
, TDB_DATA data
,
111 struct trav_size_struct
*tsize
= (struct trav_size_struct
*)state
;
113 tsize
->size
+= data
.dsize
;
119 /********************************************************************
120 returns the size of the eventlog, and if MaxSize is a non-null
121 ptr, puts the MaxSize there. This is purely a way not to have yet
122 another function that solely reads the maxsize of the eventlog.
124 ********************************************************************/
126 int elog_tdb_size( TDB_CONTEXT
* tdb
, int *MaxSize
, int *Retention
)
128 struct trav_size_struct tsize
;
133 ZERO_STRUCT( tsize
);
135 tdb_traverse( tdb
, eventlog_tdb_size_fn
, &tsize
);
137 if ( MaxSize
!= NULL
) {
138 *MaxSize
= tdb_fetch_int32( tdb
, EVT_MAXSIZE
);
141 if ( Retention
!= NULL
) {
142 *Retention
= tdb_fetch_int32( tdb
, EVT_RETENTION
);
146 ( "eventlog size: [%d] for [%d] records\n", tsize
.size
,
151 /********************************************************************
152 Discard early event logs until we have enough for 'needed' bytes...
153 NO checking done beforehand to see that we actually need to do
154 this, and it's going to pluck records one-by-one. So, it's best
155 to determine that this needs to be done before doing it.
157 Setting whack_by_date to True indicates that eventlogs falling
158 outside of the retention range need to go...
160 return True if we made enough room to accommodate needed bytes
161 ********************************************************************/
163 static bool make_way_for_eventlogs( TDB_CONTEXT
* the_tdb
, int32_t needed
,
166 int32_t start_record
, i
, new_start
;
168 int32_t reclen
, tresv1
, trecnum
, timegen
, timewr
;
169 int nbytes
, len
, Retention
, MaxSize
;
171 time_t current_time
, exp_time
;
173 /* discard some eventlogs */
175 /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
176 although records not necessarily guaranteed to have successive times */
180 tdb_lock_bystring_with_timeout( the_tdb
, EVT_NEXT_RECORD
, 1 );
182 end_record
= tdb_fetch_int32( the_tdb
, EVT_NEXT_RECORD
);
183 start_record
= tdb_fetch_int32( the_tdb
, EVT_OLDEST_ENTRY
);
184 Retention
= tdb_fetch_int32( the_tdb
, EVT_RETENTION
);
185 MaxSize
= tdb_fetch_int32( the_tdb
, EVT_MAXSIZE
);
187 time( ¤t_time
);
190 exp_time
= current_time
- Retention
; /* discard older than exp_time */
192 /* todo - check for sanity in next_record */
196 ( "MaxSize [%d] Retention [%d] Current Time [%u] exp_time [%u]\n",
197 MaxSize
, Retention
, (unsigned int)current_time
, (unsigned int)exp_time
) );
199 ( "Start Record [%u] End Record [%u]\n",
200 (unsigned int)start_record
,
201 (unsigned int)end_record
));
203 for ( i
= start_record
; i
< end_record
; i
++ ) {
204 /* read a record, add the amt to nbytes */
205 key
.dsize
= sizeof(int32_t);
206 key
.dptr
= (unsigned char *)&i
;
207 ret
= tdb_fetch( the_tdb
, key
);
208 if ( ret
.dsize
== 0 ) {
210 ( "Can't find a record for the key, record [%d]\n",
212 tdb_unlock_bystring( the_tdb
, EVT_NEXT_RECORD
);
215 nbytes
+= ret
.dsize
; /* note this includes overhead */
217 len
= tdb_unpack( ret
.dptr
, ret
.dsize
, "ddddd", &reclen
,
218 &tresv1
, &trecnum
, &timegen
, &timewr
);
220 DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
221 tdb_unlock_bystring( the_tdb
, EVT_NEXT_RECORD
);
222 SAFE_FREE( ret
.dptr
);
227 ( "read record %u, record size is [%d], total so far [%d]\n",
228 (unsigned int)i
, reclen
, nbytes
) );
230 SAFE_FREE( ret
.dptr
);
232 /* note that other servers may just stop writing records when the size limit
233 is reached, and there are no records older than 'retention'. This doesn't
234 like a very useful thing to do, so instead we whack (as in sleeps with the
235 fishes) just enough records to fit the what we need. This behavior could
236 be changed to 'match', if the need arises. */
238 if ( !whack_by_date
&& ( nbytes
>= needed
) )
240 if ( whack_by_date
&& ( timegen
>= exp_time
) )
245 ( "nbytes [%d] needed [%d] start_record is [%u], should be set to [%u]\n",
246 nbytes
, needed
, (unsigned int)start_record
, (unsigned int)i
) );
247 /* todo - remove eventlog entries here and set starting record to start_record... */
249 if ( start_record
!= new_start
) {
250 for ( i
= start_record
; i
< new_start
; i
++ ) {
251 key
.dsize
= sizeof(int32_t);
252 key
.dptr
= (unsigned char *)&i
;
253 tdb_delete( the_tdb
, key
);
256 tdb_store_int32( the_tdb
, EVT_OLDEST_ENTRY
, new_start
);
258 tdb_unlock_bystring( the_tdb
, EVT_NEXT_RECORD
);
262 /********************************************************************
263 some hygiene for an eventlog - see how big it is, and then
264 calculate how many bytes we need to remove
265 ********************************************************************/
267 bool prune_eventlog( TDB_CONTEXT
* tdb
)
269 int MaxSize
, Retention
, CalcdSize
;
272 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
276 CalcdSize
= elog_tdb_size( tdb
, &MaxSize
, &Retention
);
278 ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize
,
281 if ( CalcdSize
> MaxSize
) {
282 return make_way_for_eventlogs( tdb
, CalcdSize
- MaxSize
,
286 return make_way_for_eventlogs( tdb
, 0, True
);
289 /********************************************************************
290 ********************************************************************/
292 static bool can_write_to_eventlog( TDB_CONTEXT
* tdb
, int32_t needed
)
295 int MaxSize
, Retention
;
297 /* see if we can write to the eventlog -- do a policy enforcement */
299 return False
; /* tdb is null, so we can't write to it */
307 calcd_size
= elog_tdb_size( tdb
, &MaxSize
, &Retention
);
309 if ( calcd_size
<= MaxSize
)
310 return True
; /* you betcha */
311 if ( calcd_size
+ needed
< MaxSize
)
314 if ( Retention
== 0xffffffff ) {
315 return False
; /* see msdn - we can't write no room, discard */
318 note don't have to test, but always good to show intent, in case changes needed
322 if ( Retention
== 0x00000000 ) {
323 /* discard record(s) */
324 /* todo - decide when to remove a bunch vs. just what we need... */
325 return make_way_for_eventlogs( tdb
, calcd_size
- MaxSize
,
329 return make_way_for_eventlogs( tdb
, calcd_size
- MaxSize
, False
);
332 /*******************************************************************
333 *******************************************************************/
335 ELOG_TDB
*elog_open_tdb( const char *logname
, bool force_clear
, bool read_only
)
337 TDB_CONTEXT
*tdb
= NULL
;
340 char *tdbpath
= NULL
;
341 ELOG_TDB
*tdb_node
= NULL
;
343 TALLOC_CTX
*ctx
= talloc_tos();
346 /* check for invalid options */
348 if (force_clear
&& read_only
) {
349 DEBUG(1,("elog_open_tdb: Invalid flags\n"));
353 /* first see if we have an open context */
355 for ( ptr
=open_elog_list
; ptr
; ptr
=ptr
->next
) {
356 if ( strequal( ptr
->name
, logname
) ) {
359 /* trick to allow clearing of the eventlog tdb.
360 The force_clear flag should imply that someone
361 has done a force close. So make sure the tdb
362 is NULL. If this is a normal open, then just
363 return the existing reference */
366 SMB_ASSERT( ptr
->tdb
== NULL
);
374 /* make sure that the eventlog dir exists */
376 eventlogdir
= state_path(talloc_tos(), "eventlog");
377 if (eventlogdir
== NULL
) {
380 ok
= directory_create_or_exist(eventlogdir
, 0755);
381 TALLOC_FREE(eventlogdir
);
386 /* get the path on disk */
388 tdbpath
= elog_tdbname(ctx
, logname
);
393 DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
394 tdbpath
, force_clear
?"True":"False" ));
396 /* the tdb wasn't already open or this is a forced clear open */
398 if ( !force_clear
) {
400 tdb
= tdb_open_log( tdbpath
, 0, TDB_DEFAULT
, read_only
? O_RDONLY
: O_RDWR
, 0 );
402 vers_id
= tdb_fetch_int32( tdb
, EVT_VERSION
);
404 if ( vers_id
!= EVENTLOG_DATABASE_VERSION_V1
) {
405 DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
408 tdb
= elog_init_tdb( tdbpath
);
414 tdb
= elog_init_tdb( tdbpath
);
416 /* if we got a valid context, then add it to the list */
419 /* on a forced clear, just reset the tdb context if we already
420 have an open entry in the list */
427 if ( !(tdb_node
= talloc_zero( NULL
, ELOG_TDB
)) ) {
428 DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
433 tdb_node
->name
= talloc_strdup( tdb_node
, logname
);
435 tdb_node
->ref_count
= 1;
437 DLIST_ADD( open_elog_list
, tdb_node
);
443 /*******************************************************************
444 Wrapper to handle reference counts to the tdb
445 *******************************************************************/
447 int elog_close_tdb( ELOG_TDB
*etdb
, bool force_close
)
456 SMB_ASSERT( etdb
->ref_count
>= 0 );
458 if ( etdb
->ref_count
== 0 ) {
460 DLIST_REMOVE( open_elog_list
, etdb
);
462 return tdb_close( tdb
);
468 return tdb_close( tdb
);
474 /********************************************************************
475 Note that it's a pretty good idea to initialize the Eventlog_entry
476 structure to zero's before calling parse_logentry on an batch of
477 lines that may resolve to a record. ALSO, it's a good idea to
478 remove any linefeeds (that's EOL to you and me) on the lines
480 ********************************************************************/
482 bool parse_logentry( TALLOC_CTX
*mem_ctx
, char *line
, struct eventlog_Record_tdb
*entry
, bool * eor
)
484 char *start
= NULL
, *stop
= NULL
;
488 /* empty line signyfiying record delimiter, or we're at the end of the buffer */
489 if ( start
== NULL
|| strlen( start
) == 0 ) {
491 ( "parse_logentry: found end-of-record indicator.\n" ) );
495 if ( !( stop
= strchr( line
, ':' ) ) ) {
499 DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line
) );
501 if ( 0 == strncmp( start
, "LEN", stop
- start
) ) {
502 /* This will get recomputed later anyway -- probably not necessary */
503 entry
->size
= atoi( stop
+ 1 );
504 } else if ( 0 == strncmp( start
, "RS1", stop
- start
) ) {
505 /* For now all these reserved entries seem to have the same value,
506 which can be hardcoded to int(1699505740) for now */
507 entry
->reserved
= talloc_strdup(mem_ctx
, "eLfL");
508 } else if ( 0 == strncmp( start
, "RCN", stop
- start
) ) {
509 entry
->record_number
= atoi( stop
+ 1 );
510 } else if ( 0 == strncmp( start
, "TMG", stop
- start
) ) {
511 entry
->time_generated
= atoi( stop
+ 1 );
512 } else if ( 0 == strncmp( start
, "TMW", stop
- start
) ) {
513 entry
->time_written
= atoi( stop
+ 1 );
514 } else if ( 0 == strncmp( start
, "EID", stop
- start
) ) {
515 entry
->event_id
= atoi( stop
+ 1 );
516 } else if ( 0 == strncmp( start
, "ETP", stop
- start
) ) {
517 if ( strstr( start
, "ERROR" ) ) {
518 entry
->event_type
= EVENTLOG_ERROR_TYPE
;
519 } else if ( strstr( start
, "WARNING" ) ) {
520 entry
->event_type
= EVENTLOG_WARNING_TYPE
;
521 } else if ( strstr( start
, "INFO" ) ) {
522 entry
->event_type
= EVENTLOG_INFORMATION_TYPE
;
523 } else if ( strstr( start
, "AUDIT_SUCCESS" ) ) {
524 entry
->event_type
= EVENTLOG_AUDIT_SUCCESS
;
525 } else if ( strstr( start
, "AUDIT_FAILURE" ) ) {
526 entry
->event_type
= EVENTLOG_AUDIT_FAILURE
;
527 } else if ( strstr( start
, "SUCCESS" ) ) {
528 entry
->event_type
= EVENTLOG_SUCCESS
;
530 /* some other eventlog type -- currently not defined in MSDN docs, so error out */
536 else if(0 == strncmp(start, "NST", stop - start))
538 entry->num_of_strings = atoi(stop + 1);
541 else if ( 0 == strncmp( start
, "ECT", stop
- start
) ) {
542 entry
->event_category
= atoi( stop
+ 1 );
543 } else if ( 0 == strncmp( start
, "RS2", stop
- start
) ) {
544 entry
->reserved_flags
= atoi( stop
+ 1 );
545 } else if ( 0 == strncmp( start
, "CRN", stop
- start
) ) {
546 entry
->closing_record_number
= atoi( stop
+ 1 );
547 } else if ( 0 == strncmp( start
, "USL", stop
- start
) ) {
548 entry
->sid_length
= atoi( stop
+ 1 );
549 } else if ( 0 == strncmp( start
, "SRC", stop
- start
) ) {
551 while ( isspace( stop
[0] ) ) {
554 entry
->source_name_len
= strlen_m_term(stop
);
555 entry
->source_name
= talloc_strdup(mem_ctx
, stop
);
556 if (entry
->source_name_len
== (uint32_t)-1 ||
557 entry
->source_name
== NULL
) {
560 } else if ( 0 == strncmp( start
, "SRN", stop
- start
) ) {
562 while ( isspace( stop
[0] ) ) {
565 entry
->computer_name_len
= strlen_m_term(stop
);
566 entry
->computer_name
= talloc_strdup(mem_ctx
, stop
);
567 if (entry
->computer_name_len
== (uint32_t)-1 ||
568 entry
->computer_name
== NULL
) {
571 } else if ( 0 == strncmp( start
, "SID", stop
- start
) ) {
572 smb_ucs2_t
*dummy
= NULL
;
574 while ( isspace( stop
[0] ) ) {
577 entry
->sid_length
= rpcstr_push_talloc(mem_ctx
,
580 if (entry
->sid_length
== (uint32_t)-1) {
583 entry
->sid
= data_blob_talloc(mem_ctx
, dummy
, entry
->sid_length
);
584 if (entry
->sid
.data
== NULL
) {
587 } else if ( 0 == strncmp( start
, "STR", stop
- start
) ) {
589 size_t num_of_strings
;
590 /* skip past initial ":" */
592 /* now skip any other leading whitespace */
593 while ( isspace(stop
[0])) {
596 tmp_len
= strlen_m_term(stop
);
597 if (tmp_len
== (size_t)-1) {
600 num_of_strings
= entry
->num_of_strings
;
601 if (!add_string_to_array(mem_ctx
, stop
, &entry
->strings
,
605 if (num_of_strings
> 0xffff) {
608 entry
->num_of_strings
= num_of_strings
;
609 entry
->strings_len
+= tmp_len
;
610 } else if ( 0 == strncmp( start
, "DAT", stop
- start
) ) {
611 /* skip past initial ":" */
613 /* now skip any other leading whitespace */
614 while ( isspace( stop
[0] ) ) {
617 entry
->data_length
= strlen_m(stop
);
618 entry
->data
= data_blob_talloc(mem_ctx
, stop
, entry
->data_length
);
619 if (!entry
->data
.data
) {
623 /* some other eventlog entry -- not implemented, so dropping on the floor */
624 DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line
) );
625 /* For now return true so that we can keep on parsing this mess. Eventually
626 we will return False here. */
632 /*******************************************************************
633 calculate the correct fields etc for an eventlog entry
634 *******************************************************************/
636 size_t fixup_eventlog_record_tdb(struct eventlog_Record_tdb
*r
)
638 size_t size
= 56; /* static size of integers before buffers start */
640 r
->source_name_len
= strlen_m_term(r
->source_name
) * 2;
641 r
->computer_name_len
= strlen_m_term(r
->computer_name
) * 2;
642 r
->strings_len
= ndr_size_string_array(r
->strings
,
643 r
->num_of_strings
, LIBNDR_FLAG_STR_NULLTERM
) * 2;
645 /* fix up the eventlog entry structure as necessary */
646 r
->sid_padding
= ( ( 4 - ( ( r
->source_name_len
+ r
->computer_name_len
) % 4 ) ) % 4 );
647 r
->padding
= ( 4 - ( ( r
->strings_len
+ r
->data_length
) % 4 ) ) % 4;
649 if (r
->sid_length
== 0) {
650 /* Should not pad to a DWORD boundary for writing out the sid if there is
651 no SID, so just propagate the padding to pad the data */
652 r
->padding
+= r
->sid_padding
;
656 size
+= r
->source_name_len
;
657 size
+= r
->computer_name_len
;
658 size
+= r
->sid_padding
;
659 size
+= r
->sid_length
;
660 size
+= r
->strings_len
;
661 size
+= r
->data_length
;
663 /* need another copy of length at the end of the data */
664 size
+= sizeof(r
->size
);
672 /********************************************************************
673 ********************************************************************/
675 struct eventlog_Record_tdb
*evlog_pull_record_tdb(TALLOC_CTX
*mem_ctx
,
677 uint32_t record_number
)
679 struct eventlog_Record_tdb
*r
;
683 enum ndr_err_code ndr_err
;
686 srecno
= record_number
;
687 key
.dptr
= (unsigned char *)&srecno
;
688 key
.dsize
= sizeof(int32_t);
690 data
= tdb_fetch(tdb
, key
);
691 if (data
.dsize
== 0) {
692 DEBUG(8,("evlog_pull_record_tdb: "
693 "Can't find a record for the key, record %d\n",
698 r
= talloc_zero(mem_ctx
, struct eventlog_Record_tdb
);
703 blob
= data_blob_const(data
.dptr
, data
.dsize
);
705 ndr_err
= ndr_pull_struct_blob(&blob
, mem_ctx
, r
,
706 (ndr_pull_flags_fn_t
)ndr_pull_eventlog_Record_tdb
);
708 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
709 DEBUG(10,("evlog_pull_record_tdb: failed to decode record %d\n",
715 if (DEBUGLEVEL
>= 10) {
716 NDR_PRINT_DEBUG(eventlog_Record_tdb
, r
);
719 DEBUG(10,("evlog_pull_record_tdb: retrieved entry for record %d\n",
722 SAFE_FREE(data
.dptr
);
727 /********************************************************************
728 ********************************************************************/
730 struct EVENTLOGRECORD
*evlog_pull_record(TALLOC_CTX
*mem_ctx
,
732 uint32_t record_number
)
734 struct eventlog_Record_tdb
*t
;
735 struct EVENTLOGRECORD
*r
;
738 r
= talloc_zero(mem_ctx
, struct EVENTLOGRECORD
);
743 t
= evlog_pull_record_tdb(r
, tdb
, record_number
);
749 status
= evlog_tdb_entry_to_evt_entry(r
, t
, r
);
750 if (!NT_STATUS_IS_OK(status
)) {
755 r
->Length
= r
->Length2
= ndr_size_EVENTLOGRECORD(r
, 0);
760 /********************************************************************
761 write an eventlog entry. Note that we have to lock, read next
762 eventlog, increment, write, write the record, unlock
764 coming into this, ee has the eventlog record, and the auxiliary date
765 (computer name, etc.) filled into the other structure. Before packing
766 into a record, this routine will calc the appropriate padding, etc.,
767 and then blast out the record in a form that can be read back in
768 ********************************************************************/
770 NTSTATUS
evlog_push_record_tdb(TALLOC_CTX
*mem_ctx
,
772 struct eventlog_Record_tdb
*r
,
773 uint32_t *record_number
)
777 enum ndr_err_code ndr_err
;
781 return NT_STATUS_INVALID_PARAMETER
;
784 if (!can_write_to_eventlog(tdb
, r
->size
)) {
785 return NT_STATUS_EVENTLOG_CANT_START
;
788 /* need to read the record number and insert it into the entry here */
791 ret
= tdb_lock_bystring_with_timeout(tdb
, EVT_NEXT_RECORD
, 1);
793 return NT_STATUS_LOCK_NOT_GRANTED
;
797 r
->record_number
= tdb_fetch_int32(tdb
, EVT_NEXT_RECORD
);
799 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, r
,
800 (ndr_push_flags_fn_t
)ndr_push_eventlog_Record_tdb
);
801 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
802 tdb_unlock_bystring(tdb
, EVT_NEXT_RECORD
);
803 return ndr_map_error2ntstatus(ndr_err
);
806 /* increment the record count */
808 kbuf
.dsize
= sizeof(int32_t);
809 kbuf
.dptr
= (uint8_t *)&r
->record_number
;
811 ebuf
.dsize
= blob
.length
;
812 ebuf
.dptr
= blob
.data
;
814 ret
= tdb_store(tdb
, kbuf
, ebuf
, 0);
816 tdb_unlock_bystring(tdb
, EVT_NEXT_RECORD
);
817 return NT_STATUS_EVENTLOG_FILE_CORRUPT
;
820 ret
= tdb_store_int32(tdb
, EVT_NEXT_RECORD
, r
->record_number
+ 1);
822 tdb_unlock_bystring(tdb
, EVT_NEXT_RECORD
);
823 return NT_STATUS_EVENTLOG_FILE_CORRUPT
;
825 tdb_unlock_bystring(tdb
, EVT_NEXT_RECORD
);
828 *record_number
= r
->record_number
;
834 /********************************************************************
835 ********************************************************************/
837 NTSTATUS
evlog_push_record(TALLOC_CTX
*mem_ctx
,
839 struct EVENTLOGRECORD
*r
,
840 uint32_t *record_number
)
842 struct eventlog_Record_tdb
*t
;
845 t
= talloc_zero(mem_ctx
, struct eventlog_Record_tdb
);
847 return NT_STATUS_NO_MEMORY
;
850 status
= evlog_evt_entry_to_tdb_entry(t
, r
, t
);
851 if (!NT_STATUS_IS_OK(status
)) {
856 status
= evlog_push_record_tdb(mem_ctx
, tdb
, t
, record_number
);
862 /********************************************************************
863 ********************************************************************/
865 NTSTATUS
evlog_evt_entry_to_tdb_entry(TALLOC_CTX
*mem_ctx
,
866 const struct EVENTLOGRECORD
*e
,
867 struct eventlog_Record_tdb
*t
)
874 t
->reserved
= e
->Reserved
;
875 t
->record_number
= e
->RecordNumber
;
876 t
->time_generated
= e
->TimeGenerated
;
877 t
->time_written
= e
->TimeWritten
;
878 t
->event_id
= e
->EventID
;
879 t
->event_type
= e
->EventType
;
880 t
->num_of_strings
= e
->NumStrings
;
881 t
->event_category
= e
->EventCategory
;
882 t
->reserved_flags
= e
->ReservedFlags
;
883 t
->closing_record_number
= e
->ClosingRecordNumber
;
885 t
->stringoffset
= e
->StringOffset
;
886 t
->sid_length
= e
->UserSidLength
;
887 t
->sid_offset
= e
->UserSidOffset
;
888 t
->data_length
= e
->DataLength
;
889 t
->data_offset
= e
->DataOffset
;
891 t
->source_name_len
= 2 * strlen_m_term(e
->SourceName
);
892 t
->source_name
= talloc_strdup(mem_ctx
, e
->SourceName
);
893 NT_STATUS_HAVE_NO_MEMORY(t
->source_name
);
895 t
->computer_name_len
= 2 * strlen_m_term(e
->Computername
);
896 t
->computer_name
= talloc_strdup(mem_ctx
, e
->Computername
);
897 NT_STATUS_HAVE_NO_MEMORY(t
->computer_name
);
899 /* t->sid_padding; */
900 if (e
->UserSidLength
> 0) {
901 struct dom_sid_buf sid_str
;
902 smb_ucs2_t
*dummy
= NULL
;
903 t
->sid_length
= rpcstr_push_talloc(
906 dom_sid_str_buf(&e
->UserSid
, &sid_str
));
907 if (t
->sid_length
== -1) {
908 return NT_STATUS_NO_MEMORY
;
910 t
->sid
= data_blob_talloc(mem_ctx
, (uint8_t *)dummy
, t
->sid_length
);
911 NT_STATUS_HAVE_NO_MEMORY(t
->sid
.data
);
914 t
->strings
= talloc_array(mem_ctx
, const char *, e
->NumStrings
);
915 for (i
=0; i
< e
->NumStrings
; i
++) {
916 t
->strings
[i
] = talloc_strdup(t
->strings
, e
->Strings
[i
]);
917 NT_STATUS_HAVE_NO_MEMORY(t
->strings
[i
]);
920 t
->strings_len
= 2 * ndr_size_string_array(t
->strings
, t
->num_of_strings
, LIBNDR_FLAG_STR_NULLTERM
);
921 t
->data
= data_blob_talloc(mem_ctx
, e
->Data
, e
->DataLength
);
922 /* t->padding = r->Pad; */
927 /********************************************************************
928 ********************************************************************/
930 NTSTATUS
evlog_tdb_entry_to_evt_entry(TALLOC_CTX
*mem_ctx
,
931 const struct eventlog_Record_tdb
*t
,
932 struct EVENTLOGRECORD
*e
)
939 e
->Reserved
= t
->reserved
;
940 e
->RecordNumber
= t
->record_number
;
941 e
->TimeGenerated
= t
->time_generated
;
942 e
->TimeWritten
= t
->time_written
;
943 e
->EventID
= t
->event_id
;
944 e
->EventType
= t
->event_type
;
945 e
->NumStrings
= t
->num_of_strings
;
946 e
->EventCategory
= t
->event_category
;
947 e
->ReservedFlags
= t
->reserved_flags
;
948 e
->ClosingRecordNumber
= t
->closing_record_number
;
950 e
->StringOffset
= t
->stringoffset
;
951 e
->UserSidLength
= t
->sid_length
;
952 e
->UserSidOffset
= t
->sid_offset
;
953 e
->DataLength
= t
->data_length
;
954 e
->DataOffset
= t
->data_offset
;
956 e
->SourceName
= talloc_strdup(mem_ctx
, t
->source_name
);
957 NT_STATUS_HAVE_NO_MEMORY(e
->SourceName
);
959 e
->Computername
= talloc_strdup(mem_ctx
, t
->computer_name
);
960 NT_STATUS_HAVE_NO_MEMORY(e
->Computername
);
962 if (t
->sid_length
> 0) {
963 char *sid_str
= NULL
;
965 if (!convert_string_talloc(mem_ctx
, CH_UTF16
, CH_UNIX
,
966 t
->sid
.data
, t
->sid
.length
,
967 (void *)&sid_str
, &len
)) {
968 return NT_STATUS_INVALID_SID
;
971 bool ok
= string_to_sid(&e
->UserSid
, sid_str
);
973 return NT_STATUS_INVALID_SID
;
976 TALLOC_FREE(sid_str
);
979 e
->Strings
= talloc_array(mem_ctx
, const char *, t
->num_of_strings
);
980 for (i
=0; i
< t
->num_of_strings
; i
++) {
981 e
->Strings
[i
] = talloc_strdup(e
->Strings
, t
->strings
[i
]);
982 NT_STATUS_HAVE_NO_MEMORY(e
->Strings
[i
]);
985 e
->Data
= (uint8_t *)talloc_memdup(mem_ctx
, t
->data
.data
, t
->data_length
);
986 e
->Pad
= talloc_strdup(mem_ctx
, "");
987 NT_STATUS_HAVE_NO_MEMORY(e
->Pad
);
989 e
->Length2
= t
->size
;
994 /********************************************************************
995 ********************************************************************/
997 NTSTATUS
evlog_convert_tdb_to_evt(TALLOC_CTX
*mem_ctx
,
1000 uint32_t *num_records_p
)
1002 NTSTATUS status
= NT_STATUS_OK
;
1003 enum ndr_err_code ndr_err
;
1005 uint32_t num_records
= 0;
1006 struct EVENTLOG_EVT_FILE evt
;
1008 size_t endoffset
= 0;
1014 struct eventlog_Record_tdb
*r
;
1015 struct EVENTLOGRECORD e
;
1017 r
= evlog_pull_record_tdb(mem_ctx
, etdb
->tdb
, count
);
1022 status
= evlog_tdb_entry_to_evt_entry(mem_ctx
, r
, &e
);
1023 if (!NT_STATUS_IS_OK(status
)) {
1027 endoffset
+= ndr_size_EVENTLOGRECORD(&e
, 0);
1029 ADD_TO_ARRAY(mem_ctx
, struct EVENTLOGRECORD
, e
, &evt
.records
, &num_records
);
1033 evt
.hdr
.StartOffset
= 0x30;
1034 evt
.hdr
.EndOffset
= evt
.hdr
.StartOffset
+ endoffset
;
1035 evt
.hdr
.CurrentRecordNumber
= count
;
1036 evt
.hdr
.OldestRecordNumber
= 1;
1037 evt
.hdr
.MaxSize
= tdb_fetch_int32(etdb
->tdb
, EVT_MAXSIZE
);
1039 evt
.hdr
.Retention
= tdb_fetch_int32(etdb
->tdb
, EVT_RETENTION
);
1041 if (DEBUGLEVEL
>= 10) {
1042 NDR_PRINT_DEBUG(EVENTLOGHEADER
, &evt
.hdr
);
1045 evt
.eof
.BeginRecord
= 0x30;
1046 evt
.eof
.EndRecord
= evt
.hdr
.StartOffset
+ endoffset
;
1047 evt
.eof
.CurrentRecordNumber
= evt
.hdr
.CurrentRecordNumber
;
1048 evt
.eof
.OldestRecordNumber
= evt
.hdr
.OldestRecordNumber
;
1050 if (DEBUGLEVEL
>= 10) {
1051 NDR_PRINT_DEBUG(EVENTLOGEOF
, &evt
.eof
);
1054 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &evt
,
1055 (ndr_push_flags_fn_t
)ndr_push_EVENTLOG_EVT_FILE
);
1056 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1057 status
= ndr_map_error2ntstatus(ndr_err
);
1062 *num_records_p
= num_records
;