source: branches/samba-3.3.x/source/rpc_server/srv_eventlog_nt.c@ 614

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

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

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