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 0 : static int eventlog_info_destructor(EVENTLOG_INFO *elog)
60 : {
61 0 : if (elog->etdb) {
62 0 : elog_close_tdb(elog->etdb, false);
63 : }
64 0 : return 0;
65 : }
66 :
67 : /********************************************************************
68 : ********************************************************************/
69 :
70 0 : static EVENTLOG_INFO *find_eventlog_info_by_hnd( struct pipes_struct * p,
71 : struct policy_handle * handle )
72 : {
73 : EVENTLOG_INFO *info;
74 : NTSTATUS status;
75 :
76 0 : info = find_policy_by_hnd(p,
77 : handle,
78 : DCESRV_HANDLE_ANY,
79 : EVENTLOG_INFO,
80 : &status);
81 0 : 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 0 : 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 0 : 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 0 : TALLOC_CTX *frame = talloc_stackframe();
106 0 : struct conn_struct_tos *c = NULL;
107 0 : NTSTATUS status = NT_STATUS_OK;
108 0 : struct smb_filename *pathref_fname = NULL;
109 :
110 0 : if (!posix_locking_init(false)) {
111 0 : TALLOC_FREE(frame);
112 0 : return NT_STATUS_NO_MEMORY;
113 : }
114 :
115 0 : status = create_conn_struct_tos(global_messaging_context(),
116 : -1,
117 : "/",
118 : session_info,
119 : &c);
120 0 : 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 0 : status = synthetic_pathref(talloc_tos(),
128 0 : c->conn->cwd_fsp,
129 : fname,
130 : NULL,
131 : NULL,
132 : 0,
133 : 0,
134 : &pathref_fname);
135 0 : 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 0 : status = SMB_VFS_FGET_NT_ACL(pathref_fname->fsp,
142 : security_info_wanted,
143 : ctx,
144 : sd);
145 0 : 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 0 : TALLOC_FREE(frame);
151 :
152 0 : return status;
153 : }
154 :
155 : /********************************************************************
156 : ********************************************************************/
157 :
158 0 : static bool elog_check_access(EVENTLOG_INFO *info,
159 : struct auth_session_info *session_info)
160 : {
161 0 : const struct security_token *token = session_info->security_token;
162 0 : char *tdbname = elog_tdbname(talloc_tos(), info->logname );
163 : struct security_descriptor *sec_desc;
164 : struct security_ace *ace;
165 : NTSTATUS status;
166 :
167 0 : if ( !tdbname )
168 0 : return False;
169 :
170 : /* get the security descriptor for the file */
171 :
172 0 : status = get_nt_acl_no_snum( info,
173 : session_info,
174 : tdbname,
175 : SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL,
176 : &sec_desc);
177 0 : 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 0 : TALLOC_FREE(tdbname);
184 :
185 0 : ace = talloc_zero(sec_desc, struct security_ace);
186 0 : if (ace == NULL) {
187 0 : TALLOC_FREE(sec_desc);
188 0 : return false;
189 : }
190 :
191 0 : ace->type = SEC_ACE_TYPE_ACCESS_ALLOWED;
192 0 : ace->flags = 0;
193 0 : ace->access_mask = REG_KEY_ALL;
194 0 : ace->trustee = global_sid_System;
195 :
196 0 : status = security_descriptor_dacl_add(sec_desc, ace);
197 0 : if (!NT_STATUS_IS_OK(status)) {
198 0 : TALLOC_FREE(sec_desc);
199 0 : return false;
200 : }
201 :
202 : /* root free pass */
203 :
204 0 : if ( geteuid() == sec_initial_uid() ) {
205 0 : DEBUG(5,("elog_check_access: running as root, using system token\n"));
206 0 : token = get_system_token();
207 : }
208 :
209 : /* run the check, try for the max allowed */
210 :
211 0 : status = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS,
212 : &info->access_granted);
213 :
214 0 : TALLOC_FREE(sec_desc);
215 :
216 0 : 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 0 : return ( info->access_granted & SEC_FILE_READ_DATA );
225 : }
226 :
227 : /********************************************************************
228 : ********************************************************************/
229 :
230 0 : static bool elog_validate_logname( const char *name )
231 : {
232 : int i;
233 0 : const char **elogs = lp_eventlog_list();
234 :
235 0 : if (!elogs) {
236 0 : return False;
237 : }
238 :
239 0 : for ( i=0; elogs[i]; i++ ) {
240 0 : if ( strequal( name, elogs[i] ) )
241 0 : return True;
242 : }
243 :
244 0 : return False;
245 : }
246 :
247 : /********************************************************************
248 : ********************************************************************/
249 :
250 0 : static bool get_num_records_hook( EVENTLOG_INFO * info )
251 : {
252 : int next_record;
253 : int oldest_record;
254 :
255 0 : 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 0 : tdb_lock_bystring_with_timeout( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD, 1 );
263 0 : next_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
264 0 : oldest_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_OLDEST_ENTRY);
265 0 : tdb_unlock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
266 :
267 0 : DEBUG( 8,
268 : ( "Oldest Record %d; Next Record %d\n", oldest_record,
269 : next_record ) );
270 :
271 0 : info->num_records = ( next_record - oldest_record );
272 0 : info->oldest_entry = oldest_record;
273 :
274 0 : return True;
275 : }
276 :
277 : /********************************************************************
278 : ********************************************************************/
279 :
280 0 : static bool get_oldest_entry_hook( EVENTLOG_INFO * info )
281 : {
282 : /* it's the same thing */
283 0 : return get_num_records_hook( info );
284 : }
285 :
286 : /********************************************************************
287 : ********************************************************************/
288 :
289 0 : static NTSTATUS elog_open( struct pipes_struct * p, const char *logname, struct policy_handle *hnd )
290 : {
291 0 : struct dcesrv_call_state *dce_call = p->dce_call;
292 0 : struct auth_session_info *session_info =
293 0 : dcesrv_call_session_info(dce_call);
294 : EVENTLOG_INFO *elog;
295 :
296 : /* first thing is to validate the eventlog name */
297 :
298 0 : if ( !elog_validate_logname( logname ) )
299 0 : return NT_STATUS_OBJECT_PATH_INVALID;
300 :
301 0 : if ( !(elog = talloc_zero( NULL, EVENTLOG_INFO )) )
302 0 : return NT_STATUS_NO_MEMORY;
303 0 : talloc_set_destructor(elog, eventlog_info_destructor);
304 :
305 0 : 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 0 : become_root();
313 0 : elog->etdb = elog_open_tdb( elog->logname, False, False );
314 0 : unbecome_root();
315 :
316 0 : 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 0 : 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 0 : 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 0 : 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 0 : elog->current_record = elog->oldest_entry;
365 :
366 0 : return NT_STATUS_OK;
367 : }
368 :
369 : /********************************************************************
370 : ********************************************************************/
371 :
372 0 : static NTSTATUS elog_close( struct pipes_struct *p, struct policy_handle *hnd )
373 : {
374 0 : if ( !( close_policy_hnd( p, hnd ) ) ) {
375 0 : return NT_STATUS_INVALID_HANDLE;
376 : }
377 :
378 0 : 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 0 : static bool sync_eventlog_params(TALLOC_CTX *mem_ctx,
400 : struct messaging_context *msg_ctx,
401 : EVENTLOG_INFO *info)
402 : {
403 0 : struct dcerpc_binding_handle *h = NULL;
404 0 : uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
405 : struct policy_handle hive_hnd, key_hnd;
406 0 : uint32_t uiMaxSize = 0;
407 0 : uint32_t uiRetention = 0;
408 0 : char *path = NULL;
409 : NTSTATUS status;
410 0 : WERROR wresult = WERR_OK;
411 0 : char *elogname = info->logname;
412 : TALLOC_CTX *ctx;
413 0 : bool ret = false;
414 :
415 0 : ctx = talloc_stackframe();
416 0 : if (ctx == NULL) {
417 0 : return false;
418 : }
419 :
420 0 : DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
421 :
422 0 : if ( !info->etdb ) {
423 0 : DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) );
424 0 : goto done;
425 : }
426 : /* set resonable defaults. 512Kb on size and 1 week on time */
427 :
428 0 : uiMaxSize = 0x80000;
429 0 : 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 0 : path = talloc_asprintf(ctx, "%s\\%s", TOP_LEVEL_EVENTLOG_KEY, elogname);
436 0 : if (!path) {
437 0 : goto done;
438 : }
439 :
440 0 : 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 0 : 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 0 : 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 0 : status = dcerpc_winreg_query_dword(ctx,
463 : h,
464 : &key_hnd,
465 : "Retention",
466 : &uiRetention,
467 : &wresult);
468 0 : 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 0 : 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 0 : status = dcerpc_winreg_query_dword(ctx,
480 : h,
481 : &key_hnd,
482 : "MaxSize",
483 : &uiMaxSize,
484 : &wresult);
485 0 : 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 0 : 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 0 : tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize );
497 0 : tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention );
498 :
499 0 : ret = true;
500 :
501 0 : done:
502 0 : if (h != NULL) {
503 : WERROR ignore;
504 :
505 0 : if (is_valid_policy_hnd(&key_hnd)) {
506 0 : dcerpc_winreg_CloseKey(h, ctx, &key_hnd, &ignore);
507 : }
508 0 : if (is_valid_policy_hnd(&hive_hnd)) {
509 0 : dcerpc_winreg_CloseKey(h, ctx, &hive_hnd, &ignore);
510 : }
511 : }
512 :
513 0 : TALLOC_FREE(ctx);
514 0 : return ret;
515 : }
516 :
517 : /********************************************************************
518 : _eventlog_OpenEventLogW
519 : ********************************************************************/
520 :
521 0 : NTSTATUS _eventlog_OpenEventLogW(struct pipes_struct *p,
522 : struct eventlog_OpenEventLogW *r)
523 : {
524 : EVENTLOG_INFO *info;
525 : NTSTATUS result;
526 :
527 0 : 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 0 : if ( !NT_STATUS_IS_OK( result = elog_open( p, r->in.logname->string, r->out.handle )) )
534 0 : return result;
535 :
536 0 : 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 0 : DEBUG(10,("_eventlog_OpenEventLogW: Size [%d]\n", elog_size( info )));
544 :
545 0 : 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 0 : prune_eventlog( ELOG_TDB_CTX(info->etdb) );
552 :
553 0 : 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].",
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 0 : NTSTATUS _eventlog_CloseEventLog(struct pipes_struct * p,
612 : struct eventlog_CloseEventLog *r)
613 : {
614 : NTSTATUS status;
615 :
616 0 : status = elog_close( p, r->in.handle );
617 0 : if (!NT_STATUS_IS_OK(status)) {
618 0 : return status;
619 : }
620 :
621 0 : ZERO_STRUCTP(r->out.handle);
622 :
623 0 : return NT_STATUS_OK;
624 : }
625 :
626 : /********************************************************************
627 : _eventlog_ReadEventLogW
628 : ********************************************************************/
629 :
630 0 : NTSTATUS _eventlog_ReadEventLogW(struct pipes_struct *p,
631 : struct eventlog_ReadEventLogW *r)
632 : {
633 0 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
634 0 : uint32_t num_records_read = 0;
635 : int bytes_left, record_number;
636 : uint32_t elog_read_type, elog_read_dir;
637 :
638 0 : if (!info) {
639 0 : return NT_STATUS_INVALID_HANDLE;
640 : }
641 :
642 0 : info->flags = r->in.flags;
643 0 : bytes_left = r->in.number_of_bytes;
644 :
645 0 : if (!info->etdb) {
646 0 : return NT_STATUS_ACCESS_DENIED;
647 : }
648 :
649 : /* check for valid flags. Can't use the sequential and seek flags together */
650 :
651 0 : elog_read_type = r->in.flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ);
652 0 : elog_read_dir = r->in.flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ);
653 :
654 0 : if (r->in.flags == 0 ||
655 0 : elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) ||
656 : elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ))
657 : {
658 0 : DEBUG(3,("_eventlog_ReadEventLogW: "
659 : "Invalid flags [0x%08x] for ReadEventLog\n",
660 : r->in.flags));
661 0 : return NT_STATUS_INVALID_PARAMETER;
662 : }
663 :
664 : /* a sequential read should ignore the offset */
665 :
666 0 : if (elog_read_type & EVENTLOG_SEQUENTIAL_READ) {
667 0 : record_number = info->current_record;
668 : } else {
669 0 : record_number = r->in.offset;
670 : }
671 :
672 0 : if (r->in.number_of_bytes == 0) {
673 : struct EVENTLOGRECORD *e;
674 0 : e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb),
675 : record_number);
676 0 : if (!e) {
677 0 : return NT_STATUS_END_OF_FILE;
678 : }
679 0 : *r->out.real_size = e->Length;
680 0 : return NT_STATUS_BUFFER_TOO_SMALL;
681 : }
682 :
683 0 : while (bytes_left > 0) {
684 :
685 : DATA_BLOB blob;
686 : enum ndr_err_code ndr_err;
687 : struct EVENTLOGRECORD *e;
688 :
689 0 : e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb),
690 : record_number);
691 0 : if (!e) {
692 0 : break;
693 : }
694 :
695 0 : ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, e,
696 : (ndr_push_flags_fn_t)ndr_push_EVENTLOGRECORD);
697 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
698 0 : return ndr_map_error2ntstatus(ndr_err);
699 : }
700 :
701 0 : if (DEBUGLEVEL >= 10) {
702 0 : NDR_PRINT_DEBUG(EVENTLOGRECORD, e);
703 : }
704 :
705 0 : if (blob.length > r->in.number_of_bytes) {
706 0 : *r->out.real_size = blob.length;
707 0 : return NT_STATUS_BUFFER_TOO_SMALL;
708 : }
709 :
710 0 : if (*r->out.sent_size + blob.length > r->in.number_of_bytes) {
711 0 : break;
712 : }
713 :
714 0 : bytes_left -= blob.length;
715 :
716 0 : if (info->flags & EVENTLOG_FORWARDS_READ) {
717 0 : record_number++;
718 : } else {
719 0 : record_number--;
720 : }
721 :
722 : /* update the eventlog record pointer */
723 :
724 0 : info->current_record = record_number;
725 :
726 0 : memcpy(&r->out.data[*(r->out.sent_size)],
727 0 : blob.data, blob.length);
728 0 : *(r->out.sent_size) += blob.length;
729 :
730 0 : num_records_read++;
731 : }
732 :
733 0 : if (r->in.offset == 0 && record_number == 0 && *r->out.sent_size == 0) {
734 0 : return NT_STATUS_END_OF_FILE;
735 : }
736 :
737 0 : return NT_STATUS_OK;
738 : }
739 :
740 : /********************************************************************
741 : _eventlog_GetOldestRecord
742 : ********************************************************************/
743 :
744 0 : NTSTATUS _eventlog_GetOldestRecord(struct pipes_struct *p,
745 : struct eventlog_GetOldestRecord *r)
746 : {
747 0 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
748 :
749 0 : if (info == NULL) {
750 0 : return NT_STATUS_INVALID_HANDLE;
751 : }
752 :
753 0 : if ( !( get_oldest_entry_hook( info ) ) )
754 0 : return NT_STATUS_ACCESS_DENIED;
755 :
756 0 : *r->out.oldest_entry = info->oldest_entry;
757 :
758 0 : return NT_STATUS_OK;
759 : }
760 :
761 : /********************************************************************
762 : _eventlog_GetNumRecords
763 : ********************************************************************/
764 :
765 0 : NTSTATUS _eventlog_GetNumRecords(struct pipes_struct *p,
766 : struct eventlog_GetNumRecords *r)
767 : {
768 0 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
769 :
770 0 : if (info == NULL) {
771 0 : return NT_STATUS_INVALID_HANDLE;
772 : }
773 :
774 0 : if ( !( get_num_records_hook( info ) ) )
775 0 : return NT_STATUS_ACCESS_DENIED;
776 :
777 0 : *r->out.number = info->num_records;
778 :
779 0 : return NT_STATUS_OK;
780 : }
781 :
782 0 : NTSTATUS _eventlog_BackupEventLogW(struct pipes_struct *p, struct eventlog_BackupEventLogW *r)
783 : {
784 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
785 0 : return NT_STATUS_NOT_IMPLEMENTED;
786 : }
787 :
788 : /********************************************************************
789 : _eventlog_GetLogInformation
790 : ********************************************************************/
791 :
792 0 : NTSTATUS _eventlog_GetLogInformation(struct pipes_struct *p,
793 : struct eventlog_GetLogInformation *r)
794 : {
795 0 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
796 : struct EVENTLOG_FULL_INFORMATION f;
797 : enum ndr_err_code ndr_err;
798 : DATA_BLOB blob;
799 :
800 0 : if (!info) {
801 0 : return NT_STATUS_INVALID_HANDLE;
802 : }
803 :
804 0 : if (r->in.level != 0) {
805 0 : return NT_STATUS_INVALID_LEVEL;
806 : }
807 :
808 0 : *r->out.bytes_needed = 4;
809 :
810 0 : if (r->in.buf_size < 4) {
811 0 : return NT_STATUS_BUFFER_TOO_SMALL;
812 : }
813 :
814 : /* FIXME: this should be retrieved from the handle */
815 0 : f.full = false;
816 :
817 0 : ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &f,
818 : (ndr_push_flags_fn_t)ndr_push_EVENTLOG_FULL_INFORMATION);
819 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
820 0 : return ndr_map_error2ntstatus(ndr_err);
821 : }
822 :
823 0 : if (DEBUGLEVEL >= 10) {
824 0 : NDR_PRINT_DEBUG(EVENTLOG_FULL_INFORMATION, &f);
825 : }
826 :
827 0 : memcpy(r->out.buffer, blob.data, 4);
828 :
829 0 : return NT_STATUS_OK;
830 : }
831 :
832 : /********************************************************************
833 : _eventlog_FlushEventLog
834 : ********************************************************************/
835 :
836 0 : NTSTATUS _eventlog_FlushEventLog(struct pipes_struct *p,
837 : struct eventlog_FlushEventLog *r)
838 : {
839 0 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
840 0 : if (!info) {
841 0 : return NT_STATUS_INVALID_HANDLE;
842 : }
843 :
844 0 : return NT_STATUS_ACCESS_DENIED;
845 : }
846 :
847 : /********************************************************************
848 : ********************************************************************/
849 :
850 0 : static NTSTATUS evlog_report_to_record(TALLOC_CTX *mem_ctx,
851 : const struct eventlog_ReportEventW *r,
852 : const char *logname,
853 : struct EVENTLOGRECORD *e)
854 : {
855 : uint32_t i;
856 0 : ZERO_STRUCTP(e);
857 :
858 0 : e->TimeGenerated = r->in.timestamp;
859 0 : e->TimeWritten = time(NULL);
860 0 : e->EventID = r->in.event_id;
861 0 : e->EventType = r->in.event_type;
862 0 : e->NumStrings = r->in.num_of_strings;
863 0 : e->EventCategory = r->in.event_category;
864 0 : e->ReservedFlags = r->in.flags;
865 0 : e->DataLength = r->in.data_size;
866 0 : e->SourceName = talloc_strdup(mem_ctx, logname);
867 0 : NT_STATUS_HAVE_NO_MEMORY(e->SourceName);
868 0 : if (r->in.servername->string) {
869 0 : e->Computername = r->in.servername->string;
870 : } else {
871 0 : e->Computername = talloc_strdup(mem_ctx, "");
872 0 : NT_STATUS_HAVE_NO_MEMORY(e->Computername);
873 : }
874 0 : if (r->in.user_sid) {
875 0 : e->UserSid = *r->in.user_sid;
876 : }
877 0 : e->Strings = talloc_array(mem_ctx, const char *, e->NumStrings);
878 0 : NT_STATUS_HAVE_NO_MEMORY(e->Strings);
879 :
880 0 : for (i=0; i < e->NumStrings; i++) {
881 0 : e->Strings[i] = talloc_strdup(e->Strings,
882 0 : r->in.strings[i]->string);
883 0 : NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]);
884 : }
885 0 : e->Data = r->in.data;
886 :
887 0 : return NT_STATUS_OK;
888 : }
889 :
890 : /********************************************************************
891 : _eventlog_ReportEventW
892 : ********************************************************************/
893 :
894 0 : NTSTATUS _eventlog_ReportEventW(struct pipes_struct *p,
895 : struct eventlog_ReportEventW *r)
896 : {
897 : NTSTATUS status;
898 : struct EVENTLOGRECORD record;
899 :
900 0 : EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
901 0 : if (!info) {
902 0 : return NT_STATUS_INVALID_HANDLE;
903 : }
904 :
905 0 : status = evlog_report_to_record(p->mem_ctx, r, info->logname, &record);
906 0 : if (!NT_STATUS_IS_OK(status)) {
907 0 : return status;
908 : }
909 :
910 0 : status = evlog_push_record(p->mem_ctx,
911 0 : ELOG_TDB_CTX(info->etdb),
912 : &record,
913 : r->out.record_number);
914 0 : if (!NT_STATUS_IS_OK(status)) {
915 0 : return status;
916 : }
917 :
918 0 : return NT_STATUS_OK;
919 : }
920 :
921 : /********************************************************************
922 : ********************************************************************/
923 :
924 0 : NTSTATUS _eventlog_DeregisterEventSource(struct pipes_struct *p,
925 : struct eventlog_DeregisterEventSource *r)
926 : {
927 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
928 0 : return NT_STATUS_NOT_IMPLEMENTED;
929 : }
930 :
931 0 : NTSTATUS _eventlog_ChangeNotify(struct pipes_struct *p,
932 : struct eventlog_ChangeNotify *r)
933 : {
934 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
935 0 : return NT_STATUS_NOT_IMPLEMENTED;
936 : }
937 :
938 0 : NTSTATUS _eventlog_RegisterEventSourceW(struct pipes_struct *p,
939 : struct eventlog_RegisterEventSourceW *r)
940 : {
941 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
942 0 : return NT_STATUS_NOT_IMPLEMENTED;
943 : }
944 :
945 0 : NTSTATUS _eventlog_OpenBackupEventLogW(struct pipes_struct *p,
946 : struct eventlog_OpenBackupEventLogW *r)
947 : {
948 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
949 0 : return NT_STATUS_NOT_IMPLEMENTED;
950 : }
951 :
952 0 : NTSTATUS _eventlog_ClearEventLogA(struct pipes_struct *p,
953 : struct eventlog_ClearEventLogA *r)
954 : {
955 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
956 0 : return NT_STATUS_NOT_IMPLEMENTED;
957 : }
958 :
959 0 : NTSTATUS _eventlog_BackupEventLogA(struct pipes_struct *p,
960 : struct eventlog_BackupEventLogA *r)
961 : {
962 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
963 0 : return NT_STATUS_NOT_IMPLEMENTED;
964 : }
965 :
966 0 : NTSTATUS _eventlog_OpenEventLogA(struct pipes_struct *p,
967 : struct eventlog_OpenEventLogA *r)
968 : {
969 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
970 0 : return NT_STATUS_NOT_IMPLEMENTED;
971 : }
972 :
973 0 : NTSTATUS _eventlog_RegisterEventSourceA(struct pipes_struct *p,
974 : struct eventlog_RegisterEventSourceA *r)
975 : {
976 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
977 0 : return NT_STATUS_NOT_IMPLEMENTED;
978 : }
979 :
980 0 : NTSTATUS _eventlog_OpenBackupEventLogA(struct pipes_struct *p,
981 : struct eventlog_OpenBackupEventLogA *r)
982 : {
983 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
984 0 : return NT_STATUS_NOT_IMPLEMENTED;
985 : }
986 :
987 0 : NTSTATUS _eventlog_ReadEventLogA(struct pipes_struct *p,
988 : struct eventlog_ReadEventLogA *r)
989 : {
990 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
991 0 : return NT_STATUS_NOT_IMPLEMENTED;
992 : }
993 :
994 0 : NTSTATUS _eventlog_ReportEventA(struct pipes_struct *p,
995 : struct eventlog_ReportEventA *r)
996 : {
997 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
998 0 : return NT_STATUS_NOT_IMPLEMENTED;
999 : }
1000 :
1001 0 : NTSTATUS _eventlog_RegisterClusterSvc(struct pipes_struct *p,
1002 : struct eventlog_RegisterClusterSvc *r)
1003 : {
1004 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1005 0 : return NT_STATUS_NOT_IMPLEMENTED;
1006 : }
1007 :
1008 0 : NTSTATUS _eventlog_DeregisterClusterSvc(struct pipes_struct *p,
1009 : struct eventlog_DeregisterClusterSvc *r)
1010 : {
1011 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1012 0 : return NT_STATUS_NOT_IMPLEMENTED;
1013 : }
1014 :
1015 0 : NTSTATUS _eventlog_WriteClusterEvents(struct pipes_struct *p,
1016 : struct eventlog_WriteClusterEvents *r)
1017 : {
1018 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1019 0 : return NT_STATUS_NOT_IMPLEMENTED;
1020 : }
1021 :
1022 0 : NTSTATUS _eventlog_ReportEventAndSourceW(struct pipes_struct *p,
1023 : struct eventlog_ReportEventAndSourceW *r)
1024 : {
1025 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1026 0 : return NT_STATUS_NOT_IMPLEMENTED;
1027 : }
1028 :
1029 : static NTSTATUS eventlog__op_init_server(struct dcesrv_context *dce_ctx,
1030 : const struct dcesrv_endpoint_server *ep_server);
1031 :
1032 : #define DCESRV_INTERFACE_EVENTLOG_INIT_SERVER \
1033 : eventlog_init_server
1034 :
1035 31 : static NTSTATUS eventlog_init_server(struct dcesrv_context *dce_ctx,
1036 : const struct dcesrv_endpoint_server *ep_server)
1037 : {
1038 31 : struct messaging_context *msg_ctx = global_messaging_context();
1039 : bool ok;
1040 :
1041 31 : ok = eventlog_init_winreg(msg_ctx);
1042 31 : if (!ok) {
1043 0 : return NT_STATUS_UNSUCCESSFUL;
1044 : }
1045 :
1046 31 : return eventlog__op_init_server(dce_ctx, ep_server);
1047 : }
1048 :
1049 : /* include the generated boilerplate */
1050 : #include "librpc/gen_ndr/ndr_eventlog_scompat.c"
|