s3-registry: avoid using registry_value union.
[nivanova/samba-autobuild/.git] / source3 / rpc_server / srv_eventlog_nt.c
index 2f163a379fba9c3ef3fe3daf4e606ead5297fe47..19d0514717251c0a308724e6a887b5a4a10a10b9 100644 (file)
@@ -21,6 +21,9 @@
  */
 
 #include "includes.h"
+#include "../librpc/gen_ndr/srv_eventlog.h"
+#include "lib/eventlog/eventlog.h"
+#include "registry.h"
 
 #undef  DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
@@ -50,7 +53,7 @@ static int eventlog_info_destructor(EVENTLOG_INFO *elog)
  ********************************************************************/
 
 static EVENTLOG_INFO *find_eventlog_info_by_hnd( pipes_struct * p,
-                                               POLICY_HND * handle )
+                                               struct policy_handle * handle )
 {
        EVENTLOG_INFO *info;
 
@@ -69,7 +72,8 @@ static EVENTLOG_INFO *find_eventlog_info_by_hnd( pipes_struct * p,
 static bool elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token )
 {
        char *tdbname = elog_tdbname(talloc_tos(), info->logname );
-       SEC_DESC *sec_desc;
+       struct security_descriptor *sec_desc;
+       struct security_ace *ace;
        NTSTATUS status;
 
        if ( !tdbname )
@@ -86,11 +90,28 @@ static bool elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token )
                return False;
        }
 
+       ace = talloc_zero(sec_desc, struct security_ace);
+       if (ace == NULL) {
+               TALLOC_FREE(sec_desc);
+               return false;
+       }
+
+       ace->type               = SEC_ACE_TYPE_ACCESS_ALLOWED;
+       ace->flags              = 0;
+       ace->access_mask        = REG_KEY_ALL;
+       ace->trustee            = global_sid_System;
+
+       status = security_descriptor_dacl_add(sec_desc, ace);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(sec_desc);
+               return false;
+       }
+
        /* root free pass */
 
        if ( geteuid() == sec_initial_uid() ) {
-               DEBUG(5,("elog_check_access: using root's token\n"));
-               token = get_root_nt_token();
+               DEBUG(5,("elog_check_access: running as root, using system token\n"));
+               token = get_system_token();
        }
 
        /* run the check, try for the max allowed */
@@ -98,8 +119,7 @@ static bool elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token )
        status = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS,
                &info->access_granted);
 
-       if ( sec_desc )
-               TALLOC_FREE( sec_desc );
+       TALLOC_FREE(sec_desc);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(8,("elog_check_access: se_access_check() return %s\n",
@@ -109,7 +129,7 @@ static bool elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token )
 
        /* we have to have READ permission for a successful open */
 
-       return ( info->access_granted & SA_RIGHT_FILE_READ_DATA );
+       return ( info->access_granted & SEC_FILE_READ_DATA );
 }
 
 /********************************************************************
@@ -174,7 +194,7 @@ static bool get_oldest_entry_hook( EVENTLOG_INFO * info )
 /********************************************************************
  ********************************************************************/
 
