s4-smbtorture: fix segfault in RPC-EVENTLOG test.
[kai/samba.git] / source4 / torture / rpc / eventlog.c
index a98b3e9e79ff8ccdc8fb840fc772df3919df22e1..31d91c056bfe5071e33b081665ce5fcf6a61a5f3 100644 (file)
@@ -2,12 +2,12 @@
    Unix SMB/CIFS implementation.
    test suite for eventlog rpc operations
 
-   Copyright (C) Tim Potter 2003
+   Copyright (C) Tim Potter 2003,2005
    Copyright (C) Jelmer Vernooij 2004
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "torture/torture.h"
 #include "librpc/gen_ndr/ndr_eventlog.h"
+#include "librpc/gen_ndr/ndr_eventlog_c.h"
+#include "librpc/gen_ndr/ndr_lsa.h"
+#include "torture/rpc/rpc.h"
+#include "param/param.h"
 
-static void init_eventlog_String(struct eventlog_String *name, const char *s)
+static void init_lsa_String(struct lsa_String *name, const char *s)
 {
-       name->name = s;
-       name->name_len = 2*strlen_m(s);
-       name->name_size = name->name_len;
+       name->string = s;
+       name->length = 2*strlen_m(s);
+       name->size = name->length;
 }
 
-static BOOL test_GetNumRecords(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle)
+static bool get_policy_handle(struct torture_context *tctx, 
+                                                         struct dcerpc_pipe *p,
+                                                         struct policy_handle *handle)
+{
+       struct eventlog_OpenEventLogW r;
+       struct eventlog_OpenUnknown0 unknown0;
+       struct lsa_String logname, servername;
+
+       unknown0.unknown0 = 0x005c;
+       unknown0.unknown1 = 0x0001;
+
+       r.in.unknown0 = &unknown0;
+       init_lsa_String(&logname, "dns server");
+       init_lsa_String(&servername, NULL);
+       r.in.logname = &logname;
+       r.in.servername = &servername;
+       r.in.unknown2 = 0x00000001;
+       r.in.unknown3 = 0x00000001;
+       r.out.handle = handle;
+
+       torture_assert_ntstatus_ok(tctx, 
+                       dcerpc_eventlog_OpenEventLogW(p, tctx, &r), 
+                       "OpenEventLog failed");
+
+       torture_assert_ntstatus_ok(tctx, r.out.result, "OpenEventLog failed");
+
+       return true;
+}
+
+
+
+static bool test_GetNumRecords(struct torture_context *tctx, struct dcerpc_pipe *p)
 {
-       NTSTATUS status;
        struct eventlog_GetNumRecords r;
+       struct eventlog_CloseEventLog cr;
+       struct policy_handle handle;
+       uint32_t number = 0;
 
-       printf("\ntesting GetNumRecords\n");
+       if (!get_policy_handle(tctx, p, &handle))
+               return false;
 
-       r.in.handle = handle;
+       ZERO_STRUCT(r);
+       r.in.handle = &handle;
+       r.out.number = &number;
 
-       status = dcerpc_eventlog_GetNumRecords(p, mem_ctx, &r);
+       torture_assert_ntstatus_ok(tctx, 
+                       dcerpc_eventlog_GetNumRecords(p, tctx, &r), 
+                       "GetNumRecords failed");
 
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("GetNumRecords failed - %s\n", nt_errstr(status));
-               return False;
-       }
+       torture_comment(tctx, "%d records\n", *r.out.number);
 
-       printf("%d records\n", r.out.number);
+       cr.in.handle = cr.out.handle = &handle;
 
-       return True;
+       torture_assert_ntstatus_ok(tctx, 
+                                       dcerpc_eventlog_CloseEventLog(p, tctx, &cr), 
+                                       "CloseEventLog failed");
+       return true;
 }
 
