LCOV - code coverage report
Current view: top level - source3/lib/eventlog - eventlog.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 191 533 35.8 %
Date: 2024-02-28 12:06:22 Functions: 14 18 77.8 %

          Line data    Source code
       1             : /*
       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.
       8             :  *
       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.
      13             :  *
      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.
      18             :  *
      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/>.
      21             :  */
      22             : 
      23             : #include "includes.h"
      24             : #include "system/filesys.h"
      25             : #include "lib/eventlog/eventlog.h"
      26             : #include "../libcli/security/security.h"
      27             : #include "util_tdb.h"
      28             : 
      29             : /* maintain a list of open eventlog tdbs with reference counts */
      30             : 
      31             : static ELOG_TDB *open_elog_list;
      32             : 
      33             : /********************************************************************
      34             :  Init an Eventlog TDB, and return it. If null, something bad
      35             :  happened.
      36             : ********************************************************************/
      37             : 
      38           2 : TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
      39             : {
      40           0 :         TDB_CONTEXT *tdb;
      41             : 
      42           2 :         DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
      43             :                 tdbfilename));
      44             : 
      45           2 :         tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT,
      46             :                 O_RDWR|O_CREAT|O_TRUNC, 0660 );
      47             : 
      48           2 :         if ( !tdb ) {
      49           0 :                 DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
      50           0 :                 return NULL;
      51             :         }
      52             : 
      53             :         /* initialize with defaults, copy real values in here from registry */
      54             : 
      55           2 :         tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 );
      56           2 :         tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 );
      57           2 :         tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 );
      58           2 :         tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 );
      59             : 
      60           2 :         tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
      61             : 
      62           2 :         return tdb;
      63             : }
      64             : 
      65             : /********************************************************************
      66             :  make the tdb file name for an event log, given destination buffer
      67             :  and size. Caller must free memory.
      68             : ********************************************************************/
      69             : 
      70          24 : char *elog_tdbname(TALLOC_CTX *ctx, const char *name )
      71             : {
      72           0 :         char *path;
      73           0 :         char *file;
      74           0 :         char *tdbname;
      75             : 
      76          24 :         path = state_path(talloc_tos(), "eventlog");
      77          24 :         if (!path) {
      78           0 :                 return NULL;
      79             :         }
      80             : 
      81          24 :         file = talloc_asprintf_strlower_m(path, "%s.tdb", name);
      82          24 :         if (!file) {
      83           0 :                 talloc_free(path);
      84           0 :                 return NULL;
      85             :         }
      86             : 
      87          24 :         tdbname = talloc_asprintf(ctx, "%s/%s", path, file);
      88          24 :         if (!tdbname) {
      89           0 :                 talloc_free(path);
      90           0 :                 return NULL;
      91             :         }
      92             : 
      93          24 :         talloc_free(path);
      94          24 :         return tdbname;
      95             : }
      96             : 
      97             : 
      98             : /********************************************************************
      99             :  this function is used to count up the number of bytes in a
     100             :  particular TDB
     101             : ********************************************************************/
     102             : 
     103             : struct trav_size_struct {
     104             :         int size;
     105             :         int rec_count;
     106             : };
     107             : 
     108          74 : static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
     109             :                           void *state )
     110             : {
     111          74 :         struct trav_size_struct  *tsize = (struct trav_size_struct *)state;
     112             : 
     113          74 :         tsize->size += data.dsize;
     114          74 :         tsize->rec_count++;
     115             : 
     116          74 :         return 0;
     117             : }
     118             : 
     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.
     123             :  Yeah, that's it.
     124             : ********************************************************************/
     125             : 
     126          14 : int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
     127             : {
     128           0 :         struct trav_size_struct tsize;
     129             : 
     130          14 :         if ( !tdb )
     131           0 :                 return 0;
     132             : 
     133          14 :         ZERO_STRUCT( tsize );
     134             : 
     135          14 :         tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
     136             : 
     137          14 :         if ( MaxSize != NULL ) {
     138          14 :                 *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
     139             :         }
     140             : 
     141          14 :         if ( Retention != NULL ) {
     142          14 :                 *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
     143             :         }
     144             : 
     145          14 :         DEBUG( 1,
     146             :                ( "eventlog size: [%d] for [%d] records\n", tsize.size,
     147             :                  tsize.rec_count ) );
     148          14 :         return tsize.size;
     149             : }
     150             : 
     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.
     156             : 
     157             :  Setting whack_by_date to True indicates that eventlogs falling
     158             :  outside of the retention range need to go...
     159             : 
     160             :  return True if we made enough room to accommodate needed bytes
     161             : ********************************************************************/
     162             : 
     163          12 : static bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32_t needed,
     164             :                                     bool whack_by_date )
     165             : {
     166           0 :         int32_t start_record, i, new_start;
     167           0 :         int32_t end_record;
     168           0 :         int32_t reclen, tresv1, trecnum, timegen, timewr;
     169           0 :         int nbytes, len, Retention, MaxSize;
     170           0 :         TDB_DATA key, ret;
     171           0 :         time_t current_time, exp_time;
     172             : 
     173             :         /* discard some eventlogs */
     174             : 
     175             :         /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
     176             :            although records not necessarily guaranteed to have successive times */
     177             :         /* */
     178             : 
     179             :         /* lock */
     180          12 :         tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
     181             :         /* read */
     182          12 :         end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
     183          12 :         start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
     184          12 :         Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
     185          12 :         MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
     186             : 
     187          12 :         time( &current_time );
     188             : 
     189             :         /* calculate ... */
     190          12 :         exp_time = current_time - Retention;    /* discard older than exp_time */
     191             : 
     192             :         /* todo - check for sanity in next_record */
     193          12 :         nbytes = 0;
     194             : 
     195          12 :         DEBUG( 3,
     196             :                ( "MaxSize [%d] Retention [%d] Current Time [%u]  exp_time [%u]\n",
     197             :                  MaxSize, Retention, (unsigned int)current_time, (unsigned int)exp_time ) );
     198          12 :         DEBUG( 3,
     199             :                ( "Start Record [%u] End Record [%u]\n",
     200             :                 (unsigned int)start_record,
     201             :                 (unsigned int)end_record ));
     202             : 
     203          12 :         for ( i = start_record; i < end_record; i++ ) {
     204             :                 /* read a record, add the amt to nbytes */
     205           4 :                 key.dsize = sizeof(int32_t);
     206           4 :                 key.dptr = (unsigned char *)&i;
     207           4 :                 ret = tdb_fetch( the_tdb, key );
     208           4 :                 if ( ret.dsize == 0 ) {
     209           0 :                         DEBUG( 8,
     210             :                                ( "Can't find a record for the key, record [%d]\n",
     211             :                                  i ) );
     212           0 :                         tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
     213           0 :                         return False;
     214             :                 }
     215           4 :                 nbytes += ret.dsize;    /* note this includes overhead */
     216             : 
     217           4 :                 len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
     218             :                                   &tresv1, &trecnum, &timegen, &timewr );
     219           4 :                 if (len == -1) {
     220           0 :                         DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
     221           0 :                         tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
     222           0 :                         SAFE_FREE( ret.dptr );
     223           0 :                         return False;
     224             :                 }
     225             : 
     226           4 :                 DEBUG( 8,
     227             :                        ( "read record %u, record size is [%d], total so far [%d]\n",
     228             :                          (unsigned int)i, reclen, nbytes ) );
     229             : 
     230           4 :                 SAFE_FREE( ret.dptr );
     231             : 
     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. */
     237             : 
     238           4 :                 if ( !whack_by_date && ( nbytes >= needed ) )
     239           0 :                         break;  /* done */
     240           4 :                 if ( whack_by_date && ( timegen >= exp_time ) )
     241           4 :                         break;  /* done */
     242             :         }
     243             : 
     244          12 :         DEBUG( 3,
     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... */
     248          12 :         new_start = i;
     249          12 :         if ( start_record != new_start ) {
     250           0 :                 for ( i = start_record; i < new_start; i++ ) {
     251           0 :                         key.dsize = sizeof(int32_t);
     252           0 :                         key.dptr = (unsigned char *)&i;
     253           0 :                         tdb_delete( the_tdb, key );
     254             :                 }
     255             : 
     256           0 :                 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
     257             :         }
     258          12 :         tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
     259          12 :         return True;
     260             : }
     261             : 
     262             : /********************************************************************
     263             :   some hygiene for an eventlog - see how big it is, and then
     264             :   calculate how many bytes we need to remove
     265             : ********************************************************************/
     266             : 
     267          12 : bool prune_eventlog( TDB_CONTEXT * tdb )
     268             : {
     269           0 :         int MaxSize, Retention, CalcdSize;
     270             : 
     271          12 :         if ( !tdb ) {
     272           0 :                 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
     273           0 :                 return False;
     274             :         }
     275             : 
     276          12 :         CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
     277          12 :         DEBUG( 3,
     278             :                ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
     279             :                  MaxSize ) );
     280             : 
     281          12 :         if ( CalcdSize > MaxSize ) {
     282           0 :                 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
     283             :                                                False );
     284             :         }
     285             : 
     286          12 :         return make_way_for_eventlogs( tdb, 0, True );
     287             : }
     288             : 
     289             : /********************************************************************
     290             : ********************************************************************/
     291             : 
     292           2 : static bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed )
     293             : {
     294           0 :         int calcd_size;
     295           0 :         int MaxSize, Retention;
     296             : 
     297             :         /* see if we can write to the eventlog -- do a policy enforcement */
     298           2 :         if ( !tdb )
     299           0 :                 return False;   /* tdb is null, so we can't write to it */
     300             : 
     301             : 
     302           2 :         if ( needed < 0 )
     303           0 :                 return False;
     304           2 :         MaxSize = 0;
     305           2 :         Retention = 0;
     306             : 
     307           2 :         calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
     308             : 
     309           2 :         if ( calcd_size <= MaxSize )
     310           2 :                 return True;    /* you betcha */
     311           0 :         if ( calcd_size + needed < MaxSize )
     312           0 :                 return True;
     313             : 
     314           0 :         if ( Retention == 0xffffffff ) {
     315           0 :                 return False;   /* see msdn - we can't write no room, discard */
     316             :         }
     317             :         /*
     318             :            note don't have to test, but always good to show intent, in case changes needed
     319             :            later
     320             :          */
     321             : 
     322           0 :         if ( Retention == 0x00000000 ) {
     323             :                 /* discard record(s) */
     324             :                 /* todo  - decide when to remove a bunch vs. just what we need... */
     325           0 :                 return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
     326             :                                                True );
     327             :         }
     328             : 
     329           0 :         return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
     330             : }
     331             : 
     332             : /*******************************************************************
     333             : *******************************************************************/
     334             : 
     335          12 : ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only )
     336             : {
     337          12 :         TDB_CONTEXT *tdb = NULL;
     338           0 :         uint32_t vers_id;
     339           0 :         ELOG_TDB *ptr;
     340          12 :         char *tdbpath = NULL;
     341          12 :         ELOG_TDB *tdb_node = NULL;
     342           0 :         char *eventlogdir;
     343          12 :         TALLOC_CTX *ctx = talloc_tos();
     344           0 :         bool ok;
     345             : 
     346             :         /* check for invalid options */
     347             : 
     348          12 :         if (force_clear && read_only) {
     349           0 :                 DEBUG(1,("elog_open_tdb: Invalid flags\n"));
     350           0 :                 return NULL;
     351             :         }
     352             : 
     353             :         /* first see if we have an open context */
     354             : 
     355          12 :         for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
     356           0 :                 if ( strequal( ptr->name, logname ) ) {
     357           0 :                         ptr->ref_count++;
     358             : 
     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 */
     364             : 
     365           0 :                         if ( force_clear ) {
     366           0 :                                 SMB_ASSERT( ptr->tdb == NULL );
     367           0 :                                 break;
     368             :                         }
     369             :                         else
     370           0 :                                 return ptr;
     371             :                 }
     372             :         }
     373             : 
     374             :         /* make sure that the eventlog dir exists */
     375             : 
     376          12 :         eventlogdir = state_path(talloc_tos(), "eventlog");
     377          12 :         if (eventlogdir == NULL) {
     378           0 :                 return NULL;
     379             :         }
     380          12 :         ok = directory_create_or_exist(eventlogdir, 0755);
     381          12 :         TALLOC_FREE(eventlogdir);
     382          12 :         if (!ok) {
     383           0 :                 return NULL;
     384             :         }
     385             : 
     386             :         /* get the path on disk */
     387             : 
     388          12 :         tdbpath = elog_tdbname(ctx, logname);
     389          12 :         if (!tdbpath) {
     390           0 :                 return NULL;
     391             :         }
     392             : 
     393          12 :         DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
     394             :                 tdbpath, force_clear?"True":"False" ));
     395             : 
     396             :         /* the tdb wasn't already open or this is a forced clear open */
     397             : 
     398          12 :         if ( !force_clear ) {
     399             : 
     400          12 :                 tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, read_only ? O_RDONLY : O_RDWR , 0 );
     401          12 :                 if ( tdb ) {
     402          10 :                         vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
     403             : 
     404          10 :                         if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
     405           0 :                                 DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
     406             :                                         vers_id, tdbpath));
     407           0 :                                 tdb_close( tdb );
     408           0 :                                 tdb = elog_init_tdb( tdbpath );
     409             :                         }
     410             :                 }
     411             :         }
     412             : 
     413          12 :         if ( !tdb )
     414           2 :                 tdb = elog_init_tdb( tdbpath );
     415             : 
     416             :         /* if we got a valid context, then add it to the list */
     417             : 
     418          12 :         if ( tdb ) {
     419             :                 /* on a forced clear, just reset the tdb context if we already
     420             :                    have an open entry in the list */
     421             : 
     422          12 :                 if ( ptr ) {
     423           0 :                         ptr->tdb = tdb;
     424           0 :                         return ptr;
     425             :                 }
     426             : 
     427          12 :                 if ( !(tdb_node = talloc_zero( NULL, ELOG_TDB)) ) {
     428           0 :                         DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
     429           0 :                         tdb_close( tdb );
     430           0 :                         return NULL;
     431             :                 }
     432             : 
     433          12 :                 tdb_node->name = talloc_strdup( tdb_node, logname );
     434          12 :                 tdb_node->tdb = tdb;
     435          12 :                 tdb_node->ref_count = 1;
     436             : 
     437          12 :                 DLIST_ADD( open_elog_list, tdb_node );
     438             :         }
     439             : 
     440          12 :         return tdb_node;
     441             : }
     442             : 
     443             : /*******************************************************************
     444             :  Wrapper to handle reference counts to the tdb
     445             : *******************************************************************/
     446             : 
     447          12 : int elog_close_tdb( ELOG_TDB *etdb, bool force_close )
     448             : {
     449           0 :         TDB_CONTEXT *tdb;
     450             : 
     451          12 :         if ( !etdb )
     452           0 :                 return 0;
     453             : 
     454          12 :         etdb->ref_count--;
     455             : 
     456          12 :         SMB_ASSERT( etdb->ref_count >= 0 );
     457             : 
     458          12 :         if ( etdb->ref_count == 0 ) {
     459          12 :                 tdb = etdb->tdb;
     460          12 :                 DLIST_REMOVE( open_elog_list, etdb );
     461          12 :                 TALLOC_FREE( etdb );
     462          12 :                 return tdb_close( tdb );
     463             :         }
     464             : 
     465           0 :         if ( force_close ) {
     466           0 :                 tdb = etdb->tdb;
     467           0 :                 etdb->tdb = NULL;
     468           0 :                 return tdb_close( tdb );
     469             :         }
     470             : 
     471           0 :         return 0;
     472             : }
     473             : 
     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
     479             :  going in.
     480             : ********************************************************************/
     481             : 
     482           0 : bool parse_logentry( TALLOC_CTX *mem_ctx, char *line, struct eventlog_Record_tdb *entry, bool * eor )
     483             : {
     484           0 :         char *start = NULL, *stop = NULL;
     485             : 
     486           0 :         start = line;
     487             : 
     488             :         /* empty line signifying record delimiter, or we're at the end of the buffer */
     489           0 :         if ( start == NULL || strlen( start ) == 0 ) {
     490           0 :                 DEBUG( 6,
     491             :                        ( "parse_logentry: found end-of-record indicator.\n" ) );
     492           0 :                 *eor = True;
     493           0 :                 return True;
     494             :         }
     495           0 :         if ( !( stop = strchr( line, ':' ) ) ) {
     496           0 :                 return False;
     497             :         }
     498             : 
     499           0 :         DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
     500             : 
     501           0 :         if ( 0 == strncmp( start, "LEN", stop - start ) ) {
     502             :                 /* This will get recomputed later anyway -- probably not necessary */
     503           0 :                 entry->size = atoi( stop + 1 );
     504           0 :         } 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           0 :                 entry->reserved = talloc_strdup(mem_ctx, "eLfL");
     508           0 :         } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
     509           0 :                 entry->record_number = atoi( stop + 1 );
     510           0 :         } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
     511           0 :                 entry->time_generated = atoi( stop + 1 );
     512           0 :         } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
     513           0 :                 entry->time_written = atoi( stop + 1 );
     514           0 :         } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
     515           0 :                 entry->event_id = atoi( stop + 1 );
     516           0 :         } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
     517           0 :                 if ( strstr( start, "ERROR" ) ) {
     518           0 :                         entry->event_type = EVENTLOG_ERROR_TYPE;
     519           0 :                 } else if ( strstr( start, "WARNING" ) ) {
     520           0 :                         entry->event_type = EVENTLOG_WARNING_TYPE;
     521           0 :                 } else if ( strstr( start, "INFO" ) ) {
     522           0 :                         entry->event_type = EVENTLOG_INFORMATION_TYPE;
     523           0 :                 } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
     524           0 :                         entry->event_type = EVENTLOG_AUDIT_SUCCESS;
     525           0 :                 } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
     526           0 :                         entry->event_type = EVENTLOG_AUDIT_FAILURE;
     527           0 :                 } else if ( strstr( start, "SUCCESS" ) ) {
     528           0 :                         entry->event_type = EVENTLOG_SUCCESS;
     529             :                 } else {
     530             :                         /* some other eventlog type -- currently not defined in MSDN docs, so error out */
     531           0 :                         return False;
     532             :                 }
     533             :         }
     534             : 
     535             : /*
     536             :   else if(0 == strncmp(start, "NST", stop - start))
     537             :   {
     538             :   entry->num_of_strings = atoi(stop + 1);
     539             :   }
     540             : */
     541           0 :         else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
     542           0 :                 entry->event_category = atoi( stop + 1 );
     543           0 :         } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
     544           0 :                 entry->reserved_flags = atoi( stop + 1 );
     545           0 :         } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
     546           0 :                 entry->closing_record_number = atoi( stop + 1 );
     547           0 :         } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
     548           0 :                 entry->sid_length = atoi( stop + 1 );
     549           0 :         } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
     550           0 :                 stop++;
     551           0 :                 while ( isspace( stop[0] ) ) {
     552           0 :                         stop++;
     553             :                 }
     554           0 :                 entry->source_name_len = strlen_m_term(stop);
     555           0 :                 entry->source_name = talloc_strdup(mem_ctx, stop);
     556           0 :                 if (entry->source_name_len == (uint32_t)-1 ||
     557           0 :                                 entry->source_name == NULL) {
     558           0 :                         return false;
     559             :                 }
     560           0 :         } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
     561           0 :                 stop++;
     562           0 :                 while ( isspace( stop[0] ) ) {
     563           0 :                         stop++;
     564             :                 }
     565           0 :                 entry->computer_name_len = strlen_m_term(stop);
     566           0 :                 entry->computer_name = talloc_strdup(mem_ctx, stop);
     567           0 :                 if (entry->computer_name_len == (uint32_t)-1 ||
     568           0 :                                 entry->computer_name == NULL) {
     569           0 :                         return false;
     570             :                 }
     571           0 :         } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
     572           0 :                 smb_ucs2_t *dummy = NULL;
     573           0 :                 stop++;
     574           0 :                 while ( isspace( stop[0] ) ) {
     575           0 :                         stop++;
     576             :                 }
     577           0 :                 entry->sid_length = rpcstr_push_talloc(mem_ctx,
     578             :                                 &dummy,
     579             :                                 stop);
     580           0 :                 if (entry->sid_length == (uint32_t)-1) {
     581           0 :                         return false;
     582             :                 }
     583           0 :                 entry->sid = data_blob_talloc(mem_ctx, dummy, entry->sid_length);
     584           0 :                 if (entry->sid.data == NULL) {
     585           0 :                         return false;
     586             :                 }
     587           0 :         } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
     588           0 :                 size_t tmp_len;
     589           0 :                 size_t num_of_strings;
     590             :                 /* skip past initial ":" */
     591           0 :                 stop++;
     592             :                 /* now skip any other leading whitespace */
     593           0 :                 while ( isspace(stop[0])) {
     594           0 :                         stop++;
     595             :                 }
     596           0 :                 tmp_len = strlen_m_term(stop);
     597           0 :                 if (tmp_len == (size_t)-1) {
     598           0 :                         return false;
     599             :                 }
     600           0 :                 num_of_strings = entry->num_of_strings;
     601           0 :                 if (!add_string_to_array(mem_ctx, stop, &entry->strings,
     602             :                                          &num_of_strings)) {
     603           0 :                         return false;
     604             :                 }
     605           0 :                 if (num_of_strings > 0xffff) {
     606           0 :                         return false;
     607             :                 }
     608           0 :                 entry->num_of_strings = num_of_strings;
     609           0 :                 entry->strings_len += tmp_len;
     610           0 :         } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
     611             :                 /* skip past initial ":" */
     612           0 :                 stop++;
     613             :                 /* now skip any other leading whitespace */
     614           0 :                 while ( isspace( stop[0] ) ) {
     615           0 :                         stop++;
     616             :                 }
     617           0 :                 entry->data_length = strlen_m(stop);
     618           0 :                 entry->data = data_blob_talloc(mem_ctx, stop, entry->data_length);
     619           0 :                 if (!entry->data.data) {
     620           0 :                         return false;
     621             :                 }
     622             :         } else {
     623             :                 /* some other eventlog entry -- not implemented, so dropping on the floor */
     624           0 :                 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. */
     627           0 :                 return true;
     628             :         }
     629           0 :         return true;
     630             : }
     631             : 
     632             : /*******************************************************************
     633             :  calculate the correct fields etc for an eventlog entry
     634             : *******************************************************************/
     635             : 
     636           0 : size_t fixup_eventlog_record_tdb(struct eventlog_Record_tdb *r)
     637             : {
     638           0 :         size_t size = 56; /* static size of integers before buffers start */
     639             : 
     640           0 :         r->source_name_len = strlen_m_term(r->source_name) * 2;
     641           0 :         r->computer_name_len = strlen_m_term(r->computer_name) * 2;
     642           0 :         r->strings_len = ndr_size_string_array(r->strings,
     643           0 :                 r->num_of_strings, LIBNDR_FLAG_STR_NULLTERM) * 2;
     644             : 
     645             :         /* fix up the eventlog entry structure as necessary */
     646           0 :         r->sid_padding = ( ( 4 - ( ( r->source_name_len + r->computer_name_len ) % 4 ) ) % 4 );
     647           0 :         r->padding =       ( 4 - ( ( r->strings_len + r->data_length ) % 4 ) ) % 4;
     648             : 
     649           0 :         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           0 :                 r->padding += r->sid_padding;
     653           0 :                 r->sid_padding = 0;
     654             :         }
     655             : 
     656           0 :         size += r->source_name_len;
     657           0 :         size += r->computer_name_len;
     658           0 :         size += r->sid_padding;
     659           0 :         size += r->sid_length;
     660           0 :         size += r->strings_len;
     661           0 :         size += r->data_length;
     662           0 :         size += r->padding;
     663             :         /* need another copy of length at the end of the data */
     664           0 :         size += sizeof(r->size);
     665             : 
     666           0 :         r->size = size;
     667             : 
     668           0 :         return size;
     669             : }
     670             : 
     671             : 
     672             : /********************************************************************
     673             :  ********************************************************************/
     674             : 
     675           2 : struct eventlog_Record_tdb *evlog_pull_record_tdb(TALLOC_CTX *mem_ctx,
     676             :                                                   TDB_CONTEXT *tdb,
     677             :                                                   uint32_t record_number)
     678             : {
     679           0 :         struct eventlog_Record_tdb *r;
     680           0 :         TDB_DATA data, key;
     681             : 
     682           0 :         int32_t srecno;
     683           0 :         enum ndr_err_code ndr_err;
     684           0 :         DATA_BLOB blob;
     685             : 
     686           2 :         srecno = record_number;
     687           2 :         key.dptr = (unsigned char *)&srecno;
     688           2 :         key.dsize = sizeof(int32_t);
     689             : 
     690           2 :         data = tdb_fetch(tdb, key);
     691           2 :         if (data.dsize == 0) {
     692           2 :                 DEBUG(8,("evlog_pull_record_tdb: "
     693             :                         "Can't find a record for the key, record %d\n",
     694             :                         record_number));
     695           2 :                 return NULL;
     696             :         }
     697             : 
     698           0 :         r = talloc_zero(mem_ctx, struct eventlog_Record_tdb);
     699           0 :         if (!r) {
     700           0 :                 goto done;
     701             :         }
     702             : 
     703           0 :         blob = data_blob_const(data.dptr, data.dsize);
     704             : 
     705           0 :         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, r,
     706             :                            (ndr_pull_flags_fn_t)ndr_pull_eventlog_Record_tdb);
     707             : 
     708           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     709           0 :                 DEBUG(10,("evlog_pull_record_tdb: failed to decode record %d\n",
     710             :                         record_number));
     711           0 :                 TALLOC_FREE(r);
     712           0 :                 goto done;
     713             :         }
     714             : 
     715           0 :         if (DEBUGLEVEL >= 10) {
     716           0 :                 NDR_PRINT_DEBUG(eventlog_Record_tdb, r);
     717             :         }
     718             : 
     719           0 :         DEBUG(10,("evlog_pull_record_tdb: retrieved entry for record %d\n",
     720             :                 record_number));
     721           0 :  done:
     722           0 :         SAFE_FREE(data.dptr);
     723             : 
     724           0 :         return r;
     725             : }
     726             : 
     727             : /********************************************************************
     728             :  ********************************************************************/
     729             : 
     730           2 : struct EVENTLOGRECORD *evlog_pull_record(TALLOC_CTX *mem_ctx,
     731             :                                          TDB_CONTEXT *tdb,
     732             :                                          uint32_t record_number)
     733             : {
     734           0 :         struct eventlog_Record_tdb *t;
     735           0 :         struct EVENTLOGRECORD *r;
     736           0 :         NTSTATUS status;
     737             : 
     738           2 :         r = talloc_zero(mem_ctx, struct EVENTLOGRECORD);
     739           2 :         if (!r) {
     740           0 :                 return NULL;
     741             :         }
     742             : 
     743           2 :         t = evlog_pull_record_tdb(r, tdb, record_number);
     744           2 :         if (!t) {
     745           2 :                 talloc_free(r);
     746           2 :                 return NULL;
     747             :         }
     748             : 
     749           0 :         status = evlog_tdb_entry_to_evt_entry(r, t, r);
     750           0 :         if (!NT_STATUS_IS_OK(status)) {
     751           0 :                 talloc_free(r);
     752           0 :                 return NULL;
     753             :         }
     754             : 
     755           0 :         r->Length = r->Length2 = ndr_size_EVENTLOGRECORD(r, 0);
     756             : 
     757           0 :         return r;
     758             : }
     759             : 
     760             : /********************************************************************
     761             :  write an eventlog entry. Note that we have to lock, read next
     762             :  eventlog, increment, write, write the record, unlock
     763             : 
     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             :  ********************************************************************/
     769             : 
     770           2 : NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx,
     771             :                                TDB_CONTEXT *tdb,
     772             :                                struct eventlog_Record_tdb *r,
     773             :                                uint32_t *record_number)
     774             : {
     775           0 :         TDB_DATA kbuf, ebuf;
     776           0 :         DATA_BLOB blob;
     777           0 :         enum ndr_err_code ndr_err;
     778           0 :         int ret;
     779             : 
     780           2 :         if (!r) {
     781           0 :                 return NT_STATUS_INVALID_PARAMETER;
     782             :         }
     783             : 
     784           2 :         if (!can_write_to_eventlog(tdb, r->size)) {
     785           0 :                 return NT_STATUS_EVENTLOG_CANT_START;
     786             :         }
     787             : 
     788             :         /* need to read the record number and insert it into the entry here */
     789             : 
     790             :         /* lock */
     791           2 :         ret = tdb_lock_bystring_with_timeout(tdb, EVT_NEXT_RECORD, 1);
     792           2 :         if (ret != 0) {
     793           0 :                 return NT_STATUS_LOCK_NOT_GRANTED;
     794             :         }
     795             : 
     796             :         /* read */
     797           2 :         r->record_number = tdb_fetch_int32(tdb, EVT_NEXT_RECORD);
     798             : 
     799           2 :         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, r,
     800             :                       (ndr_push_flags_fn_t)ndr_push_eventlog_Record_tdb);
     801           2 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     802           0 :                 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
     803           0 :                 return ndr_map_error2ntstatus(ndr_err);
     804             :         }
     805             : 
     806             :         /* increment the record count */
     807             : 
     808           2 :         kbuf.dsize = sizeof(int32_t);
     809           2 :         kbuf.dptr = (uint8_t *)&r->record_number;
     810             : 
     811           2 :         ebuf.dsize = blob.length;
     812           2 :         ebuf.dptr  = blob.data;
     813             : 
     814           2 :         ret = tdb_store(tdb, kbuf, ebuf, 0);
     815           2 :         if (ret != 0) {
     816           0 :                 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
     817           0 :                 return NT_STATUS_EVENTLOG_FILE_CORRUPT;
     818             :         }
     819             : 
     820           2 :         ret = tdb_store_int32(tdb, EVT_NEXT_RECORD, r->record_number + 1);
     821           2 :         if (ret != 0) {
     822           0 :                 tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
     823           0 :                 return NT_STATUS_EVENTLOG_FILE_CORRUPT;
     824             :         }
     825           2 :         tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
     826             : 
     827           2 :         if (record_number) {
     828           2 :                 *record_number = r->record_number;
     829             :         }
     830             : 
     831           2 :         return NT_STATUS_OK;
     832             : }
     833             : 
     834             : /********************************************************************
     835             :  ********************************************************************/
     836             : 
     837           2 : NTSTATUS evlog_push_record(TALLOC_CTX *mem_ctx,
     838             :                            TDB_CONTEXT *tdb,
     839             :                            struct EVENTLOGRECORD *r,
     840             :                            uint32_t *record_number)
     841             : {
     842           0 :         struct eventlog_Record_tdb *t;
     843           0 :         NTSTATUS status;
     844             : 
     845           2 :         t = talloc_zero(mem_ctx, struct eventlog_Record_tdb);
     846           2 :         if (!t) {
     847           0 :                 return NT_STATUS_NO_MEMORY;
     848             :         }
     849             : 
     850           2 :         status = evlog_evt_entry_to_tdb_entry(t, r, t);
     851           2 :         if (!NT_STATUS_IS_OK(status)) {
     852           0 :                 talloc_free(t);
     853           0 :                 return status;
     854             :         }
     855             : 
     856           2 :         status = evlog_push_record_tdb(mem_ctx, tdb, t, record_number);
     857           2 :         talloc_free(t);
     858             : 
     859           2 :         return status;
     860             : }
     861             : 
     862             : /********************************************************************
     863             :  ********************************************************************/
     864             : 
     865           2 : NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx,
     866             :                                       const struct EVENTLOGRECORD *e,
     867             :                                       struct eventlog_Record_tdb *t)
     868             : {
     869           0 :         uint32_t i;
     870             : 
     871           2 :         ZERO_STRUCTP(t);
     872             : 
     873           2 :         t->size                              = e->Length;
     874           2 :         t->reserved                  = e->Reserved;
     875           2 :         t->record_number             = e->RecordNumber;
     876           2 :         t->time_generated            = e->TimeGenerated;
     877           2 :         t->time_written                      = e->TimeWritten;
     878           2 :         t->event_id                  = e->EventID;
     879           2 :         t->event_type                        = e->EventType;
     880           2 :         t->num_of_strings            = e->NumStrings;
     881           2 :         t->event_category            = e->EventCategory;
     882           2 :         t->reserved_flags            = e->ReservedFlags;
     883           2 :         t->closing_record_number     = e->ClosingRecordNumber;
     884             : 
     885           2 :         t->stringoffset                      = e->StringOffset;
     886           2 :         t->sid_length                        = e->UserSidLength;
     887           2 :         t->sid_offset                        = e->UserSidOffset;
     888           2 :         t->data_length                       = e->DataLength;
     889           2 :         t->data_offset                       = e->DataOffset;
     890             : 
     891           2 :         t->source_name_len           = 2 * strlen_m_term(e->SourceName);
     892           2 :         t->source_name                       = talloc_strdup(mem_ctx, e->SourceName);
     893           2 :         NT_STATUS_HAVE_NO_MEMORY(t->source_name);
     894             : 
     895           2 :         t->computer_name_len         = 2 * strlen_m_term(e->Computername);
     896           2 :         t->computer_name             = talloc_strdup(mem_ctx, e->Computername);
     897           2 :         NT_STATUS_HAVE_NO_MEMORY(t->computer_name);
     898             : 
     899             :         /* t->sid_padding; */
     900           2 :         if (e->UserSidLength > 0) {
     901           0 :                 struct dom_sid_buf sid_str;
     902           0 :                 smb_ucs2_t *dummy = NULL;
     903           0 :                 t->sid_length = rpcstr_push_talloc(
     904             :                         mem_ctx,
     905             :                         &dummy,
     906           0 :                         dom_sid_str_buf(&e->UserSid, &sid_str));
     907           0 :                 if (t->sid_length == -1) {
     908           0 :                         return NT_STATUS_NO_MEMORY;
     909             :                 }
     910           0 :                 t->sid = data_blob_talloc(mem_ctx, (uint8_t *)dummy, t->sid_length);
     911           0 :                 NT_STATUS_HAVE_NO_MEMORY(t->sid.data);
     912             :         }
     913             : 
     914           2 :         t->strings                   = talloc_array(mem_ctx, const char *, e->NumStrings);
     915           4 :         for (i=0; i < e->NumStrings; i++) {
     916           2 :                 t->strings[i]                = talloc_strdup(t->strings, e->Strings[i]);
     917           2 :                 NT_STATUS_HAVE_NO_MEMORY(t->strings[i]);
     918             :         }
     919             : 
     920           2 :         t->strings_len                       = 2 * ndr_size_string_array(t->strings, t->num_of_strings, LIBNDR_FLAG_STR_NULLTERM);
     921           2 :         t->data                              = data_blob_talloc(mem_ctx, e->Data, e->DataLength);
     922             :         /* t->padding                        = r->Pad; */
     923             : 
     924           2 :         return NT_STATUS_OK;
     925             : }
     926             : 
     927             : /********************************************************************
     928             :  ********************************************************************/
     929             : 
     930           0 : NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx,
     931             :                                       const struct eventlog_Record_tdb *t,
     932             :                                       struct EVENTLOGRECORD *e)
     933             : {
     934           0 :         uint32_t i;
     935             : 
     936           0 :         ZERO_STRUCTP(e);
     937             : 
     938           0 :         e->Length            = t->size;
     939           0 :         e->Reserved          = t->reserved;
     940           0 :         e->RecordNumber              = t->record_number;
     941           0 :         e->TimeGenerated     = t->time_generated;
     942           0 :         e->TimeWritten               = t->time_written;
     943           0 :         e->EventID           = t->event_id;
     944           0 :         e->EventType         = t->event_type;
     945           0 :         e->NumStrings                = t->num_of_strings;
     946           0 :         e->EventCategory     = t->event_category;
     947           0 :         e->ReservedFlags     = t->reserved_flags;
     948           0 :         e->ClosingRecordNumber       = t->closing_record_number;
     949             : 
     950           0 :         e->StringOffset              = t->stringoffset;
     951           0 :         e->UserSidLength     = t->sid_length;
     952           0 :         e->UserSidOffset     = t->sid_offset;
     953           0 :         e->DataLength                = t->data_length;
     954           0 :         e->DataOffset                = t->data_offset;
     955             : 
     956           0 :         e->SourceName                = talloc_strdup(mem_ctx, t->source_name);
     957           0 :         NT_STATUS_HAVE_NO_MEMORY(e->SourceName);
     958             : 
     959           0 :         e->Computername              = talloc_strdup(mem_ctx, t->computer_name);
     960           0 :         NT_STATUS_HAVE_NO_MEMORY(e->Computername);
     961             : 
     962           0 :         if (t->sid_length > 0) {
     963           0 :                 char *sid_str = NULL;
     964           0 :                 size_t len;
     965           0 :                 if (!convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
     966           0 :                                            t->sid.data, t->sid.length,
     967             :                                            (void *)&sid_str, &len)) {
     968           0 :                         return NT_STATUS_INVALID_SID;
     969             :                 }
     970           0 :                 if (len > 0) {
     971           0 :                         bool ok = string_to_sid(&e->UserSid, sid_str);
     972           0 :                         if (!ok) {
     973           0 :                                 return NT_STATUS_INVALID_SID;
     974             :                         }
     975             :                 }
     976           0 :                 TALLOC_FREE(sid_str);
     977             :         }
     978             : 
     979           0 :         e->Strings           = talloc_array(mem_ctx, const char *, t->num_of_strings);
     980           0 :         for (i=0; i < t->num_of_strings; i++) {
     981           0 :                 e->Strings[i] = talloc_strdup(e->Strings, t->strings[i]);
     982           0 :                 NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]);
     983             :         }
     984             : 
     985           0 :         e->Data                      = (uint8_t *)talloc_memdup(mem_ctx, t->data.data, t->data_length);
     986           0 :         e->Pad                       = talloc_strdup(mem_ctx, "");
     987           0 :         NT_STATUS_HAVE_NO_MEMORY(e->Pad);
     988             : 
     989           0 :         e->Length2           = t->size;
     990             : 
     991           0 :         return NT_STATUS_OK;
     992             : }
     993             : 
     994             : /********************************************************************
     995             :  ********************************************************************/
     996             : 
     997           0 : NTSTATUS evlog_convert_tdb_to_evt(TALLOC_CTX *mem_ctx,
     998             :                                   ELOG_TDB *etdb,
     999             :                                   DATA_BLOB *blob_p,
    1000             :                                   uint32_t *num_records_p)
    1001             : {
    1002           0 :         NTSTATUS status = NT_STATUS_OK;
    1003           0 :         enum ndr_err_code ndr_err;
    1004           0 :         DATA_BLOB blob;
    1005           0 :         uint32_t num_records = 0;
    1006           0 :         struct EVENTLOG_EVT_FILE evt;
    1007           0 :         uint32_t count = 1;
    1008           0 :         size_t endoffset = 0;
    1009             : 
    1010           0 :         ZERO_STRUCT(evt);
    1011             : 
    1012           0 :         while (1) {
    1013             : 
    1014           0 :                 struct eventlog_Record_tdb *r;
    1015           0 :                 struct EVENTLOGRECORD e;
    1016             : 
    1017           0 :                 r = evlog_pull_record_tdb(mem_ctx, etdb->tdb, count);
    1018           0 :                 if (!r) {
    1019           0 :                         break;
    1020             :                 }
    1021             : 
    1022           0 :                 status = evlog_tdb_entry_to_evt_entry(mem_ctx, r, &e);
    1023           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1024           0 :                         goto done;
    1025             :                 }
    1026             : 
    1027           0 :                 endoffset += ndr_size_EVENTLOGRECORD(&e, 0);
    1028             : 
    1029           0 :                 ADD_TO_ARRAY(mem_ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records);
    1030           0 :                 count++;
    1031             :         }
    1032             : 
    1033           0 :         evt.hdr.StartOffset             = 0x30;
    1034           0 :         evt.hdr.EndOffset               = evt.hdr.StartOffset + endoffset;
    1035           0 :         evt.hdr.CurrentRecordNumber     = count;
    1036           0 :         evt.hdr.OldestRecordNumber      = 1;
    1037           0 :         evt.hdr.MaxSize                 = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE);
    1038           0 :         evt.hdr.Flags                   = 0;
    1039           0 :         evt.hdr.Retention               = tdb_fetch_int32(etdb->tdb, EVT_RETENTION);
    1040             : 
    1041           0 :         if (DEBUGLEVEL >= 10) {
    1042           0 :                 NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr);
    1043             :         }
    1044             : 
    1045           0 :         evt.eof.BeginRecord             = 0x30;
    1046           0 :         evt.eof.EndRecord               = evt.hdr.StartOffset + endoffset;
    1047           0 :         evt.eof.CurrentRecordNumber     = evt.hdr.CurrentRecordNumber;
    1048           0 :         evt.eof.OldestRecordNumber      = evt.hdr.OldestRecordNumber;
    1049             : 
    1050           0 :         if (DEBUGLEVEL >= 10) {
    1051           0 :                 NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof);
    1052             :         }
    1053             : 
    1054           0 :         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &evt,
    1055             :                    (ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE);
    1056           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1057           0 :                 status = ndr_map_error2ntstatus(ndr_err);
    1058           0 :                 goto done;
    1059             :         }
    1060             : 
    1061           0 :         *blob_p = blob;
    1062           0 :         *num_records_p = num_records;
    1063             : 
    1064           0 :  done:
    1065           0 :         return status;
    1066             : }

Generated by: LCOV version 1.14