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