r6304: missed some files in the previous commit
[Samba.git] / source / rpc_server / srv_eventlog_nt.c
blob7501434a134033e8917115c7fbe327595c0074c7
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Marcin Krzysztof Porwit 2005.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_RPC_SRV
26 typedef struct eventlog_info
28 /* for use by the \PIPE\eventlog policy */
29 fstring source_log_file_name;
30 fstring source_server_name;
31 fstring handle_string;
32 uint32 num_records;
33 uint32 oldest_entry;
34 } Eventlog_info;
36 static void free_eventlog_info(void *ptr)
38 struct eventlog_info *info = (struct eventlog_info *)ptr;
39 memset(info->source_log_file_name, '0', sizeof(*(info->source_log_file_name)));
40 memset(info->source_server_name, '0', sizeof(*(info->source_server_name)));
41 memset(info->handle_string, '0', sizeof(*(info->handle_string)));
42 memset(info, 0, sizeof(*(info)));
43 SAFE_FREE(info);
46 static Eventlog_info *find_eventlog_info_by_hnd(pipes_struct *p,
47 POLICY_HND *handle)
49 Eventlog_info *info = NULL;
51 if(!(find_policy_by_hnd(p,handle,(void **)&info)))
53 DEBUG(2,("find_eventlog_info_by_hnd: eventlog not found.\n"));
56 return info;
59 void policy_handle_to_string(POLICY_HND *handle, fstring *dest)
61 memset(dest, 0, sizeof(*dest));
62 snprintf((char *)dest, sizeof(*dest), "%08X-%08X-%04X-%04X-%02X%02X%02X%02X%02X",
63 handle->data1,
64 handle->data2,
65 handle->data3,
66 handle->data4,
67 handle->data5[0],
68 handle->data5[1],
69 handle->data5[2],
70 handle->data5[3],
71 handle->data5[4]);
74 /**
75 * Callout to open the specified event log
77 * smbrun calling convention --
78 * INPUT: <open_cmd> <log name> <policy handle>
79 * OUTPUT: the string "SUCCESS" if the command succeeded
80 * no such string if there was a failure.
82 static BOOL _eventlog_open_eventlog_hook(Eventlog_info *info)
84 char *cmd = lp_eventlog_open_cmd();
85 char **qlines;
86 pstring command;
87 int numlines = 0;
88 int ret;
89 int fd = -1;
91 if(cmd == NULL || strlen(cmd) == 0)
93 DEBUG(0, ("Must define an \"eventlog open command\" entry in the config.\n"));
94 return False;
97 memset(command, 0, sizeof(command));
98 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
99 cmd,
100 info->source_log_file_name,
101 info->handle_string);
103 DEBUG(10, ("Running [%s]\n", command));
104 ret = smbrun(command, &fd);
105 DEBUGADD(10, ("returned [%d]\n", ret));
107 if(ret != 0)
109 if(fd != -1)
110 close(fd);
111 return False;
114 qlines = fd_lines_load(fd, &numlines);
115 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
116 close(fd);
118 if(numlines)
120 DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
121 if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
123 DEBUGADD(10, ("Able to open [%s].\n", info->source_log_file_name));
124 file_lines_free(qlines);
125 return True;
129 file_lines_free(qlines);
130 return False;
133 WERROR _eventlog_open_eventlog(pipes_struct *p,
134 EVENTLOG_Q_OPEN_EVENTLOG *q_u,
135 EVENTLOG_R_OPEN_EVENTLOG *r_u)
137 Eventlog_info *info = NULL;
139 if(!q_u || !r_u)
140 return WERR_NOMEM;
142 if((info = SMB_MALLOC_P(Eventlog_info)) == NULL)
143 return WERR_NOMEM;
145 ZERO_STRUCTP(info);
147 if(q_u->servername_ptr != 0)
149 unistr2_to_ascii(info->source_server_name, &(q_u->servername), sizeof(info->source_server_name));
151 else
153 /* if servername == NULL, use the local computer */
154 fstrcpy(info->source_server_name, global_myname());
156 DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the server name.\n", info->source_server_name));
158 if(q_u->sourcename_ptr != 0)
160 unistr2_to_ascii(info->source_log_file_name, &(q_u->sourcename), sizeof(info->source_log_file_name));
162 else
164 /* if sourcename == NULL, default to "Application" log */
165 fstrcpy(info->source_log_file_name, "Application");
167 DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the source log file.\n", info->source_log_file_name));
169 if(!create_policy_hnd(p, &(r_u->handle), free_eventlog_info, (void *)info))
170 return WERR_NOMEM;
172 policy_handle_to_string(&r_u->handle, &info->handle_string);
174 if(!(_eventlog_open_eventlog_hook(info)))
175 return WERR_BADFILE;
177 return WERR_OK;
180 * Callout to get the number of records in the specified event log
182 * smbrun calling convention --
183 * INPUT: <get_num_records_cmd> <log name> <policy handle>
184 * OUTPUT: A single line with a single integer containing the number of
185 * entries in the log. If there are no entries in the log, return 0.
187 static BOOL _eventlog_get_num_records_hook(Eventlog_info *info)
189 char *cmd = lp_eventlog_num_records_cmd();
190 char **qlines;
191 pstring command;
192 int numlines = 0;
193 int ret;
194 int fd = -1;
196 if(cmd == NULL || strlen(cmd) == 0)
198 DEBUG(0, ("Must define an \"eventlog num records command\" entry in the config.\n"));
199 return False;
202 memset(command, 0, sizeof(command));
203 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
204 cmd,
205 info->source_log_file_name,
206 info->handle_string);
208 DEBUG(10, ("Running [%s]\n", command));
209 ret = smbrun(command, &fd);
210 DEBUGADD(10, ("returned [%d]\n", ret));
212 if(ret != 0)
214 if(fd != -1)
215 close(fd);
216 return False;
219 qlines = fd_lines_load(fd, &numlines);
220 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
221 close(fd);
223 if(numlines)
225 DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
226 sscanf(qlines[0], "%d", &(info->num_records));
227 file_lines_free(qlines);
228 return True;
231 file_lines_free(qlines);
232 return False;
235 WERROR _eventlog_get_num_records(pipes_struct *p,
236 EVENTLOG_Q_GET_NUM_RECORDS *q_u,
237 EVENTLOG_R_GET_NUM_RECORDS *r_u)
239 Eventlog_info *info = NULL;
240 POLICY_HND *handle = NULL;
242 if(!q_u || !r_u)
243 return WERR_NOMEM;
245 handle = &(q_u->handle);
246 info = find_eventlog_info_by_hnd(p, handle);
248 if(!(_eventlog_get_num_records_hook(info)))
249 return WERR_BADFILE;
251 r_u->num_records = info->num_records;
253 return WERR_OK;
256 * Callout to find the oldest record in the log
258 * smbrun calling convention --
259 * INPUT: <oldest_entry_cmd> <log name> <policy handle>
260 * OUTPUT: If there are entries in the event log, the index of the
261 * oldest entry. Must be 1 or greater.
262 * If there are no entries in the log, returns a 0
264 static BOOL _eventlog_get_oldest_entry_hook(Eventlog_info *info)
266 char *cmd = lp_eventlog_oldest_record_cmd();
267 char **qlines;
268 pstring command;
269 int numlines = 0;
270 int ret;
271 int fd = -1;
273 if(cmd == NULL || strlen(cmd) == 0)
275 DEBUG(0, ("Must define an \"eventlog oldest record command\" entry in the config.\n"));
276 return False;
279 memset(command, 0, sizeof(command));
280 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
281 cmd,
282 info->source_log_file_name,
283 info->handle_string);
285 DEBUG(10, ("Running [%s]\n", command));
286 ret = smbrun(command, &fd);
287 DEBUGADD(10, ("returned [%d]\n", ret));
289 if(ret != 0)
291 if(fd != -1)
292 close(fd);
293 return False;
296 qlines = fd_lines_load(fd, &numlines);
297 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
298 close(fd);
300 if(numlines)
302 DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
303 sscanf(qlines[0], "%d", &(info->oldest_entry));
304 file_lines_free(qlines);
305 return True;
308 file_lines_free(qlines);
309 return False;
312 WERROR _eventlog_get_oldest_entry(pipes_struct *p,
313 EVENTLOG_Q_GET_OLDEST_ENTRY *q_u,
314 EVENTLOG_R_GET_OLDEST_ENTRY *r_u)
316 Eventlog_info *info = NULL;
317 POLICY_HND *handle = NULL;
319 if(!q_u || !r_u)
320 return WERR_NOMEM;
322 handle = &(q_u->handle);
323 info = find_eventlog_info_by_hnd(p, handle);
325 if(!(_eventlog_get_oldest_entry_hook(info)))
326 return WERR_BADFILE;
328 r_u->oldest_entry = info->oldest_entry;
330 return WERR_OK;
334 * Callout to close the specified event log
336 * smbrun calling convention --
337 * INPUT: <close_cmd> <log name> <policy handle>
338 * OUTPUT: the string "SUCCESS" if the command succeeded
339 * no such string if there was a failure.
341 static BOOL _eventlog_close_eventlog_hook(Eventlog_info *info)
343 char *cmd = lp_eventlog_close_cmd();
344 char **qlines;
345 pstring command;
346 int numlines = 0;
347 int ret;
348 int fd = -1;
350 if(cmd == NULL || strlen(cmd) == 0)
352 DEBUG(0, ("Must define an \"eventlog close command\" entry in the config.\n"));
353 return False;
356 memset(command, 0, sizeof(command));
357 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
358 cmd,
359 info->source_log_file_name,
360 info->handle_string);
362 DEBUG(10, ("Running [%s]\n", command));
363 ret = smbrun(command, &fd);
364 DEBUGADD(10, ("returned [%d]\n", ret));
366 if(ret != 0)
368 if(fd != -1)
369 close(fd);
370 return False;
373 qlines = fd_lines_load(fd, &numlines);
374 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
375 close(fd);
377 if(numlines)
379 DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
380 if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
382 DEBUGADD(10, ("Able to close [%s].\n", info->source_log_file_name));
383 file_lines_free(qlines);
384 return True;
388 file_lines_free(qlines);
389 return False;
392 WERROR _eventlog_close_eventlog(pipes_struct *p,
393 EVENTLOG_Q_CLOSE_EVENTLOG *q_u,
394 EVENTLOG_R_CLOSE_EVENTLOG *r_u)
396 Eventlog_info *info = NULL;
397 POLICY_HND *handle;
399 if(!q_u || !r_u)
400 return WERR_NOMEM;
402 handle = &(q_u->handle);
404 info = find_eventlog_info_by_hnd(p, handle);
405 if(!(_eventlog_close_eventlog_hook(info)))
406 return WERR_BADFILE;
408 if(!(close_policy_hnd(p, handle)))
410 /* WERR_NOMEM is probably not the correct error, but until I figure out a better
411 one it will have to do */
412 return WERR_NOMEM;
415 return WERR_OK;
418 static BOOL _eventlog_read_parse_line(char *line, Eventlog_entry *entry)
420 char *start = NULL, *stop = NULL;
421 pstring temp;
422 int temp_len = 0, i;
424 start = line;
426 if(start == NULL || strlen(start) == 0)
427 return False;
428 if(!(stop = strchr(line, ':')))
429 return False;
431 DEBUG(6, ("_eventlog_read_parse_line: trying to parse [%s].\n", line));
433 if(0 == strncmp(start, "LEN", stop - start))
435 /* This will get recomputed later anyway -- probably not necessary */
436 entry->record.length = atoi(stop + 1);
438 else if(0 == strncmp(start, "RS1", stop - start))
440 /* For now all these reserved entries seem to have the same value,
441 which can be hardcoded to int(1699505740) for now */
442 entry->record.reserved1 = atoi(stop + 1);
444 else if(0 == strncmp(start, "RCN", stop - start))
446 entry->record.record_number = atoi(stop + 1);
448 else if(0 == strncmp(start, "TMG", stop - start))
450 entry->record.time_generated = atoi(stop + 1);
452 else if(0 == strncmp(start, "TMW", stop - start))
454 entry->record.time_written = atoi(stop + 1);
456 else if(0 == strncmp(start, "EID", stop - start))
458 entry->record.event_id = atoi(stop + 1);
460 else if(0 == strncmp(start, "ETP", stop - start))
462 if(strstr(start, "ERROR"))
464 entry->record.event_type = EVENTLOG_ERROR_TYPE;
466 else if(strstr(start, "WARNING"))
468 entry->record.event_type = EVENTLOG_WARNING_TYPE;
470 else if(strstr(start, "INFO"))
472 entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
474 else if(strstr(start, "AUDIT_SUCCESS"))
476 entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
478 else if(strstr(start, "AUDIT_FAILURE"))
480 entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
482 else if(strstr(start, "SUCCESS"))
484 entry->record.event_type = EVENTLOG_SUCCESS;
486 else
488 /* some other eventlog type -- currently not defined in MSDN docs, so error out */
489 return False;
493 else if(0 == strncmp(start, "NST", stop - start))
495 entry->record.num_strings = atoi(stop + 1);
498 else if(0 == strncmp(start, "ECT", stop - start))
500 entry->record.event_category = atoi(stop + 1);
502 else if(0 == strncmp(start, "RS2", stop - start))
504 entry->record.reserved2 = atoi(stop + 1);
506 else if(0 == strncmp(start, "CRN", stop - start))
508 entry->record.closing_record_number = atoi(stop + 1);
510 else if(0 == strncmp(start, "USL", stop - start))
512 entry->record.user_sid_length = atoi(stop + 1);
514 else if(0 == strncmp(start, "SRC", stop - start))
516 memset(temp, 0, sizeof(temp));
517 sscanf(stop+1, "%s", temp);
518 temp_len = strlen(temp);
519 rpcstr_push((void *)(entry->data_record.source_name), temp,
520 sizeof(entry->data_record.source_name), STR_TERMINATE);
521 entry->data_record.source_name_len = (strlen_w(entry->data_record.source_name)* 2) + 2;
523 else if(0 == strncmp(start, "SRN", stop - start))
525 memset(temp, 0, sizeof(temp));
526 sscanf(stop+1, "%s", temp);
527 temp_len = strlen(temp);
528 rpcstr_push((void *)(entry->data_record.computer_name), temp,
529 sizeof(entry->data_record.computer_name), STR_TERMINATE);
530 entry->data_record.computer_name_len = (strlen_w(entry->data_record.computer_name)* 2) + 2;
532 else if(0 == strncmp(start, "SID", stop - start))
534 memset(temp, 0, sizeof(temp));
535 sscanf(stop+1, "%s", temp);
536 temp_len = strlen(temp);
537 rpcstr_push((void *)(entry->data_record.sid), temp,
538 sizeof(entry->data_record.sid), STR_TERMINATE);
539 entry->record.user_sid_length = (strlen_w(entry->data_record.sid) * 2) + 2;
541 else if(0 == strncmp(start, "STR", stop - start))
543 /* skip past initial ":" */
544 stop++;
545 /* now skip any other leading whitespace */
546 while(isspace(stop[0]))
547 stop++;
548 temp_len = strlen(stop);
549 memset(temp, 0, sizeof(temp));
550 strncpy(temp, stop, temp_len);
551 rpcstr_push((void *)(entry->data_record.strings + entry->data_record.strings_len),
552 temp,
553 sizeof(entry->data_record.strings) - entry->data_record.strings_len,
554 STR_TERMINATE);
555 entry->data_record.strings_len += temp_len + 1;
556 fprintf(stderr, "Dumping strings:\n");
557 for(i = 0; i < entry->data_record.strings_len; i++)
559 fputc((char)entry->data_record.strings[i], stderr);
561 fprintf(stderr, "\nDone\n");
562 entry->record.num_strings++;
564 else if(0 == strncmp(start, "DAT", stop - start))
566 /* Now that we're done processing the STR data, adjust the length to account for
567 unicode, then proceed with the DAT data. */
568 entry->data_record.strings_len *= 2;
569 /* skip past initial ":" */
570 stop++;
571 /* now skip any other leading whitespace */
572 while(isspace(stop[0]))
573 stop++;
574 memset(temp, 0, sizeof(temp));
575 temp_len = strlen(stop);
576 strncpy(temp, stop, temp_len);
577 rpcstr_push((void *)(entry->data_record.user_data), temp,
578 sizeof(entry->data_record.user_data), STR_TERMINATE);
579 entry->data_record.user_data_len = (strlen_w((const smb_ucs2_t *)entry->data_record.user_data) * 2) + 2;
581 else
583 /* some other eventlog entry -- not implemented, so dropping on the floor */
584 DEBUG(10, ("Unknown entry [%s]. Ignoring.\n", line));
585 /* For now return true so that we can keep on parsing this mess. Eventually
586 we will return False here. */
587 return True;
589 return True;
592 * Callout to read entries from the specified event log
594 * smbrun calling convention --
595 * INPUT: <read_cmd> <log name> <direction> <starting record> <buffer size> <policy handle>
596 * where direction is either "forward" or "backward", the starting record is somewhere
597 * between the oldest_record and oldest_record+num_records, and the buffer size is the
598 * maximum size of the buffer that the client can accomodate.
599 * OUTPUT: A buffer containing a set of entries, one to a line, of the format:
600 * line type:line data
601 * These are the allowed line types:
602 * RS1:(uint32) - reserved. All M$ entries seem to have int(1699505740) for now
603 * RCN:(uint32) - record number of the record, however it may be calculated by the script
604 * TMG:(uint32) - time generated, seconds since January 1, 1970, 0000 UTC
605 * TMW:(uint32) - time written, seconds since January 1, 1970, 0000 UTC
606 * EID:(uint32) - eventlog source defined event identifier. If there's a stringfile for the event, it is an index into that
607 * ETP:(uint16) - eventlog type - one of ERROR, WARNING, INFO, AUDIT_SUCCESS, AUDIT_FAILURE
608 * ECT:(uint16) - event category - depends on the eventlog generator...
609 * RS2:(uint16) - reserved, make it 0000
610 * CRN:(uint32) - reserved, make it 00000000 for now
611 * USL:(uint32) - user SID length. No sid? Make this 0. Must match SID below
612 * SRC:[(uint8)] - Name of the source, for example ccPwdSvc, in hex bytes. Can not be multiline.
613 * SRN:[(uint8)] - Name of the computer on which this is generated, the short hostname usually.
614 * SID:[(uint8)] - User sid if one exists. Must be present even if there is no SID.
615 * STR:[(uint8)] - String data. One string per line. Multiple strings can be specified using consecutive "STR" lines,
616 * up to a total aggregate string length of 1024 characters.
617 * DAT:[(uint8)] - The user-defined data portion of the event log. Can not be multiple lines.
619 static BOOL _eventlog_read_eventlog_hook(Eventlog_info *info, Eventlog_entry *entry, const char *direction, int starting_record, int buffer_size, BOOL *eof)
621 char *cmd = lp_eventlog_read_cmd();
622 char **qlines;
623 pstring command;
624 int numlines = 0;
625 int ret;
626 int fd = -1;
627 int i;
629 if(info == NULL)
630 return False;
632 if(cmd == NULL || strlen(cmd) == 0)
634 DEBUG(0, ("Must define an \"eventlog read command\" entry in the config.\n"));
635 return False;
638 slprintf(command, sizeof(command)-1, "%s \"%s\" %s %d %d \"%s\"",
639 cmd,
640 info->source_log_file_name,
641 direction,
642 starting_record,
643 buffer_size,
644 info->handle_string);
646 DEBUG(10, ("Running [%s]\n", command));
647 ret = smbrun(command, &fd);
648 DEBUGADD(10, ("returned [%d]\n", ret));
650 if(ret != 0)
652 if(fd != -1)
653 close(fd);
654 return False;
657 qlines = fd_lines_load(fd, &numlines);
658 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
659 close(fd);
661 if(numlines)
663 for(i = 0; i < numlines; i++)
665 DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i]));
666 _eventlog_read_parse_line(qlines[i], entry);
668 file_lines_free(qlines);
669 return True;
671 else
672 *eof = True;
674 file_lines_free(qlines);
675 return False;
678 static BOOL _eventlog_read_prepare_data_buffer(prs_struct *ps,
679 EVENTLOG_Q_READ_EVENTLOG *q_u,
680 EVENTLOG_R_READ_EVENTLOG *r_u,
681 Eventlog_entry *entry)
683 uint8 *offset;
684 Eventlog_entry *new = NULL, *insert_point = NULL;
686 new = PRS_ALLOC_MEM(ps, Eventlog_entry, 1);
687 if(new == NULL)
688 return False;
690 entry->data_record.sid_padding = ((4 - ((entry->data_record.source_name_len
691 + entry->data_record.computer_name_len) % 4)) %4);
692 entry->data_record.data_padding = (4 - ((entry->data_record.strings_len
693 + entry->data_record.user_data_len) % 4)) % 4;
694 entry->record.length = sizeof(Eventlog_record);
695 entry->record.length += entry->data_record.source_name_len;
696 entry->record.length += entry->data_record.computer_name_len;
697 if(entry->record.user_sid_length == 0)
699 /* Should not pad to a DWORD boundary for writing out the sid if there is
700 no SID, so just propagate the padding to pad the data */
701 entry->data_record.data_padding += entry->data_record.sid_padding;
702 entry->data_record.sid_padding = 0;
704 DEBUG(10, ("sid_padding is [%d].\n", entry->data_record.sid_padding));
705 DEBUG(10, ("data_padding is [%d].\n", entry->data_record.data_padding));
707 entry->record.length += entry->data_record.sid_padding;
708 entry->record.length += entry->record.user_sid_length;
709 entry->record.length += entry->data_record.strings_len;
710 entry->record.length += entry->data_record.user_data_len;
711 entry->record.length += entry->data_record.data_padding;
712 /* need another copy of length at the end of the data */
713 entry->record.length += sizeof(entry->record.length);
714 DEBUG(10, ("entry->record.length is [%d].\n", entry->record.length));
715 entry->data = PRS_ALLOC_MEM(ps, uint8, entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length));
716 if(entry->data == NULL)
717 return False;
718 offset = entry->data;
719 memcpy(offset, &(entry->data_record.source_name), entry->data_record.source_name_len);
720 offset += entry->data_record.source_name_len;
721 memcpy(offset, &(entry->data_record.computer_name), entry->data_record.computer_name_len);
722 offset += entry->data_record.computer_name_len;
723 /* SID needs to be DWORD-aligned */
724 offset += entry->data_record.sid_padding;
725 entry->record.user_sid_offset = sizeof(Eventlog_record) + (offset - entry->data);
726 memcpy(offset, &(entry->data_record.sid), entry->record.user_sid_length);
727 offset += entry->record.user_sid_length;
728 /* Now do the strings */
729 entry->record.string_offset = sizeof(Eventlog_record) + (offset - entry->data);
730 memcpy(offset, &(entry->data_record.strings), entry->data_record.strings_len);
731 offset += entry->data_record.strings_len;
732 /* Now do the data */
733 entry->record.data_length = entry->data_record.user_data_len;
734 entry->record.data_offset = sizeof(Eventlog_record) + (offset - entry->data);
735 memcpy(offset, &(entry->data_record.user_data), entry->data_record.user_data_len);
736 offset += entry->data_record.user_data_len;
737 /* Now that we've massaged the current entry, copy it into the new entry and add it
738 to end of the list */
739 insert_point=r_u->entry;
741 if (NULL == insert_point)
743 r_u->entry = new;
744 new->next = NULL;
746 else
748 while ((NULL != insert_point->next))
750 insert_point=insert_point->next;
752 new->next = NULL;
753 insert_point->next = new;
756 memcpy(&(new->record), &entry->record, sizeof(Eventlog_record));
757 memcpy(&(new->data_record), &entry->data_record, sizeof(Eventlog_data_record));
758 new->data = entry->data;
760 r_u->num_records++;
761 r_u->num_bytes_in_resp += entry->record.length;
763 return True;
766 WERROR _eventlog_read_eventlog(pipes_struct *p,
767 EVENTLOG_Q_READ_EVENTLOG *q_u,
768 EVENTLOG_R_READ_EVENTLOG *r_u)
770 Eventlog_info *info = NULL;
771 POLICY_HND *handle;
772 Eventlog_entry entry;
773 BOOL eof = False;
774 const char *direction = "";
775 int starting_record;
776 prs_struct *ps;
778 if(!q_u || !r_u)
779 return WERR_NOMEM;
781 handle = &(q_u->handle);
782 info = find_eventlog_info_by_hnd(p, handle);
783 ps = &p->out_data.rdata;
784 /* Rather than checking the EVENTLOG_SEQUENTIAL_READ/EVENTLOG_SEEK_READ flags,
785 we'll just go to the offset specified in the request, or the oldest entry
786 if no offset is specified */
787 if(q_u->offset > 0)
788 starting_record = q_u->offset;
789 else
790 starting_record = info->oldest_entry;
791 if(q_u->flags & EVENTLOG_FORWARDS_READ)
792 direction = "forward";
793 else if(q_u->flags & EVENTLOG_BACKWARDS_READ)
794 direction = "backward";
798 ZERO_STRUCT(entry);
799 if(!(_eventlog_read_eventlog_hook(info, &entry, direction, starting_record, q_u->max_read_size, &eof)))
801 if(eof == False)
802 return WERR_NOMEM;
804 if(eof == False)
806 /* only if the read hook returned data */
807 if(!(_eventlog_read_prepare_data_buffer(ps, q_u, r_u, &entry)))
808 return WERR_NOMEM;
809 DEBUG(10, ("_eventlog_read_eventlog: read [%d] bytes out of a max of [%d].\n",
810 r_u->num_bytes_in_resp,
811 q_u->max_read_size));
813 } while((r_u->num_bytes_in_resp <= q_u->max_read_size) && (eof != True));
815 return WERR_OK;
818 * Callout to clear (and optionally backup) a specified event log
820 * smbrun calling convention --
821 * INPUT: <clear_eventlog_cmd> <log name> <policy handle>
822 * OUTPUT: A single line with the string "SUCCESS" if the command succeeded.
823 * Otherwise it is assumed to have failed
825 * INPUT: <clear_eventlog_cmd> <log name> <backup file> <policy handle>
826 * OUTPUT: A single line with the string "SUCCESS" if the command succeeded.
827 * Otherwise it is assumed to have failed
828 * The given log is copied to that location on the server. See comments for
829 * eventlog_io_q_clear_eventlog for info about odd file name behavior
831 static BOOL _eventlog_clear_eventlog_hook(Eventlog_info *info,
832 pstring backup_file_name)
834 char *cmd = lp_eventlog_clear_cmd();
835 char **qlines;
836 pstring command;
837 int numlines = 0;
838 int ret;
839 int fd = -1;
841 if(cmd == NULL || strlen(cmd) == 0)
843 DEBUG(0, ("Must define an \"eventlog clear command\" entry in the config.\n"));
844 return False;
847 memset(command, 0, sizeof(command));
848 if(strlen(backup_file_name) > 0)
849 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\"",
850 cmd,
851 info->source_log_file_name,
852 backup_file_name,
853 info->handle_string);
854 else
855 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
856 cmd,
857 info->source_log_file_name,
858 info->handle_string);
860 DEBUG(10, ("Running [%s]\n", command));
861 ret = smbrun(command, &fd);
862 DEBUGADD(10, ("returned [%d]\n", ret));
864 if(ret != 0)
866 if(fd != -1)
867 close(fd);
868 return False;
871 qlines = fd_lines_load(fd, &numlines);
872 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
873 close(fd);
875 if(numlines)
877 DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
878 if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
880 DEBUGADD(10, ("Able to clear [%s].\n", info->source_log_file_name));
881 file_lines_free(qlines);
882 return True;
886 file_lines_free(qlines);
887 return False;
890 WERROR _eventlog_clear_eventlog(pipes_struct *p,
891 EVENTLOG_Q_CLEAR_EVENTLOG *q_u,
892 EVENTLOG_R_CLEAR_EVENTLOG *r_u)
894 Eventlog_info *info = NULL;
895 pstring backup_file_name;
896 POLICY_HND *handle = NULL;
898 if(!q_u || !r_u)
899 return WERR_NOMEM;
901 handle = &(q_u->handle);
902 info = find_eventlog_info_by_hnd(p, handle);
903 memset(backup_file_name, 0, sizeof(backup_file_name));
905 if(q_u->backup_file_ptr != 0)
907 unistr2_to_ascii(backup_file_name, &(q_u->backup_file), sizeof(backup_file_name));
908 DEBUG(10, ("_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].",
909 backup_file_name,
910 info->source_log_file_name));
912 else
914 /* if backup_file == NULL, do not back up the log before clearing it */
915 DEBUG(10, ("_eventlog_clear_eventlog: clearing [%s] log without making a backup.",
916 info->source_log_file_name));
919 if(!(_eventlog_clear_eventlog_hook(info, backup_file_name)))
920 return WERR_BADFILE;
922 return WERR_OK;