-static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hnd )
+static NTSTATUS elog_open( pipes_struct * p, const char *logname, struct policy_handle *hnd )
 {
        EVENTLOG_INFO *elog;
 
@@ -254,7 +274,7 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn
 /********************************************************************
  ********************************************************************/
 
-static NTSTATUS elog_close( pipes_struct *p, POLICY_HND *hnd )
+static NTSTATUS elog_close( pipes_struct *p, struct policy_handle *hnd )
 {
         if ( !( close_policy_hnd( p, hnd ) ) ) {
                 return NT_STATUS_INVALID_HANDLE;
@@ -284,8 +304,8 @@ static int elog_size( EVENTLOG_INFO *info )
 static bool sync_eventlog_params( EVENTLOG_INFO *info )
 {
        char *path = NULL;
-       uint32 uiMaxSize;
-       uint32 uiRetention;
+       uint32_t uiMaxSize = 0;
+       uint32_t uiRetention = 0;
        struct registry_key *key;
        struct registry_value *value;
        WERROR wresult;
@@ -309,12 +329,12 @@ static bool sync_eventlog_params( EVENTLOG_INFO *info )
           to use the same fetch/store api that we use in
           srv_reg_nt.c */
 
-       path = talloc_asprintf(ctx, "%s/%s", KEY_EVENTLOG, elogname );
+       path = talloc_asprintf(ctx, "%s\\%s", KEY_EVENTLOG, elogname);
        if (!path) {
                goto done;
        }
 
-       wresult = reg_open_path(ctx, path, REG_KEY_READ, get_root_nt_token(),
+       wresult = reg_open_path(ctx, path, REG_KEY_READ, get_system_token(),
                                &key);
 
        if ( !W_ERROR_IS_OK( wresult ) ) {
@@ -330,7 +350,10 @@ static bool sync_eventlog_params( EVENTLOG_INFO *info )
                          win_errstr(wresult)));
                goto done;
        }
-       uiRetention = value->v.dword;
+
+       if (value->data.length >= 4) {
+               uiRetention = IVAL(value->data.data, 0);
+       }
 
        wresult = reg_queryvalue(key, key, "MaxSize", &value);
        if (!W_ERROR_IS_OK(wresult)) {
@@ -338,7 +361,9 @@ static bool sync_eventlog_params( EVENTLOG_INFO *info )
                          win_errstr(wresult)));
                goto done;
        }
-       uiMaxSize = value->v.dword;
+       if (value->data.length >= 4) {
+               uiMaxSize = IVAL(value->data.data, 0);
+       }
 
        tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize );
        tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention );
