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
* Copyright (C) Guenther Deschner 2009.
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 3 of the License, or
12
* (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, see <http://www.gnu.org/licenses/>.
24
#include "../librpc/gen_ndr/srv_eventlog.h"
27
#define DBGC_CLASS DBGC_RPC_SRV
32
uint32 current_record;
36
uint32 access_granted;
39
/********************************************************************
40
********************************************************************/
42
static int eventlog_info_destructor(EVENTLOG_INFO *elog)
45
elog_close_tdb(elog->etdb, false);
50
/********************************************************************
51
********************************************************************/
53
static EVENTLOG_INFO *find_eventlog_info_by_hnd( pipes_struct * p,
54
struct policy_handle * handle )
58
if ( !find_policy_by_hnd( p, handle, (void **)(void *)&info ) ) {
60
( "find_eventlog_info_by_hnd: eventlog not found.\n" ) );
67
/********************************************************************
68
********************************************************************/
70
static bool elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token )
72
char *tdbname = elog_tdbname(talloc_tos(), info->logname );
79
/* get the security descriptor for the file */
81
sec_desc = get_nt_acl_no_snum( info, tdbname );
82
TALLOC_FREE( tdbname );
85
DEBUG(5,("elog_check_access: Unable to get NT ACL for %s\n",
92
if ( geteuid() == sec_initial_uid() ) {
93
DEBUG(5,("elog_check_access: using root's token\n"));
94
token = get_root_nt_token();
97
/* run the check, try for the max allowed */
99
status = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS,
100
&info->access_granted);
103
TALLOC_FREE( sec_desc );
105
if (!NT_STATUS_IS_OK(status)) {
106
DEBUG(8,("elog_check_access: se_access_check() return %s\n",
111
/* we have to have READ permission for a successful open */
113
return ( info->access_granted & SA_RIGHT_FILE_READ_DATA );
116
/********************************************************************
117
********************************************************************/
119
static bool elog_validate_logname( const char *name )
122
const char **elogs = lp_eventlog_list();
128
for ( i=0; elogs[i]; i++ ) {
129
if ( strequal( name, elogs[i] ) )
136
/********************************************************************
137
********************************************************************/
139
static bool get_num_records_hook( EVENTLOG_INFO * info )
145
DEBUG( 10, ( "No open tdb for %s\n", info->logname ) );
149
/* lock the tdb since we have to get 2 records */
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);
157
( "Oldest Record %d; Next Record %d\n", oldest_record,
160
info->num_records = ( next_record - oldest_record );
161
info->oldest_entry = oldest_record;
166
/********************************************************************
167
********************************************************************/
169
static bool get_oldest_entry_hook( EVENTLOG_INFO * info )
171
/* it's the same thing */
172
return get_num_records_hook( info );
175
/********************************************************************
176
********************************************************************/
178
static NTSTATUS elog_open( pipes_struct * p, const char *logname, struct policy_handle *hnd )
182
/* first thing is to validate the eventlog name */
184
if ( !elog_validate_logname( logname ) )
185
return NT_STATUS_OBJECT_PATH_INVALID;
187
if ( !(elog = TALLOC_ZERO_P( NULL, EVENTLOG_INFO )) )
188
return NT_STATUS_NO_MEMORY;
189
talloc_set_destructor(elog, eventlog_info_destructor);
191
elog->logname = talloc_strdup( elog, logname );
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 */
199
elog->etdb = elog_open_tdb( elog->logname, False, False );
203
/* according to MSDN, if the logfile cannot be found, we should
204
default to the "Application" log */
206
if ( !strequal( logname, ELOG_APPL ) ) {
208
TALLOC_FREE( elog->logname );
210
elog->logname = talloc_strdup( elog, ELOG_APPL );
212
/* do the access check */
213
if ( !elog_check_access( elog, p->server_info->ptok ) ) {
215
return NT_STATUS_ACCESS_DENIED;
219
elog->etdb = elog_open_tdb( elog->logname, False, False );
225
return NT_STATUS_ACCESS_DENIED; /* ??? */
229
/* now do the access check. Close the tdb if we fail here */
231
if ( !elog_check_access( elog, p->server_info->ptok ) ) {
233
return NT_STATUS_ACCESS_DENIED;
236
/* create the policy handle */
238
if ( !create_policy_hnd( p, hnd, elog ) ) {
240
return NT_STATUS_NO_MEMORY;
243
/* set the initial current_record pointer */
245
if ( !get_oldest_entry_hook( elog ) ) {
246
DEBUG(3,("elog_open: Successfully opened eventlog but can't "
247
"get any information on internal records!\n"));
250
elog->current_record = elog->oldest_entry;
255
/********************************************************************
256
********************************************************************/
258
static NTSTATUS elog_close( pipes_struct *p, struct policy_handle *hnd )
260
if ( !( close_policy_hnd( p, hnd ) ) ) {
261
return NT_STATUS_INVALID_HANDLE;
267
/*******************************************************************
268
*******************************************************************/
270
static int elog_size( EVENTLOG_INFO *info )
272
if ( !info || !info->etdb ) {
273
DEBUG(0,("elog_size: Invalid info* structure!\n"));
277
return elog_tdb_size( ELOG_TDB_CTX(info->etdb), NULL, NULL );
280
/********************************************************************
281
note that this can only be called AFTER the table is constructed,
282
since it uses the table to find the tdb handle
283
********************************************************************/
285
static bool sync_eventlog_params( EVENTLOG_INFO *info )
290
struct registry_key *key;
291
struct registry_value *value;
293
char *elogname = info->logname;
294
TALLOC_CTX *ctx = talloc_stackframe();
297
DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
300
DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) );
303
/* set resonable defaults. 512Kb on size and 1 week on time */
306
uiRetention = 604800;
308
/* the general idea is to internally open the registry
309
key and retrieve the values. That way we can continue
310
to use the same fetch/store api that we use in
313
path = talloc_asprintf(ctx, "%s/%s", KEY_EVENTLOG, elogname );
318
wresult = reg_open_path(ctx, path, REG_KEY_READ, get_root_nt_token(),
321
if ( !W_ERROR_IS_OK( wresult ) ) {
323
( "sync_eventlog_params: Failed to open key [%s] (%s)\n",
324
path, win_errstr( wresult ) ) );
328
wresult = reg_queryvalue(key, key, "Retention", &value);
329
if (!W_ERROR_IS_OK(wresult)) {
330
DEBUG(4, ("Failed to query value \"Retention\": %s\n",
331
win_errstr(wresult)));
334
uiRetention = value->v.dword;
336
wresult = reg_queryvalue(key, key, "MaxSize", &value);
337
if (!W_ERROR_IS_OK(wresult)) {
338
DEBUG(4, ("Failed to query value \"MaxSize\": %s\n",
339
win_errstr(wresult)));
342
uiMaxSize = value->v.dword;
344
tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize );
345
tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention );
354
/********************************************************************
355
_eventlog_OpenEventLogW
356
********************************************************************/
358
NTSTATUS _eventlog_OpenEventLogW(pipes_struct *p,
359
struct eventlog_OpenEventLogW *r)
364
DEBUG( 10,("_eventlog_OpenEventLogW: Server [%s], Log [%s]\n",
365
r->in.servername->string, r->in.logname->string ));
367
/* according to MSDN, if the logfile cannot be found, we should
368
default to the "Application" log */
370
if ( !NT_STATUS_IS_OK( result = elog_open( p, r->in.logname->string, r->out.handle )) )
373
if ( !(info = find_eventlog_info_by_hnd( p, r->out.handle )) ) {
374
DEBUG(0,("_eventlog_OpenEventLogW: eventlog (%s) opened but unable to find handle!\n",
375
r->in.logname->string ));
376
elog_close( p, r->out.handle );
377
return NT_STATUS_INVALID_HANDLE;
380
DEBUG(10,("_eventlog_OpenEventLogW: Size [%d]\n", elog_size( info )));
382
sync_eventlog_params( info );
383
prune_eventlog( ELOG_TDB_CTX(info->etdb) );
388
/********************************************************************
389
_eventlog_ClearEventLogW
390
This call still needs some work
391
********************************************************************/
392
/** The windows client seems to be doing something funny with the file name
394
ClearEventLog(handle, "backup_file")
395
on the client side will result in the backup file name looking like this on the
397
\??\${CWD of client}\backup_file
398
If an absolute path gets specified, such as
399
ClearEventLog(handle, "C:\\temp\\backup_file")
400
then it is still mangled by the client into this:
401
\??\C:\temp\backup_file
402
when it is on the wire.
403
I'm not sure where the \?? is coming from, or why the ${CWD} of the client process
404
would be added in given that the backup file gets written on the server side. */
406
NTSTATUS _eventlog_ClearEventLogW(pipes_struct *p,
407
struct eventlog_ClearEventLogW *r)
409
EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
412
return NT_STATUS_INVALID_HANDLE;
414
if (r->in.backupfile && r->in.backupfile->string) {
416
DEBUG(8,( "_eventlog_ClearEventLogW: Using [%s] as the backup "
417
"file name for log [%s].",
418
r->in.backupfile->string, info->logname ) );
421
/* check for WRITE access to the file */
423
if ( !(info->access_granted&SA_RIGHT_FILE_WRITE_DATA) )
424
return NT_STATUS_ACCESS_DENIED;
426
/* Force a close and reopen */
428
elog_close_tdb( info->etdb, True );
430
info->etdb = elog_open_tdb( info->logname, True, False );
434
return NT_STATUS_ACCESS_DENIED;
439
/********************************************************************
440
_eventlog_CloseEventLog
441
********************************************************************/
443
NTSTATUS _eventlog_CloseEventLog(pipes_struct * p,
444
struct eventlog_CloseEventLog *r)
448
status = elog_close( p, r->in.handle );
449
if (!NT_STATUS_IS_OK(status)) {
453
ZERO_STRUCTP(r->out.handle);
458
/********************************************************************
459
_eventlog_ReadEventLogW
460
********************************************************************/
462
NTSTATUS _eventlog_ReadEventLogW(pipes_struct *p,
463
struct eventlog_ReadEventLogW *r)
465
EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
466
uint32_t num_records_read = 0;
467
int bytes_left, record_number;
468
uint32_t elog_read_type, elog_read_dir;
471
return NT_STATUS_INVALID_HANDLE;
474
info->flags = r->in.flags;
475
bytes_left = r->in.number_of_bytes;
478
return NT_STATUS_ACCESS_DENIED;
481
/* check for valid flags. Can't use the sequential and seek flags together */
483
elog_read_type = r->in.flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ);
484
elog_read_dir = r->in.flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ);
486
if (r->in.flags == 0 ||
487
elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) ||
488
elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ))
490
DEBUG(3,("_eventlog_ReadEventLogW: "
491
"Invalid flags [0x%08x] for ReadEventLog\n",
493
return NT_STATUS_INVALID_PARAMETER;
496
/* a sequential read should ignore the offset */
498
if (elog_read_type & EVENTLOG_SEQUENTIAL_READ) {
499
record_number = info->current_record;
501
record_number = r->in.offset;
504
if (r->in.number_of_bytes == 0) {
505
struct EVENTLOGRECORD *e;
506
e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb),
509
return NT_STATUS_END_OF_FILE;
511
*r->out.real_size = e->Length;
512
return NT_STATUS_BUFFER_TOO_SMALL;
515
while (bytes_left > 0) {
518
enum ndr_err_code ndr_err;
519
struct EVENTLOGRECORD *e;
521
e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb),
527
ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL, e,
528
(ndr_push_flags_fn_t)ndr_push_EVENTLOGRECORD);
529
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
530
return ndr_map_error2ntstatus(ndr_err);
533
if (DEBUGLEVEL >= 10) {
534
NDR_PRINT_DEBUG(EVENTLOGRECORD, e);
537
if (blob.length > r->in.number_of_bytes) {
538
*r->out.real_size = blob.length;
539
return NT_STATUS_BUFFER_TOO_SMALL;
542
if (*r->out.sent_size + blob.length > r->in.number_of_bytes) {
546
bytes_left -= blob.length;
548
if (info->flags & EVENTLOG_FORWARDS_READ) {
554
/* update the eventlog record pointer */
556
info->current_record = record_number;
558
memcpy(&r->out.data[*(r->out.sent_size)],
559
blob.data, blob.length);
560
*(r->out.sent_size) += blob.length;
565
if (r->in.offset == 0 && record_number == 0 && *r->out.sent_size == 0) {
566
return NT_STATUS_END_OF_FILE;
572
/********************************************************************
573
_eventlog_GetOldestRecord
574
********************************************************************/
576
NTSTATUS _eventlog_GetOldestRecord(pipes_struct *p,
577
struct eventlog_GetOldestRecord *r)
579
EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
582
return NT_STATUS_INVALID_HANDLE;
585
if ( !( get_oldest_entry_hook( info ) ) )
586
return NT_STATUS_ACCESS_DENIED;
588
*r->out.oldest_entry = info->oldest_entry;
593
/********************************************************************
594
_eventlog_GetNumRecords
595
********************************************************************/
597
NTSTATUS _eventlog_GetNumRecords(pipes_struct *p,
598
struct eventlog_GetNumRecords *r)
600
EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
603
return NT_STATUS_INVALID_HANDLE;
606
if ( !( get_num_records_hook( info ) ) )
607
return NT_STATUS_ACCESS_DENIED;
609
*r->out.number = info->num_records;
614
NTSTATUS _eventlog_BackupEventLogW(pipes_struct *p, struct eventlog_BackupEventLogW *r)
616
p->rng_fault_state = True;
617
return NT_STATUS_NOT_IMPLEMENTED;
620
/********************************************************************
621
_eventlog_GetLogInformation
622
********************************************************************/
624
NTSTATUS _eventlog_GetLogInformation(pipes_struct *p,
625
struct eventlog_GetLogInformation *r)
627
EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
628
struct EVENTLOG_FULL_INFORMATION f;
629
enum ndr_err_code ndr_err;
633
return NT_STATUS_INVALID_HANDLE;
636
if (r->in.level != 0) {
637
return NT_STATUS_INVALID_LEVEL;
640
*r->out.bytes_needed = 4;
642
if (r->in.buf_size < 4) {
643
return NT_STATUS_BUFFER_TOO_SMALL;
646
/* FIXME: this should be retrieved from the handle */
649
ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL, &f,
650
(ndr_push_flags_fn_t)ndr_push_EVENTLOG_FULL_INFORMATION);
651
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
652
return ndr_map_error2ntstatus(ndr_err);
655
if (DEBUGLEVEL >= 10) {
656
NDR_PRINT_DEBUG(EVENTLOG_FULL_INFORMATION, &f);
659
memcpy(r->out.buffer, blob.data, 4);
664
/********************************************************************
665
_eventlog_FlushEventLog
666
********************************************************************/
668
NTSTATUS _eventlog_FlushEventLog(pipes_struct *p,
669
struct eventlog_FlushEventLog *r)
671
EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
673
return NT_STATUS_INVALID_HANDLE;
676
return NT_STATUS_ACCESS_DENIED;
679
/********************************************************************
680
********************************************************************/
682
static NTSTATUS evlog_report_to_record(TALLOC_CTX *mem_ctx,
683
const struct eventlog_ReportEventW *r,
685
struct EVENTLOGRECORD *e)
690
e->TimeGenerated = r->in.timestamp;
691
e->TimeWritten = time(NULL);
692
e->EventID = r->in.event_id;
693
e->EventType = r->in.event_type;
694
e->NumStrings = r->in.num_of_strings;
695
e->EventCategory = r->in.event_category;
696
e->ReservedFlags = r->in.flags;
697
e->DataLength = r->in.data_size;
698
e->SourceName = talloc_strdup(mem_ctx, logname);
699
NT_STATUS_HAVE_NO_MEMORY(e->SourceName);
700
if (r->in.servername->string) {
701
e->Computername = r->in.servername->string;
703
e->Computername = talloc_strdup(mem_ctx, "");
704
NT_STATUS_HAVE_NO_MEMORY(e->Computername);
706
if (r->in.user_sid) {
707
e->UserSid = *r->in.user_sid;
709
e->Strings = talloc_array(mem_ctx, const char *, e->NumStrings);
710
NT_STATUS_HAVE_NO_MEMORY(e->Strings);
712
for (i=0; i < e->NumStrings; i++) {
713
e->Strings[i] = talloc_strdup(e->Strings,
714
r->in.strings[i]->string);
715
NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]);
717
e->Data = r->in.data;
722
/********************************************************************
723
_eventlog_ReportEventW
724
********************************************************************/
726
NTSTATUS _eventlog_ReportEventW(pipes_struct *p,
727
struct eventlog_ReportEventW *r)
730
struct EVENTLOGRECORD record;
732
EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
734
return NT_STATUS_INVALID_HANDLE;
737
status = evlog_report_to_record(p->mem_ctx, r, info->logname, &record);
738
if (!NT_STATUS_IS_OK(status)) {
742
status = evlog_push_record(p->mem_ctx,
743
ELOG_TDB_CTX(info->etdb),
745
r->out.record_number);
746
if (!NT_STATUS_IS_OK(status)) {
753
/********************************************************************
754
********************************************************************/
756
NTSTATUS _eventlog_DeregisterEventSource(pipes_struct *p, struct eventlog_DeregisterEventSource *r)
758
p->rng_fault_state = True;
759
return NT_STATUS_NOT_IMPLEMENTED;
762
NTSTATUS _eventlog_ChangeNotify(pipes_struct *p, struct eventlog_ChangeNotify *r)
764
p->rng_fault_state = True;
765
return NT_STATUS_NOT_IMPLEMENTED;
768
NTSTATUS _eventlog_RegisterEventSourceW(pipes_struct *p, struct eventlog_RegisterEventSourceW *r)
770
p->rng_fault_state = True;
771
return NT_STATUS_NOT_IMPLEMENTED;
774
NTSTATUS _eventlog_OpenBackupEventLogW(pipes_struct *p, struct eventlog_OpenBackupEventLogW *r)
776
p->rng_fault_state = True;
777
return NT_STATUS_NOT_IMPLEMENTED;
780
NTSTATUS _eventlog_ClearEventLogA(pipes_struct *p, struct eventlog_ClearEventLogA *r)
782
p->rng_fault_state = True;
783
return NT_STATUS_NOT_IMPLEMENTED;
786
NTSTATUS _eventlog_BackupEventLogA(pipes_struct *p, struct eventlog_BackupEventLogA *r)
788
p->rng_fault_state = True;
789
return NT_STATUS_NOT_IMPLEMENTED;
792
NTSTATUS _eventlog_OpenEventLogA(pipes_struct *p, struct eventlog_OpenEventLogA *r)
794
p->rng_fault_state = True;
795
return NT_STATUS_NOT_IMPLEMENTED;
798
NTSTATUS _eventlog_RegisterEventSourceA(pipes_struct *p, struct eventlog_RegisterEventSourceA *r)
800
p->rng_fault_state = True;
801
return NT_STATUS_NOT_IMPLEMENTED;
804
NTSTATUS _eventlog_OpenBackupEventLogA(pipes_struct *p, struct eventlog_OpenBackupEventLogA *r)
806
p->rng_fault_state = True;
807
return NT_STATUS_NOT_IMPLEMENTED;
810
NTSTATUS _eventlog_ReadEventLogA(pipes_struct *p, struct eventlog_ReadEventLogA *r)
812
p->rng_fault_state = True;
813
return NT_STATUS_NOT_IMPLEMENTED;
816
NTSTATUS _eventlog_ReportEventA(pipes_struct *p, struct eventlog_ReportEventA *r)
818
p->rng_fault_state = True;
819
return NT_STATUS_NOT_IMPLEMENTED;
822
NTSTATUS _eventlog_RegisterClusterSvc(pipes_struct *p, struct eventlog_RegisterClusterSvc *r)
824
p->rng_fault_state = True;
825
return NT_STATUS_NOT_IMPLEMENTED;
828
NTSTATUS _eventlog_DeregisterClusterSvc(pipes_struct *p, struct eventlog_DeregisterClusterSvc *r)
830
p->rng_fault_state = True;
831
return NT_STATUS_NOT_IMPLEMENTED;
834
NTSTATUS _eventlog_WriteClusterEvents(pipes_struct *p, struct eventlog_WriteClusterEvents *r)
836
p->rng_fault_state = True;
837
return NT_STATUS_NOT_IMPLEMENTED;
840
NTSTATUS _eventlog_ReportEventAndSourceW(pipes_struct *p, struct eventlog_ReportEventAndSourceW *r)
842
p->rng_fault_state = True;
843
return NT_STATUS_NOT_IMPLEMENTED;