f21e983eb7285c56c05d598a05602fa506468d20
[samba.git] / source3 / rpc_server / srv_eventlog_lib.c
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  *  
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *  
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *  
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23
24 /* maintain a list of open eventlog tdbs with reference counts */
25
26 static ELOG_TDB *open_elog_list;
27
28 /********************************************************************
29  Init an Eventlog TDB, and return it. If null, something bad 
30  happened.
31 ********************************************************************/
32
33 TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
34 {
35         TDB_CONTEXT *tdb;
36
37         DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
38                 tdbfilename));
39
40         tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT, 
41                 O_RDWR|O_CREAT|O_TRUNC, 0660 );
42
43         if ( !tdb ) {
44                 DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
45                 return NULL;
46         }
47
48         /* initialize with defaults, copy real values in here from registry */
49
50         tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 );
51         tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 );
52         tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 );
53         tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 );
54
55         tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
56
57         return tdb;
58 }
59
60 /********************************************************************
61  make the tdb file name for an event log, given destination buffer 
62  and size. Caller must free memory.
63 ********************************************************************/
64
65 char *elog_tdbname( const char *name )
66 {
67         fstring path;
68         char *tdb_fullpath;
69         char *eventlogdir = lock_path( "eventlog" );
70         
71         pstr_sprintf( path, "%s/%s.tdb", eventlogdir, name );
72         strlower_m( path );
73         tdb_fullpath = SMB_STRDUP( path );
74         
75         return tdb_fullpath;
76 }
77
78
79 /********************************************************************
80  this function is used to count up the number of bytes in a 
81  particular TDB
82 ********************************************************************/
83
84 struct trav_size_struct {
85         int size;
86         int rec_count;
87 };
88
89 static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
90                           void *state )
91 {
92         struct trav_size_struct  *tsize = (struct trav_size_struct *)state;
93         
94         tsize->size += data.dsize;
95         tsize->rec_count++;
96         
97         return 0;
98 }
99
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. 
104  Yeah, that's it.
105 ********************************************************************/
106
107 int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
108 {
109         struct trav_size_struct tsize;
110         
111         if ( !tdb )
112                 return 0;
113                 
114         ZERO_STRUCT( tsize );
115
116         tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
117
118         if ( MaxSize != NULL ) {
119                 *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
120         }
121
122         if ( Retention != NULL ) {
123                 *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
124         }
125
126         DEBUG( 1,
127                ( "eventlog size: [%d] for [%d] records\n", tsize.size,
128                  tsize.rec_count ) );
129         return tsize.size;
130 }
131
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.  
137
138  Setting whack_by_date to True indicates that eventlogs falling 
139  outside of the retention range need to go...
140  
141  return True if we made enough room to accommodate needed bytes
142 ********************************************************************/
143
144 BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
145                              BOOL whack_by_date )
146 {
147         int start_record, i, new_start;
148         int end_record;
149         int nbytes, reclen, len, Retention, MaxSize;
150         int tresv1, trecnum, timegen, timewr;
151         TDB_DATA key, ret;
152         TALLOC_CTX *mem_ctx = NULL;
153         time_t current_time, exp_time;
154
155         /* discard some eventlogs */
156
157         /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
158            although records not necessarily guaranteed to have successive times */
159         /* */
160         mem_ctx = talloc_init( "make_way_for_eventlogs" );      /* Homage to BPG */
161
162         if ( mem_ctx == NULL )
163                 return False;   /* can't allocate memory indicates bigger problems */
164         /* lock */
165         tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
166         /* read */
167         end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
168         start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
169         Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
170         MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
171
172         time( &current_time );
173
174         /* calculate ... */
175         exp_time = current_time - Retention;    /* discard older than exp_time */
176
177         /* todo - check for sanity in next_record */
178         nbytes = 0;
179
180         DEBUG( 3,
181                ( "MaxSize [%d] Retention [%d] Current Time [%d]  exp_time [%d]\n",
182                  MaxSize, Retention, (uint32)current_time, (uint32)exp_time ) );
183         DEBUG( 3,
184                ( "Start Record [%d] End Record [%d]\n", start_record,
185                  end_record ) );
186
187         for ( i = start_record; i < end_record; i++ ) {
188                 /* read a record, add the amt to nbytes */
189                 key.dsize = sizeof( int32 );
190                 key.dptr = ( uint8 * ) ( int32 * ) & i;
191                 ret = tdb_fetch( the_tdb, key );
192                 if ( ret.dsize == 0 ) {
193                         DEBUG( 8,
194                                ( "Can't find a record for the key, record [%d]\n",
195                                  i ) );
196                         tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
197                         return False;
198                 }
199                 nbytes += ret.dsize;    /* note this includes overhead */
200
201                 len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
202                                   &tresv1, &trecnum, &timegen, &timewr );
203                 if (len == -1) {
204                         DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
205                         tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
206                         return False;
207                 }
208
209                 DEBUG( 8,
210                        ( "read record %d, record size is [%d], total so far [%d]\n",
211                          i, reclen, nbytes ) );
212
213                 SAFE_FREE( ret.dptr );
214
215                 /* note that other servers may just stop writing records when the size limit
216                    is reached, and there are no records older than 'retention'. This doesn't 
217                    like a very useful thing to do, so instead we whack (as in sleeps with the 
218                    fishes) just enough records to fit the what we need.  This behavior could
219                    be changed to 'match', if the need arises. */
220
221                 if ( !whack_by_date && ( nbytes >= needed ) )
222                         break;  /* done */
223                 if ( whack_by_date && ( timegen >= exp_time ) )
224                         break;  /* done */
225         }
226
227         DEBUG( 3,
228                ( "nbytes [%d] needed [%d] start_record is [%d], should be set to [%d]\n",
229                  nbytes, needed, start_record, i ) );
230         /* todo - remove eventlog entries here and set starting record to start_record... */
231         new_start = i;
232         if ( start_record != new_start ) {
233                 for ( i = start_record; i < new_start; i++ ) {
234                         key.dsize = sizeof( int32 );
235                         key.dptr = ( uint8 * ) ( int32 * ) & i;
236                         tdb_delete( the_tdb, key );
237                 }
238
239                 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
240         }
241         tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
242         return True;
243 }
244
245 /********************************************************************
246   some hygiene for an eventlog - see how big it is, and then 
247   calculate how many bytes we need to remove                   
248 ********************************************************************/
249
250 BOOL prune_eventlog( TDB_CONTEXT * tdb )
251 {
252         int MaxSize, Retention, CalcdSize;
253
254         if ( !tdb ) {
255                 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
256                 return False;
257         }
258
259         CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
260         DEBUG( 3,
261                ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
262                  MaxSize ) );
263
264         if ( CalcdSize > MaxSize ) {
265                 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
266                                                False );
267         }
268
269         return make_way_for_eventlogs( tdb, 0, True );
270 }
271
272 /********************************************************************
273 ********************************************************************/
274
275 BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
276 {
277         int calcd_size;
278         int MaxSize, Retention;
279
280         /* see if we can write to the eventlog -- do a policy enforcement */
281         if ( !tdb )
282                 return False;   /* tdb is null, so we can't write to it */
283
284
285         if ( needed < 0 )
286                 return False;
287         MaxSize = 0;
288         Retention = 0;
289
290         calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
291
292         if ( calcd_size <= MaxSize )
293                 return True;    /* you betcha */
294         if ( calcd_size + needed < MaxSize )
295                 return True;
296
297         if ( Retention == 0xffffffff ) {
298                 return False;   /* see msdn - we can't write no room, discard */
299         }
300         /*
301            note don't have to test, but always good to show intent, in case changes needed
302            later
303          */
304
305         if ( Retention == 0x00000000 ) {
306                 /* discard record(s) */
307                 /* todo  - decide when to remove a bunch vs. just what we need... */
308                 return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
309                                                True );
310         }
311
312         return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
313 }
314
315 /*******************************************************************
316 *******************************************************************/
317
318 ELOG_TDB *elog_open_tdb( char *logname, BOOL force_clear )
319 {
320         TDB_CONTEXT *tdb = NULL;
321         uint32 vers_id;
322         ELOG_TDB *ptr;
323         char *tdbfilename;
324         pstring tdbpath;
325         ELOG_TDB *tdb_node = NULL;
326         char *eventlogdir;
327
328         /* first see if we have an open context */
329         
330         for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
331                 if ( strequal( ptr->name, logname ) ) {
332                         ptr->ref_count++;
333
334                         /* trick to alow clearing of the eventlog tdb.
335                            The force_clear flag should imply that someone
336                            has done a force close.  So make sure the tdb 
337                            is NULL.  If this is a normal open, then just 
338                            return the existing reference */
339
340                         if ( force_clear ) {
341                                 SMB_ASSERT( ptr->tdb == NULL );
342                                 break;
343                         }
344                         else
345                                 return ptr;
346                 }
347         }
348         
349         /* make sure that the eventlog dir exists */
350         
351         eventlogdir = lock_path( "eventlog" );
352         if ( !directory_exist( eventlogdir, NULL ) )
353                 mkdir( eventlogdir, 0755 );     
354         
355         /* get the path on disk */
356         
357         tdbfilename = elog_tdbname( logname );
358         pstrcpy( tdbpath, tdbfilename );
359         SAFE_FREE( tdbfilename );
360
361         DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n", 
362                 tdbpath, force_clear?"True":"False" ));
363                 
364         /* the tdb wasn't already open or this is a forced clear open */
365
366         if ( !force_clear ) {
367
368                 tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 );      
369                 if ( tdb ) {
370                         vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
371
372                         if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
373                                 DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
374                                         vers_id, tdbpath));
375                                 tdb_close( tdb );
376                                 tdb = elog_init_tdb( tdbpath );
377                         }
378                 }
379         }
380         
381         if ( !tdb )
382                 tdb = elog_init_tdb( tdbpath );
383         
384         /* if we got a valid context, then add it to the list */
385         
386         if ( tdb ) {
387                 /* on a forced clear, just reset the tdb context if we already
388                    have an open entry in the list */
389
390                 if ( ptr ) {
391                         ptr->tdb = tdb;
392                         return ptr;
393                 }
394
395                 if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
396                         DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
397                         tdb_close( tdb );
398                         return NULL;
399                 }
400                 
401                 tdb_node->name = talloc_strdup( tdb_node, logname );
402                 tdb_node->tdb = tdb;
403                 tdb_node->ref_count = 1;
404                 
405                 DLIST_ADD( open_elog_list, tdb_node );
406         }
407
408         return tdb_node;
409 }
410
411 /*******************************************************************
412  Wrapper to handle reference counts to the tdb
413 *******************************************************************/
414
415 int elog_close_tdb( ELOG_TDB *etdb, BOOL force_close )
416 {
417         TDB_CONTEXT *tdb;
418
419         if ( !etdb )
420                 return 0;
421                 
422         etdb->ref_count--;
423         
424         SMB_ASSERT( etdb->ref_count >= 0 );
425
426         if ( etdb->ref_count == 0 ) {
427                 tdb = etdb->tdb;
428                 DLIST_REMOVE( open_elog_list, etdb );
429                 TALLOC_FREE( etdb );
430                 return tdb_close( tdb );
431         }
432         
433         if ( force_close ) {
434                 tdb = etdb->tdb;
435                 etdb->tdb = NULL;
436                 return tdb_close( tdb );
437         }
438
439         return 0;
440 }
441
442
443 /*******************************************************************
444  write an eventlog entry. Note that we have to lock, read next 
445  eventlog, increment, write, write the record, unlock 
446  
447  coming into this, ee has the eventlog record, and the auxilliary date 
448  (computer name, etc.) filled into the other structure. Before packing 
449  into a record, this routine will calc the appropriate padding, etc., 
450  and then blast out the record in a form that can be read back in
451 *******************************************************************/
452  
453 #define MARGIN 512
454
455 int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
456 {
457         int32 next_record;
458         uint8 *packed_ee;
459         TALLOC_CTX *mem_ctx = NULL;
460         TDB_DATA kbuf, ebuf;
461         uint32 n_packed;
462
463         if ( !ee )
464                 return 0;
465
466         mem_ctx = talloc_init( "write_eventlog_tdb" );
467
468         if ( mem_ctx == NULL )
469                 return 0;
470
471         if ( !ee )
472                 return 0;
473         /* discard any entries that have bogus time, which usually indicates a bogus entry as well. */
474         if ( ee->record.time_generated == 0 )
475                 return 0;
476
477         /* todo - check for sanity in next_record */
478
479         fixup_eventlog_entry( ee );
480
481         if ( !can_write_to_eventlog( the_tdb, ee->record.length ) ) {
482                 DEBUG( 3, ( "Can't write to Eventlog, no room \n" ) );
483                 talloc_destroy( mem_ctx );
484                 return 0;
485         }
486
487         /* alloc mem for the packed version */
488         packed_ee = (uint8 *)TALLOC( mem_ctx, ee->record.length + MARGIN );
489         if ( !packed_ee ) {
490                 talloc_destroy( mem_ctx );
491                 return 0;
492         }
493
494         /* need to read the record number and insert it into the entry here */
495
496         /* lock */
497         tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
498         /* read */
499         next_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
500
501         n_packed =
502                 tdb_pack( (uint8 *)packed_ee, ee->record.length + MARGIN,
503                           "ddddddwwwwddddddBBdBBBd", ee->record.length,
504                           ee->record.reserved1, next_record,
505                           ee->record.time_generated, ee->record.time_written,
506                           ee->record.event_id, ee->record.event_type,
507                           ee->record.num_strings, ee->record.event_category,
508                           ee->record.reserved2,
509                           ee->record.closing_record_number,
510                           ee->record.string_offset,
511                           ee->record.user_sid_length,
512                           ee->record.user_sid_offset, ee->record.data_length,
513                           ee->record.data_offset,
514                           ee->data_record.source_name_len,
515                           ee->data_record.source_name,
516                           ee->data_record.computer_name_len,
517                           ee->data_record.computer_name,
518                           ee->data_record.sid_padding,
519                           ee->record.user_sid_length, ee->data_record.sid,
520                           ee->data_record.strings_len,
521                           ee->data_record.strings,
522                           ee->data_record.user_data_len,
523                           ee->data_record.user_data,
524                           ee->data_record.data_padding );
525
526         /*DEBUG(3,("write_eventlog_tdb: packed into  %d\n",n_packed)); */
527
528         /* increment the record count */
529
530         kbuf.dsize = sizeof( int32 );
531         kbuf.dptr = (uint8 * ) & next_record;
532
533         ebuf.dsize = n_packed;
534         ebuf.dptr = (uint8 *)packed_ee;
535
536         if ( tdb_store( the_tdb, kbuf, ebuf, 0 ) ) {
537                 /* DEBUG(1,("write_eventlog_tdb: Can't write record %d to eventlog\n",next_record)); */
538                 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
539                 talloc_destroy( mem_ctx );
540                 return 0;
541         }
542         next_record++;
543         tdb_store_int32( the_tdb, EVT_NEXT_RECORD, next_record );
544         tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
545         talloc_destroy( mem_ctx );
546         return ( next_record - 1 );
547 }
548
549 /*******************************************************************
550  calculate the correct fields etc for an eventlog entry
551 *******************************************************************/
552
553 void fixup_eventlog_entry( Eventlog_entry * ee )
554 {
555         /* fix up the eventlog entry structure as necessary */
556
557         ee->data_record.sid_padding =
558                 ( ( 4 -
559                     ( ( ee->data_record.source_name_len +
560                         ee->data_record.computer_name_len ) % 4 ) ) % 4 );
561         ee->data_record.data_padding =
562                 ( 4 -
563                   ( ( ee->data_record.strings_len +
564                       ee->data_record.user_data_len ) % 4 ) ) % 4;
565         ee->record.length = sizeof( Eventlog_record );
566         ee->record.length += ee->data_record.source_name_len;
567         ee->record.length += ee->data_record.computer_name_len;
568         if ( ee->record.user_sid_length == 0 ) {
569                 /* Should not pad to a DWORD boundary for writing out the sid if there is
570                    no SID, so just propagate the padding to pad the data */
571                 ee->data_record.data_padding += ee->data_record.sid_padding;
572                 ee->data_record.sid_padding = 0;
573         }
574         /* DEBUG(10, ("sid_padding is [%d].\n", ee->data_record.sid_padding)); */
575         /* DEBUG(10, ("data_padding is [%d].\n", ee->data_record.data_padding)); */
576
577         ee->record.length += ee->data_record.sid_padding;
578         ee->record.length += ee->record.user_sid_length;
579         ee->record.length += ee->data_record.strings_len;
580         ee->record.length += ee->data_record.user_data_len;
581         ee->record.length += ee->data_record.data_padding;
582         /* need another copy of length at the end of the data */
583         ee->record.length += sizeof( ee->record.length );
584 }
585
586 /********************************************************************
587  Note that it's a pretty good idea to initialize the Eventlog_entry 
588  structure to zero's before calling parse_logentry on an batch of 
589  lines that may resolve to a record.  ALSO, it's a good idea to 
590  remove any linefeeds (that's EOL to you and me) on the lines 
591  going in.
592 ********************************************************************/
593
594 BOOL parse_logentry( char *line, Eventlog_entry * entry, BOOL * eor )
595 {
596         char *start = NULL, *stop = NULL;
597         pstring temp;
598         int temp_len = 0;
599
600         start = line;
601
602         /* empty line signyfiying record delimeter, or we're at the end of the buffer */
603         if ( start == NULL || strlen( start ) == 0 ) {
604                 DEBUG( 6,
605                        ( "parse_logentry: found end-of-record indicator.\n" ) );
606                 *eor = True;
607                 return True;
608         }
609         if ( !( stop = strchr( line, ':' ) ) ) {
610                 return False;
611         }
612
613         DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
614
615         if ( 0 == strncmp( start, "LEN", stop - start ) ) {
616                 /* This will get recomputed later anyway -- probably not necessary */
617                 entry->record.length = atoi( stop + 1 );
618         } else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
619                 /* For now all these reserved entries seem to have the same value,
620                    which can be hardcoded to int(1699505740) for now */
621                 entry->record.reserved1 = atoi( stop + 1 );
622         } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
623                 entry->record.record_number = atoi( stop + 1 );
624         } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
625                 entry->record.time_generated = atoi( stop + 1 );
626         } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
627                 entry->record.time_written = atoi( stop + 1 );
628         } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
629                 entry->record.event_id = atoi( stop + 1 );
630         } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
631                 if ( strstr( start, "ERROR" ) ) {
632                         entry->record.event_type = EVENTLOG_ERROR_TYPE;
633                 } else if ( strstr( start, "WARNING" ) ) {
634                         entry->record.event_type = EVENTLOG_WARNING_TYPE;
635                 } else if ( strstr( start, "INFO" ) ) {
636                         entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
637                 } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
638                         entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
639                 } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
640                         entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
641                 } else if ( strstr( start, "SUCCESS" ) ) {
642                         entry->record.event_type = EVENTLOG_SUCCESS;
643                 } else {
644                         /* some other eventlog type -- currently not defined in MSDN docs, so error out */
645                         return False;
646                 }
647         }
648
649 /*
650   else if(0 == strncmp(start, "NST", stop - start))
651   {
652   entry->record.num_strings = atoi(stop + 1);
653   }
654 */
655         else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
656                 entry->record.event_category = atoi( stop + 1 );
657         } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
658                 entry->record.reserved2 = atoi( stop + 1 );
659         } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
660                 entry->record.closing_record_number = atoi( stop + 1 );
661         } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
662                 entry->record.user_sid_length = atoi( stop + 1 );
663         } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
664                 memset( temp, 0, sizeof( temp ) );
665                 stop++;
666                 while ( isspace( stop[0] ) ) {
667                         stop++;
668                 }
669                 temp_len = strlen( stop );
670                 strncpy( temp, stop, temp_len );
671                 rpcstr_push( ( void * ) ( entry->data_record.source_name ),
672                              temp, sizeof( entry->data_record.source_name ),
673                              STR_TERMINATE );
674                 entry->data_record.source_name_len =
675                         ( strlen_w( entry->data_record.source_name ) * 2 ) +
676                         2;
677         } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
678                 memset( temp, 0, sizeof( temp ) );
679                 stop++;
680                 while ( isspace( stop[0] ) ) {
681                         stop++;
682                 }
683                 temp_len = strlen( stop );
684                 strncpy( temp, stop, temp_len );
685                 rpcstr_push( ( void * ) ( entry->data_record.computer_name ),
686                              temp, sizeof( entry->data_record.computer_name ),
687                              STR_TERMINATE );
688                 entry->data_record.computer_name_len =
689                         ( strlen_w( entry->data_record.computer_name ) * 2 ) +
690                         2;
691         } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
692                 memset( temp, 0, sizeof( temp ) );
693                 stop++;
694                 while ( isspace( stop[0] ) ) {
695                         stop++;
696                 }
697                 temp_len = strlen( stop );
698                 strncpy( temp, stop, temp_len );
699                 rpcstr_push( ( void * ) ( entry->data_record.sid ), temp,
700                              sizeof( entry->data_record.sid ),
701                              STR_TERMINATE );
702                 entry->record.user_sid_length =
703                         ( strlen_w( entry->data_record.sid ) * 2 ) + 2;
704         } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
705                 /* skip past initial ":" */
706                 stop++;
707                 /* now skip any other leading whitespace */
708                 while ( isspace( stop[0] ) ) {
709                         stop++;
710                 }
711                 temp_len = strlen( stop );
712                 memset( temp, 0, sizeof( temp ) );
713                 strncpy( temp, stop, temp_len );
714                 rpcstr_push( ( void * ) ( entry->data_record.strings +
715                                           ( entry->data_record.strings_len / 2 ) ),
716                              temp,
717                              sizeof( entry->data_record.strings ) -
718                              ( entry->data_record.strings_len / 2 ), STR_TERMINATE );
719                 entry->data_record.strings_len += ( temp_len * 2 ) + 2;
720                 entry->record.num_strings++;
721         } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
722                 /* skip past initial ":" */
723                 stop++;
724                 /* now skip any other leading whitespace */
725                 while ( isspace( stop[0] ) ) {
726                         stop++;
727                 }
728                 entry->data_record.user_data_len = strlen( stop );
729                 memset( entry->data_record.user_data, 0,
730                         sizeof( entry->data_record.user_data ) );
731                 if ( entry->data_record.user_data_len > 0 ) {
732                         /* copy no more than the first 1024 bytes */
733                         if ( entry->data_record.user_data_len >
734                              sizeof( entry->data_record.user_data ) )
735                                 entry->data_record.user_data_len =
736                                         sizeof( entry->data_record.
737                                                 user_data );
738                         memcpy( entry->data_record.user_data, stop,
739                                 entry->data_record.user_data_len );
740                 }
741         } else {
742                 /* some other eventlog entry -- not implemented, so dropping on the floor */
743                 DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
744                 /* For now return true so that we can keep on parsing this mess. Eventually
745                    we will return False here. */
746                 return True;
747         }
748         return True;
749 }