1/* 2 Unix SMB/CIFS implementation. 3 RPC pipe client 4 5 Copyright (C) G��nther Deschner 2009 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19*/ 20 21#include "includes.h" 22#include "rpcclient.h" 23#include "../librpc/gen_ndr/cli_eventlog.h" 24 25static NTSTATUS get_eventlog_handle(struct rpc_pipe_client *cli, 26 TALLOC_CTX *mem_ctx, 27 const char *log, 28 struct policy_handle *handle) 29{ 30 NTSTATUS status; 31 struct eventlog_OpenUnknown0 unknown0; 32 struct lsa_String logname, servername; 33 34 unknown0.unknown0 = 0x005c; 35 unknown0.unknown1 = 0x0001; 36 37 init_lsa_String(&logname, log); 38 init_lsa_String(&servername, NULL); 39 40 status = rpccli_eventlog_OpenEventLogW(cli, mem_ctx, 41 &unknown0, 42 &logname, 43 &servername, 44 0x00000001, /* major */ 45 0x00000001, /* minor */ 46 handle); 47 if (!NT_STATUS_IS_OK(status)) { 48 return status; 49 } 50 51 return NT_STATUS_OK; 52} 53 54static NTSTATUS cmd_eventlog_readlog(struct rpc_pipe_client *cli, 55 TALLOC_CTX *mem_ctx, 56 int argc, 57 const char **argv) 58{ 59 NTSTATUS status = NT_STATUS_OK; 60 struct policy_handle handle; 61 62 uint32_t flags = EVENTLOG_BACKWARDS_READ | 63 EVENTLOG_SEQUENTIAL_READ; 64 uint32_t offset = 0; 65 uint32_t number_of_bytes = 0; 66 uint8_t *data = NULL; 67 uint32_t sent_size = 0; 68 uint32_t real_size = 0; 69 70 if (argc < 2 || argc > 4) { 71 printf("Usage: %s logname [offset] [number_of_bytes]\n", argv[0]); 72 return NT_STATUS_OK; 73 } 74 75 if (argc >= 3) { 76 offset = atoi(argv[2]); 77 } 78 79 if (argc >= 4) { 80 number_of_bytes = atoi(argv[3]); 81 data = talloc_array(mem_ctx, uint8_t, number_of_bytes); 82 if (!data) { 83 goto done; 84 } 85 } 86 87 status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle); 88 if (!NT_STATUS_IS_OK(status)) { 89 return status; 90 } 91 92 do { 93 94 enum ndr_err_code ndr_err; 95 DATA_BLOB blob; 96 struct EVENTLOGRECORD r; 97 uint32_t size = 0; 98 uint32_t pos = 0; 99 100 status = rpccli_eventlog_ReadEventLogW(cli, mem_ctx, 101 &handle, 102 flags, 103 offset, 104 number_of_bytes, 105 data, 106 &sent_size, 107 &real_size); 108 if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL) && 109 real_size > 0 ) { 110 number_of_bytes = real_size; 111 data = talloc_array(mem_ctx, uint8_t, real_size); 112 if (!data) { 113 goto done; 114 } 115 status = rpccli_eventlog_ReadEventLogW(cli, mem_ctx, 116 &handle, 117 flags, 118 offset, 119 number_of_bytes, 120 data, 121 &sent_size, 122 &real_size); 123 } 124 125 if (!NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) && 126 !NT_STATUS_IS_OK(status)) { 127 goto done; 128 } 129 130 number_of_bytes = 0; 131 132 size = IVAL(data, pos); 133 134 while (size > 0) { 135 136 blob = data_blob_const(data + pos, size); 137 /* dump_data(0, blob.data, blob.length); */ 138 ndr_err = ndr_pull_struct_blob_all(&blob, mem_ctx, NULL, &r, 139 (ndr_pull_flags_fn_t)ndr_pull_EVENTLOGRECORD); 140 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 141 status = ndr_map_error2ntstatus(ndr_err); 142 goto done; 143 } 144 145 NDR_PRINT_DEBUG(EVENTLOGRECORD, &r); 146 147 pos += size; 148 149 if (pos + 4 > sent_size) { 150 break; 151 } 152 153 size = IVAL(data, pos); 154 } 155 156 offset++; 157 158 } while (NT_STATUS_IS_OK(status)); 159 160 done: 161 rpccli_eventlog_CloseEventLog(cli, mem_ctx, &handle); 162 163 return status; 164} 165 166static NTSTATUS cmd_eventlog_numrecords(struct rpc_pipe_client *cli, 167 TALLOC_CTX *mem_ctx, 168 int argc, 169 const char **argv) 170{ 171 NTSTATUS status; 172 struct policy_handle handle; 173 uint32_t number = 0; 174 175 if (argc != 2) { 176 printf("Usage: %s logname\n", argv[0]); 177 return NT_STATUS_OK; 178 } 179 180 status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle); 181 if (!NT_STATUS_IS_OK(status)) { 182 return status; 183 } 184 185 status = rpccli_eventlog_GetNumRecords(cli, mem_ctx, 186 &handle, 187 &number); 188 if (!NT_STATUS_IS_OK(status)) { 189 goto done; 190 } 191 192 printf("number of records: %d\n", number); 193 194 done: 195 rpccli_eventlog_CloseEventLog(cli, mem_ctx, &handle); 196 197 return status; 198} 199 200static NTSTATUS cmd_eventlog_oldestrecord(struct rpc_pipe_client *cli, 201 TALLOC_CTX *mem_ctx, 202 int argc, 203 const char **argv) 204{ 205 NTSTATUS status; 206 struct policy_handle handle; 207 uint32_t oldest_entry = 0; 208 209 if (argc != 2) { 210 printf("Usage: %s logname\n", argv[0]); 211 return NT_STATUS_OK; 212 } 213 214 status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle); 215 if (!NT_STATUS_IS_OK(status)) { 216 return status; 217 } 218 219 status = rpccli_eventlog_GetOldestRecord(cli, mem_ctx, 220 &handle, 221 &oldest_entry); 222 if (!NT_STATUS_IS_OK(status)) { 223 goto done; 224 } 225 226 printf("oldest entry: %d\n", oldest_entry); 227 228 done: 229 rpccli_eventlog_CloseEventLog(cli, mem_ctx, &handle); 230 231 return status; 232} 233 234static NTSTATUS cmd_eventlog_reportevent(struct rpc_pipe_client *cli, 235 TALLOC_CTX *mem_ctx, 236 int argc, 237 const char **argv) 238{ 239 NTSTATUS status; 240 struct policy_handle handle; 241 242 uint16_t num_of_strings = 1; 243 uint32_t data_size = 0; 244 struct lsa_String servername; 245 struct lsa_String *strings; 246 uint8_t *data = NULL; 247 uint32_t record_number = 0; 248 time_t time_written = 0; 249 250 if (argc != 2) { 251 printf("Usage: %s logname\n", argv[0]); 252 return NT_STATUS_OK; 253 } 254 255 status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle); 256 if (!NT_STATUS_IS_OK(status)) { 257 return status; 258 } 259 260 strings = talloc_array(mem_ctx, struct lsa_String, num_of_strings); 261 if (!strings) { 262 return NT_STATUS_NO_MEMORY; 263 } 264 265 init_lsa_String(&strings[0], "test event written by rpcclient\n"); 266 init_lsa_String(&servername, NULL); 267 268 status = rpccli_eventlog_ReportEventW(cli, mem_ctx, 269 &handle, 270 time(NULL), 271 EVENTLOG_INFORMATION_TYPE, 272 0, /* event_category */ 273 0, /* event_id */ 274 num_of_strings, 275 data_size, 276 &servername, 277 NULL, /* user_sid */ 278 &strings, 279 data, 280 0, /* flags */ 281 &record_number, 282 &time_written); 283 284 if (!NT_STATUS_IS_OK(status)) { 285 goto done; 286 } 287 288 printf("entry: %d written at %s\n", record_number, 289 http_timestring(talloc_tos(), time_written)); 290 291 done: 292 rpccli_eventlog_CloseEventLog(cli, mem_ctx, &handle); 293 294 return status; 295} 296 297static NTSTATUS cmd_eventlog_reporteventsource(struct rpc_pipe_client *cli, 298 TALLOC_CTX *mem_ctx, 299 int argc, 300 const char **argv) 301{ 302 NTSTATUS status; 303 struct policy_handle handle; 304 305 uint16_t num_of_strings = 1; 306 uint32_t data_size = 0; 307 struct lsa_String servername, sourcename; 308 struct lsa_String *strings; 309 uint8_t *data = NULL; 310 uint32_t record_number = 0; 311 time_t time_written = 0; 312 313 if (argc != 2) { 314 printf("Usage: %s logname\n", argv[0]); 315 return NT_STATUS_OK; 316 } 317 318 status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle); 319 if (!NT_STATUS_IS_OK(status)) { 320 return status; 321 } 322 323 strings = talloc_array(mem_ctx, struct lsa_String, num_of_strings); 324 if (!strings) { 325 return NT_STATUS_NO_MEMORY; 326 } 327 328 init_lsa_String(&strings[0], "test event written by rpcclient\n"); 329 init_lsa_String(&servername, NULL); 330 init_lsa_String(&sourcename, "rpcclient"); 331 332 status = rpccli_eventlog_ReportEventAndSourceW(cli, mem_ctx, 333 &handle, 334 time(NULL), 335 EVENTLOG_INFORMATION_TYPE, 336 0, /* event_category */ 337 0, /* event_id */ 338 &sourcename, 339 num_of_strings, 340 data_size, 341 &servername, 342 NULL, /* user_sid */ 343 &strings, 344 data, 345 0, /* flags */ 346 &record_number, 347 &time_written); 348 if (!NT_STATUS_IS_OK(status)) { 349 goto done; 350 } 351 352 printf("entry: %d written at %s\n", record_number, 353 http_timestring(talloc_tos(), time_written)); 354 355 done: 356 rpccli_eventlog_CloseEventLog(cli, mem_ctx, &handle); 357 358 return status; 359} 360 361static NTSTATUS cmd_eventlog_registerevsource(struct rpc_pipe_client *cli, 362 TALLOC_CTX *mem_ctx, 363 int argc, 364 const char **argv) 365{ 366 NTSTATUS status; 367 struct policy_handle log_handle; 368 struct lsa_String module_name, reg_module_name; 369 struct eventlog_OpenUnknown0 unknown0; 370 371 unknown0.unknown0 = 0x005c; 372 unknown0.unknown1 = 0x0001; 373 374 if (argc != 2) { 375 printf("Usage: %s logname\n", argv[0]); 376 return NT_STATUS_OK; 377 } 378 379 init_lsa_String(&module_name, "rpcclient"); 380 init_lsa_String(®_module_name, NULL); 381 382 status = rpccli_eventlog_RegisterEventSourceW(cli, mem_ctx, 383 &unknown0, 384 &module_name, 385 ®_module_name, 386 1, /* major_version */ 387 1, /* minor_version */ 388 &log_handle); 389 if (!NT_STATUS_IS_OK(status)) { 390 goto done; 391 } 392 393 done: 394 rpccli_eventlog_DeregisterEventSource(cli, mem_ctx, &log_handle); 395 396 return status; 397} 398 399static NTSTATUS cmd_eventlog_backuplog(struct rpc_pipe_client *cli, 400 TALLOC_CTX *mem_ctx, 401 int argc, 402 const char **argv) 403{ 404 NTSTATUS status; 405 struct policy_handle handle; 406 struct lsa_String backup_filename; 407 const char *tmp; 408 409 if (argc != 3) { 410 printf("Usage: %s logname backupname\n", argv[0]); 411 return NT_STATUS_OK; 412 } 413 414 status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle); 415 if (!NT_STATUS_IS_OK(status)) { 416 return status; 417 } 418 419 tmp = talloc_asprintf(mem_ctx, "\\??\\%s", argv[2]); 420 if (!tmp) { 421 status = NT_STATUS_NO_MEMORY; 422 goto done; 423 } 424 425 init_lsa_String(&backup_filename, tmp); 426 427 status = rpccli_eventlog_BackupEventLogW(cli, mem_ctx, 428 &handle, 429 &backup_filename); 430 431 done: 432 rpccli_eventlog_CloseEventLog(cli, mem_ctx, &handle); 433 434 return status; 435} 436 437static NTSTATUS cmd_eventlog_loginfo(struct rpc_pipe_client *cli, 438 TALLOC_CTX *mem_ctx, 439 int argc, 440 const char **argv) 441{ 442 NTSTATUS status; 443 struct policy_handle handle; 444 uint8_t *buffer = NULL; 445 uint32_t buf_size = 0; 446 uint32_t bytes_needed = 0; 447 448 if (argc != 2) { 449 printf("Usage: %s logname\n", argv[0]); 450 return NT_STATUS_OK; 451 } 452 453 status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle); 454 if (!NT_STATUS_IS_OK(status)) { 455 return status; 456 } 457 458 status = rpccli_eventlog_GetLogInformation(cli, mem_ctx, 459 &handle, 460 0, /* level */ 461 buffer, 462 buf_size, 463 &bytes_needed); 464 if (!NT_STATUS_IS_OK(status) && 465 !NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) { 466 goto done; 467 } 468 469 buf_size = bytes_needed; 470 buffer = talloc_array(mem_ctx, uint8_t, bytes_needed); 471 if (!buffer) { 472 status = NT_STATUS_NO_MEMORY; 473 goto done; 474 } 475 476 status = rpccli_eventlog_GetLogInformation(cli, mem_ctx, 477 &handle, 478 0, /* level */ 479 buffer, 480 buf_size, 481 &bytes_needed); 482 if (!NT_STATUS_IS_OK(status)) { 483 goto done; 484 } 485 486 done: 487 rpccli_eventlog_CloseEventLog(cli, mem_ctx, &handle); 488 489 return status; 490} 491 492 493struct cmd_set eventlog_commands[] = { 494 { "EVENTLOG" }, 495 { "eventlog_readlog", RPC_RTYPE_NTSTATUS, cmd_eventlog_readlog, NULL, &ndr_table_eventlog.syntax_id, NULL, "Read Eventlog", "" }, 496 { "eventlog_numrecord", RPC_RTYPE_NTSTATUS, cmd_eventlog_numrecords, NULL, &ndr_table_eventlog.syntax_id, NULL, "Get number of records", "" }, 497 { "eventlog_oldestrecord", RPC_RTYPE_NTSTATUS, cmd_eventlog_oldestrecord, NULL, &ndr_table_eventlog.syntax_id, NULL, "Get oldest record", "" }, 498 { "eventlog_reportevent", RPC_RTYPE_NTSTATUS, cmd_eventlog_reportevent, NULL, &ndr_table_eventlog.syntax_id, NULL, "Report event", "" }, 499 { "eventlog_reporteventsource", RPC_RTYPE_NTSTATUS, cmd_eventlog_reporteventsource, NULL, &ndr_table_eventlog.syntax_id, NULL, "Report event and source", "" }, 500 { "eventlog_registerevsource", RPC_RTYPE_NTSTATUS, cmd_eventlog_registerevsource, NULL, &ndr_table_eventlog.syntax_id, NULL, "Register event source", "" }, 501 { "eventlog_backuplog", RPC_RTYPE_NTSTATUS, cmd_eventlog_backuplog, NULL, &ndr_table_eventlog.syntax_id, NULL, "Backup Eventlog File", "" }, 502 { "eventlog_loginfo", RPC_RTYPE_NTSTATUS, cmd_eventlog_loginfo, NULL, &ndr_table_eventlog.syntax_id, NULL, "Get Eventlog Information", "" }, 503 { NULL } 504}; 505