Samba 3: added Samba 3.0.24 sources
[tomato.git] / release / src / router / samba3 / source / rpc_server / srv_eventlog_lib.c
blob66be1dc34ff58e74ddfc5de710cb1c773f53858f
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 2 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, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 /* maintain a list of open eventlog tdbs with reference counts */
27 static ELOG_TDB *open_elog_list;
29 /********************************************************************
30 Init an Eventlog TDB, and return it. If null, something bad
31 happened.
32 ********************************************************************/
34 TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
36 TDB_CONTEXT *tdb;
38 DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
39 tdbfilename));
41 tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT,
42 O_RDWR|O_CREAT|O_TRUNC, 0660 );
44 if ( !tdb ) {
45 DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
46 return NULL;
49 /* initialize with defaults, copy real values in here from registry */
51 tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 );
52 tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 );
53 tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 );
54 tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 );
56 tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
58 return tdb;
61 /********************************************************************
62 make the tdb file name for an event log, given destination buffer
63 and size. Caller must free memory.
64 ********************************************************************/
66 char *elog_tdbname( const char *name )
68 fstring path;
69 char *tdb_fullpath;
70 char *eventlogdir = lock_path( "eventlog" );
72 pstr_sprintf( path, "%s/%s.tdb", eventlogdir, name );
73 strlower_m( path );
74 tdb_fullpath = SMB_STRDUP( path );
76 return tdb_fullpath;
80 /********************************************************************
81 this function is used to count up the number of bytes in a
82 particular TDB
83 ********************************************************************/
85 struct trav_size_struct {
86 int size;
87 int rec_count;
90 static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
91 void *state )
93 struct trav_size_struct *tsize = state;
95 tsize->size += data.dsize;
96 tsize->rec_count++;
98 return 0;
101 /********************************************************************
102 returns the size of the eventlog, and if MaxSize is a non-null
103 ptr, puts the MaxSize there. This is purely a way not to have yet
104 another function that solely reads the maxsize of the eventlog.
105 Yeah, that's it.
106 ********************************************************************/
108 int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
110 struct trav_size_struct tsize;
112 if ( !tdb )
113 return 0;
115 ZERO_STRUCT( tsize );
117 tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
119 if ( MaxSize != NULL ) {
120 *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
123 if ( Retention != NULL ) {
124 *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
127 DEBUG( 1,
128 ( "eventlog size: [%d] for [%d] records\n", tsize.size,
129 tsize.rec_count ) );
130 return tsize.size;
133 /********************************************************************
134 Discard early event logs until we have enough for 'needed' bytes...
135 NO checking done beforehand to see that we actually need to do
136 this, and it's going to pluck records one-by-one. So, it's best
137 to determine that this needs to be done before doing it.
139 Setting whack_by_date to True indicates that eventlogs falling
140 outside of the retention range need to go...
142 return True if we made enough room to accommodate needed bytes
143 ********************************************************************/
145 BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
146 BOOL whack_by_date )
148 int start_record, i, new_start;
149 int end_record;
150 int nbytes, reclen, len, Retention, MaxSize;
151 int tresv1, trecnum, timegen, timewr;
152 TDB_DATA key, ret;
153 TALLOC_CTX *mem_ctx = NULL;
154 time_t current_time, exp_time;
156 /* discard some eventlogs */
158 /* read eventlogs from oldest_entry -- there can't be any discontinuity in recnos,
159 although records not necessarily guaranteed to have successive times */
160 /* */
161 mem_ctx = talloc_init( "make_way_for_eventlogs" ); /* Homage to BPG */
163 if ( mem_ctx == NULL )
164 return False; /* can't allocate memory indicates bigger problems */
165 /* lock */
166 tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
167 /* read */
168 end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
169 start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
170 Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
171 MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
173 time( &current_time );
175 /* calculate ... */
176 exp_time = current_time - Retention; /* discard older than exp_time */
178 /* todo - check for sanity in next_record */
179 nbytes = 0;
181 DEBUG( 3,
182 ( "MaxSize [%d] Retention [%d] Current Time [%d] exp_time [%d]\n",
183 MaxSize, Retention, (uint32)current_time, (uint32)exp_time ) );
184 DEBUG( 3,
185 ( "Start Record [%d] End Record [%d]\n", start_record,
186 end_record ) );
188 for ( i = start_record; i < end_record; i++ ) {
189 /* read a record, add the amt to nbytes */
190 key.dsize = sizeof( int32 );
191 key.dptr = ( char * ) ( int32 * ) & i;
192 ret = tdb_fetch( the_tdb, key );
193 if ( ret.dsize == 0 ) {
194 DEBUG( 8,
195 ( "Can't find a record for the key, record [%d]\n",
196 i ) );
197 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
198 return False;
200 nbytes += ret.dsize; /* note this includes overhead */
202 len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
203 &tresv1, &trecnum, &timegen, &timewr );
204 if (len == -1) {
205 DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
206 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
207 return False;
210 DEBUG( 8,
211 ( "read record %d, record size is [%d], total so far [%d]\n",
212 i, reclen, nbytes ) );
214 SAFE_FREE( ret.dptr );
216 /* note that other servers may just stop writing records when the size limit
217 is reached, and there are no records older than 'retention'. This doesn't
218 like a very useful thing to do, so instead we whack (as in sleeps with the
219 fishes) just enough records to fit the what we need. This behavior could
220 be changed to 'match', if the need arises. */
222 if ( !whack_by_date && ( nbytes >= needed ) )
223 break; /* done */
224 if ( whack_by_date && ( timegen >= exp_time ) )
225 break; /* done */
228 DEBUG( 3,
229 ( "nbytes [%d] needed [%d] start_record is [%d], should be set to [%d]\n",
230 nbytes, needed, start_record, i ) );
231 /* todo - remove eventlog entries here and set starting record to start_record... */
232 new_start = i;
233 if ( start_record != new_start ) {
234 for ( i = start_record; i < new_start; i++ ) {
235 key.dsize = sizeof( int32 );
236 key.dptr = ( char * ) ( int32 * ) & i;
237 tdb_delete( the_tdb, key );
240 tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
242 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
243 return True;
246 /********************************************************************
247 some hygiene for an eventlog - see how big it is, and then
248 calculate how many bytes we need to remove
249 ********************************************************************/
251 BOOL prune_eventlog( TDB_CONTEXT * tdb )
253 int MaxSize, Retention, CalcdSize;
255 if ( !tdb ) {
256 DEBUG( 4, ( "No eventlog tdb handle\n" ) );
257 return False;
260 CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
261 DEBUG( 3,
262 ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
263 MaxSize ) );
265 if ( CalcdSize > MaxSize ) {
266 return make_way_for_eventlogs( tdb, CalcdSize - MaxSize,
267 False );
270 return make_way_for_eventlogs( tdb, 0, True );
273 /********************************************************************
274 ********************************************************************/
276 BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
278 int calcd_size;
279 int MaxSize, Retention;
281 /* see if we can write to the eventlog -- do a policy enforcement */
282 if ( !tdb )
283 return False; /* tdb is null, so we can't write to it */
286 if ( needed < 0 )
287 return False;
288 MaxSize = 0;
289 Retention = 0;
291 calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
293 if ( calcd_size <= MaxSize )
294 return True; /* you betcha */
295 if ( calcd_size + needed < MaxSize )
296 return True;
298 if ( Retention == 0xffffffff ) {
299 return False; /* see msdn - we can't write no room, discard */
302 note don't have to test, but always good to show intent, in case changes needed
303 later
306 if ( Retention == 0x00000000 ) {
307 /* discard record(s) */
308 /* todo - decide when to remove a bunch vs. just what we need... */
309 return make_way_for_eventlogs( tdb, calcd_size - MaxSize,
310 True );
313 return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
316 /*******************************************************************
317 *******************************************************************/
319 ELOG_TDB *elog_open_tdb( char *logname, BOOL force_clear )
321 TDB_CONTEXT *tdb = NULL;
322 uint32 vers_id;
323 ELOG_TDB *ptr;
324 char *tdbfilename;
325 pstring tdbpath;
326 ELOG_TDB *tdb_node = NULL;
327 char *eventlogdir;
329 /* first see if we have an open context */
331 for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
332 if ( strequal( ptr->name, logname ) ) {
333 ptr->ref_count++;
335 /* trick to alow clearing of the eventlog tdb.
336 The force_clear flag should imply that someone
337 has done a force close. So make sure the tdb
338 is NULL. If this is a normal open, then just
339 return the existing reference */
341 if ( force_clear ) {
342 SMB_ASSERT( ptr->tdb == NULL );
343 break;
345 else
346 return ptr;
350 /* make sure that the eventlog dir exists */
352 eventlogdir = lock_path( "eventlog" );
353 if ( !directory_exist( eventlogdir, NULL ) )
354 mkdir( eventlogdir, 0755 );
356 /* get the path on disk */
358 tdbfilename = elog_tdbname( logname );
359 pstrcpy( tdbpath, tdbfilename );
360 SAFE_FREE( tdbfilename );
362 DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
363 tdbpath, force_clear?"True":"False" ));
365 /* the tdb wasn't already open or this is a forced clear open */
367 if ( !force_clear ) {
369 tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 );
370 if ( tdb ) {
371 vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
373 if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
374 DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
375 vers_id, tdbpath));
376 tdb_close( tdb );
377 tdb = elog_init_tdb( tdbpath );
382 if ( !tdb )
383 tdb = elog_init_tdb( tdbpath );
385 /* if we got a valid context, then add it to the list */
387 if ( tdb ) {
388 /* on a forced clear, just reset the tdb context if we already
389 have an open entry in the list */
391 if ( ptr ) {
392 ptr->tdb = tdb;
393 return ptr;
396 if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
397 DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
398 tdb_close( tdb );
399 return NULL;
402 tdb_node->name = talloc_strdup( tdb_node, logname );
403 tdb_node->tdb = tdb;
404 tdb_node->ref_count = 1;
406 DLIST_ADD( open_elog_list, tdb_node );
409 return tdb_node;
412 /*******************************************************************
413 Wrapper to handle reference counts to the tdb
414 *******************************************************************/
416 int elog_close_tdb( ELOG_TDB *etdb, BOOL force_close )
418 TDB_CONTEXT *tdb;
420 if ( !etdb )
421 return 0;
423 etdb->ref_count--;
425 SMB_ASSERT( etdb->ref_count >= 0 );
427 if ( etdb->ref_count == 0 ) {
428 tdb = etdb->tdb;
429 DLIST_REMOVE( open_elog_list, etdb );
430 TALLOC_FREE( etdb );
431 return tdb_close( tdb );
434 if ( force_close ) {
435 tdb = etdb->tdb;
436 etdb->tdb = NULL;
437 return tdb_close( tdb );
440 return 0;
444 /*******************************************************************
445 write an eventlog entry. Note that we have to lock, read next
446 eventlog, increment, write, write the record, unlock
448 coming into this, ee has the eventlog record, and the auxilliary date
449 (computer name, etc.) filled into the other structure. Before packing
450 into a record, this routine will calc the appropriate padding, etc.,
451 and then blast out the record in a form that can be read back in
452 *******************************************************************/
454 #define MARGIN 512
456 int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
458 int32 next_record;
459 uint8 *packed_ee;
460 TALLOC_CTX *mem_ctx = NULL;
461 TDB_DATA kbuf, ebuf;
462 uint32 n_packed;
464 if ( !ee )
465 return 0;
467 mem_ctx = talloc_init( "write_eventlog_tdb" );
469 if ( mem_ctx == NULL )
470 return 0;
472 if ( !ee )
473 return 0;
474 /* discard any entries that have bogus time, which usually indicates a bogus entry as well. */
475 if ( ee->record.time_generated == 0 )
476 return 0;
478 /* todo - check for sanity in next_record */
480 fixup_eventlog_entry( ee );
482 if ( !can_write_to_eventlog( the_tdb, ee->record.length ) ) {
483 DEBUG( 3, ( "Can't write to Eventlog, no room \n" ) );
484 talloc_destroy( mem_ctx );
485 return 0;
488 /* alloc mem for the packed version */
489 packed_ee = TALLOC( mem_ctx, ee->record.length + MARGIN );
490 if ( !packed_ee ) {
491 talloc_destroy( mem_ctx );
492 return 0;
495 /* need to read the record number and insert it into the entry here */
497 /* lock */
498 tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
499 /* read */
500 next_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
502 n_packed =
503 tdb_pack( (char *)packed_ee, ee->record.length + MARGIN,
504 "ddddddwwwwddddddBBdBBBd", ee->record.length,
505 ee->record.reserved1, next_record,
506 ee->record.time_generated, ee->record.time_written,
507 ee->record.event_id, ee->record.event_type,
508 ee->record.num_strings, ee->record.event_category,
509 ee->record.reserved2,
510 ee->record.closing_record_number,
511 ee->record.string_offset,
512 ee->record.user_sid_length,
513 ee->record.user_sid_offset, ee->record.data_length,
514 ee->record.data_offset,
515 ee->data_record.source_name_len,
516 ee->data_record.source_name,
517 ee->data_record.computer_name_len,
518 ee->data_record.computer_name,
519 ee->data_record.sid_padding,
520 ee->record.user_sid_length, ee->data_record.sid,
521 ee->data_record.strings_len,
522 ee->data_record.strings,
523 ee->data_record.user_data_len,
524 ee->data_record.user_data,
525 ee->data_record.data_padding );
527 /*DEBUG(3,("write_eventlog_tdb: packed into %d\n",n_packed)); */
529 /* increment the record count */
531 kbuf.dsize = sizeof( int32 );
532 kbuf.dptr = (char * ) & next_record;
534 ebuf.dsize = n_packed;
535 ebuf.dptr = (char *)packed_ee;
537 if ( tdb_store( the_tdb, kbuf, ebuf, 0 ) ) {
538 /* DEBUG(1,("write_eventlog_tdb: Can't write record %d to eventlog\n",next_record)); */
539 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
540 talloc_destroy( mem_ctx );
541 return 0;
543 next_record++;
544 tdb_store_int32( the_tdb, EVT_NEXT_RECORD, next_record );
545 tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
546 talloc_destroy( mem_ctx );
547 return ( next_record - 1 );
550 /*******************************************************************
551 calculate the correct fields etc for an eventlog entry
552 *******************************************************************/
554 void fixup_eventlog_entry( Eventlog_entry * ee )
556 /* fix up the eventlog entry structure as necessary */
558 ee->data_record.sid_padding =
559 ( ( 4 -
560 ( ( ee->data_record.source_name_len +
561 ee->data_record.computer_name_len ) % 4 ) ) % 4 );
562 ee->data_record.data_padding =
563 ( 4 -
564 ( ( ee->data_record.strings_len +
565 ee->data_record.user_data_len ) % 4 ) ) % 4;
566 ee->record.length = sizeof( Eventlog_record );
567 ee->record.length += ee->data_record.source_name_len;
568 ee->record.length += ee->data_record.computer_name_len;
569 if ( ee->record.user_sid_length == 0 ) {
570 /* Should not pad to a DWORD boundary for writing out the sid if there is
571 no SID, so just propagate the padding to pad the data */
572 ee->data_record.data_padding += ee->data_record.sid_padding;
573 ee->data_record.sid_padding = 0;
575 /* DEBUG(10, ("sid_padding is [%d].\n", ee->data_record.sid_padding)); */
576 /* DEBUG(10, ("data_padding is [%d].\n", ee->data_record.data_padding)); */
578 ee->record.length += ee->data_record.sid_padding;
579 ee->record.length += ee->record.user_sid_length;
580 ee->record.length += ee->data_record.strings_len;
581 ee->record.length += ee->data_record.user_data_len;
582 ee->record.length += ee->data_record.data_padding;
583 /* need another copy of length at the end of the data */
584 ee->record.length += sizeof( ee->record.length );
587 /********************************************************************
588 Note that it's a pretty good idea to initialize the Eventlog_entry
589 structure to zero's before calling parse_logentry on an batch of
590 lines that may resolve to a record. ALSO, it's a good idea to
591 remove any linefeeds (that's EOL to you and me) on the lines
592 going in.
593 ********************************************************************/
595 BOOL parse_logentry( char *line, Eventlog_entry * entry, BOOL * eor )
597 char *start = NULL, *stop = NULL;
598 pstring temp;
599 int temp_len = 0;
601 start = line;
603 /* empty line signyfiying record delimeter, or we're at the end of the buffer */
604 if ( start == NULL || strlen( start ) == 0 ) {
605 DEBUG( 6,
606 ( "parse_logentry: found end-of-record indicator.\n" ) );
607 *eor = True;
608 return True;
610 if ( !( stop = strchr( line, ':' ) ) ) {
611 return False;
614 DEBUG( 6, ( "parse_logentry: trying to parse [%s].\n", line ) );
616 if ( 0 == strncmp( start, "LEN", stop - start ) ) {
617 /* This will get recomputed later anyway -- probably not necessary */
618 entry->record.length = atoi( stop + 1 );
619 } else if ( 0 == strncmp( start, "RS1", stop - start ) ) {
620 /* For now all these reserved entries seem to have the same value,
621 which can be hardcoded to int(1699505740) for now */
622 entry->record.reserved1 = atoi( stop + 1 );
623 } else if ( 0 == strncmp( start, "RCN", stop - start ) ) {
624 entry->record.record_number = atoi( stop + 1 );
625 } else if ( 0 == strncmp( start, "TMG", stop - start ) ) {
626 entry->record.time_generated = atoi( stop + 1 );
627 } else if ( 0 == strncmp( start, "TMW", stop - start ) ) {
628 entry->record.time_written = atoi( stop + 1 );
629 } else if ( 0 == strncmp( start, "EID", stop - start ) ) {
630 entry->record.event_id = atoi( stop + 1 );
631 } else if ( 0 == strncmp( start, "ETP", stop - start ) ) {
632 if ( strstr( start, "ERROR" ) ) {
633 entry->record.event_type = EVENTLOG_ERROR_TYPE;
634 } else if ( strstr( start, "WARNING" ) ) {
635 entry->record.event_type = EVENTLOG_WARNING_TYPE;
636 } else if ( strstr( start, "INFO" ) ) {
637 entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
638 } else if ( strstr( start, "AUDIT_SUCCESS" ) ) {
639 entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
640 } else if ( strstr( start, "AUDIT_FAILURE" ) ) {
641 entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
642 } else if ( strstr( start, "SUCCESS" ) ) {
643 entry->record.event_type = EVENTLOG_SUCCESS;
644 } else {
645 /* some other eventlog type -- currently not defined in MSDN docs, so error out */
646 return False;
651 else if(0 == strncmp(start, "NST", stop - start))
653 entry->record.num_strings = atoi(stop + 1);
656 else if ( 0 == strncmp( start, "ECT", stop - start ) ) {
657 entry->record.event_category = atoi( stop + 1 );
658 } else if ( 0 == strncmp( start, "RS2", stop - start ) ) {
659 entry->record.reserved2 = atoi( stop + 1 );
660 } else if ( 0 == strncmp( start, "CRN", stop - start ) ) {
661 entry->record.closing_record_number = atoi( stop + 1 );
662 } else if ( 0 == strncmp( start, "USL", stop - start ) ) {
663 entry->record.user_sid_length = atoi( stop + 1 );
664 } else if ( 0 == strncmp( start, "SRC", stop - start ) ) {
665 memset( temp, 0, sizeof( temp ) );
666 stop++;
667 while ( isspace( stop[0] ) ) {
668 stop++;
670 temp_len = strlen( stop );
671 strncpy( temp, stop, temp_len );
672 rpcstr_push( ( void * ) ( entry->data_record.source_name ),
673 temp, sizeof( entry->data_record.source_name ),
674 STR_TERMINATE );
675 entry->data_record.source_name_len =
676 ( strlen_w( entry->data_record.source_name ) * 2 ) +
678 } else if ( 0 == strncmp( start, "SRN", stop - start ) ) {
679 memset( temp, 0, sizeof( temp ) );
680 stop++;
681 while ( isspace( stop[0] ) ) {
682 stop++;
684 temp_len = strlen( stop );
685 strncpy( temp, stop, temp_len );
686 rpcstr_push( ( void * ) ( entry->data_record.computer_name ),
687 temp, sizeof( entry->data_record.computer_name ),
688 STR_TERMINATE );
689 entry->data_record.computer_name_len =
690 ( strlen_w( entry->data_record.computer_name ) * 2 ) +
692 } else if ( 0 == strncmp( start, "SID", stop - start ) ) {
693 memset( temp, 0, sizeof( temp ) );
694 stop++;
695 while ( isspace( stop[0] ) ) {
696 stop++;
698 temp_len = strlen( stop );
699 strncpy( temp, stop, temp_len );
700 rpcstr_push( ( void * ) ( entry->data_record.sid ), temp,
701 sizeof( entry->data_record.sid ),
702 STR_TERMINATE );
703 entry->record.user_sid_length =
704 ( strlen_w( entry->data_record.sid ) * 2 ) + 2;
705 } else if ( 0 == strncmp( start, "STR", stop - start ) ) {
706 /* skip past initial ":" */
707 stop++;
708 /* now skip any other leading whitespace */
709 while ( isspace( stop[0] ) ) {
710 stop++;
712 temp_len = strlen( stop );
713 memset( temp, 0, sizeof( temp ) );
714 strncpy( temp, stop, temp_len );
715 rpcstr_push( ( void * ) ( entry->data_record.strings +
716 ( entry->data_record.strings_len / 2 ) ),
717 temp,
718 sizeof( entry->data_record.strings ) -
719 ( entry->data_record.strings_len / 2 ), STR_TERMINATE );
720 entry->data_record.strings_len += ( temp_len * 2 ) + 2;
721 entry->record.num_strings++;
722 } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
723 /* skip past initial ":" */
724 stop++;
725 /* now skip any other leading whitespace */
726 while ( isspace( stop[0] ) ) {
727 stop++;
729 entry->data_record.user_data_len = strlen( stop );
730 memset( entry->data_record.user_data, 0,
731 sizeof( entry->data_record.user_data ) );
732 if ( entry->data_record.user_data_len > 0 ) {
733 /* copy no more than the first 1024 bytes */
734 if ( entry->data_record.user_data_len >
735 sizeof( entry->data_record.user_data ) )
736 entry->data_record.user_data_len =
737 sizeof( entry->data_record.
738 user_data );
739 memcpy( entry->data_record.user_data, stop,
740 entry->data_record.user_data_len );
742 } else {
743 /* some other eventlog entry -- not implemented, so dropping on the floor */
744 DEBUG( 10, ( "Unknown entry [%s]. Ignoring.\n", line ) );
745 /* For now return true so that we can keep on parsing this mess. Eventually
746 we will return False here. */
747 return True;
749 return True;