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