objectclass -> objectClass
[Samba/gebeck_regimport.git] / source3 / rpc_server / srv_eventlog_lib.c
blobe232a30078244bb4dd186d9e7e7b714bdf7bc8dc
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.
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.
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/>.
22 #include "includes.h"
24 /* maintain a list of open eventlog tdbs with reference counts */
26 static ELOG_TDB *open_elog_list;
28 /********************************************************************
29 Init an Eventlog TDB, and return it. If null, something bad
30 happened.
31 ********************************************************************/
33 TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
35 TDB_CONTEXT *tdb;
37 DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
38 tdbfilename));
40 tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT,
41 O_RDWR|O_CREAT|O_TRUNC, 0660 );
43 if ( !tdb ) {
44 DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
45 return NULL;
48 /* initialize with defaults, copy real values in here from registry */
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 );
55 tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
57 return tdb;
60 /********************************************************************
61 make the tdb file name for an event log, given destination buffer
62 and size. Caller must free memory.
63 ********************************************************************/
65 char *elog_tdbname(TALLOC_CTX *ctx, const char *name )
67 char *path = talloc_asprintf(ctx, "%s/%s.tdb",
68 state_path("eventlog"),
69 name);
70 if (!path) {
71 return NULL;
73 strlower_m(path);
74 return path;
78 /********************************************************************
79 this function is used to count up the number of bytes in a
80 particular TDB
81 ********************************************************************/
83 struct trav_size_struct {
84 int size;
85 int rec_count;
88 static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
89 void *state )
91 struct trav_size_struct *tsize = (struct trav_size_struct *)state;
93 tsize->size += data.dsize;
94 tsize->rec_count++;
96 return 0;
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 ********************************************************************/
106 int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
108 struct trav_size_struct tsize;
110 if ( !tdb )
111 return 0;
113 ZERO_STRUCT( tsize );
115 tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
117 if ( MaxSize != NULL ) {
118 *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
121 if ( Retention != NULL ) {
122 *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
125 DEBUG( 1,
126 ( "eventlog size: [%d] for [%d] records\n", tsize.size,
127 tsize.rec_count ) );
128 return tsize.size;
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.
137 Setting whack_by_date to True indicates that eventlogs falling
138 outside of the retention range need to go...
140 return True if we made enough room to accommodate needed bytes
141 ********************************************************************/
143 static bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
144 bool whack_by_date )
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 time_t current_time, exp_time;
153 /* discard some eventlogs */
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 /* */
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 );
167 time( &current_time );
169 /* calculate ... */
170 exp_time = current_time - Retention; /* discard older than exp_time */
172 /* todo - check for sanity in next_record */
173 nbytes = 0;
175 DEBUG( 3,
176 ( "MaxSize [%d] Retention [%d] Current Time [%d] exp_time [%d]\n",
177 MaxSize, Retention, (uint32)current_time, (uint32)exp_time ) );
178 DEBUG( 3,
179 ( "Start Record [%d] End Record [%d]\n", start_record,
180 end_record ) );
182 for ( i = start_record; i < end_record; i++ ) {
183 /* read a record, add the amt to nbytes */
184 key.dsize = sizeof( int32 );
185 key.dptr = ( uint8 * ) ( int32 * ) & i;
186 ret = tdb_fetch( the_tdb, key );
187 if ( ret.dsize == 0 ) {
188 DEBUG( 8,
189 ( "Can't find a record for the key, record [%d]\n",
190 i ) );
191 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
192 return False;
194 nbytes += ret.dsize; /* note this includes overhead */
196 len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
197 &tresv1, &trecnum, &timegen, &timewr );
198 if (len == -1) {
199 DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
200 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
201 return False;
204 DEBUG( 8,
205 ( "read record %d, record size is [%d], total so far [%d]\n",
206 i, reclen, nbytes ) );
208 SAFE_FREE( ret.dptr );
210 /* note that other servers may just stop writing records when the size limit
211 is reached, and there are no records older than 'retention'. This doesn't
212 like a very useful thing to do, so instead we whack (as in sleeps with the
213 fishes) just enough records to fit the what we need. This behavior could
214 be changed to 'match', if the need arises. */
216 if ( !whack_by_date && ( nbytes >= needed ) )
217 break; /* done */
218 if ( whack_by_date && ( timegen >= exp_time ) )
219 break; /* done */
222 DEBUG( 3,
223 ( "nbytes [%d] needed [%d] start_record is [%d], should be set to [%d]\n",
224 nbytes, needed, start_record, i ) );
225 /* todo - remove eventlog entries here and set starting record to start_record... */
226 new_start = i;
227 if ( start_record != new_start ) {
228 for ( i = start_record; i < new_start; i++ ) {
229 key.dsize = sizeof( int32 );
230 key.dptr = ( uint8 * ) ( int32 * ) & i;
231 tdb_delete( the_tdb, key );
234 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
236 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
237 return True;
240 /********************************************************************
241 some hygiene for an eventlog - see how big it is, and then
242 calculate how many bytes we need to remove
243 ********************************************************************/
245 bool prune_eventlog( TDB_CONTEXT * tdb )
247 int MaxSize, Retention, CalcdSize;
249 if ( !tdb ) {
250 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
251 return False;
254 CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
255 DEBUG( 3,
256 ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
257 MaxSize ) );
259 if ( CalcdSize > MaxSize ) {
260 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
261 False );
264 return make_way_for_eventlogs( tdb, 0, True );
267 /********************************************************************
268 ********************************************************************/
270 bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
272 int calcd_size;
273 int MaxSize, Retention;
275 /* see if we can write to the eventlog -- do a policy enforcement */
276 if ( !tdb )
277 return False; /* tdb is null, so we can't write to it */
280 if ( needed < 0 )
281 return False;
282 MaxSize = 0;
283 Retention = 0;
285 calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
287 if ( calcd_size <= MaxSize )
288 return True; /* you betcha */
289 if ( calcd_size + needed < MaxSize )
290 return True;
292 if ( Retention == 0xffffffff ) {
293 return False; /* see msdn - we can't write no room, discard */
296 note don't have to test, but always good to show intent, in case changes needed
297 later
300 if ( Retention == 0x00000000 ) {
301 /* discard record(s) */
302 /* todo - decide when to remove a bunch vs. just what we need... */
303 return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
304 True );
307 return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
310 /*******************************************************************
311 *******************************************************************/
313 ELOG_TDB *elog_open_tdb( char *logname, bool force_clear )
315 TDB_CONTEXT *tdb = NULL;
316 uint32 vers_id;
317 ELOG_TDB *ptr;
318 char *tdbpath = NULL;
319 ELOG_TDB *tdb_node = NULL;
320 char *eventlogdir;
321 TALLOC_CTX *ctx = talloc_tos();
323 /* first see if we have an open context */
325 for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
326 if ( strequal( ptr->name, logname ) ) {
327 ptr->ref_count++;
329 /* trick to alow clearing of the eventlog tdb.
330 The force_clear flag should imply that someone
331 has done a force close. So make sure the tdb
332 is NULL. If this is a normal open, then just
333 return the existing reference */
335 if ( force_clear ) {
336 SMB_ASSERT( ptr->tdb == NULL );
337 break;
339 else
340 return ptr;
344 /* make sure that the eventlog dir exists */
346 eventlogdir = state_path( "eventlog" );
347 if ( !directory_exist( eventlogdir, NULL ) )
348 mkdir( eventlogdir, 0755 );
350 /* get the path on disk */
352 tdbpath = elog_tdbname(ctx, logname);
353 if (!tdbpath) {
354 return NULL;
357 DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
358 tdbpath, force_clear?"True":"False" ));
360 /* the tdb wasn't already open or this is a forced clear open */
362 if ( !force_clear ) {
364 tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 );
365 if ( tdb ) {
366 vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
368 if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
369 DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
370 vers_id, tdbpath));
371 tdb_close( tdb );
372 tdb = elog_init_tdb( tdbpath );
377 if ( !tdb )
378 tdb = elog_init_tdb( tdbpath );
380 /* if we got a valid context, then add it to the list */
382 if ( tdb ) {
383 /* on a forced clear, just reset the tdb context if we already
384 have an open entry in the list */
386 if ( ptr ) {
387 ptr->tdb = tdb;
388 return ptr;
391 if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
392 DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
393 tdb_close( tdb );
394 return NULL;
397 tdb_node->name = talloc_strdup( tdb_node, logname );
398 tdb_node->tdb = tdb;
399 tdb_node->ref_count = 1;
401 DLIST_ADD( open_elog_list, tdb_node );
404 return tdb_node;
407 /*******************************************************************
408 Wrapper to handle reference counts to the tdb
409 *******************************************************************/
411 int elog_close_tdb( ELOG_TDB *etdb, bool force_close )
413 TDB_CONTEXT *tdb;
415 if ( !etdb )
416 return 0;
418 etdb->ref_count--;
420 SMB_ASSERT( etdb->ref_count >= 0 );
422 if ( etdb->ref_count == 0 ) {
423 tdb = etdb->tdb;
424 DLIST_REMOVE( open_elog_list, etdb );
425 TALLOC_FREE( etdb );
426 return tdb_close( tdb );
429 if ( force_close ) {
430 tdb = etdb->tdb;
431 etdb->tdb = NULL;
432 return tdb_close( tdb );
435 return 0;
439 /*******************************************************************
440 write an eventlog entry. Note that we have to lock, read next
441 eventlog, increment, write, write the record, unlock
443 coming into this, ee has the eventlog record, and the auxilliary date
444 (computer name, etc.) filled into the other structure. Before packing
445 into a record, this routine will calc the appropriate padding, etc.,
446 and then blast out the record in a form that can be read back in
447 *******************************************************************/
449 #define MARGIN 512
451 int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
453 int32 next_record;
454 uint8 *packed_ee;
455 TALLOC_CTX *mem_ctx = NULL;
456 TDB_DATA kbuf, ebuf;
457 uint32 n_packed;
459 if ( !ee )
460 return 0;
462 mem_ctx = talloc_init( "write_eventlog_tdb" );
464 if ( mem_ctx == NULL )
465 return 0;
467 /* discard any entries that have bogus time, which usually indicates a bogus entry as well. */
468 if ( ee->record.time_generated == 0 )
469 return 0;
471 /* todo - check for sanity in next_record */
473 fixup_eventlog_entry( ee );
475 if ( !can_write_to_eventlog( the_tdb, ee->record.length ) ) {
476 DEBUG( 3, ( "Can't write to Eventlog, no room \n" ) );
477 talloc_destroy( mem_ctx );
478 return 0;
481 /* alloc mem for the packed version */
482 packed_ee = (uint8 *)TALLOC( mem_ctx, ee->record.length + MARGIN );
483 if ( !packed_ee ) {
484 talloc_destroy( mem_ctx );
485 return 0;
488 /* need to read the record number and insert it into the entry here */
490 /* lock */
491 tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
492 /* read */
493 next_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
495 n_packed =
496 tdb_pack( (uint8 *)packed_ee, ee->record.length + MARGIN,
497 "ddddddwwwwddddddBBdBBBd", ee->record.length,
498 ee->record.reserved1, next_record,
499 ee->record.time_generated, ee->record.time_written,
500 ee->record.event_id, ee->record.event_type,
501 ee->record.num_strings, ee->record.event_category,
502 ee->record.reserved2,
503 ee->record.closing_record_number,
504 ee->record.string_offset,
505 ee->record.user_sid_length,
506 ee->record.user_sid_offset, ee->record.data_length,
507 ee->record.data_offset,
508 ee->data_record.source_name_len,
509 ee->data_record.source_name,
510 ee->data_record.computer_name_len,
511 ee->data_record.computer_name,
512 ee->data_record.sid_padding,
513 ee->record.user_sid_length, ee->data_record.sid,
514 ee->data_record.strings_len,
515 ee->data_record.strings,
516 ee->data_record.user_data_len,
517 ee->data_record.user_data,
518 ee->data_record.data_padding );
520 /*DEBUG(3,("write_eventlog_tdb: packed into %d\n",n_packed)); */
522 /* increment the record count */
524 kbuf.dsize = sizeof( int32 );
525 kbuf.dptr = (uint8 * ) & next_record;
527 ebuf.dsize = n_packed;
528 ebuf.dptr = (uint8 *)packed_ee;
530 if ( tdb_store( the_tdb, kbuf, ebuf, 0 ) ) {
531 /* DEBUG(1,("write_eventlog_tdb: Can't write record %d to eventlog\n",next_record)); */
532 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
533 talloc_destroy( mem_ctx );
534 return 0;
536 next_record++;
537 tdb_store_int32( the_tdb, EVT_NEXT_RECORD, next_record );
538 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
539 talloc_destroy( mem_ctx );
540 return ( next_record - 1 );
543 /*******************************************************************
544 calculate the correct fields etc for an eventlog entry
545 *******************************************************************/
547 void fixup_eventlog_entry( Eventlog_entry * ee )
549 /* fix up the eventlog entry structure as necessary */
551 ee->data_record.sid_padding =
552 ( ( 4 -
553 ( ( ee->data_record.source_name_len +
554 ee->data_record.computer_name_len ) % 4 ) ) % 4 );
555 ee->data_record.data_padding =
556 ( 4 -
557 ( ( ee->data_record.strings_len +
558 ee->data_record.user_data_len ) % 4 ) ) % 4;
559 ee->record.length = sizeof( Eventlog_record );
560 ee->record.length += ee->data_record.source_name_len;
561 ee->record.length += ee->data_record.computer_name_len;
562 if ( ee->record.user_sid_length == 0 ) {
563 /* Should not pad to a DWORD boundary for writing out the sid if there is
564 no SID, so just propagate the padding to pad the data */
565 ee->data_record.data_padding += ee->data_record.sid_padding;
566 ee->data_record.sid_padding = 0;
568 /* DEBUG(10, ("sid_padding is [%d].\n", ee->data_record.sid_padding)); */
569 /* DEBUG(10, ("data_padding is [%d].\n", ee->data_record.data_padding)); */
571 ee->record.length += ee->data_record.sid_padding;
572 ee->record.length += ee->record.user_sid_length;
573 ee->record.length += ee->data_record.strings_len;
574 ee->record.length += ee->data_record.user_data_len;
575 ee->record.length += ee->data_record.data_padding;
576 /* need another copy of length at the end of the data */
577 ee->record.length += sizeof( ee->record.length );
580 /********************************************************************
581 Note that it's a pretty good idea to initialize the Eventlog_entry
582 structure to zero's before calling parse_logentry on an batch of
583 lines that may resolve to a record. ALSO, it's a good idea to
584 remove any linefeeds (that's EOL to you and me) on the lines
585 going in.
586 ********************************************************************/
588 bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor )
590 TALLOC_CTX *ctx = talloc_tos();
591 char *start = NULL, *stop = NULL;
593 start = line;
595 /* empty line signyfiying record delimeter, or we're at the end of the buffer */
596 if ( start == NULL || strlen( start ) == 0 ) {
597 DEBUG( 6,
598 ( "parse_logentry: found end-of-record indicator.\n" ) );
599 *eor = True;
600 return True;
602 if ( !( stop = strchr( line, ':' ) ) ) {
603 return False;
606 DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
608 if ( 0 == strncmp( start, "LEN", stop - start ) ) {
609 /* This will get recomputed later anyway -- probably not necessary */
610 entry->record.length = atoi( stop + 1 );
611 } else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
612 /* For now all these reserved entries seem to have the same value,
613 which can be hardcoded to int(1699505740) for now */
614 entry->record.reserved1 = atoi( stop + 1 );
615 } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
616 entry->record.record_number = atoi( stop + 1 );
617 } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
618 entry->record.time_generated = atoi( stop + 1 );
619 } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
620 entry->record.time_written = atoi( stop + 1 );
621 } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
622 entry->record.event_id = atoi( stop + 1 );
623 } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
624 if ( strstr( start, "ERROR" ) ) {
625 entry->record.event_type = EVENTLOG_ERROR_TYPE;
626 } else if ( strstr( start, "WARNING" ) ) {
627 entry->record.event_type = EVENTLOG_WARNING_TYPE;
628 } else if ( strstr( start, "INFO" ) ) {
629 entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
630 } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
631 entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
632 } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
633 entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
634 } else if ( strstr( start, "SUCCESS" ) ) {
635 entry->record.event_type = EVENTLOG_SUCCESS;
636 } else {
637 /* some other eventlog type -- currently not defined in MSDN docs, so error out */
638 return False;
643 else if(0 == strncmp(start, "NST", stop - start))
645 entry->record.num_strings = atoi(stop + 1);
648 else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
649 entry->record.event_category = atoi( stop + 1 );
650 } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
651 entry->record.reserved2 = atoi( stop + 1 );
652 } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
653 entry->record.closing_record_number = atoi( stop + 1 );
654 } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
655 entry->record.user_sid_length = atoi( stop + 1 );
656 } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
657 stop++;
658 while ( isspace( stop[0] ) ) {
659 stop++;
661 entry->data_record.source_name_len = rpcstr_push_talloc(ctx,
662 &entry->data_record.source_name,
663 stop);
664 if (entry->data_record.source_name_len == (uint32_t)-1 ||
665 entry->data_record.source_name == NULL) {
666 return false;
668 } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
669 stop++;
670 while ( isspace( stop[0] ) ) {
671 stop++;
673 entry->data_record.computer_name_len = rpcstr_push_talloc(ctx,
674 &entry->data_record.computer_name,
675 stop);
676 if (entry->data_record.computer_name_len == (uint32_t)-1 ||
677 entry->data_record.computer_name == NULL) {
678 return false;
680 } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
681 stop++;
682 while ( isspace( stop[0] ) ) {
683 stop++;
685 entry->record.user_sid_length = rpcstr_push_talloc(ctx,
686 &entry->data_record.sid,
687 stop);
688 if (entry->record.user_sid_length == (uint32_t)-1 ||
689 entry->data_record.sid == NULL) {
690 return false;
692 } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
693 smb_ucs2_t *temp = NULL;
694 size_t tmp_len;
695 uint32_t old_len;
696 /* skip past initial ":" */
697 stop++;
698 /* now skip any other leading whitespace */
699 while ( isspace(stop[0])) {
700 stop++;
702 tmp_len = rpcstr_push_talloc(ctx,
703 &temp,
704 stop);
705 if (tmp_len == (size_t)-1 || !temp) {
706 return false;
708 old_len = entry->data_record.strings_len;
709 entry->data_record.strings = (smb_ucs2_t *)TALLOC_REALLOC_ARRAY(ctx,
710 entry->data_record.strings,
711 char,
712 old_len + tmp_len);
713 if (!entry->data_record.strings) {
714 return false;
716 memcpy(entry->data_record.strings + old_len,
717 temp,
718 tmp_len);
719 entry->data_record.strings_len += tmp_len;
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++;
728 entry->data_record.user_data_len = strlen(stop);
729 entry->data_record.user_data = talloc_strdup(ctx,
730 stop);
731 if (!entry->data_record.user_data) {
732 return false;
734 } else {
735 /* some other eventlog entry -- not implemented, so dropping on the floor */
736 DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
737 /* For now return true so that we can keep on parsing this mess. Eventually
738 we will return False here. */
739 return true;
741 return true;