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