source: branches/samba-3.2.x/source/rpc_server/srv_eventlog_nt.c@ 228

Last change on this file since 228 was 228, checked in by Herwig Bauernfeind, 17 years ago

Update 3.2 branch to 3.2.6

File size: 27.4 KB
Line 
1/*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Marcin Krzysztof Porwit 2005,
5 * Copyright (C) Brian Moran 2005,
6 * Copyright (C) Gerald (Jerry) Carter 2005.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "includes.h"
23
24#undef DBGC_CLASS
25#define DBGC_CLASS DBGC_RPC_SRV
26
27typedef struct {
28 char *logname;
29 ELOG_TDB *etdb;
30 uint32 current_record;
31 uint32 num_records;
32 uint32 oldest_entry;
33 uint32 flags;
34 uint32 access_granted;
35} EVENTLOG_INFO;
36
37/********************************************************************
38 ********************************************************************/
39
40static void free_eventlog_info( void *ptr )
41{
42 EVENTLOG_INFO *elog = (EVENTLOG_INFO *)ptr;
43
44 if ( elog->etdb )
45 elog_close_tdb( elog->etdb, False );
46
47 TALLOC_FREE( elog );
48}
49
50/********************************************************************
51 ********************************************************************/
52
53static EVENTLOG_INFO *find_eventlog_info_by_hnd( pipes_struct * p,
54 POLICY_HND * handle )
55{
56 EVENTLOG_INFO *info;
57
58 if ( !find_policy_by_hnd( p, handle, (void **)(void *)&info ) ) {
59 DEBUG( 2,
60 ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) );
61 return NULL;
62 }
63
64 return info;
65}
66
67/********************************************************************
68********************************************************************/
69
70static bool elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token )
71{
72 char *tdbname = elog_tdbname(talloc_tos(), info->logname );
73 SEC_DESC *sec_desc;
74 bool ret;
75 NTSTATUS ntstatus;
76
77 if ( !tdbname )
78 return False;
79
80 /* get the security descriptor for the file */
81
82 sec_desc = get_nt_acl_no_snum( info, tdbname );
83 TALLOC_FREE( tdbname );
84
85 if ( !sec_desc ) {
86 DEBUG(5,("elog_check_access: Unable to get NT ACL for %s\n",
87 tdbname));
88 return False;
89 }
90
91 /* root free pass */
92
93 if ( geteuid() == sec_initial_uid() ) {
94 DEBUG(5,("elog_check_access: using root's token\n"));
95 token = get_root_nt_token();
96 }
97
98 /* run the check, try for the max allowed */
99
100 ret = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS,
101 &info->access_granted, &ntstatus );
102
103 if ( sec_desc )
104 TALLOC_FREE( sec_desc );
105
106 if ( !ret ) {
107 DEBUG(8,("elog_check_access: se_access_check() return %s\n",
108 nt_errstr( ntstatus)));
109 return False;
110 }
111
112 /* we have to have READ permission for a successful open */
113
114 return ( info->access_granted & SA_RIGHT_FILE_READ_DATA );
115}
116
117/********************************************************************
118 ********************************************************************/
119
120static bool elog_validate_logname( const char *name )
121{
122 int i;
123 const char **elogs = lp_eventlog_list();
124
125 if (!elogs) {
126 return False;
127 }
128
129 for ( i=0; elogs[i]; i++ ) {
130 if ( strequal( name, elogs[i] ) )
131 return True;
132 }
133
134 return False;
135}
136
137/********************************************************************
138********************************************************************/
139
140static bool get_num_records_hook( EVENTLOG_INFO * info )
141{
142 int next_record;
143 int oldest_record;
144
145 if ( !info->etdb ) {
146 DEBUG( 10, ( "No open tdb for %s\n", info->logname ) );
147 return False;
148 }
149
150 /* lock the tdb since we have to get 2 records */
151
152 tdb_lock_bystring_with_timeout( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD, 1 );
153 next_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
154 oldest_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_OLDEST_ENTRY);
155 tdb_unlock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
156
157 DEBUG( 8,
158 ( "Oldest Record %d; Next Record %d\n", oldest_record,
159 next_record ) );
160
161 info->num_records = ( next_record - oldest_record );
162 info->oldest_entry = oldest_record;
163
164 return True;
165}
166
167/********************************************************************
168 ********************************************************************/
169
170static bool get_oldest_entry_hook( EVENTLOG_INFO * info )
171{
172 /* it's the same thing */
173 return get_num_records_hook( info );
174}
175
176/********************************************************************
177 ********************************************************************/
178
179static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hnd )
180{
181 EVENTLOG_INFO *elog;
182
183 /* first thing is to validate the eventlog name */
184
185 if ( !elog_validate_logname( logname ) )
186 return NT_STATUS_OBJECT_PATH_INVALID;
187
188 if ( !(elog = TALLOC_ZERO_P( NULL, EVENTLOG_INFO )) )
189 return NT_STATUS_NO_MEMORY;
190
191 elog->logname = talloc_strdup( elog, logname );
192
193 /* Open the tdb first (so that we can create any new tdbs if necessary).
194 We have to do this as root and then use an internal access check
195 on the file permissions since you can only have a tdb open once
196 in a single process */
197
198 become_root();
199 elog->etdb = elog_open_tdb( elog->logname, False );
200 unbecome_root();
201
202 if ( !elog->etdb ) {
203 /* according to MSDN, if the logfile cannot be found, we should
204 default to the "Application" log */
205
206 if ( !strequal( logname, ELOG_APPL ) ) {
207
208 TALLOC_FREE( elog->logname );
209
210 elog->logname = talloc_strdup( elog, ELOG_APPL );
211
212 /* do the access check */
213 if ( !elog_check_access( elog, p->pipe_user.nt_user_token ) ) {
214 TALLOC_FREE( elog );
215 return NT_STATUS_ACCESS_DENIED;
216 }
217
218 become_root();
219 elog->etdb = elog_open_tdb( elog->logname, False );
220 unbecome_root();
221 }
222
223 if ( !elog->etdb ) {
224 TALLOC_FREE( elog );
225 return NT_STATUS_ACCESS_DENIED; /* ??? */
226 }
227 }
228
229 /* now do the access check. Close the tdb if we fail here */
230
231 if ( !elog_check_access( elog, p->pipe_user.nt_user_token ) ) {
232 elog_close_tdb( elog->etdb, False );
233 TALLOC_FREE( elog );
234 return NT_STATUS_ACCESS_DENIED;
235 }
236
237 /* create the policy handle */
238
239 if ( !create_policy_hnd
240 ( p, hnd, free_eventlog_info, ( void * ) elog ) ) {
241 free_eventlog_info( elog );
242 return NT_STATUS_NO_MEMORY;
243 }
244
245 /* set the initial current_record pointer */
246
247 if ( !get_oldest_entry_hook( elog ) ) {
248 DEBUG(3,("elog_open: Successfully opened eventlog but can't "
249 "get any information on internal records!\n"));
250 }
251
252 elog->current_record = elog->oldest_entry;
253
254 return NT_STATUS_OK;
255}
256
257/********************************************************************
258 ********************************************************************/
259
260static NTSTATUS elog_close( pipes_struct *p, POLICY_HND *hnd )
261{
262 if ( !( close_policy_hnd( p, hnd ) ) ) {
263 return NT_STATUS_INVALID_HANDLE;
264 }
265
266 return NT_STATUS_OK;
267}
268
269/*******************************************************************
270 *******************************************************************/
271
272static int elog_size( EVENTLOG_INFO *info )
273{
274 if ( !info || !info->etdb ) {
275 DEBUG(0,("elog_size: Invalid info* structure!\n"));
276 return 0;
277 }
278
279 return elog_tdb_size( ELOG_TDB_CTX(info->etdb), NULL, NULL );
280}
281
282/********************************************************************
283 For the given tdb, get the next eventlog record into the passed
284 Eventlog_entry. returns NULL if it can't get the record for some reason.
285 ********************************************************************/
286
287static Eventlog_entry *get_eventlog_record(prs_struct *ps,
288 TDB_CONTEXT *tdb,
289 int recno)
290{
291 Eventlog_entry *ee = NULL;
292 TDB_DATA ret, key;
293
294 int32_t srecno;
295 int32_t reclen;
296 int len;
297
298 char *wpsource = NULL;
299 char *wpcomputer = NULL;
300 char *wpsid = NULL;
301 char *wpstrs = NULL;
302 char *puserdata = NULL;
303
304 key.dsize = sizeof(int32_t);
305
306 srecno = recno;
307 key.dptr = (unsigned char *)&srecno;
308
309 ret = tdb_fetch( tdb, key );
310
311 if ( ret.dsize == 0 ) {
312 DEBUG( 8,
313 ( "Can't find a record for the key, record %d\n",
314 recno ) );
315 return NULL;
316 }
317
318 len = tdb_unpack( ret.dptr, ret.dsize, "d", &reclen );
319
320 DEBUG( 10, ( "Unpacking record %d, size is %d\n", srecno, len ) );
321
322 if ( !len )
323 return NULL;
324
325 ee = TALLOC_ARRAY(ps->mem_ctx, Eventlog_entry, 1);
326 if (!ee) {
327 return NULL;
328 }
329 ZERO_STRUCTP(ee);
330
331 len = tdb_unpack( ret.dptr, ret.dsize, "ddddddwwwwddddddBBdBBBd",
332 &ee->record.length, &ee->record.reserved1,
333 &ee->record.record_number,
334 &ee->record.time_generated,
335 &ee->record.time_written, &ee->record.event_id,
336 &ee->record.event_type, &ee->record.num_strings,
337 &ee->record.event_category, &ee->record.reserved2,
338 &ee->record.closing_record_number,
339 &ee->record.string_offset,
340 &ee->record.user_sid_length,
341 &ee->record.user_sid_offset,
342 &ee->record.data_length, &ee->record.data_offset,
343 &ee->data_record.source_name_len, &wpsource,
344 &ee->data_record.computer_name_len, &wpcomputer,
345 &ee->data_record.sid_padding,
346 &ee->record.user_sid_length, &wpsid,
347 &ee->data_record.strings_len, &wpstrs,
348 &ee->data_record.user_data_len, &puserdata,
349 &ee->data_record.data_padding );
350 DEBUG( 10,
351 ( "Read record %d, len in tdb was %d\n",
352 ee->record.record_number, len ) );
353
354 /* have to do the following because the tdb_unpack allocs a buff, stuffs a pointer to the buff
355 into it's 2nd argment for 'B' */
356
357 if (wpcomputer) {
358 ee->data_record.computer_name = (smb_ucs2_t *)TALLOC_MEMDUP(
359 ee, wpcomputer, ee->data_record.computer_name_len);
360 if (!ee->data_record.computer_name) {
361 TALLOC_FREE(ee);
362 goto out;
363 }
364 }
365 if (wpsource) {
366 ee->data_record.source_name = (smb_ucs2_t *)TALLOC_MEMDUP(
367 ee, wpsource, ee->data_record.source_name_len);
368 if (!ee->data_record.source_name) {
369 TALLOC_FREE(ee);
370 goto out;
371 }
372 }
373
374 if (wpsid) {
375 ee->data_record.sid = (smb_ucs2_t *)TALLOC_MEMDUP(
376 ee, wpsid, ee->record.user_sid_length);
377 if (!ee->data_record.sid) {
378 TALLOC_FREE(ee);
379 goto out;
380 }
381 }
382 if (wpstrs) {
383 ee->data_record.strings = (smb_ucs2_t *)TALLOC_MEMDUP(
384 ee, wpstrs, ee->data_record.strings_len);
385 if (!ee->data_record.strings) {
386 TALLOC_FREE(ee);
387 goto out;
388 }
389 }
390
391 if (puserdata) {
392 ee->data_record.user_data = (char *)TALLOC_MEMDUP(
393 ee, puserdata, ee->data_record.user_data_len);
394 if (!ee->data_record.user_data) {
395 TALLOC_FREE(ee);
396 goto out;
397 }
398 }
399
400 out:
401
402 SAFE_FREE(wpcomputer);
403 SAFE_FREE(wpsource);
404 SAFE_FREE(wpsid);
405 SAFE_FREE(wpstrs);
406 SAFE_FREE(puserdata);
407
408 DEBUG( 10, ( "get_eventlog_record: read back %d\n", len ) );
409 DEBUG( 10,
410 ( "get_eventlog_record: computer_name %d is ",
411 ee->data_record.computer_name_len ) );
412 SAFE_FREE(ret.dptr);
413 return ee;
414}
415
416/********************************************************************
417 note that this can only be called AFTER the table is constructed,
418 since it uses the table to find the tdb handle
419 ********************************************************************/
420
421static bool sync_eventlog_params( EVENTLOG_INFO *info )
422{
423 char *path = NULL;
424 uint32 uiMaxSize;
425 uint32 uiRetention;
426 struct registry_key *key;
427 struct registry_value *value;
428 WERROR wresult;
429 char *elogname = info->logname;
430 TALLOC_CTX *ctx = talloc_stackframe();
431 bool ret = false;
432
433 DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
434
435 if ( !info->etdb ) {
436 DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) );
437 goto done;
438 }
439 /* set resonable defaults. 512Kb on size and 1 week on time */
440
441 uiMaxSize = 0x80000;
442 uiRetention = 604800;
443
444 /* the general idea is to internally open the registry
445 key and retrieve the values. That way we can continue
446 to use the same fetch/store api that we use in
447 srv_reg_nt.c */
448
449 path = talloc_asprintf(ctx, "%s/%s", KEY_EVENTLOG, elogname );
450 if (!path) {
451 goto done;
452 }
453
454 wresult = reg_open_path(ctx, path, REG_KEY_READ, get_root_nt_token(),
455 &key);
456
457 if ( !W_ERROR_IS_OK( wresult ) ) {
458 DEBUG( 4,
459 ( "sync_eventlog_params: Failed to open key [%s] (%s)\n",
460 path, dos_errstr( wresult ) ) );
461 goto done;
462 }
463
464 wresult = reg_queryvalue(key, key, "Retention", &value);
465 if (!W_ERROR_IS_OK(wresult)) {
466 DEBUG(4, ("Failed to query value \"Retention\": %s\n",
467 dos_errstr(wresult)));
468 goto done;
469 }
470 uiRetention = value->v.dword;
471
472 wresult = reg_queryvalue(key, key, "MaxSize", &value);
473 if (!W_ERROR_IS_OK(wresult)) {
474 DEBUG(4, ("Failed to query value \"MaxSize\": %s\n",
475 dos_errstr(wresult)));
476 goto done;
477 }
478 uiMaxSize = value->v.dword;
479
480 tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize );
481 tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention );
482
483 ret = true;
484
485done:
486 TALLOC_FREE(ctx);
487 return ret;
488}
489
490/********************************************************************
491 ********************************************************************/
492
493static Eventlog_entry *read_package_entry( prs_struct * ps,
494 Eventlog_entry * entry )
495{
496 uint8 *offset;
497 Eventlog_entry *ee_new = NULL;
498
499 ee_new = PRS_ALLOC_MEM( ps, Eventlog_entry, 1 );
500 if ( ee_new == NULL ) {
501 return NULL;
502 }
503
504 entry->data_record.sid_padding =
505 ( ( 4 -
506 ( ( entry->data_record.source_name_len +
507 entry->data_record.computer_name_len ) % 4 ) ) % 4 );
508 entry->data_record.data_padding =
509 ( 4 -
510 ( ( entry->data_record.strings_len +
511 entry->data_record.user_data_len ) % 4 ) ) % 4;
512 entry->record.length = sizeof( Eventlog_record );
513 entry->record.length += entry->data_record.source_name_len;
514 entry->record.length += entry->data_record.computer_name_len;
515 if ( entry->record.user_sid_length == 0 ) {
516 /* Should not pad to a DWORD boundary for writing out the sid if there is
517 no SID, so just propagate the padding to pad the data */
518 entry->data_record.data_padding +=
519 entry->data_record.sid_padding;
520 entry->data_record.sid_padding = 0;
521 }
522 DEBUG( 10,
523 ( "sid_padding is [%d].\n", entry->data_record.sid_padding ) );
524 DEBUG( 10,
525 ( "data_padding is [%d].\n",
526 entry->data_record.data_padding ) );
527
528 entry->record.length += entry->data_record.sid_padding;
529 entry->record.length += entry->record.user_sid_length;
530 entry->record.length += entry->data_record.strings_len;
531 entry->record.length += entry->data_record.user_data_len;
532 entry->record.length += entry->data_record.data_padding;
533 /* need another copy of length at the end of the data */
534 entry->record.length += sizeof( entry->record.length );
535 DEBUG( 10,
536 ( "entry->record.length is [%d].\n", entry->record.length ) );
537 entry->data =
538 PRS_ALLOC_MEM( ps, uint8,
539 entry->record.length -
540 sizeof( Eventlog_record ) -
541 sizeof( entry->record.length ) );
542 if ( entry->data == NULL ) {
543 return NULL;
544 }
545 offset = entry->data;
546 memcpy( offset, &( entry->data_record.source_name ),
547 entry->data_record.source_name_len );
548 offset += entry->data_record.source_name_len;
549 memcpy( offset, &( entry->data_record.computer_name ),
550 entry->data_record.computer_name_len );
551 offset += entry->data_record.computer_name_len;
552 /* SID needs to be DWORD-aligned */
553 offset += entry->data_record.sid_padding;
554 entry->record.user_sid_offset =
555 sizeof( Eventlog_record ) + ( offset - entry->data );
556 memcpy( offset, &( entry->data_record.sid ),
557 entry->record.user_sid_length );
558 offset += entry->record.user_sid_length;
559 /* Now do the strings */
560 entry->record.string_offset =
561 sizeof( Eventlog_record ) + ( offset - entry->data );
562 memcpy( offset, &( entry->data_record.strings ),
563 entry->data_record.strings_len );
564 offset += entry->data_record.strings_len;
565 /* Now do the data */
566 entry->record.data_length = entry->data_record.user_data_len;
567 entry->record.data_offset =
568 sizeof( Eventlog_record ) + ( offset - entry->data );
569 memcpy( offset, &( entry->data_record.user_data ),
570 entry->data_record.user_data_len );
571 offset += entry->data_record.user_data_len;
572
573 memcpy( &( ee_new->record ), &entry->record,
574 sizeof( Eventlog_record ) );
575 memcpy( &( ee_new->data_record ), &entry->data_record,
576 sizeof( Eventlog_data_record ) );
577 ee_new->data = entry->data;
578
579 return ee_new;
580}
581
582/********************************************************************
583 ********************************************************************/
584
585static bool add_record_to_resp( EVENTLOG_R_READ_EVENTLOG * r_u,
586 Eventlog_entry * ee_new )
587{
588 Eventlog_entry *insert_point;
589
590 insert_point = r_u->entry;
591
592 if ( NULL == insert_point ) {
593 r_u->entry = ee_new;
594 ee_new->next = NULL;
595 } else {
596 while ( ( NULL != insert_point->next ) ) {
597 insert_point = insert_point->next;
598 }
599 ee_new->next = NULL;
600 insert_point->next = ee_new;
601 }
602 r_u->num_records++;
603 r_u->num_bytes_in_resp += ee_new->record.length;
604
605 return True;
606}
607
608/********************************************************************
609 _eventlog_OpenEventLogW
610 ********************************************************************/
611
612NTSTATUS _eventlog_OpenEventLogW(pipes_struct *p,
613 struct eventlog_OpenEventLogW *r)
614{
615 const char *servername = "";
616 const char *logname = "";
617 EVENTLOG_INFO *info;
618 NTSTATUS result;
619
620 if (r->in.servername->string) {
621 servername = r->in.servername->string;
622 }
623
624 if (r->in.logname->string) {
625 logname = r->in.logname->string;
626 }
627
628 DEBUG( 10,("_eventlog_open_eventlog: Server [%s], Log [%s]\n",
629 servername, logname ));
630
631 /* according to MSDN, if the logfile cannot be found, we should
632 default to the "Application" log */
633
634 if ( !NT_STATUS_IS_OK( result = elog_open( p, logname, r->out.handle )) )
635 return result;
636
637 if ( !(info = find_eventlog_info_by_hnd( p, r->out.handle )) ) {
638 DEBUG(0,("_eventlog_open_eventlog: eventlog (%s) opened but unable to find handle!\n",
639 logname ));
640 elog_close( p, r->out.handle );
641 return NT_STATUS_INVALID_HANDLE;
642 }
643
644 DEBUG(10,("_eventlog_open_eventlog: Size [%d]\n", elog_size( info )));
645
646 sync_eventlog_params( info );
647 prune_eventlog( ELOG_TDB_CTX(info->etdb) );
648
649 return NT_STATUS_OK;
650}
651
652/********************************************************************
653 _eventlog_ClearEventLogW
654 This call still needs some work
655 ********************************************************************/
656/** The windows client seems to be doing something funny with the file name
657 A call like
658 ClearEventLog(handle, "backup_file")
659 on the client side will result in the backup file name looking like this on the
660 server side:
661 \??\${CWD of client}\backup_file
662 If an absolute path gets specified, such as
663 ClearEventLog(handle, "C:\\temp\\backup_file")
664 then it is still mangled by the client into this:
665 \??\C:\temp\backup_file
666 when it is on the wire.
667 I'm not sure where the \?? is coming from, or why the ${CWD} of the client process
668 would be added in given that the backup file gets written on the server side. */
669
670NTSTATUS _eventlog_ClearEventLogW(pipes_struct *p,
671 struct eventlog_ClearEventLogW *r)
672{
673 EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
674 const char *backup_file_name = NULL;
675
676 if ( !info )
677 return NT_STATUS_INVALID_HANDLE;
678
679 if (r->in.backupfile && r->in.backupfile->string) {
680
681 backup_file_name = r->in.backupfile->string;
682
683 DEBUG(8,( "_eventlog_clear_eventlog: Using [%s] as the backup "
684 "file name for log [%s].",
685 backup_file_name, info->logname ) );
686 }
687
688 /* check for WRITE access to the file */
689
690 if ( !(info->access_granted&SA_RIGHT_FILE_WRITE_DATA) )
691 return NT_STATUS_ACCESS_DENIED;
692
693 /* Force a close and reopen */
694
695 elog_close_tdb( info->etdb, True );
696 become_root();
697 info->etdb = elog_open_tdb( info->logname, True );
698 unbecome_root();
699
700 if ( !info->etdb )
701 return NT_STATUS_ACCESS_DENIED;
702
703 return NT_STATUS_OK;
704}
705
706/********************************************************************
707 ********************************************************************/
708
709NTSTATUS _eventlog_CloseEventLog( pipes_struct * p, struct eventlog_CloseEventLog *r )
710{
711 return elog_close( p, r->in.handle );
712}
713
714/********************************************************************
715 ********************************************************************/
716
717NTSTATUS _eventlog_read_eventlog( pipes_struct * p,
718 EVENTLOG_Q_READ_EVENTLOG * q_u,
719 EVENTLOG_R_READ_EVENTLOG * r_u )
720{
721 EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle );
722 Eventlog_entry *entry = NULL, *ee_new = NULL;
723 uint32 num_records_read = 0;
724 prs_struct *ps;
725 int bytes_left, record_number;
726 uint32 elog_read_type, elog_read_dir;
727
728 if (info == NULL) {
729 return NT_STATUS_INVALID_HANDLE;
730 }
731
732 info->flags = q_u->flags;
733 ps = &p->out_data.rdata;
734
735 bytes_left = q_u->max_read_size;
736
737 if ( !info->etdb )
738 return NT_STATUS_ACCESS_DENIED;
739
740 /* check for valid flags. Can't use the sequential and seek flags together */
741
742 elog_read_type = q_u->flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ);
743 elog_read_dir = q_u->flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ);
744
745 if ( elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ)
746 || elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ) )
747 {
748 DEBUG(3,("_eventlog_read_eventlog: Invalid flags [0x%x] for ReadEventLog\n", q_u->flags));
749 return NT_STATUS_INVALID_PARAMETER;
750 }
751
752 /* a sequential read should ignore the offset */
753
754 if ( elog_read_type & EVENTLOG_SEQUENTIAL_READ )
755 record_number = info->current_record;
756 else
757 record_number = q_u->offset;
758
759 while ( bytes_left > 0 ) {
760
761 /* assume that when the record fetch fails, that we are done */
762
763 entry = get_eventlog_record (ps, ELOG_TDB_CTX(info->etdb), record_number);
764 if (!entry) {
765 break;
766 }
767
768 DEBUG( 8, ( "Retrieved record %d\n", record_number ) );
769
770 /* Now see if there is enough room to add */
771
772 if ( !(ee_new = read_package_entry( ps, entry )) )
773 return NT_STATUS_NO_MEMORY;
774
775 if ( r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size ) {
776 r_u->bytes_in_next_record = ee_new->record.length;
777
778 /* response would be too big to fit in client-size buffer */
779
780 bytes_left = 0;
781 break;
782 }
783
784 add_record_to_resp( r_u, ee_new );
785 bytes_left -= ee_new->record.length;
786 TALLOC_FREE(entry);
787 num_records_read = r_u->num_records - num_records_read;
788
789 DEBUG( 10, ( "_eventlog_read_eventlog: read [%d] records for a total "
790 "of [%d] records using [%d] bytes out of a max of [%d].\n",
791 num_records_read, r_u->num_records,
792 r_u->num_bytes_in_resp,
793 q_u->max_read_size ) );
794
795 if ( info->flags & EVENTLOG_FORWARDS_READ )
796 record_number++;
797 else
798 record_number--;
799
800 /* update the eventlog record pointer */
801
802 info->current_record = record_number;
803 }
804
805 /* crazy by WinXP uses NT_STATUS_BUFFER_TOO_SMALL to
806 say when there are no more records */
807
808 return (num_records_read ? NT_STATUS_OK : NT_STATUS_BUFFER_TOO_SMALL);
809}
810
811/********************************************************************
812 _eventlog_GetOldestRecord
813 ********************************************************************/
814
815NTSTATUS _eventlog_GetOldestRecord(pipes_struct *p,
816 struct eventlog_GetOldestRecord *r)
817{
818 EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
819
820 if (info == NULL) {
821 return NT_STATUS_INVALID_HANDLE;
822 }
823
824 if ( !( get_oldest_entry_hook( info ) ) )
825 return NT_STATUS_ACCESS_DENIED;
826
827 *r->out.oldest_entry = info->oldest_entry;
828
829 return NT_STATUS_OK;
830}
831
832/********************************************************************
833_eventlog_GetNumRecords
834 ********************************************************************/
835
836NTSTATUS _eventlog_GetNumRecords(pipes_struct *p,
837 struct eventlog_GetNumRecords *r)
838{
839 EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
840
841 if (info == NULL) {
842 return NT_STATUS_INVALID_HANDLE;
843 }
844
845 if ( !( get_num_records_hook( info ) ) )
846 return NT_STATUS_ACCESS_DENIED;
847
848 *r->out.number = info->num_records;
849
850 return NT_STATUS_OK;
851}
852
853NTSTATUS _eventlog_BackupEventLogW(pipes_struct *p, struct eventlog_BackupEventLogW *r)
854{
855 p->rng_fault_state = True;
856 return NT_STATUS_NOT_IMPLEMENTED;
857}
858
859NTSTATUS _eventlog_DeregisterEventSource(pipes_struct *p, struct eventlog_DeregisterEventSource *r)
860{
861 p->rng_fault_state = True;
862 return NT_STATUS_NOT_IMPLEMENTED;
863}
864
865NTSTATUS _eventlog_ChangeNotify(pipes_struct *p, struct eventlog_ChangeNotify *r)
866{
867 p->rng_fault_state = True;
868 return NT_STATUS_NOT_IMPLEMENTED;
869}
870
871NTSTATUS _eventlog_RegisterEventSourceW(pipes_struct *p, struct eventlog_RegisterEventSourceW *r)
872{
873 p->rng_fault_state = True;
874 return NT_STATUS_NOT_IMPLEMENTED;
875}
876
877NTSTATUS _eventlog_OpenBackupEventLogW(pipes_struct *p, struct eventlog_OpenBackupEventLogW *r)
878{
879 p->rng_fault_state = True;
880 return NT_STATUS_NOT_IMPLEMENTED;
881}
882
883NTSTATUS _eventlog_ReadEventLogW(pipes_struct *p, struct eventlog_ReadEventLogW *r)
884{
885 p->rng_fault_state = True;
886 return NT_STATUS_NOT_IMPLEMENTED;
887}
888
889NTSTATUS _eventlog_ReportEventW(pipes_struct *p, struct eventlog_ReportEventW *r)
890{
891 p->rng_fault_state = True;
892 return NT_STATUS_NOT_IMPLEMENTED;
893}
894
895NTSTATUS _eventlog_ClearEventLogA(pipes_struct *p, struct eventlog_ClearEventLogA *r)
896{
897 p->rng_fault_state = True;
898 return NT_STATUS_NOT_IMPLEMENTED;
899}
900
901NTSTATUS _eventlog_BackupEventLogA(pipes_struct *p, struct eventlog_BackupEventLogA *r)
902{
903 p->rng_fault_state = True;
904 return NT_STATUS_NOT_IMPLEMENTED;
905}
906
907NTSTATUS _eventlog_OpenEventLogA(pipes_struct *p, struct eventlog_OpenEventLogA *r)
908{
909 p->rng_fault_state = True;
910 return NT_STATUS_NOT_IMPLEMENTED;
911}
912
913NTSTATUS _eventlog_RegisterEventSourceA(pipes_struct *p, struct eventlog_RegisterEventSourceA *r)
914{
915 p->rng_fault_state = True;
916 return NT_STATUS_NOT_IMPLEMENTED;
917}
918
919NTSTATUS _eventlog_OpenBackupEventLogA(pipes_struct *p, struct eventlog_OpenBackupEventLogA *r)
920{
921 p->rng_fault_state = True;
922 return NT_STATUS_NOT_IMPLEMENTED;
923}
924
925NTSTATUS _eventlog_ReadEventLogA(pipes_struct *p, struct eventlog_ReadEventLogA *r)
926{
927 p->rng_fault_state = True;
928 return NT_STATUS_NOT_IMPLEMENTED;
929}
930
931NTSTATUS _eventlog_ReportEventA(pipes_struct *p, struct eventlog_ReportEventA *r)
932{
933 p->rng_fault_state = True;
934 return NT_STATUS_NOT_IMPLEMENTED;
935}
936
937NTSTATUS _eventlog_RegisterClusterSvc(pipes_struct *p, struct eventlog_RegisterClusterSvc *r)
938{
939 p->rng_fault_state = True;
940 return NT_STATUS_NOT_IMPLEMENTED;
941}
942
943NTSTATUS _eventlog_DeregisterClusterSvc(pipes_struct *p, struct eventlog_DeregisterClusterSvc *r)
944{
945 p->rng_fault_state = True;
946 return NT_STATUS_NOT_IMPLEMENTED;
947}
948
949NTSTATUS _eventlog_WriteClusterEvents(pipes_struct *p, struct eventlog_WriteClusterEvents *r)
950{
951 p->rng_fault_state = True;
952 return NT_STATUS_NOT_IMPLEMENTED;
953}
954
955NTSTATUS _eventlog_GetLogIntormation(pipes_struct *p, struct eventlog_GetLogIntormation *r)
956{
957 p->rng_fault_state = True;
958 return NT_STATUS_NOT_IMPLEMENTED;
959}
960
961NTSTATUS _eventlog_FlushEventLog(pipes_struct *p, struct eventlog_FlushEventLog *r)
962{
963 p->rng_fault_state = True;
964 return NT_STATUS_NOT_IMPLEMENTED;
965}
966
Note: See TracBrowser for help on using the repository browser.