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/>.
26 #define DBGC_CLASS DBGC_RPC_SRV
31 uint32 current_record
;
35 uint32 access_granted
;
38 /********************************************************************
39 ********************************************************************/
41 static int eventlog_info_destructor(EVENTLOG_INFO
*elog
)
44 elog_close_tdb(elog
->etdb
, false);
49 /********************************************************************
50 ********************************************************************/
52 static EVENTLOG_INFO
*find_eventlog_info_by_hnd( pipes_struct
* p
,
57 if ( !find_policy_by_hnd( p
, handle
, (void **)(void *)&info
) ) {
59 ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) );
66 /********************************************************************
67 ********************************************************************/
69 static bool elog_check_access( EVENTLOG_INFO
*info
, NT_USER_TOKEN
*token
)
71 char *tdbname
= elog_tdbname(talloc_tos(), info
->logname
);
78 /* get the security descriptor for the file */
80 sec_desc
= get_nt_acl_no_snum( info
, tdbname
);
81 TALLOC_FREE( tdbname
);
84 DEBUG(5,("elog_check_access: Unable to get NT ACL for %s\n",
91 if ( geteuid() == sec_initial_uid() ) {
92 DEBUG(5,("elog_check_access: using root's token\n"));
93 token
= get_root_nt_token();
96 /* run the check, try for the max allowed */
98 status
= se_access_check( sec_desc
, token
, MAXIMUM_ALLOWED_ACCESS
,
99 &info
->access_granted
);
102 TALLOC_FREE( sec_desc
);
104 if (!NT_STATUS_IS_OK(status
)) {
105 DEBUG(8,("elog_check_access: se_access_check() return %s\n",
110 /* we have to have READ permission for a successful open */
112 return ( info
->access_granted
& SA_RIGHT_FILE_READ_DATA
);
115 /********************************************************************
116 ********************************************************************/
118 static bool elog_validate_logname( const char *name
)
121 const char **elogs
= lp_eventlog_list();
127 for ( i
=0; elogs
[i
]; i
++ ) {
128 if ( strequal( name
, elogs
[i
] ) )
135 /********************************************************************
136 ********************************************************************/
138 static bool get_num_records_hook( EVENTLOG_INFO
* info
)
144 DEBUG( 10, ( "No open tdb for %s\n", info
->logname
) );
148 /* lock the tdb since we have to get 2 records */
150 tdb_lock_bystring_with_timeout( ELOG_TDB_CTX(info
->etdb
), EVT_NEXT_RECORD
, 1 );
151 next_record
= tdb_fetch_int32( ELOG_TDB_CTX(info
->etdb
), EVT_NEXT_RECORD
);
152 oldest_record
= tdb_fetch_int32( ELOG_TDB_CTX(info
->etdb
), EVT_OLDEST_ENTRY
);
153 tdb_unlock_bystring( ELOG_TDB_CTX(info
->etdb
), EVT_NEXT_RECORD
);
156 ( "Oldest Record %d; Next Record %d\n", oldest_record
,
159 info
->num_records
= ( next_record
- oldest_record
);
160 info
->oldest_entry
= oldest_record
;
165 /********************************************************************
166 ********************************************************************/
168 static bool get_oldest_entry_hook( EVENTLOG_INFO
* info
)
170 /* it's the same thing */
171 return get_num_records_hook( info
);
174 /********************************************************************
175 ********************************************************************/
177 static NTSTATUS
elog_open( pipes_struct
* p
, const char *logname
, POLICY_HND
*hnd
)
181 /* first thing is to validate the eventlog name */
183 if ( !elog_validate_logname( logname
) )
184 return NT_STATUS_OBJECT_PATH_INVALID
;
186 if ( !(elog
= TALLOC_ZERO_P( NULL
, EVENTLOG_INFO
)) )
187 return NT_STATUS_NO_MEMORY
;
188 talloc_set_destructor(elog
, eventlog_info_destructor
);
190 elog
->logname
= talloc_strdup( elog
, logname
);
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 */
198 elog
->etdb
= elog_open_tdb( elog
->logname
, False
, False
);
202 /* according to MSDN, if the logfile cannot be found, we should
203 default to the "Application" log */
205 if ( !strequal( logname
, ELOG_APPL
) ) {
207 TALLOC_FREE( elog
->logname
);
209 elog
->logname
= talloc_strdup( elog
, ELOG_APPL
);
211 /* do the access check */
212 if ( !elog_check_access( elog
, p
->server_info
->ptok
) ) {
214 return NT_STATUS_ACCESS_DENIED
;
218 elog
->etdb
= elog_open_tdb( elog
->logname
, False
, False
);
224 return NT_STATUS_ACCESS_DENIED
; /* ??? */
228 /* now do the access check. Close the tdb if we fail here */
230 if ( !elog_check_access( elog
, p
->server_info
->ptok
) ) {
232 return NT_STATUS_ACCESS_DENIED
;
235 /* create the policy handle */
237 if ( !create_policy_hnd( p
, hnd
, elog
) ) {
239 return NT_STATUS_NO_MEMORY
;
242 /* set the initial current_record pointer */
244 if ( !get_oldest_entry_hook( elog
) ) {
245 DEBUG(3,("elog_open: Successfully opened eventlog but can't "
246 "get any information on internal records!\n"));
249 elog
->current_record
= elog
->oldest_entry
;
254 /********************************************************************
255 ********************************************************************/
257 static NTSTATUS
elog_close( pipes_struct
*p
, POLICY_HND
*hnd
)
259 if ( !( close_policy_hnd( p
, hnd
) ) ) {
260 return NT_STATUS_INVALID_HANDLE
;
266 /*******************************************************************
267 *******************************************************************/
269 static int elog_size( EVENTLOG_INFO
*info
)
271 if ( !info
|| !info
->etdb
) {
272 DEBUG(0,("elog_size: Invalid info* structure!\n"));
276 return elog_tdb_size( ELOG_TDB_CTX(info
->etdb
), NULL
, NULL
);
279 /********************************************************************
280 note that this can only be called AFTER the table is constructed,
281 since it uses the table to find the tdb handle
282 ********************************************************************/
284 static bool sync_eventlog_params( EVENTLOG_INFO
*info
)
289 struct registry_key
*key
;
290 struct registry_value
*value
;
292 char *elogname
= info
->logname
;
293 TALLOC_CTX
*ctx
= talloc_stackframe();
296 DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname
) );
299 DEBUG( 4, ( "No open tdb! (%s)\n", info
->logname
) );
302 /* set resonable defaults. 512Kb on size and 1 week on time */
305 uiRetention
= 604800;
307 /* the general idea is to internally open the registry
308 key and retrieve the values. That way we can continue
309 to use the same fetch/store api that we use in
312 path
= talloc_asprintf(ctx
, "%s/%s", KEY_EVENTLOG
, elogname
);
317 wresult
= reg_open_path(ctx
, path
, REG_KEY_READ
, get_root_nt_token(),
320 if ( !W_ERROR_IS_OK( wresult
) ) {
322 ( "sync_eventlog_params: Failed to open key [%s] (%s)\n",
323 path
, win_errstr( wresult
) ) );
327 wresult
= reg_queryvalue(key
, key
, "Retention", &value
);
328 if (!W_ERROR_IS_OK(wresult
)) {
329 DEBUG(4, ("Failed to query value \"Retention\": %s\n",
330 win_errstr(wresult
)));
333 uiRetention
= value
->v
.dword
;
335 wresult
= reg_queryvalue(key
, key
, "MaxSize", &value
);
336 if (!W_ERROR_IS_OK(wresult
)) {
337 DEBUG(4, ("Failed to query value \"MaxSize\": %s\n",
338 win_errstr(wresult
)));
341 uiMaxSize
= value
->v
.dword
;
343 tdb_store_int32( ELOG_TDB_CTX(info
->etdb
), EVT_MAXSIZE
, uiMaxSize
);
344 tdb_store_int32( ELOG_TDB_CTX(info
->etdb
), EVT_RETENTION
, uiRetention
);
353 /********************************************************************
354 _eventlog_OpenEventLogW
355 ********************************************************************/
357 NTSTATUS
_eventlog_OpenEventLogW(pipes_struct
*p
,
358 struct eventlog_OpenEventLogW
*r
)
363 DEBUG( 10,("_eventlog_OpenEventLogW: Server [%s], Log [%s]\n",
364 r
->in
.servername
->string
, r
->in
.logname
->string
));
366 /* according to MSDN, if the logfile cannot be found, we should
367 default to the "Application" log */
369 if ( !NT_STATUS_IS_OK( result
= elog_open( p
, r
->in
.logname
->string
, r
->out
.handle
)) )
372 if ( !(info
= find_eventlog_info_by_hnd( p
, r
->out
.handle
)) ) {
373 DEBUG(0,("_eventlog_OpenEventLogW: eventlog (%s) opened but unable to find handle!\n",
374 r
->in
.logname
->string
));
375 elog_close( p
, r
->out
.handle
);
376 return NT_STATUS_INVALID_HANDLE
;
379 DEBUG(10,("_eventlog_OpenEventLogW: Size [%d]\n", elog_size( info
)));
381 sync_eventlog_params( info
);
382 prune_eventlog( ELOG_TDB_CTX(info
->etdb
) );
387 /********************************************************************
388 _eventlog_ClearEventLogW
389 This call still needs some work
390 ********************************************************************/
391 /** The windows client seems to be doing something funny with the file name
393 ClearEventLog(handle, "backup_file")
394 on the client side will result in the backup file name looking like this on the
396 \??\${CWD of client}\backup_file
397 If an absolute path gets specified, such as
398 ClearEventLog(handle, "C:\\temp\\backup_file")
399 then it is still mangled by the client into this:
400 \??\C:\temp\backup_file
401 when it is on the wire.
402 I'm not sure where the \?? is coming from, or why the ${CWD} of the client process
403 would be added in given that the backup file gets written on the server side. */
405 NTSTATUS
_eventlog_ClearEventLogW(pipes_struct
*p
,
406 struct eventlog_ClearEventLogW
*r
)
408 EVENTLOG_INFO
*info
= find_eventlog_info_by_hnd( p
, r
->in
.handle
);
411 return NT_STATUS_INVALID_HANDLE
;
413 if (r
->in
.backupfile
&& r
->in
.backupfile
->string
) {
415 DEBUG(8,( "_eventlog_ClearEventLogW: Using [%s] as the backup "
416 "file name for log [%s].",
417 r
->in
.backupfile
->string
, info
->logname
) );
420 /* check for WRITE access to the file */
422 if ( !(info
->access_granted
&SA_RIGHT_FILE_WRITE_DATA
) )
423 return NT_STATUS_ACCESS_DENIED
;
425 /* Force a close and reopen */
427 elog_close_tdb( info
->etdb
, True
);
429 info
->etdb
= elog_open_tdb( info
->logname
, True
, False
);
433 return NT_STATUS_ACCESS_DENIED
;
438 /********************************************************************
439 _eventlog_CloseEventLog
440 ********************************************************************/
442 NTSTATUS
_eventlog_CloseEventLog(pipes_struct
* p
,
443 struct eventlog_CloseEventLog
*r
)
447 status
= elog_close( p
, r
->in
.handle
);
448 if (!NT_STATUS_IS_OK(status
)) {
452 ZERO_STRUCTP(r
->out
.handle
);
457 /********************************************************************
458 _eventlog_ReadEventLogW
459 ********************************************************************/
461 NTSTATUS
_eventlog_ReadEventLogW(pipes_struct
*p
,
462 struct eventlog_ReadEventLogW
*r
)
464 EVENTLOG_INFO
*info
= find_eventlog_info_by_hnd( p
, r
->in
.handle
);
465 uint32_t num_records_read
= 0;
466 int bytes_left
, record_number
;
467 uint32_t elog_read_type
, elog_read_dir
;
470 return NT_STATUS_INVALID_HANDLE
;
473 info
->flags
= r
->in
.flags
;
474 bytes_left
= r
->in
.number_of_bytes
;
477 return NT_STATUS_ACCESS_DENIED
;
480 /* check for valid flags. Can't use the sequential and seek flags together */
482 elog_read_type
= r
->in
.flags
& (EVENTLOG_SEQUENTIAL_READ
|EVENTLOG_SEEK_READ
);
483 elog_read_dir
= r
->in
.flags
& (EVENTLOG_FORWARDS_READ
|EVENTLOG_BACKWARDS_READ
);
485 if (r
->in
.flags
== 0 ||
486 elog_read_type
== (EVENTLOG_SEQUENTIAL_READ
|EVENTLOG_SEEK_READ
) ||
487 elog_read_dir
== (EVENTLOG_FORWARDS_READ
|EVENTLOG_BACKWARDS_READ
))
489 DEBUG(3,("_eventlog_ReadEventLogW: "
490 "Invalid flags [0x%08x] for ReadEventLog\n",
492 return NT_STATUS_INVALID_PARAMETER
;
495 /* a sequential read should ignore the offset */
497 if (elog_read_type
& EVENTLOG_SEQUENTIAL_READ
) {
498 record_number
= info
->current_record
;
500 record_number
= r
->in
.offset
;
503 if (r
->in
.number_of_bytes
== 0) {
504 struct EVENTLOGRECORD
*e
;
505 e
= evlog_pull_record(p
->mem_ctx
, ELOG_TDB_CTX(info
->etdb
),
508 return NT_STATUS_END_OF_FILE
;
510 *r
->out
.real_size
= e
->Length
;
511 return NT_STATUS_BUFFER_TOO_SMALL
;
514 while (bytes_left
> 0) {
517 enum ndr_err_code ndr_err
;
518 struct EVENTLOGRECORD
*e
;
520 e
= evlog_pull_record(p
->mem_ctx
, ELOG_TDB_CTX(info
->etdb
),
526 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, NULL
, e
,
527 (ndr_push_flags_fn_t
)ndr_push_EVENTLOGRECORD
);
528 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
529 return ndr_map_error2ntstatus(ndr_err
);
532 if (DEBUGLEVEL
>= 10) {
533 NDR_PRINT_DEBUG(EVENTLOGRECORD
, e
);
536 if (blob
.length
> r
->in
.number_of_bytes
) {
537 *r
->out
.real_size
= blob
.length
;
538 return NT_STATUS_BUFFER_TOO_SMALL
;
541 if (*r
->out
.sent_size
+ blob
.length
> r
->in
.number_of_bytes
) {
545 bytes_left
-= blob
.length
;
547 if (info
->flags
& EVENTLOG_FORWARDS_READ
) {
553 /* update the eventlog record pointer */
555 info
->current_record
= record_number
;
557 memcpy(&r
->out
.data
[*(r
->out
.sent_size
)],
558 blob
.data
, blob
.length
);
559 *(r
->out
.sent_size
) += blob
.length
;
564 if (r
->in
.offset
== 0 && record_number
== 0 && *r
->out
.sent_size
== 0) {
565 return NT_STATUS_END_OF_FILE
;
571 /********************************************************************
572 _eventlog_GetOldestRecord
573 ********************************************************************/
575 NTSTATUS
_eventlog_GetOldestRecord(pipes_struct
*p
,
576 struct eventlog_GetOldestRecord
*r
)
578 EVENTLOG_INFO
*info
= find_eventlog_info_by_hnd( p
, r
->in
.handle
);
581 return NT_STATUS_INVALID_HANDLE
;
584 if ( !( get_oldest_entry_hook( info
) ) )
585 return NT_STATUS_ACCESS_DENIED
;
587 *r
->out
.oldest_entry
= info
->oldest_entry
;
592 /********************************************************************
593 _eventlog_GetNumRecords
594 ********************************************************************/
596 NTSTATUS
_eventlog_GetNumRecords(pipes_struct
*p
,
597 struct eventlog_GetNumRecords
*r
)
599 EVENTLOG_INFO
*info
= find_eventlog_info_by_hnd( p
, r
->in
.handle
);
602 return NT_STATUS_INVALID_HANDLE
;
605 if ( !( get_num_records_hook( info
) ) )
606 return NT_STATUS_ACCESS_DENIED
;
608 *r
->out
.number
= info
->num_records
;
613 NTSTATUS
_eventlog_BackupEventLogW(pipes_struct
*p
, struct eventlog_BackupEventLogW
*r
)
615 p
->rng_fault_state
= True
;
616 return NT_STATUS_NOT_IMPLEMENTED
;
619 NTSTATUS
_eventlog_DeregisterEventSource(pipes_struct
*p
, struct eventlog_DeregisterEventSource
*r
)
621 p
->rng_fault_state
= True
;
622 return NT_STATUS_NOT_IMPLEMENTED
;
625 NTSTATUS
_eventlog_ChangeNotify(pipes_struct
*p
, struct eventlog_ChangeNotify
*r
)
627 p
->rng_fault_state
= True
;
628 return NT_STATUS_NOT_IMPLEMENTED
;
631 NTSTATUS
_eventlog_RegisterEventSourceW(pipes_struct
*p
, struct eventlog_RegisterEventSourceW
*r
)
633 p
->rng_fault_state
= True
;
634 return NT_STATUS_NOT_IMPLEMENTED
;
637 NTSTATUS
_eventlog_OpenBackupEventLogW(pipes_struct
*p
, struct eventlog_OpenBackupEventLogW
*r
)
639 p
->rng_fault_state
= True
;
640 return NT_STATUS_NOT_IMPLEMENTED
;
643 NTSTATUS
_eventlog_ReportEventW(pipes_struct
*p
, struct eventlog_ReportEventW
*r
)
645 p
->rng_fault_state
= True
;
646 return NT_STATUS_NOT_IMPLEMENTED
;
649 NTSTATUS
_eventlog_ClearEventLogA(pipes_struct
*p
, struct eventlog_ClearEventLogA
*r
)
651 p
->rng_fault_state
= True
;
652 return NT_STATUS_NOT_IMPLEMENTED
;
655 NTSTATUS
_eventlog_BackupEventLogA(pipes_struct
*p
, struct eventlog_BackupEventLogA
*r
)
657 p
->rng_fault_state
= True
;
658 return NT_STATUS_NOT_IMPLEMENTED
;
661 NTSTATUS
_eventlog_OpenEventLogA(pipes_struct
*p
, struct eventlog_OpenEventLogA
*r
)
663 p
->rng_fault_state
= True
;
664 return NT_STATUS_NOT_IMPLEMENTED
;
667 NTSTATUS
_eventlog_RegisterEventSourceA(pipes_struct
*p
, struct eventlog_RegisterEventSourceA
*r
)
669 p
->rng_fault_state
= True
;
670 return NT_STATUS_NOT_IMPLEMENTED
;
673 NTSTATUS
_eventlog_OpenBackupEventLogA(pipes_struct
*p
, struct eventlog_OpenBackupEventLogA
*r
)
675 p
->rng_fault_state
= True
;
676 return NT_STATUS_NOT_IMPLEMENTED
;
679 NTSTATUS
_eventlog_ReadEventLogA(pipes_struct
*p
, struct eventlog_ReadEventLogA
*r
)
681 p
->rng_fault_state
= True
;
682 return NT_STATUS_NOT_IMPLEMENTED
;
685 NTSTATUS
_eventlog_ReportEventA(pipes_struct
*p
, struct eventlog_ReportEventA
*r
)
687 p
->rng_fault_state
= True
;
688 return NT_STATUS_NOT_IMPLEMENTED
;
691 NTSTATUS
_eventlog_RegisterClusterSvc(pipes_struct
*p
, struct eventlog_RegisterClusterSvc
*r
)
693 p
->rng_fault_state
= True
;
694 return NT_STATUS_NOT_IMPLEMENTED
;
697 NTSTATUS
_eventlog_DeregisterClusterSvc(pipes_struct
*p
, struct eventlog_DeregisterClusterSvc
*r
)
699 p
->rng_fault_state
= True
;
700 return NT_STATUS_NOT_IMPLEMENTED
;
703 NTSTATUS
_eventlog_WriteClusterEvents(pipes_struct
*p
, struct eventlog_WriteClusterEvents
*r
)
705 p
->rng_fault_state
= True
;
706 return NT_STATUS_NOT_IMPLEMENTED
;
709 NTSTATUS
_eventlog_GetLogInformation(pipes_struct
*p
, struct eventlog_GetLogInformation
*r
)
711 p
->rng_fault_state
= True
;
712 return NT_STATUS_NOT_IMPLEMENTED
;
715 NTSTATUS
_eventlog_FlushEventLog(pipes_struct
*p
, struct eventlog_FlushEventLog
*r
)
717 p
->rng_fault_state
= True
;
718 return NT_STATUS_NOT_IMPLEMENTED
;
721 NTSTATUS
_eventlog_ReportEventAndSourceW(pipes_struct
*p
, struct eventlog_ReportEventAndSourceW
*r
)
723 p
->rng_fault_state
= True
;
724 return NT_STATUS_NOT_IMPLEMENTED
;