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