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