Line data Source code
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 : * Copyright (C) Guenther Deschner 2009.
8 : *
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.
13 : *
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.
18 : *
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/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "system/passwd.h" /* uid_wrapper */
25 : #include "ntdomain.h"
26 : #include "lib/eventlog/eventlog.h"
27 : #include "../libcli/security/security.h"
28 : #include "../librpc/gen_ndr/ndr_winreg_c.h"
29 : #include "rpc_client/cli_winreg_int.h"
30 : #include "rpc_client/cli_winreg.h"
31 : #include "smbd/smbd.h"
32 : #include "auth.h"
33 : #include "util_tdb.h"
34 :
35 : #include "rpc_server/rpc_server.h"
36 : #include "librpc/rpc/dcesrv_core.h"
37 : #include "librpc/gen_ndr/ndr_eventlog_scompat.h"
38 : #include "rpc_server/eventlog/srv_eventlog_reg.h"
39 : #include "lib/global_contexts.h"
40 :
41 : #undef DBGC_CLASS
42 : #define DBGC_CLASS DBGC_RPC_SRV
43 :
44 : #define TOP_LEVEL_EVENTLOG_KEY "SYSTEM\\CurrentControlSet\\Services\\Eventlog"
45 :
46 : typedef struct {
47 : char *logname;
48 : ELOG_TDB *etdb;
49 : uint32_t current_record;
50 : uint32_t num_records;
51 : uint32_t oldest_entry;
52 : uint32_t flags;
53 : uint32_t access_granted;
54 : } EVENTLOG_INFO;
55 :
56 : /********************************************************************
57 : ********************************************************************/
58 :
59 12 : static int eventlog_info_destructor(EVENTLOG_INFO *elog)
60 : {
61 12 : if (elog->etdb) {
62 12 : elog_close_tdb(elog->etdb, false);
63 : }
64 12 : return 0;
65 : }
66 :
67 : /********************************************************************
68 : ********************************************************************/
69 :
70 28 : static EVENTLOG_INFO *find_eventlog_info_by_hnd( struct pipes_struct * p,
71 : struct policy_handle * handle )
72 : {
73 0 : EVENTLOG_INFO *info;
74 0 : NTSTATUS status;
75 :
76 28 : info = find_policy_by_hnd(p,
77 : handle,
78 : DCESRV_HANDLE_ANY,
79 : EVENTLOG_INFO,
80 0 : &status);
81 28 : if (!NT_STATUS_IS_OK(status)) {
82 0 : DEBUG( 2,
83 : ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) );
84 0 : return NULL;
85 : }
86 :
87 28 : return info;
88 : }
89 :
90 : /********************************************************************
91 : Pull the NT ACL from a file on disk or the OpenEventlog() access
92 : check. Caller is responsible for freeing the returned security
93 : descriptor via TALLOC_FREE(). This is designed for dealing with
94 : user space access checks in smbd outside of the VFS. For example,
95 : checking access rights in OpenEventlog() or from python.
96 :
97 : ********************************************************************/
98 :
99 12 : static NTSTATUS get_nt_acl_no_snum(TALLOC_CTX *ctx,
100 : struct auth_session_info *session_info,
101 : const char *fname,
102 : uint32_t security_info_wanted,
103 : struct security_descriptor **sd)
104 : {
105 12 : TALLOC_CTX *frame = talloc_stackframe();
106 12 : struct conn_struct_tos *c = NULL;
107 12 : NTSTATUS status = NT_STATUS_OK;
108 12 : struct smb_filename *pathref_fname = NULL;
109 :
110 12 : if (!posix_locking_init(false)) {
111 0 : TALLOC_FREE(frame);
112 0 : return NT_STATUS_NO_MEMORY;
113 : }
114 :
115 12 : status = create_conn_struct_tos(global_messaging_context(),
116 : -1,
117 : "/",
118 : session_info,
119 : &c);
120 12 : if (!NT_STATUS_IS_OK(status)) {
121 0 : DBG_ERR("create_conn_struct_tos() returned %s.\n",
122 : nt_errstr(status));
123 0 : TALLOC_FREE(frame);
124 0 : return status;
125 : }
126 :
127 12 : status = synthetic_pathref(talloc_tos(),
128 12 : c->conn->cwd_fsp,
129 : fname,
130 : NULL,
131 : NULL,
132 : 0,
133 : 0,
134 : &pathref_fname);
135 12 : if (!NT_STATUS_IS_OK(status)) {
136 0 : DBG_ERR("synthetic_pathref for file %s returned %s.\n",
137 : fname, nt_errstr(status));
138 0 : TALLOC_FREE(frame);
139 0 : return status;
140 : }
141 12 : status = SMB_VFS_FGET_NT_ACL(pathref_fname->fsp,
142 : security_info_wanted,
143 : ctx,
144 : sd);
145 12 : if (!NT_STATUS_IS_OK(status)) {
146 0 : DBG_ERR("SMB_VFS_FGET_NT_ACL for file %s returned %s.\n",
147 : fname, nt_errstr(status));
148 : }
149 :
150 12 : TALLOC_FREE(frame);
151 :
152 12 : return status;
153 : }
154 :
155 : /********************************************************************
156 : ********************************************************************/
157 :
158 12 : static bool elog_check_access(EVENTLOG_INFO *info,
159 : struct auth_session_info *session_info)
160 : {
161 12 : const struct security_token *token = session_info->security_token;
162 12 : char *tdbname = elog_tdbname(talloc_tos(), info->logname );
163 0 : struct security_descriptor *sec_desc;
164 0 : struct security_ace *ace;
165 0 : NTSTATUS status;
166 :
167 12 : if ( !tdbname )
168 0 : return False;
169 :
170 : /* get the security descriptor for the file */
171 :
172 12 : status = get_nt_acl_no_snum( info,
173 : session_info,
174 : tdbname,
175 : SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL,
176 : &sec_desc);
177 12 : if (!NT_STATUS_IS_OK(status)) {
178 0 : DEBUG(5,("elog_check_access: Unable to get NT ACL for %s: %s\n",
179 : tdbname, nt_errstr(status)));
180 0 : TALLOC_FREE(tdbname);
181 0 : return False;
182 : }
183 12 : TALLOC_FREE(tdbname);
184 :
185 12 : ace = talloc_zero(sec_desc, struct security_ace);
186 12 : if (ace == NULL) {
187 0 : TALLOC_FREE(sec_desc);
188 0 : return false;
189 : }
190 :
191 12 : ace->type = SEC_ACE_TYPE_ACCESS_ALLOWED;
192 12 : ace->flags = 0;
193 12 : ace->access_mask = REG_KEY_ALL;
194 12 : ace->trustee = global_sid_System;
195 :
196 12 : status = security_descriptor_dacl_add(sec_desc, ace);
197 12 : if (!NT_STATUS_IS_OK(status)) {
198 0 : TALLOC_FREE(sec_desc);
199 0 : return false;
200 : }
201 :
202 : /* root free pass */
203 :
204 12 : if ( geteuid() == sec_initial_uid() ) {
205 12 : DEBUG(5,("elog_check_access: running as root, using system token\n"));
206 12 : token = get_system_token();
207 : }
208 :
209 : /* run the check, try for the max allowed */
210 :
211 12 : status = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS,
212 : &info->access_granted);
213 :
214 12 : TALLOC_FREE(sec_desc);
215 :
216 12 : if (!NT_STATUS_IS_OK(status)) {
217 0 : DEBUG(8,("elog_check_access: se_access_check() return %s\n",
218 : nt_errstr(status)));
219 0 : return False;
220 : }
221 :
222 : /* we have to have READ permission for a successful open */
223 :
224 12 : return ( info->access_granted & SEC_FILE_READ_DATA );
225 : }
226 :
227 : /********************************************************************
228 : ********************************************************************/
229 :
230 24 : static bool elog_validate_logname( const char *name )
231 : {
232 0 : int i;
233 24 : const char **elogs = lp_eventlog_list();
234 :
235 24 : if (!elogs) {
236 12 : return False;
237 : }
238 :
239 24 : for ( i=0; elogs[i]; i++ ) {
240 24 : if ( strequal( name, elogs[i] ) )
241 12 : return True;
242 : }
243 :
244 0 : return False;
245 : }
246 :
247 : /********************************************************************
248 : ********************************************************************/
249 :
250 14 : static bool get_num_records_hook( EVENTLOG_INFO * info )
251 : {
252 0 : int next_record;
253 0 : int oldest_record;
254 :
255 14 : if ( !info->etdb ) {
256 0 : DEBUG( 10, ( "No open tdb for %s\n", info->logname ) );
257 0 : return False;
258 : }
259 :
260 : /* lock the tdb since we have to get 2 records */
261 :
262 14 : tdb_lock_bystring_with_timeout( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD, 1 );
263 14 : next_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
264 14 : oldest_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_OLDEST_ENTRY);
265 14 : tdb_unlock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
266 :
267 14 : DEBUG( 8,
268 : ( "Oldest Record %d; Next Record %d\n", oldest_record,
269 : next_record ) );
270 :
271 14 : info->num_records = ( next_record - oldest_record );
272 14 : info->oldest_entry = oldest_record;
273 :
274 14 : return True;
275 : }
276 :
277 : /********************************************************************
278 : ********************************************************************/
279 :
280 12 : static bool get_oldest_entry_hook( EVENTLOG_INFO * info )
281 : {
282 : /* it's the same thing */
283 12 : return get_num_records_hook( info );
284 : }
285 :
286 : /********************************************************************
287 : ********************************************************************/
288 :
289 24 : static NTSTATUS elog_open( struct pipes_struct * p, const char *logname, struct policy_handle *hnd )
290 : {
291 24 : struct dcesrv_call_state *dce_call = p->dce_call;
292 0 : struct auth_session_info *session_info =
293 24 : dcesrv_call_session_info(dce_call);
294 0 : EVENTLOG_INFO *elog;
295 :
296 : /* first thing is to validate the eventlog name */
297 :
298 24 : if ( !elog_validate_logname( logname ) )
299 12 : return NT_STATUS_OBJECT_PATH_INVALID;
300 :
301 12 : if ( !(elog = talloc_zero( NULL, EVENTLOG_INFO )) )
302 0 : return NT_STATUS_NO_MEMORY;
303 12 : talloc_set_destructor(elog, eventlog_info_destructor);
304 :
305 12 : elog->logname = talloc_strdup( elog, logname );
306 :
307 : /* Open the tdb first (so that we can create any new tdbs if necessary).
308 : We have to do this as root and then use an internal access check
309 : on the file permissions since you can only have a tdb open once
310 : in a single process */
311 :
312 12 : become_root();
313 12 : elog->etdb = elog_open_tdb( elog->logname, False, False );
314 12 : unbecome_root();
315 :
316 12 : if ( !elog->etdb ) {
317 : /* according to MSDN, if the logfile cannot be found, we should
318 : default to the "Application" log */
319 :
320 0 : if ( !strequal( logname, ELOG_APPL ) ) {
321 :
322 0 : TALLOC_FREE( elog->logname );
323 :
324 0 : elog->logname = talloc_strdup( elog, ELOG_APPL );
325 :
326 : /* do the access check */
327 0 : if ( !elog_check_access( elog, session_info) ) {
328 0 : TALLOC_FREE( elog );
329 0 : return NT_STATUS_ACCESS_DENIED;
330 : }
331 :
332 0 : become_root();
333 0 : elog->etdb = elog_open_tdb( elog->logname, False, False );
334 0 : unbecome_root();
335 : }
336 :
337 0 : if ( !elog->etdb ) {
338 0 : TALLOC_FREE( elog );
339 0 : return NT_STATUS_ACCESS_DENIED; /* ??? */
340 : }
341 : }
342 :
343 : /* now do the access check. Close the tdb if we fail here */
344 :
345 12 : if ( !elog_check_access( elog, session_info) ) {
346 0 : TALLOC_FREE( elog );
347 0 : return NT_STATUS_ACCESS_DENIED;
348 : }
349 :
350 : /* create the policy handle */
351 :
352 12 : if ( !create_policy_hnd( p, hnd, 0, elog ) ) {
353 0 : TALLOC_FREE(elog);
354 0 : return NT_STATUS_NO_MEMORY;
355 : }
356 :
357 : /* set the initial current_record pointer */
358 :
359 12 : if ( !get_oldest_entry_hook( elog ) ) {
360 0 : DEBUG(3,("elog_open: Successfully opened eventlog but can't "
361 : "get any information on internal records!\n"));
362 : }
363 :
364 12 : elog->current_record = elog->oldest_entry;
365 :
366 12 : return NT_STATUS_OK;
367 : }
368 :
369 : /********************************************************************
370 : ********************************************************************/
371 :
372 12 : static NTSTATUS elog_close( struct pipes_struct *p, struct policy_handle *hnd )
373 : {
374 12 : if ( !( close_policy_hnd( p, hnd ) ) ) {
375 0 : return NT_STATUS_INVALID_HANDLE;
376 : }
377 :
378 12 : return NT_STATUS_OK;
379 : }
380 :
381 : /*******************************************************************
382 : *******************************************************************/
383 :
384 0 : static int elog_size( EVENTLOG_INFO *info )
385 : {
386 0 : if ( !info || !info->etdb ) {
387 0 : DEBUG(0,("elog_size: Invalid info* structure!\n"));
388 0 : return 0;
389 : }
390 :
391 0 : return elog_tdb_size( ELOG_TDB_CTX(info->etdb), NULL, NULL );
392 : }
393 :
394 : /********************************************************************
395 : note that this can only be called AFTER the table is constructed,
396 : since it uses the table to find the tdb handle
397 : ********************************************************************/
398 :
399 12 : static bool sync_eventlog_params(TALLOC_CTX *mem_ctx,
400 : struct messaging_context *msg_ctx,
401 : EVENTLOG_INFO *info)
402 : {
403 12 : struct dcerpc_binding_handle *h = NULL;
404 12 : uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
405 0 : struct policy_handle hive_hnd, key_hnd;
406 12 : uint32_t uiMaxSize = 0;
407 12 : uint32_t uiRetention = 0;
408 12 : char *path = NULL;
409 0 : NTSTATUS status;
410 12 : WERROR wresult = WERR_OK;
411 12 : char *elogname = info->logname;
412 0 : TALLOC_CTX *ctx;
413 12 : bool ret = false;
414 :
415 12 : ctx = talloc_stackframe();
416 12 : if (ctx == NULL) {
417 0 : return false;
418 : }
419 :
420 12 : DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
421 :
422 12 : if ( !info->etdb ) {
423 0 : DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) );
424 0 : goto done;
425 : }
426 : /* set reasonable defaults. 512Kb on size and 1 week on time */
427 :
428 12 : uiMaxSize = 0x80000;
429 12 : uiRetention = 604800;
430 :
431 : /* the general idea is to internally open the registry
432 : key and retrieve the values. That way we can continue
433 : to use the same fetch/store api that we use in
434 : srv_reg_nt.c */
435 12 : path = talloc_asprintf(ctx, "%s\\%s", TOP_LEVEL_EVENTLOG_KEY, elogname);
436 12 : if (!path) {
437 0 : goto done;
438 : }
439 :
440 12 : status = dcerpc_winreg_int_hklm_openkey(ctx,
441 : get_session_info_system(),
442 : msg_ctx,
443 : &h,
444 : path,
445 : false,
446 : access_mask,
447 : &hive_hnd,
448 : &key_hnd,
449 : &wresult);
450 12 : if (!NT_STATUS_IS_OK(status)) {
451 0 : DEBUG(4,("sync_eventlog_params: Failed to open key [%s] (%s)\n",
452 : path, nt_errstr(status)));
453 0 : goto done;
454 : }
455 12 : if ( !W_ERROR_IS_OK( wresult ) ) {
456 0 : DEBUG( 4,
457 : ( "sync_eventlog_params: Failed to open key [%s] (%s)\n",
458 : path, win_errstr( wresult ) ) );
459 0 : goto done;
460 : }
461 :
462 12 : status = dcerpc_winreg_query_dword(ctx,
463 : h,
464 : &key_hnd,
465 : "Retention",
466 : &uiRetention,
467 : &wresult);
468 12 : if (!NT_STATUS_IS_OK(status)) {
469 0 : DEBUG(4, ("Failed to query value \"Retention\": %s\n",
470 : nt_errstr(status)));
471 0 : goto done;
472 : }
473 12 : if (!W_ERROR_IS_OK(wresult)) {
474 0 : DEBUG(4, ("Failed to query value \"Retention\": %s\n",
475 : win_errstr(wresult)));
476 0 : goto done;
477 : }
478 :
479 12 : status = dcerpc_winreg_query_dword(ctx,
480 : h,
481 : &key_hnd,
482 : "MaxSize",
483 : &uiMaxSize,
484 : &wresult);
485 12 : if (!NT_STATUS_IS_OK(status)) {
486 0 : DEBUG(4, ("Failed to query value \"Retention\": %s\n",
487 : nt_errstr(status)));
488 0 : goto done;
489 : }
490 12 : if (!W_ERROR_IS_OK(wresult)) {
491 0 : DEBUG(4, ("Failed to query value \"MaxSize\": %s\n",
492 : win_errstr(wresult)));
493 0 : goto done;
494 : }
495 :
496 12 : tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize );
497 12 : tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention );
498 :
499 12 : ret = true;
500 :
501 12 : done:
502 12 : if (h != NULL) {
503 0 : WERROR ignore;
504 :
505 12 : if (is_valid_policy_hnd(&key_hnd)) {
506 12 : dcerpc_winreg_CloseKey(h, ctx, &key_hnd, &ignore);
507 : }
508 12 : if (is_valid_policy_hnd(&hive_hnd)) {
509 12 : dcerpc_winreg_CloseKey(h, ctx, &hive_hnd, &ignore);
510 : }
511 : }
512 :
513 12 : TALLOC_FREE(ctx);
514 12 : return ret;
515 : }
516 :
517 : /********************************************************************
518 : _eventlog_OpenEventLogW
519 : ********************************************************************/
520 :
521 24 : NTSTATUS _eventlog_OpenEventLogW(struct pipes_struct *p,
522 : struct eventlog_OpenEventLogW *r)
523 : {
524 0 : EVENTLOG_INFO *info;
525 0 : NTSTATUS result;
526 :
527 24 : DEBUG( 10,("_eventlog_OpenEventLogW: Server [%s], Log [%s]\n",
528 : r->in.servername->string, r->in.logname->string ));
529 :
530 : /* according to MSDN, if the logfile cannot be found, we should
531 : default to the "Application" log */
532 :
533 24 : if ( !NT_STATUS_IS_OK( result = elog_open( p, r->in.logname->string, r->out.handle )) )
534 12 : return result;
535 :
536 12 : if ( !(info = find_eventlog_info_by_hnd( p, r->out.handle )) ) {
537 0 : DEBUG(0,("_eventlog_OpenEventLogW: eventlog (%s) opened but unable to find handle!\n",
538 : r->in.logname->string ));
539 0 : elog_close( p, r->out.handle );
540 0 : return NT_STATUS_INVALID_HANDLE;
541 : }
542 :
543 12 : DEBUG(10,("_eventlog_OpenEventLogW: Size [%d]\n", elog_size( info )));
544 :
545 12 : if (!sync_eventlog_params(p->mem_ctx,
546 : p->msg_ctx,
547 : info)) {
548 0 : elog_close(p, r->out.handle);
549 0 : return NT_STATUS_EVENTLOG_FILE_CORRUPT;
550 : }
551 12 : prune_eventlog( ELOG_TDB_CTX(info->etdb) );
552 :
553 12 : return NT_STATUS_OK;
554 : }
555 :
556 : /********************************************************************
557 : _eventlog_ClearEventLogW
558 : This call still needs some work
559 : ********************************************************************/
560 : /** The windows client seems to be doing something funny with the file name
561 : A call like
562 : ClearEventLog(handle, "backup_file")
563 : on the client side will result in the backup file name looking like this on the
564 : server side:
565 : \??\${CWD of client}\backup_file
566 : If an absolute path gets specified, such as
567 : ClearEventLog(handle, "C:\\temp\\backup_file")
568 : then it is still mangled by the client into this:
569 : \??\C:\temp\backup_file
570 : when it is on the wire.
571 : I'm not sure where the \?? is coming from, or why the ${CWD} of the client process
572 : would be added in given that the backup file gets written on the server side. */
573 :
574 0 : NTSTATUS _eventlog_ClearEventLogW(struct pipes_struct *p,
575 : struct eventlog_ClearEventLogW *r)
576 : {
577 0 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
578 :
579 0 : if ( !info )
580 0 : return NT_STATUS_INVALID_HANDLE;
581 :
582 0 : if (r->in.backupfile && r->in.backupfile->string) {
583 :
584 0 : DEBUG(8,( "_eventlog_ClearEventLogW: Using [%s] as the backup "
585 : "file name for log [%s].\n",
586 : r->in.backupfile->string, info->logname ) );
587 : }
588 :
589 : /* check for WRITE access to the file */
590 :
591 0 : if ( !(info->access_granted & SEC_FILE_WRITE_DATA) )
592 0 : return NT_STATUS_ACCESS_DENIED;
593 :
594 : /* Force a close and reopen */
595 :
596 0 : elog_close_tdb( info->etdb, True );
597 0 : become_root();
598 0 : info->etdb = elog_open_tdb( info->logname, True, False );
599 0 : unbecome_root();
600 :
601 0 : if ( !info->etdb )
602 0 : return NT_STATUS_ACCESS_DENIED;
603 :
604 0 : return NT_STATUS_OK;
605 : }
606 :
607 : /********************************************************************
608 : _eventlog_CloseEventLog
609 : ********************************************************************/
610 :
611 12 : NTSTATUS _eventlog_CloseEventLog(struct pipes_struct * p,
612 : struct eventlog_CloseEventLog *r)
613 : {
614 0 : NTSTATUS status;
615 :
616 12 : status = elog_close( p, r->in.handle );
617 12 : if (!NT_STATUS_IS_OK(status)) {
618 0 : return status;
619 : }
620 :
621 12 : ZERO_STRUCTP(r->out.handle);
622 :
623 12 : return NT_STATUS_OK;
624 : }
625 :
626 : /********************************************************************
627 : _eventlog_ReadEventLogW
628 : ********************************************************************/
629 :
630 4 : NTSTATUS _eventlog_ReadEventLogW(struct pipes_struct *p,
631 : struct eventlog_ReadEventLogW *r)
632 : {
633 4 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
634 0 : int bytes_left, record_number;
635 0 : uint32_t elog_read_type, elog_read_dir;
636 :
637 4 : if (!info) {
638 0 : return NT_STATUS_INVALID_HANDLE;
639 : }
640 :
641 4 : info->flags = r->in.flags;
642 4 : bytes_left = r->in.number_of_bytes;
643 :
644 4 : if (!info->etdb) {
645 0 : return NT_STATUS_ACCESS_DENIED;
646 : }
647 :
648 : /* check for valid flags. Can't use the sequential and seek flags together */
649 :
650 4 : elog_read_type = r->in.flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ);
651 4 : elog_read_dir = r->in.flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ);
652 :
653 4 : if (r->in.flags == 0 ||
654 2 : elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) ||
655 0 : elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ))
656 : {
657 2 : DEBUG(3,("_eventlog_ReadEventLogW: "
658 : "Invalid flags [0x%08x] for ReadEventLog\n",
659 : r->in.flags));
660 2 : return NT_STATUS_INVALID_PARAMETER;
661 : }
662 :
663 : /* a sequential read should ignore the offset */
664 :
665 2 : if (elog_read_type & EVENTLOG_SEQUENTIAL_READ) {
666 2 : record_number = info->current_record;
667 : } else {
668 0 : record_number = r->in.offset;
669 : }
670 :
671 2 : if (r->in.number_of_bytes == 0) {
672 0 : struct EVENTLOGRECORD *e;
673 2 : e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb),
674 : record_number);
675 2 : if (!e) {
676 2 : return NT_STATUS_END_OF_FILE;
677 : }
678 0 : *r->out.real_size = e->Length;
679 0 : return NT_STATUS_BUFFER_TOO_SMALL;
680 : }
681 :
682 0 : while (bytes_left > 0) {
683 :
684 0 : DATA_BLOB blob;
685 0 : enum ndr_err_code ndr_err;
686 0 : struct EVENTLOGRECORD *e;
687 :
688 0 : e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb),
689 : record_number);
690 0 : if (!e) {
691 0 : break;
692 : }
693 :
694 0 : ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, e,
695 : (ndr_push_flags_fn_t)ndr_push_EVENTLOGRECORD);
696 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
697 0 : return ndr_map_error2ntstatus(ndr_err);
698 : }
699 :
700 0 : if (DEBUGLEVEL >= 10) {
701 0 : NDR_PRINT_DEBUG(EVENTLOGRECORD, e);
702 : }
703 :
704 0 : if (blob.length > r->in.number_of_bytes) {
705 0 : *r->out.real_size = blob.length;
706 0 : return NT_STATUS_BUFFER_TOO_SMALL;
707 : }
708 :
709 0 : if (*r->out.sent_size + blob.length > r->in.number_of_bytes) {
710 0 : break;
711 : }
712 :
713 0 : bytes_left -= blob.length;
714 :
715 0 : if (info->flags & EVENTLOG_FORWARDS_READ) {
716 0 : record_number++;
717 : } else {
718 0 : record_number--;
719 : }
720 :
721 : /* update the eventlog record pointer */
722 :
723 0 : info->current_record = record_number;
724 :
725 0 : memcpy(&r->out.data[*(r->out.sent_size)],
726 0 : blob.data, blob.length);
727 0 : *(r->out.sent_size) += blob.length;
728 : }
729 :
730 0 : if (r->in.offset == 0 && record_number == 0 && *r->out.sent_size == 0) {
731 0 : return NT_STATUS_END_OF_FILE;
732 : }
733 :
734 0 : return NT_STATUS_OK;
735 : }
736 :
737 : /********************************************************************
738 : _eventlog_GetOldestRecord
739 : ********************************************************************/
740 :
741 0 : NTSTATUS _eventlog_GetOldestRecord(struct pipes_struct *p,
742 : struct eventlog_GetOldestRecord *r)
743 : {
744 0 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
745 :
746 0 : if (info == NULL) {
747 0 : return NT_STATUS_INVALID_HANDLE;
748 : }
749 :
750 0 : if ( !( get_oldest_entry_hook( info ) ) )
751 0 : return NT_STATUS_ACCESS_DENIED;
752 :
753 0 : *r->out.oldest_entry = info->oldest_entry;
754 :
755 0 : return NT_STATUS_OK;
756 : }
757 :
758 : /********************************************************************
759 : _eventlog_GetNumRecords
760 : ********************************************************************/
761 :
762 2 : NTSTATUS _eventlog_GetNumRecords(struct pipes_struct *p,
763 : struct eventlog_GetNumRecords *r)
764 : {
765 2 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
766 :
767 2 : if (info == NULL) {
768 0 : return NT_STATUS_INVALID_HANDLE;
769 : }
770 :
771 2 : if ( !( get_num_records_hook( info ) ) )
772 0 : return NT_STATUS_ACCESS_DENIED;
773 :
774 2 : *r->out.number = info->num_records;
775 :
776 2 : return NT_STATUS_OK;
777 : }
778 :
779 0 : NTSTATUS _eventlog_BackupEventLogW(struct pipes_struct *p, struct eventlog_BackupEventLogW *r)
780 : {
781 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
782 0 : return NT_STATUS_NOT_IMPLEMENTED;
783 : }
784 :
785 : /********************************************************************
786 : _eventlog_GetLogInformation
787 : ********************************************************************/
788 :
789 6 : NTSTATUS _eventlog_GetLogInformation(struct pipes_struct *p,
790 : struct eventlog_GetLogInformation *r)
791 : {
792 6 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
793 0 : struct EVENTLOG_FULL_INFORMATION f;
794 0 : enum ndr_err_code ndr_err;
795 0 : DATA_BLOB blob;
796 :
797 6 : if (!info) {
798 0 : return NT_STATUS_INVALID_HANDLE;
799 : }
800 :
801 6 : if (r->in.level != 0) {
802 2 : return NT_STATUS_INVALID_LEVEL;
803 : }
804 :
805 4 : *r->out.bytes_needed = 4;
806 :
807 4 : if (r->in.buf_size < 4) {
808 2 : return NT_STATUS_BUFFER_TOO_SMALL;
809 : }
810 :
811 : /* FIXME: this should be retrieved from the handle */
812 2 : f.full = false;
813 :
814 2 : ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &f,
815 : (ndr_push_flags_fn_t)ndr_push_EVENTLOG_FULL_INFORMATION);
816 2 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
817 0 : return ndr_map_error2ntstatus(ndr_err);
818 : }
819 :
820 2 : if (DEBUGLEVEL >= 10) {
821 0 : NDR_PRINT_DEBUG(EVENTLOG_FULL_INFORMATION, &f);
822 : }
823 :
824 2 : memcpy(r->out.buffer, blob.data, 4);
825 :
826 2 : return NT_STATUS_OK;
827 : }
828 :
829 : /********************************************************************
830 : _eventlog_FlushEventLog
831 : ********************************************************************/
832 :
833 2 : NTSTATUS _eventlog_FlushEventLog(struct pipes_struct *p,
834 : struct eventlog_FlushEventLog *r)
835 : {
836 2 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
837 2 : if (!info) {
838 0 : return NT_STATUS_INVALID_HANDLE;
839 : }
840 :
841 2 : return NT_STATUS_ACCESS_DENIED;
842 : }
843 :
844 : /********************************************************************
845 : ********************************************************************/
846 :
847 2 : static NTSTATUS evlog_report_to_record(TALLOC_CTX *mem_ctx,
848 : const struct eventlog_ReportEventW *r,
849 : const char *logname,
850 : struct EVENTLOGRECORD *e)
851 : {
852 0 : uint32_t i;
853 2 : ZERO_STRUCTP(e);
854 :
855 2 : e->TimeGenerated = r->in.timestamp;
856 2 : e->TimeWritten = time(NULL);
857 2 : e->EventID = r->in.event_id;
858 2 : e->EventType = r->in.event_type;
859 2 : e->NumStrings = r->in.num_of_strings;
860 2 : e->EventCategory = r->in.event_category;
861 2 : e->ReservedFlags = r->in.flags;
862 2 : e->DataLength = r->in.data_size;
863 2 : e->SourceName = talloc_strdup(mem_ctx, logname);
864 2 : NT_STATUS_HAVE_NO_MEMORY(e->SourceName);
865 2 : if (r->in.servername->string) {
866 0 : e->Computername = r->in.servername->string;
867 : } else {
868 2 : e->Computername = talloc_strdup(mem_ctx, "");
869 2 : NT_STATUS_HAVE_NO_MEMORY(e->Computername);
870 : }
871 2 : if (r->in.user_sid) {
872 0 : e->UserSid = *r->in.user_sid;
873 : }
874 2 : e->Strings = talloc_array(mem_ctx, const char *, e->NumStrings);
875 2 : NT_STATUS_HAVE_NO_MEMORY(e->Strings);
876 :
877 4 : for (i=0; i < e->NumStrings; i++) {
878 4 : e->Strings[i] = talloc_strdup(e->Strings,
879 2 : r->in.strings[i]->string);
880 2 : NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]);
881 : }
882 2 : e->Data = r->in.data;
883 :
884 2 : return NT_STATUS_OK;
885 : }
886 :
887 : /********************************************************************
888 : _eventlog_ReportEventW
889 : ********************************************************************/
890 :
891 2 : NTSTATUS _eventlog_ReportEventW(struct pipes_struct *p,
892 : struct eventlog_ReportEventW *r)
893 : {
894 0 : NTSTATUS status;
895 0 : struct EVENTLOGRECORD record;
896 :
897 2 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
898 2 : if (!info) {
899 0 : return NT_STATUS_INVALID_HANDLE;
900 : }
901 :
902 2 : status = evlog_report_to_record(p->mem_ctx, r, info->logname, &record);
903 2 : if (!NT_STATUS_IS_OK(status)) {
904 0 : return status;
905 : }
906 :
907 2 : status = evlog_push_record(p->mem_ctx,
908 2 : ELOG_TDB_CTX(info->etdb),
909 : &record,
910 : r->out.record_number);
911 2 : if (!NT_STATUS_IS_OK(status)) {
912 0 : return status;
913 : }
914 :
915 2 : return NT_STATUS_OK;
916 : }
917 :
918 : /********************************************************************
919 : ********************************************************************/
920 :
921 0 : NTSTATUS _eventlog_DeregisterEventSource(struct pipes_struct *p,
922 : struct eventlog_DeregisterEventSource *r)
923 : {
924 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
925 0 : return NT_STATUS_NOT_IMPLEMENTED;
926 : }
927 :
928 0 : NTSTATUS _eventlog_ChangeNotify(struct pipes_struct *p,
929 : struct eventlog_ChangeNotify *r)
930 : {
931 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
932 0 : return NT_STATUS_NOT_IMPLEMENTED;
933 : }
934 :
935 0 : NTSTATUS _eventlog_RegisterEventSourceW(struct pipes_struct *p,
936 : struct eventlog_RegisterEventSourceW *r)
937 : {
938 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
939 0 : return NT_STATUS_NOT_IMPLEMENTED;
940 : }
941 :
942 0 : NTSTATUS _eventlog_OpenBackupEventLogW(struct pipes_struct *p,
943 : struct eventlog_OpenBackupEventLogW *r)
944 : {
945 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
946 0 : return NT_STATUS_NOT_IMPLEMENTED;
947 : }
948 :
949 0 : NTSTATUS _eventlog_ClearEventLogA(struct pipes_struct *p,
950 : struct eventlog_ClearEventLogA *r)
951 : {
952 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
953 0 : return NT_STATUS_NOT_IMPLEMENTED;
954 : }
955 :
956 0 : NTSTATUS _eventlog_BackupEventLogA(struct pipes_struct *p,
957 : struct eventlog_BackupEventLogA *r)
958 : {
959 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
960 0 : return NT_STATUS_NOT_IMPLEMENTED;
961 : }
962 :
963 0 : NTSTATUS _eventlog_OpenEventLogA(struct pipes_struct *p,
964 : struct eventlog_OpenEventLogA *r)
965 : {
966 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
967 0 : return NT_STATUS_NOT_IMPLEMENTED;
968 : }
969 :
970 0 : NTSTATUS _eventlog_RegisterEventSourceA(struct pipes_struct *p,
971 : struct eventlog_RegisterEventSourceA *r)
972 : {
973 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
974 0 : return NT_STATUS_NOT_IMPLEMENTED;
975 : }
976 :
977 0 : NTSTATUS _eventlog_OpenBackupEventLogA(struct pipes_struct *p,
978 : struct eventlog_OpenBackupEventLogA *r)
979 : {
980 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
981 0 : return NT_STATUS_NOT_IMPLEMENTED;
982 : }
983 :
984 0 : NTSTATUS _eventlog_ReadEventLogA(struct pipes_struct *p,
985 : struct eventlog_ReadEventLogA *r)
986 : {
987 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
988 0 : return NT_STATUS_NOT_IMPLEMENTED;
989 : }
990 :
991 0 : NTSTATUS _eventlog_ReportEventA(struct pipes_struct *p,
992 : struct eventlog_ReportEventA *r)
993 : {
994 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
995 0 : return NT_STATUS_NOT_IMPLEMENTED;
996 : }
997 :
998 0 : NTSTATUS _eventlog_RegisterClusterSvc(struct pipes_struct *p,
999 : struct eventlog_RegisterClusterSvc *r)
1000 : {
1001 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1002 0 : return NT_STATUS_NOT_IMPLEMENTED;
1003 : }
1004 :
1005 0 : NTSTATUS _eventlog_DeregisterClusterSvc(struct pipes_struct *p,
1006 : struct eventlog_DeregisterClusterSvc *r)
1007 : {
1008 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1009 0 : return NT_STATUS_NOT_IMPLEMENTED;
1010 : }
1011 :
1012 0 : NTSTATUS _eventlog_WriteClusterEvents(struct pipes_struct *p,
1013 : struct eventlog_WriteClusterEvents *r)
1014 : {
1015 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1016 0 : return NT_STATUS_NOT_IMPLEMENTED;
1017 : }
1018 :
1019 0 : NTSTATUS _eventlog_ReportEventAndSourceW(struct pipes_struct *p,
1020 : struct eventlog_ReportEventAndSourceW *r)
1021 : {
1022 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1023 0 : return NT_STATUS_NOT_IMPLEMENTED;
1024 : }
1025 :
1026 : static NTSTATUS eventlog__op_init_server(struct dcesrv_context *dce_ctx,
1027 : const struct dcesrv_endpoint_server *ep_server);
1028 :
1029 : #define DCESRV_INTERFACE_EVENTLOG_INIT_SERVER \
1030 : eventlog_init_server
1031 :
1032 126 : static NTSTATUS eventlog_init_server(struct dcesrv_context *dce_ctx,
1033 : const struct dcesrv_endpoint_server *ep_server)
1034 : {
1035 126 : struct messaging_context *msg_ctx = global_messaging_context();
1036 0 : bool ok;
1037 :
1038 126 : ok = eventlog_init_winreg(msg_ctx);
1039 126 : if (!ok) {
1040 0 : return NT_STATUS_UNSUCCESSFUL;
1041 : }
1042 :
1043 126 : return eventlog__op_init_server(dce_ctx, ep_server);
1044 : }
1045 :
1046 : /* include the generated boilerplate */
1047 : #include "librpc/gen_ndr/ndr_eventlog_scompat.c"
|