-static BOOL test_ReadEventLog(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle, uint32_t offset)
+static bool test_ReadEventLog(struct torture_context *tctx, 
+                                                         struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct eventlog_ReadEventLogW r;
+       struct eventlog_CloseEventLog cr;
+       struct policy_handle handle;
 
-       printf("\ntesting ReadEventLog\n");
+       if (!get_policy_handle(tctx, p, &handle))
+               return false;
 
-       r.in.flags = 0x0;
-       r.in.offset = offset;
-       r.in.handle = handle;
-       r.in.number_of_bytes = 0x0;
+       ZERO_STRUCT(r);
+       r.in.offset = 0;
+       r.in.handle = &handle;
+       r.in.flags = EVENTLOG_BACKWARDS_READ|EVENTLOG_SEQUENTIAL_READ;
 
-       status = dcerpc_eventlog_ReadEventLogW(p, mem_ctx, &r);
+       while (1) {
+               DATA_BLOB blob;
+               struct eventlog_Record rec;
+               struct ndr_pull *ndr;
+               enum ndr_err_code ndr_err;
+               uint32_t sent_size = 0;
+               uint32_t real_size = 0;
 
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ReadEventLog failed - %s\n", nt_errstr(status));
-               return False;
-       }
+               /* Read first for number of bytes in record */
 
-       if (NT_STATUS_IS_OK(r.out.result)) {
-               /* No data */
-               return True;
-       }
+               r.in.number_of_bytes = 0;
+               r.out.data = NULL;
+               r.out.sent_size = &sent_size;
+               r.out.real_size = &real_size;
 
-       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_BUFFER_TOO_SMALL)) {
-               printf("ReadEventLog failed - %s\n", nt_errstr(r.out.result));
-               return False;
-       }
+               status = dcerpc_eventlog_ReadEventLogW(p, tctx, &r);
 
-       r.in.number_of_bytes = r.out.real_size;
+               if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_END_OF_FILE)) {
+                       break;
+               }
 
-       status = dcerpc_eventlog_ReadEventLogW(p, mem_ctx, &r);
+               torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_BUFFER_TOO_SMALL,
+                       "ReadEventLog failed");
+               
+               /* Now read the actual record */
 
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ReadEventLog failed - %s\n", nt_errstr(status));
-               return False;
-       }
+               r.in.number_of_bytes = *r.out.real_size;
+               r.out.data = talloc_array(tctx, uint8_t, r.in.number_of_bytes);
 
+               status = dcerpc_eventlog_ReadEventLogW(p, tctx, &r);
 
-       return True;
-}
+               torture_assert_ntstatus_ok(tctx, status, "ReadEventLog failed");
+               
+               /* Decode a user-marshalled record */
 
-BOOL test_CloseEventLog(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                       struct policy_handle *handle)
-{
-       NTSTATUS status;
-       struct eventlog_CloseEventLog r;
+               blob.length = *r.out.sent_size;
+               blob.data = talloc_steal(tctx, r.out.data);
+
+               ndr = ndr_pull_init_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx));
 
-       r.in.handle = r.out.handle = handle;
+               ndr_err = ndr_pull_eventlog_Record(
+                       ndr, NDR_SCALARS|NDR_BUFFERS, &rec);
+               status = ndr_map_error2ntstatus(ndr_err);
 
-       printf("Testing CloseEventLog\n");
+               NDR_PRINT_DEBUG(eventlog_Record, &rec);
 
-       status = dcerpc_eventlog_CloseEventLog(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("CloseEventLog failed - %s\n", nt_errstr(status));
-               return False;
+               torture_assert_ntstatus_ok(tctx, status, 
+                               "ReadEventLog failed parsing event log record");
+
+               r.in.offset++;
        }
 
-       return True;
+       cr.in.handle = cr.out.handle = &handle;
+
+       torture_assert_ntstatus_ok(tctx, 
+                                       dcerpc_eventlog_CloseEventLog(p, tctx, &cr), 
+                                       "CloseEventLog failed");
+
+       return true;
 }
 
-static BOOL test_OpenEventLog(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle)
+static bool test_FlushEventLog(struct torture_context *tctx, 
+                                                          struct dcerpc_pipe *p)
 {
-       NTSTATUS status;
-       struct eventlog_OpenEventLogW r;
-       struct eventlog_OpenUnknown0 unknown0;
+       struct eventlog_FlushEventLog r;
+       struct eventlog_CloseEventLog cr;
+       struct policy_handle handle;
 
-       printf("\ntesting OpenEventLog\n");
+       if (!get_policy_handle(tctx, p, &handle))
+               return false;
 
-       unknown0.unknown0 = 0x005c;
-       unknown0.unknown1 = 0x0001;
-
-       r.in.unknown0 = &unknown0;
-       init_eventlog_String(&r.in.source, "system");
-       init_eventlog_String(&r.in.unknown1, NULL);
-       r.in.unknown2 = 0x00000001;
-       r.in.unknown3 = 0x00000001;
-       r.out.handle = handle;
+       r.in.handle = &handle;
 
-       status = dcerpc_eventlog_OpenEventLogW(p, mem_ctx, &r);
+       /* Huh?  Does this RPC always return access denied? */
+       torture_assert_ntstatus_equal(tctx, 
+                       dcerpc_eventlog_FlushEventLog(p, tctx, &r),
+                       NT_STATUS_ACCESS_DENIED, 
+                       "FlushEventLog failed");
 
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenEventLog failed - %s\n", nt_errstr(status));
-               return False;
-       }
+       cr.in.handle = cr.out.handle = &handle;
 
