Fix bug #6154 - zfs does not honor admin users.
[Samba.git] / source / rpc_server / srv_eventlog_lib.c
blob17427d2dafc46834d30ae6360112bfe3a4060afe
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_t needed,
144 bool whack_by_date )
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;
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 [%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 ));
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;
195 nbytes += ret.dsize; /* note this includes overhead */
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;
206 DEBUG( 8,
207 ( "read record %u, record size is [%d], total so far [%d]\n",
208 (unsigned int)i, reclen, nbytes ) );
210 SAFE_FREE( ret.dptr );
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. */
218 if ( !whack_by_date && ( nbytes >= needed ) )
219 break; /* done */
220 if ( whack_by_date && ( timegen >= exp_time ) )
221 break; /* done */
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 );
236 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
238 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
239 return True;
242 /********************************************************************
243 some hygiene for an eventlog - see how big it is, and then
244 calculate how many bytes we need to remove
245 ********************************************************************/
247 bool prune_eventlog( TDB_CONTEXT * tdb )
249 int MaxSize, Retention, CalcdSize;
251 if ( !tdb ) {
252 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
253 return False;
256 CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
257 DEBUG( 3,
258 ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
259 MaxSize ) );
261 if ( CalcdSize > MaxSize ) {
262 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
263 False );
266 return make_way_for_eventlogs( tdb, 0, True );
269 /********************************************************************
270 ********************************************************************/
272 bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32_t needed )
274 int calcd_size;
275 int MaxSize, Retention;
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 */
282 if ( needed < 0 )
283 return False;
284 MaxSize = 0;
285 Retention = 0;
287 calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
289 if ( calcd_size <= MaxSize )
290 return True; /* you betcha */
291 if ( calcd_size + needed < MaxSize )
292 return True;
294 if ( Retention == 0xffffffff ) {
295 return False; /* see msdn - we can't write no room, discard */
298 note don't have to test, but always good to show intent, in case changes needed
299 later
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 );
309 return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
312 /*******************************************************************
313 *******************************************************************/
315 ELOG_TDB *elog_open_tdb( char *logname, bool force_clear )
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();
325 /* first see if we have an open context */
327 for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
328 if ( strequal( ptr->name, logname ) ) {
329 ptr->ref_count++;
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 */
337 if ( force_clear ) {
338 SMB_ASSERT( ptr->tdb == NULL );
339 break;
341 else
342 return ptr;
346 /* make sure that the eventlog dir exists */
348 eventlogdir = state_path( "eventlog" );
349 if ( !directory_exist( eventlogdir, NULL ) )
350 mkdir( eventlogdir, 0755 );
352 /* get the path on disk */
354 tdbpath = elog_tdbname(ctx, logname);
355 if (!tdbpath) {
356 return NULL;
359 DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
360 tdbpath, force_clear?"True":"False" ));
362 /* the tdb wasn't already open or this is a forced clear open */
364 if ( !force_clear ) {
366 tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 );
367 if ( tdb ) {
368 vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
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 );
379 if ( !tdb )
380 tdb = elog_init_tdb( tdbpath );
382 /* if we got a valid context, then add it to the list */
384 if ( tdb ) {
385 /* on a forced clear, just reset the tdb context if we already
386 have an open entry in the list */
388 if ( ptr ) {
389 ptr->tdb = tdb;
390 return ptr;
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;
399 tdb_node->name = talloc_strdup( tdb_node, logname );
400 tdb_node->tdb = tdb;
401 tdb_node->ref_count = 1;
403 DLIST_ADD( open_elog_list, tdb_node );
406 return tdb_node;
409 /*******************************************************************
410 Wrapper to handle reference counts to the tdb
411 *******************************************************************/
413 int elog_close_tdb( ELOG_TDB *etdb, bool force_close )
415 TDB_CONTEXT *tdb;
417 if ( !etdb )
418 return 0;
420 etdb->ref_count--;
422 SMB_ASSERT( etdb->ref_count >= 0 );
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 );
431 if ( force_close ) {
432 tdb = etdb->tdb;
433 etdb->tdb = NULL;
434 return tdb_close( tdb );
437 return 0;
441 /*******************************************************************
442 write an eventlog entry. Note that we have to lock, read next
443 eventlog, increment, write, write the record, unlock
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 *******************************************************************/
451 #define MARGIN 512
453 int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
455 int32 next_record;
456 uint8 *packed_ee;
457 TALLOC_CTX *mem_ctx = NULL;
458 TDB_DATA kbuf, ebuf;
459 uint32_t n_packed;
461 if ( !ee )
462 return 0;
464 mem_ctx = talloc_init( "write_eventlog_tdb" );
466 if ( mem_ctx == NULL )
467 return 0;
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;
473 /* todo - check for sanity in next_record */
475 fixup_eventlog_entry( ee );
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;
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;
490 /* need to read the record number and insert it into the entry here */
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 );
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 );
522 /*DEBUG(3,("write_eventlog_tdb: packed into %d\n",n_packed)); */
524 /* increment the record count */
526 kbuf.dsize = sizeof( int32 );
527 kbuf.dptr = (uint8 * ) & next_record;
529 ebuf.dsize = n_packed;
530 ebuf.dptr = (uint8 *)packed_ee;
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;
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 );
545 /*******************************************************************
546 calculate the correct fields etc for an eventlog entry
547 *******************************************************************/
549 void fixup_eventlog_entry( Eventlog_entry * ee )
551 /* fix up the eventlog entry structure as necessary */
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;
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)); */
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 );
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 ********************************************************************/
590 bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor )
592 TALLOC_CTX *ctx = talloc_tos();
593 char *start = NULL, *stop = NULL;
595 start = line;
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;
604 if ( !( stop = strchr( line, ':' ) ) ) {
605 return False;
608 DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
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;
645 else if(0 == strncmp(start, "NST", stop - start))
647 entry->record.num_strings = atoi(stop + 1);
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++;
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;
670 } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
671 stop++;
672 while ( isspace( stop[0] ) ) {
673 stop++;
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;
682 } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
683 stop++;
684 while ( isspace( stop[0] ) ) {
685 stop++;
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;
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++;
704 tmp_len = rpcstr_push_talloc(ctx,
705 &temp,
706 stop);
707 if (tmp_len == (size_t)-1 || !temp) {
708 return false;
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;
718 memcpy(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++;
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;
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;
743 return true;