@@ -378,7 +403,10 @@ NTSTATUS _eventlog_OpenEventLogW(pipes_struct *p,
 
        DEBUG(10,("_eventlog_OpenEventLogW: Size [%d]\n", elog_size( info )));
 
-       sync_eventlog_params( info );
+       if (!sync_eventlog_params(info)) {
+               elog_close(p, r->out.handle);
+               return NT_STATUS_EVENTLOG_FILE_CORRUPT;
+       }
        prune_eventlog( ELOG_TDB_CTX(info->etdb) );
 
        return NT_STATUS_OK;
@@ -419,7 +447,7 @@ NTSTATUS _eventlog_ClearEventLogW(pipes_struct *p,
 
        /* check for WRITE access to the file */
 
-       if ( !(info->access_granted&SA_RIGHT_FILE_WRITE_DATA) )
+       if ( !(info->access_granted & SEC_FILE_WRITE_DATA) )
                return NT_STATUS_ACCESS_DENIED;
 
        /* Force a close and reopen */
@@ -523,7 +551,7 @@ NTSTATUS _eventlog_ReadEventLogW(pipes_struct *p,
                        break;
                }
 
-               ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL, e,
+               ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, e,
                              (ndr_push_flags_fn_t)ndr_push_EVENTLOGRECORD);
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        return ndr_map_error2ntstatus(ndr_err);
@@ -616,6 +644,142 @@ NTSTATUS _eventlog_BackupEventLogW(pipes_struct *p, struct eventlog_BackupEventL
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+/********************************************************************
+_eventlog_GetLogInformation
+ ********************************************************************/
+
+NTSTATUS _eventlog_GetLogInformation(pipes_struct *p,
+                                    struct eventlog_GetLogInformation *r)
+{
+       EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
+       struct EVENTLOG_FULL_INFORMATION f;
+       enum ndr_err_code ndr_err;
+       DATA_BLOB blob;
+
+       if (!info) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (r->in.level != 0) {
+               return NT_STATUS_INVALID_LEVEL;
+       }
+
+       *r->out.bytes_needed = 4;
+
+       if (r->in.buf_size < 4) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+
+       /* FIXME: this should be retrieved from the handle */
+       f.full = false;
+
+       ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &f,
+                     (ndr_push_flags_fn_t)ndr_push_EVENTLOG_FULL_INFORMATION);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return ndr_map_error2ntstatus(ndr_err);
+       }
+
+       if (DEBUGLEVEL >= 10) {
+               NDR_PRINT_DEBUG(EVENTLOG_FULL_INFORMATION, &f);
+       }
+
+       memcpy(r->out.buffer, blob.data, 4);
+
+       return NT_STATUS_OK;
+}
+
+/********************************************************************
+_eventlog_FlushEventLog
+ ********************************************************************/
+
+NTSTATUS _eventlog_FlushEventLog(pipes_struct *p,
+                                struct eventlog_FlushEventLog *r)
+{
+       EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
+       if (!info) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       return NT_STATUS_ACCESS_DENIED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+static NTSTATUS evlog_report_to_record(TALLOC_CTX *mem_ctx,
+                                      const struct eventlog_ReportEventW *r,
+                                      const char *logname,
+                                      struct EVENTLOGRECORD *e)
+{
+       uint32_t i;
+       ZERO_STRUCTP(e);
+
+       e->TimeGenerated        = r->in.timestamp;
+       e->TimeWritten          = time(NULL);
+       e->EventID              = r->in.event_id;
+       e->EventType            = r->in.event_type;
+       e->NumStrings           = r->in.num_of_strings;
+       e->EventCategory        = r->in.event_category;
+       e->ReservedFlags        = r->in.flags;
+       e->DataLength           = r->in.data_size;
+       e->SourceName           = talloc_strdup(mem_ctx, logname);
+       NT_STATUS_HAVE_NO_MEMORY(e->SourceName);
+       if (r->in.servername->string) {
+               e->Computername = r->in.servername->string;
+       } else {
+               e->Computername = talloc_strdup(mem_ctx, "");
+               NT_STATUS_HAVE_NO_MEMORY(e->Computername);
+       }
+       if (r->in.user_sid) {
+               e->UserSid      = *r->in.user_sid;
+       }
+       e->Strings              = talloc_array(mem_ctx, const char *, e->NumStrings);
+       NT_STATUS_HAVE_NO_MEMORY(e->Strings);
+
+       for (i=0; i < e->NumStrings; i++) {
+               e->Strings[i] = talloc_strdup(e->Strings,
+                                             r->in.strings[i]->string);
+               NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]);
+       }
+       e->Data                 = r->in.data;
+
+       return NT_STATUS_OK;
+}
+
+/********************************************************************
+_eventlog_ReportEventW
+ ********************************************************************/
+
+NTSTATUS _eventlog_ReportEventW(pipes_struct *p,
+                               struct eventlog_ReportEventW *r)
+{
+       NTSTATUS status;
+       struct EVENTLOGRECORD record;
+
+       EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
+       if (!info) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       status = evlog_report_to_record(p->mem_ctx, r, info->logname, &record);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       status = evlog_push_record(p->mem_ctx,
+                                  ELOG_TDB_CTX(info->etdb),
+                                  &record,
+                                  r->out.record_number);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/********************************************************************
+ ********************************************************************/
+
 NTSTATUS _eventlog_DeregisterEventSource(pipes_struct *p, struct eventlog_DeregisterEventSource *r)
 {
        p->rng_fault_state = True;
@@ -640,12 +804,6 @@ NTSTATUS _eventlog_OpenBackupEventLogW(pipes_struct *p, struct eventlog_OpenBack
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS _eventlog_ReportEventW(pipes_struct *p, struct eventlog_ReportEventW *r)
-{
-       p->rng_fault_state = True;
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
 NTSTATUS _eventlog_ClearEventLogA(pipes_struct *p, struct eventlog_ClearEventLogA *r)
 {
        p->rng_fault_state = True;
@@ -706,18 +864,6 @@ NTSTATUS _eventlog_WriteClusterEvents(pipes_struct *p, struct eventlog_WriteClus
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS _eventlog_GetLogInformation(pipes_struct *p, struct eventlog_GetLogInformation *r)
-{
-       p->rng_fault_state = True;
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS _eventlog_FlushEventLog(pipes_struct *p, struct eventlog_FlushEventLog *r)
-{
-       p->rng_fault_state = True;
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
 NTSTATUS _eventlog_ReportEventAndSourceW(pipes_struct *p, struct eventlog_ReportEventAndSourceW *r)
 {
        p->rng_fault_state = True;