-       if (!NT_STATUS_IS_OK(r.out.result)) {
-               printf("OpenEventLog failed - %s\n", nt_errstr(r.out.result));
-               return False;
-       }
+       torture_assert_ntstatus_ok(tctx, 
+                                       dcerpc_eventlog_CloseEventLog(p, tctx, &cr), 
+                                       "CloseEventLog failed");
 
-       return True;
+       return true;
 }
 
-BOOL torture_rpc_eventlog(void)
+static bool test_ClearEventLog(struct torture_context *tctx, 
+                              struct dcerpc_pipe *p)
 {
-    NTSTATUS status;
-    struct dcerpc_pipe *p;
+       struct eventlog_ClearEventLogW r;
+       struct eventlog_CloseEventLog cr;
        struct policy_handle handle;
-       TALLOC_CTX *mem_ctx;
-       BOOL ret = True;
 
-       mem_ctx = talloc_init("torture_rpc_atsvc");
+       if (!get_policy_handle(tctx, p, &handle))
+               return false;
 
-       status = torture_rpc_connection(&p, 
-                                       DCERPC_EVENTLOG_NAME, 
-                                       DCERPC_EVENTLOG_UUID, 
-                                       DCERPC_EVENTLOG_VERSION);
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
-       }
+       r.in.handle = &handle;
+       r.in.backupfile = NULL;
 
-       if (!test_OpenEventLog(p, mem_ctx, &handle)) {
-               return False;
-       }
+       torture_assert_ntstatus_ok(tctx, 
+                       dcerpc_eventlog_ClearEventLogW(p, tctx, &r), 
+                       "ClearEventLog failed");
+
+       cr.in.handle = cr.out.handle = &handle;
 
-       test_GetNumRecords(p, mem_ctx, &handle);
+       torture_assert_ntstatus_ok(tctx, 
+                                       dcerpc_eventlog_CloseEventLog(p, tctx, &cr), 
+                                       "CloseEventLog failed");
 
-       test_ReadEventLog(p, mem_ctx, &handle, 0);
+       return true;
+}
+
+static bool test_OpenEventLog(struct torture_context *tctx, 
+                                                         struct dcerpc_pipe *p)
+{
+       struct policy_handle handle;
+       struct eventlog_CloseEventLog cr;
 
-       test_CloseEventLog(p, mem_ctx, &handle);
+       if (!get_policy_handle(tctx, p, &handle))
+               return false;
 
-       talloc_destroy(mem_ctx);
+       cr.in.handle = cr.out.handle = &handle;
 
-    torture_rpc_close(p);
+       torture_assert_ntstatus_ok(tctx, 
+                                       dcerpc_eventlog_CloseEventLog(p, tctx, &cr), 
+                                       "CloseEventLog failed");
 
-       return ret;
+       return true;
+}
+
+struct torture_suite *torture_rpc_eventlog(TALLOC_CTX *mem_ctx)
+{
+       struct torture_suite *suite;
+       struct torture_rpc_tcase *tcase;
+       struct torture_test *test;
+
+       suite = torture_suite_create(mem_ctx, "EVENTLOG");
+       tcase = torture_suite_add_rpc_iface_tcase(suite, "eventlog", 
+                                                 &ndr_table_eventlog);
+
+       torture_rpc_tcase_add_test(tcase, "OpenEventLog", test_OpenEventLog);
+       test = torture_rpc_tcase_add_test(tcase, "ClearEventLog", 
+                                         test_ClearEventLog);
+       test->dangerous = true;
+       torture_rpc_tcase_add_test(tcase, "GetNumRecords", test_GetNumRecords);
+       torture_rpc_tcase_add_test(tcase, "ReadEventLog", test_ReadEventLog);
+       torture_rpc_tcase_add_test(tcase, "FlushEventLog", test_FlushEventLog);
+
+       return suite;
 }