Patch 2 of 3 from Debian Samba packagers:
[Samba.git] / source / rpc_server / srv_eventlog_lib.c
blob00afe5b05c30c4ad0dc86f40c5a48b169211091e
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( const char *name )
67 fstring path;
68 char *tdb_fullpath;
69 char *eventlogdir = state_path( "eventlog" );
71 pstr_sprintf( path, "%s/%s.tdb", eventlogdir, name );
72 strlower_m( path );
73 tdb_fullpath = SMB_STRDUP( path );
75 return tdb_fullpath;
79 /********************************************************************
80 this function is used to count up the number of bytes in a
81 particular TDB
82 ********************************************************************/
84 struct trav_size_struct {
85 int size;
86 int rec_count;
89 static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
90 void *state )
92 struct trav_size_struct *tsize = (struct trav_size_struct *)state;
94 tsize->size += data.dsize;
95 tsize->rec_count++;
97 return 0;
100 /********************************************************************
101 returns the size of the eventlog, and if MaxSize is a non-null
102 ptr, puts the MaxSize there. This is purely a way not to have yet
103 another function that solely reads the maxsize of the eventlog.
104 Yeah, that's it.
105 ********************************************************************/
107 int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
109 struct trav_size_struct tsize;
111 if ( !tdb )
112 return 0;
114 ZERO_STRUCT( tsize );
116 tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
118 if ( MaxSize != NULL ) {
119 *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
122 if ( Retention != NULL ) {
123 *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
126 DEBUG( 1,
127 ( "eventlog size: [%d] for [%d] records\n", tsize.size,
128 tsize.rec_count ) );
129 return tsize.size;
132 /********************************************************************
133 Discard early event logs until we have enough for 'needed' bytes...
134 NO checking done beforehand to see that we actually need to do
135 this, and it's going to pluck records one-by-one. So, it's best
136 to determine that this needs to be done before doing it.
138 Setting whack_by_date to True indicates that eventlogs falling
139 outside of the retention range need to go...
141 return True if we made enough room to accommodate needed bytes
142 ********************************************************************/
144 bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
145 bool whack_by_date )
147 int start_record, i, new_start;
148 int end_record;
149 int nbytes, reclen, len, Retention, MaxSize;
150 int tresv1, trecnum, timegen, timewr;
151 TDB_DATA key, ret;
152 TALLOC_CTX *mem_ctx = NULL;
153 time_t current_time, exp_time;
155 /* discard some eventlogs */
157 /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
158 although records not necessarily guaranteed to have successive times */
159 /* */
160 mem_ctx = talloc_init( "make_way_for_eventlogs" ); /* Homage to BPG */
162 if ( mem_ctx == NULL )
163 return False; /* can't allocate memory indicates bigger problems */
164 /* lock */
165 tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
166 /* read */
167 end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
168 start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
169 Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
170 MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
172 time( &current_time );
174 /* calculate ... */
175 exp_time = current_time - Retention; /* discard older than exp_time */
177 /* todo - check for sanity in next_record */
178 nbytes = 0;
180 DEBUG( 3,
181 ( "MaxSize [%d] Retention [%d] Current Time [%d] exp_time [%d]\n",
182 MaxSize, Retention, (uint32)current_time, (uint32)exp_time ) );
183 DEBUG( 3,
184 ( "Start Record [%d] End Record [%d]\n", start_record,
185 end_record ) );
187 for ( i = start_record; i < end_record; i++ ) {
188 /* read a record, add the amt to nbytes */
189 key.dsize = sizeof( int32 );
190 key.dptr = ( uint8 * ) ( int32 * ) & i;
191 ret = tdb_fetch( the_tdb, key );
192 if ( ret.dsize == 0 ) {
193 DEBUG( 8,
194 ( "Can't find a record for the key, record [%d]\n",
195 i ) );
196 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
197 return False;
199 nbytes += ret.dsize; /* note this includes overhead */
201 len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
202 &tresv1, &trecnum, &timegen, &timewr );
203 if (len == -1) {
204 DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
205 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
206 return False;
209 DEBUG( 8,
210 ( "read record %d, record size is [%d], total so far [%d]\n",
211 i, reclen, nbytes ) );
213 SAFE_FREE( ret.dptr );
215 /* note that other servers may just stop writing records when the size limit
216 is reached, and there are no records older than 'retention'. This doesn't
217 like a very useful thing to do, so instead we whack (as in sleeps with the
218 fishes) just enough records to fit the what we need. This behavior could
219 be changed to 'match', if the need arises. */
221 if ( !whack_by_date && ( nbytes >= needed ) )
222 break; /* done */
223 if ( whack_by_date && ( timegen >= exp_time ) )
224 break; /* done */
227 DEBUG( 3,
228 ( "nbytes [%d] needed [%d] start_record is [%d], should be set to [%d]\n",
229 nbytes, needed, start_record, i ) );
230 /* todo - remove eventlog entries here and set starting record to start_record... */
231 new_start = i;
232 if ( start_record != new_start ) {
233 for ( i = start_record; i < new_start; i++ ) {
234 key.dsize = sizeof( int32 );
235 key.dptr = ( uint8 * ) ( int32 * ) & i;
236 tdb_delete( the_tdb, key );
239 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
241 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
242 return True;
245 /********************************************************************
246 some hygiene for an eventlog - see how big it is, and then
247 calculate how many bytes we need to remove
248 ********************************************************************/
250 bool prune_eventlog( TDB_CONTEXT * tdb )
252 int MaxSize, Retention, CalcdSize;
254 if ( !tdb ) {
255 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
256 return False;
259 CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
260 DEBUG( 3,
261 ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
262 MaxSize ) );
264 if ( CalcdSize > MaxSize ) {
265 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
266 False );
269 return make_way_for_eventlogs( tdb, 0, True );
272 /********************************************************************
273 ********************************************************************/
275 bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
277 int calcd_size;
278 int MaxSize, Retention;
280 /* see if we can write to the eventlog -- do a policy enforcement */
281 if ( !tdb )
282 return False; /* tdb is null, so we can't write to it */
285 if ( needed < 0 )
286 return False;
287 MaxSize = 0;
288 Retention = 0;
290 calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
292 if ( calcd_size <= MaxSize )
293 return True; /* you betcha */
294 if ( calcd_size + needed < MaxSize )
295 return True;
297 if ( Retention == 0xffffffff ) {
298 return False; /* see msdn - we can't write no room, discard */
301 note don't have to test, but always good to show intent, in case changes needed
302 later
305 if ( Retention == 0x00000000 ) {
306 /* discard record(s) */
307 /* todo - decide when to remove a bunch vs. just what we need... */
308 return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
309 True );
312 return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
315 /*******************************************************************
316 *******************************************************************/
318 ELOG_TDB *elog_open_tdb( char *logname, bool force_clear )
320 TDB_CONTEXT *tdb = NULL;
321 uint32 vers_id;
322 ELOG_TDB *ptr;
323 char *tdbfilename;
324 pstring tdbpath;
325 ELOG_TDB *tdb_node = NULL;
326 char *eventlogdir;
328 /* first see if we have an open context */
330 for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
331 if ( strequal( ptr->name, logname ) ) {
332 ptr->ref_count++;
334 /* trick to alow clearing of the eventlog tdb.
335 The force_clear flag should imply that someone
336 has done a force close. So make sure the tdb
337 is NULL. If this is a normal open, then just
338 return the existing reference */
340 if ( force_clear ) {
341 SMB_ASSERT( ptr->tdb == NULL );
342 break;
344 else
345 return ptr;
349 /* make sure that the eventlog dir exists */
351 eventlogdir = state_path( "eventlog" );
352 if ( !directory_exist( eventlogdir, NULL ) )
353 mkdir( eventlogdir, 0755 );
355 /* get the path on disk */
357 tdbfilename = elog_tdbname( logname );
358 pstrcpy( tdbpath, tdbfilename );
359 SAFE_FREE( tdbfilename );
361 DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
362 tdbpath, force_clear?"True":"False" ));
364 /* the tdb wasn't already open or this is a forced clear open */
366 if ( !force_clear ) {
368 tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 );
369 if ( tdb ) {
370 vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
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 );
381 if ( !tdb )
382 tdb = elog_init_tdb( tdbpath );
384 /* if we got a valid context, then add it to the list */
386 if ( tdb ) {
387 /* on a forced clear, just reset the tdb context if we already
388 have an open entry in the list */
390 if ( ptr ) {
391 ptr->tdb = tdb;
392 return ptr;
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;
401 tdb_node->name = talloc_strdup( tdb_node, logname );
402 tdb_node->tdb = tdb;
403 tdb_node->ref_count = 1;
405 DLIST_ADD( open_elog_list, tdb_node );
408 return tdb_node;
411 /*******************************************************************
412 Wrapper to handle reference counts to the tdb
413 *******************************************************************/
415 int elog_close_tdb( ELOG_TDB *etdb, bool force_close )
417 TDB_CONTEXT *tdb;
419 if ( !etdb )
420 return 0;
422 etdb->ref_count--;
424 SMB_ASSERT( etdb->ref_count >= 0 );
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 );
433 if ( force_close ) {
434 tdb = etdb->tdb;
435 etdb->tdb = NULL;
436 return tdb_close( tdb );
439 return 0;
443 /*******************************************************************
444 write an eventlog entry. Note that we have to lock, read next
445 eventlog, increment, write, write the record, unlock
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 *******************************************************************/
453 #define MARGIN 512
455 int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
457 int32 next_record;
458 uint8 *packed_ee;
459 TALLOC_CTX *mem_ctx = NULL;
460 TDB_DATA kbuf, ebuf;
461 uint32 n_packed;
463 if ( !ee )
464 return 0;
466 mem_ctx = talloc_init( "write_eventlog_tdb" );
468 if ( mem_ctx == NULL )
469 return 0;
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;
477 /* todo - check for sanity in next_record */
479 fixup_eventlog_entry( ee );
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;
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;
494 /* need to read the record number and insert it into the entry here */
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 );
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 );
526 /*DEBUG(3,("write_eventlog_tdb: packed into %d\n",n_packed)); */
528 /* increment the record count */
530 kbuf.dsize = sizeof( int32 );
531 kbuf.dptr = (uint8 * ) & next_record;
533 ebuf.dsize = n_packed;
534 ebuf.dptr = (uint8 *)packed_ee;
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;
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 );
549 /*******************************************************************
550 calculate the correct fields etc for an eventlog entry
551 *******************************************************************/
553 void fixup_eventlog_entry( Eventlog_entry * ee )
555 /* fix up the eventlog entry structure as necessary */
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;
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)); */
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 );
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 ********************************************************************/
594 bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor )
596 char *start = NULL, *stop = NULL;
597 pstring temp;
598 int temp_len = 0;
600 start = line;
602 /* empty line signyfiying record delimeter, or we're at the end of the buffer */
603 if ( start == NULL || strlen( start ) == 0 ) {
604 DEBUG( 6,
605 ( "parse_logentry: found end-of-record indicator.\n" ) );
606 *eor = True;
607 return True;
609 if ( !( stop = strchr( line, ':' ) ) ) {
610 return False;
613 DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
615 if ( 0 == strncmp( start, "LEN", stop - start ) ) {
616 /* This will get recomputed later anyway -- probably not necessary */
617 entry->record.length = atoi( stop + 1 );
618 } else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
619 /* For now all these reserved entries seem to have the same value,
620 which can be hardcoded to int(1699505740) for now */
621 entry->record.reserved1 = atoi( stop + 1 );
622 } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
623 entry->record.record_number = atoi( stop + 1 );
624 } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
625 entry->record.time_generated = atoi( stop + 1 );
626 } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
627 entry->record.time_written = atoi( stop + 1 );
628 } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
629 entry->record.event_id = atoi( stop + 1 );
630 } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
631 if ( strstr( start, "ERROR" ) ) {
632 entry->record.event_type = EVENTLOG_ERROR_TYPE;
633 } else if ( strstr( start, "WARNING" ) ) {
634 entry->record.event_type = EVENTLOG_WARNING_TYPE;
635 } else if ( strstr( start, "INFO" ) ) {
636 entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
637 } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
638 entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
639 } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
640 entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
641 } else if ( strstr( start, "SUCCESS" ) ) {
642 entry->record.event_type = EVENTLOG_SUCCESS;
643 } else {
644 /* some other eventlog type -- currently not defined in MSDN docs, so error out */
645 return False;
650 else if(0 == strncmp(start, "NST", stop - start))
652 entry->record.num_strings = atoi(stop + 1);
655 else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
656 entry->record.event_category = atoi( stop + 1 );
657 } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
658 entry->record.reserved2 = atoi( stop + 1 );
659 } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
660 entry->record.closing_record_number = atoi( stop + 1 );
661 } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
662 entry->record.user_sid_length = atoi( stop + 1 );
663 } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
664 memset( temp, 0, sizeof( temp ) );
665 stop++;
666 while ( isspace( stop[0] ) ) {
667 stop++;
669 temp_len = strlen( stop );
670 strncpy( temp, stop, temp_len );
671 rpcstr_push( ( void * ) ( entry->data_record.source_name ),
672 temp, sizeof( entry->data_record.source_name ),
673 STR_TERMINATE );
674 entry->data_record.source_name_len =
675 ( strlen_w( entry->data_record.source_name ) * 2 ) +
677 } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
678 memset( temp, 0, sizeof( temp ) );
679 stop++;
680 while ( isspace( stop[0] ) ) {
681 stop++;
683 temp_len = strlen( stop );
684 strncpy( temp, stop, temp_len );
685 rpcstr_push( ( void * ) ( entry->data_record.computer_name ),
686 temp, sizeof( entry->data_record.computer_name ),
687 STR_TERMINATE );
688 entry->data_record.computer_name_len =
689 ( strlen_w( entry->data_record.computer_name ) * 2 ) +
691 } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
692 memset( temp, 0, sizeof( temp ) );
693 stop++;
694 while ( isspace( stop[0] ) ) {
695 stop++;
697 temp_len = strlen( stop );
698 strncpy( temp, stop, temp_len );
699 rpcstr_push( ( void * ) ( entry->data_record.sid ), temp,
700 sizeof( entry->data_record.sid ),
701 STR_TERMINATE );
702 entry->record.user_sid_length =
703 ( strlen_w( entry->data_record.sid ) * 2 ) + 2;
704 } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
705 /* skip past initial ":" */
706 stop++;
707 /* now skip any other leading whitespace */
708 while ( isspace( stop[0] ) ) {
709 stop++;
711 temp_len = strlen( stop );
712 memset( temp, 0, sizeof( temp ) );
713 strncpy( temp, stop, temp_len );
714 rpcstr_push( ( void * ) ( entry->data_record.strings +
715 ( entry->data_record.strings_len / 2 ) ),
716 temp,
717 sizeof( entry->data_record.strings ) -
718 ( entry->data_record.strings_len / 2 ), STR_TERMINATE );
719 entry->data_record.strings_len += ( temp_len * 2 ) + 2;
720 entry->record.num_strings++;
721 } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
722 /* skip past initial ":" */
723 stop++;
724 /* now skip any other leading whitespace */
725 while ( isspace( stop[0] ) ) {
726 stop++;
728 entry->data_record.user_data_len = strlen( stop );
729 memset( entry->data_record.user_data, 0,
730 sizeof( entry->data_record.user_data ) );
731 if ( entry->data_record.user_data_len > 0 ) {
732 /* copy no more than the first 1024 bytes */
733 if ( entry->data_record.user_data_len >
734 sizeof( entry->data_record.user_data ) )
735 entry->data_record.user_data_len =
736 sizeof( entry->data_record.
737 user_data );
738 memcpy( entry->data_record.user_data, stop,
739 entry->data_record.user_data_len );
741 } else {
742 /* some other eventlog entry -- not implemented, so dropping on the floor */
743 DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
744 /* For now return true so that we can keep on parsing this mess. Eventually
745 we will return False here. */
746 return True;
748 return True;