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