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