Remove pstring from everything in rpc_server except
[metze/samba/wip.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(TALLOC_CTX *ctx, const char *name )
66 {
67         char *path = talloc_asprintf(ctx, "%s/%s.tdb",
68                         state_path("eventlog"),
69                         name);
70         if (!path) {
71                 return NULL;
72         }
73         strlower_m(path);
74         return path;
75 }
76
77
78 /********************************************************************
79  this function is used to count up the number of bytes in a 
80  particular TDB
81 ********************************************************************/
82
83 struct trav_size_struct {
84         int size;
85         int rec_count;
86 };
87
88 static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
89                           void *state )
90 {
91         struct trav_size_struct  *tsize = (struct trav_size_struct *)state;
92         
93         tsize->size += data.dsize;
94         tsize->rec_count++;
95         
96         return 0;
97 }
98
99 /********************************************************************
100  returns the size of the eventlog, and if MaxSize is a non-null 
101  ptr, puts the MaxSize there. This is purely a way not to have yet 
102  another function that solely reads the maxsize of the eventlog. 
103  Yeah, that's it.
104 ********************************************************************/
105
106 int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
107 {
108         struct trav_size_struct tsize;
109         
110         if ( !tdb )
111                 return 0;
112                 
113         ZERO_STRUCT( tsize );
114
115         tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
116
117         if ( MaxSize != NULL ) {
118                 *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
119         }
120
121         if ( Retention != NULL ) {
122                 *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
123         }
124
125         DEBUG( 1,
126                ( "eventlog size: [%d] for [%d] records\n", tsize.size,
127                  tsize.rec_count ) );
128         return tsize.size;
129 }
130
131 /********************************************************************
132  Discard early event logs until we have enough for 'needed' bytes...
133  NO checking done beforehand to see that we actually need to do 
134  this, and it's going to pluck records one-by-one. So, it's best 
135  to determine that this needs to be done before doing it.  
136
137  Setting whack_by_date to True indicates that eventlogs falling 
138  outside of the retention range need to go...
139  
140  return True if we made enough room to accommodate needed bytes
141 ********************************************************************/
142
143 bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
144                              bool whack_by_date )
145 {
146         int start_record, i, new_start;
147         int end_record;
148         int nbytes, reclen, len, Retention, MaxSize;
149         int tresv1, trecnum, timegen, timewr;
150         TDB_DATA key, ret;
151         TALLOC_CTX *mem_ctx = NULL;
152         time_t current_time, exp_time;
153
154         /* discard some eventlogs */
155
156         /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
157            although records not necessarily guaranteed to have successive times */
158         /* */
159         mem_ctx = talloc_init( "make_way_for_eventlogs" );      /* Homage to BPG */
160
161         if ( mem_ctx == NULL )
162                 return False;   /* can't allocate memory indicates bigger problems */
163         /* lock */
164         tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
165         /* read */
166         end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
167         start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
168         Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
169         MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
170
171         time( &current_time );
172
173         /* calculate ... */
174         exp_time = current_time - Retention;    /* discard older than exp_time */
175
176         /* todo - check for sanity in next_record */
177         nbytes = 0;
178
179         DEBUG( 3,
180                ( "MaxSize [%d] Retention [%d] Current Time [%d]  exp_time [%d]\n",
181                  MaxSize, Retention, (uint32)current_time, (uint32)exp_time ) );
182         DEBUG( 3,
183                ( "Start Record [%d] End Record [%d]\n", start_record,
184                  end_record ) );
185
186         for ( i = start_record; i < end_record; i++ ) {
187                 /* read a record, add the amt to nbytes */
188                 key.dsize = sizeof( int32 );
189                 key.dptr = ( uint8 * ) ( int32 * ) & i;
190                 ret = tdb_fetch( the_tdb, key );
191                 if ( ret.dsize == 0 ) {
192                         DEBUG( 8,
193                                ( "Can't find a record for the key, record [%d]\n",
194                                  i ) );
195                         tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
196                         return False;
197                 }
198                 nbytes += ret.dsize;    /* note this includes overhead */
199
200                 len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
201                                   &tresv1, &trecnum, &timegen, &timewr );
202                 if (len == -1) {
203                         DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
204                         tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
205                         return False;
206                 }
207
208                 DEBUG( 8,
209                        ( "read record %d, record size is [%d], total so far [%d]\n",
210                          i, reclen, nbytes ) );
211
212                 SAFE_FREE( ret.dptr );
213
214                 /* note that other servers may just stop writing records when the size limit
215                    is reached, and there are no records older than 'retention'. This doesn't 
216                    like a very useful thing to do, so instead we whack (as in sleeps with the 
217                    fishes) just enough records to fit the what we need.  This behavior could
218                    be changed to 'match', if the need arises. */
219
220                 if ( !whack_by_date && ( nbytes >= needed ) )
221                         break;  /* done */
222                 if ( whack_by_date && ( timegen >= exp_time ) )
223                         break;  /* done */
224         }
225
226         DEBUG( 3,
227                ( "nbytes [%d] needed [%d] start_record is [%d], should be set to [%d]\n",
228                  nbytes, needed, start_record, i ) );
229         /* todo - remove eventlog entries here and set starting record to start_record... */
230         new_start = i;
231         if ( start_record != new_start ) {
232                 for ( i = start_record; i < new_start; i++ ) {
233                         key.dsize = sizeof( int32 );
234                         key.dptr = ( uint8 * ) ( int32 * ) & i;
235                         tdb_delete( the_tdb, key );
236                 }
237
238                 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
239         }
240         tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
241         return True;
242 }
243
244 /********************************************************************
245   some hygiene for an eventlog - see how big it is, and then 
246   calculate how many bytes we need to remove                   
247 ********************************************************************/
248
249 bool prune_eventlog( TDB_CONTEXT * tdb )
250 {
251         int MaxSize, Retention, CalcdSize;
252
253         if ( !tdb ) {
254                 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
255                 return False;
256         }
257
258         CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
259         DEBUG( 3,
260                ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
261                  MaxSize ) );
262
263         if ( CalcdSize > MaxSize ) {
264                 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
265                                                False );
266         }
267
268         return make_way_for_eventlogs( tdb, 0, True );
269 }
270
271 /********************************************************************
272 ********************************************************************/
273
274 bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
275 {
276         int calcd_size;
277         int MaxSize, Retention;
278
279         /* see if we can write to the eventlog -- do a policy enforcement */
280         if ( !tdb )
281                 return False;   /* tdb is null, so we can't write to it */
282
283
284         if ( needed < 0 )
285                 return False;
286         MaxSize = 0;
287         Retention = 0;
288
289         calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
290
291         if ( calcd_size <= MaxSize )
292                 return True;    /* you betcha */
293         if ( calcd_size + needed < MaxSize )
294                 return True;
295
296         if ( Retention == 0xffffffff ) {
297                 return False;   /* see msdn - we can't write no room, discard */
298         }
299         /*
300            note don't have to test, but always good to show intent, in case changes needed
301            later
302          */
303
304         if ( Retention == 0x00000000 ) {
305                 /* discard record(s) */
306                 /* todo  - decide when to remove a bunch vs. just what we need... */
307                 return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
308                                                True );
309         }
310
311         return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
312 }
313
314 /*******************************************************************
315 *******************************************************************/
316
317 ELOG_TDB *elog_open_tdb( char *logname, bool force_clear )
318 {
319         TDB_CONTEXT *tdb = NULL;
320         uint32 vers_id;
321         ELOG_TDB *ptr;
322         char *tdbpath = NULL;
323         ELOG_TDB *tdb_node = NULL;
324         char *eventlogdir;
325         TALLOC_CTX *ctx = talloc_tos();
326
327         /* first see if we have an open context */
328
329         for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
330                 if ( strequal( ptr->name, logname ) ) {
331                         ptr->ref_count++;
332
333                         /* trick to alow clearing of the eventlog tdb.
334                            The force_clear flag should imply that someone
335                            has done a force close.  So make sure the tdb 
336                            is NULL.  If this is a normal open, then just 
337                            return the existing reference */
338
339                         if ( force_clear ) {
340                                 SMB_ASSERT( ptr->tdb == NULL );
341                                 break;
342                         }
343                         else
344                                 return ptr;
345                 }
346         }
347
348         /* make sure that the eventlog dir exists */
349
350         eventlogdir = state_path( "eventlog" );
351         if ( !directory_exist( eventlogdir, NULL ) )
352                 mkdir( eventlogdir, 0755 );
353
354         /* get the path on disk */
355
356         tdbpath = elog_tdbname(ctx, logname);
357         if (!tdbpath) {
358                 return NULL;
359         }
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         TALLOC_CTX *ctx = talloc_tos();
597         char *start = NULL, *stop = NULL;
598
599         start = line;
600
601         /* empty line signyfiying record delimeter, or we're at the end of the buffer */
602         if ( start == NULL || strlen( start ) == 0 ) {
603                 DEBUG( 6,
604                        ( "parse_logentry: found end-of-record indicator.\n" ) );
605                 *eor = True;
606                 return True;
607         }
608         if ( !( stop = strchr( line, ':' ) ) ) {
609                 return False;
610         }
611
612         DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
613
614         if ( 0 == strncmp( start, "LEN", stop - start ) ) {
615                 /* This will get recomputed later anyway -- probably not necessary */
616                 entry->record.length = atoi( stop + 1 );
617         } else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
618                 /* For now all these reserved entries seem to have the same value,
619                    which can be hardcoded to int(1699505740) for now */
620                 entry->record.reserved1 = atoi( stop + 1 );
621         } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
622                 entry->record.record_number = atoi( stop + 1 );
623         } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
624                 entry->record.time_generated = atoi( stop + 1 );
625         } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
626                 entry->record.time_written = atoi( stop + 1 );
627         } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
628                 entry->record.event_id = atoi( stop + 1 );
629         } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
630                 if ( strstr( start, "ERROR" ) ) {
631                         entry->record.event_type = EVENTLOG_ERROR_TYPE;
632                 } else if ( strstr( start, "WARNING" ) ) {
633                         entry->record.event_type = EVENTLOG_WARNING_TYPE;
634                 } else if ( strstr( start, "INFO" ) ) {
635                         entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
636                 } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
637                         entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
638                 } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
639                         entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
640                 } else if ( strstr( start, "SUCCESS" ) ) {
641                         entry->record.event_type = EVENTLOG_SUCCESS;
642                 } else {
643                         /* some other eventlog type -- currently not defined in MSDN docs, so error out */
644                         return False;
645                 }
646         }
647
648 /*
649   else if(0 == strncmp(start, "NST", stop - start))
650   {
651   entry->record.num_strings = atoi(stop + 1);
652   }
653 */
654         else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
655                 entry->record.event_category = atoi( stop + 1 );
656         } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
657                 entry->record.reserved2 = atoi( stop + 1 );
658         } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
659                 entry->record.closing_record_number = atoi( stop + 1 );
660         } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
661                 entry->record.user_sid_length = atoi( stop + 1 );
662         } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
663                 stop++;
664                 while ( isspace( stop[0] ) ) {
665                         stop++;
666                 }
667                 entry->data_record.source_name_len = rpcstr_push_talloc(ctx,
668                                 &entry->data_record.source_name,
669                                 stop);
670                 if (entry->data_record.source_name_len == (size_t)-1 ||
671                                 entry->data_record.source_name == NULL) {
672                         return false;
673                 }
674         } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
675                 stop++;
676                 while ( isspace( stop[0] ) ) {
677                         stop++;
678                 }
679                 entry->data_record.computer_name_len = rpcstr_push_talloc(ctx,
680                                 &entry->data_record.computer_name,
681                                 stop);
682                 if (entry->data_record.computer_name_len == (size_t)-1 ||
683                                 entry->data_record.computer_name == NULL) {
684                         return false;
685                 }
686         } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
687                 stop++;
688                 while ( isspace( stop[0] ) ) {
689                         stop++;
690                 }
691                 entry->record.user_sid_length = rpcstr_push_talloc(ctx,
692                                 &entry->data_record.sid,
693                                 stop);
694                 if (entry->record.user_sid_length == (size_t)-1 ||
695                                 entry->data_record.sid == NULL) {
696                         return false;
697                 }
698         } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
699                 smb_ucs2_t *temp = NULL;
700                 size_t tmp_len;
701                 uint32_t old_len;
702                 /* skip past initial ":" */
703                 stop++;
704                 /* now skip any other leading whitespace */
705                 while ( isspace(stop[0])) {
706                         stop++;
707                 }
708                 tmp_len = rpcstr_push_talloc(ctx,
709                                                 &temp,
710                                                 stop);
711                 if (tmp_len == (size_t)-1 || !temp) {
712                         return false;
713                 }
714                 old_len = entry->data_record.strings_len;
715                 entry->data_record.strings = (smb_ucs2_t *)TALLOC_REALLOC_ARRAY(ctx,
716                                                 entry->data_record.strings,
717                                                 char,
718                                                 old_len + tmp_len);
719                 if (!entry->data_record.strings) {
720                         return false;
721                 }
722                 memcpy(entry->data_record.strings + old_len,
723                                 temp,
724                                 tmp_len);
725                 entry->data_record.strings_len += tmp_len;
726                 entry->record.num_strings++;
727         } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
728                 /* skip past initial ":" */
729                 stop++;
730                 /* now skip any other leading whitespace */
731                 while ( isspace( stop[0] ) ) {
732                         stop++;
733                 }
734                 entry->data_record.user_data_len = strlen(stop);
735                 entry->data_record.user_data = talloc_strdup(ctx,
736                                                 stop);
737                 if (!entry->data_record.user_data) {
738                         return false;
739                 }
740         } else {
741                 /* some other eventlog entry -- not implemented, so dropping on the floor */
742                 DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
743                 /* For now return true so that we can keep on parsing this mess. Eventually
744                    we will return False here. */
745                 return true;
746         }
747         return true;
748 }