예제 #1
0
/* Get the next eventlog message */
char * EventlogNext(EventList ignore_list[MAX_IGNORED_EVENTS], int log, int * level)
{
	BOOL reopen = FALSE;
	DWORD errnum;
	DWORD needed;
	DWORD loglevel;
	EVENTLOGRECORD * event;
	char * cp;
	char * current;
	char * formatted_string;
	char * message_file;
	char * source;
	char * string_array[EVENTLOG_ARRAY_SZ];
	char * username;
	char hostname[HOSTNAME_SZ];
	char defmsg[ERRMSG_SZ];
	int event_id;
	int i;
	char *index;

	static char message[SYSLOG_DEF_SZ-17];
	static char tstamped_message[SYSLOG_DEF_SZ];

	/* Initialize array to prevent memory exceptions with bad message definitions */
	for(i = 0; i < EVENTLOG_ARRAY_SZ; i++)
		string_array[i]="*";

	/* Are there any records left in buffer */
	while (EventlogList[log].pos == EventlogList[log].count) {

		/* Reset input position */
		EventlogList[log].count = 0;
		EventlogList[log].pos = 0;

		/* Read a record */
		needed = 0;
		if (ReadEventLog(EventlogList[log].handle, EVENTLOG_FORWARDS_READ | EVENTLOG_SEEK_READ, EventlogList[log].recnum, EventlogList[log].buffer, sizeof(EventlogList[log].buffer), &EventlogList[log].count, &needed) == 0) {

			/* Check error */
			errnum = GetLastError();
			switch (errnum) {

			/* Message too large... skip over */
			case ERROR_INSUFFICIENT_BUFFER:
				Log(LOG_WARNING, "Eventlog message size too large: \"%s\": %u bytes", EventlogList[log].name, needed);
				EventlogList[log].recnum++;
				break;

			/* Eventlog corrupted (?)... Reopen */
			case ERROR_EVENTLOG_FILE_CORRUPT:
				Log(LOG_INFO, "Eventlog was corrupted: \"%s\"", EventlogList[log].name);
				reopen = TRUE;
				break;

			/* Eventlog files are clearing... Reopen */
			case ERROR_EVENTLOG_FILE_CHANGED:
				Log(LOG_INFO, "Eventlog was cleared: \"%s\"", EventlogList[log].name);
				reopen = TRUE;
				break;

			/* Record not available (yet) */
			case ERROR_INVALID_PARAMETER:
				return NULL;

			/* Normal end of eventlog messages */
			case ERROR_HANDLE_EOF:
				return NULL;

			/* Eventlog probably closing down */
			case RPC_S_UNKNOWN_IF:
				return NULL;

			/* Unknown condition */
			default:
				Log(LOG_ERROR|LOG_SYS, "Eventlog \"%s\" returned error: ", EventlogList[log].name);
				ServiceIsRunning = FALSE;
				return NULL;
			}

			/* Process reopen */
			if (reopen) {
				EventlogClose(log);
				if (EventlogOpen(log)) {
					ServiceIsRunning = FALSE;
					return NULL;
				}
				reopen = FALSE;
			}
		}
	}

	/* Increase record number */
	EventlogList[log].recnum++;

	/* Get position into buffer */
	current = EventlogList[log].buffer + EventlogList[log].pos;

	/* Get pointer to current event record */
	event = (EVENTLOGRECORD *) current;

	/* Advance position */
	EventlogList[log].pos += event->Length;

	/* Get source and event id */
	source = current + sizeof(*event);
	event_id = (int) HRESULT_CODE(event->EventID);
	
	/* Check Event Info Against Ignore List */
	if (IgnoreSyslogEvent(ignore_list, source, event_id)) {
		if (LogInteractive)
			printf("IGNORING_EVENT: SOURCE=%s & ID=%i\n", source, event_id);
		return NULL;
	}
	
	/* Check number of strings */
	if (event->NumStrings > COUNT_OF(string_array)) {

		/* Too many strings */
		Log(LOG_WARNING, "Eventlog message has too many strings to print message: \"%s\": %u strings", EventlogList[log].name, event->NumStrings);
		formatted_string = NULL;
	} else {

		/* Convert strings to arrays */
		cp = current + event->StringOffset;
		for (i = 0; i < event->NumStrings; i++) {
			string_array[i] = cp;
			while (*cp++ != '\0');
		}

		message_file = LookupMessageFile(EventlogList[log].name, source, event->EventID);

		if (message_file == NULL) {
			/* Cannot load resources */
			formatted_string = NULL;
		} else {
			/* Format eventlog message */
			formatted_string = FormatLibraryMessage(message_file, event->EventID, string_array);
		}
	}

	/* Create a default message if resources or formatting didn't work */
	if (formatted_string == NULL) {
		_snprintf_s(defmsg, sizeof(defmsg), _TRUNCATE,
			"(Facility: %u, Status: %s)",
			HRESULT_FACILITY(event->EventID),
			FAILED(event->EventID) ? "Failure" : "Success"
		);
		formatted_string = defmsg;
	}

	/* replace every space in source by underscores */
	index = source;
	while( *index ) {
		if( *index == ' ' ) {
			*index = '_';
		}
		index++;
	}

	/* Format source and event ID number */
	if(SyslogIncludeTag) {
		_snprintf_s(message, sizeof(message), _TRUNCATE,
			"%s: %s: %u: ",
			SyslogTag,
			source,
			HRESULT_CODE(event->EventID)
		);
	} else {
		_snprintf_s(message, sizeof(message), _TRUNCATE,
			"%s: %u: ",
			source,
			HRESULT_CODE(event->EventID)
		);
	}

	/* Convert user */
	if (event->UserSidLength > 0) {
		username = GetUsername((SID *) (current + event->UserSidOffset));
		if (username) {
			strncat_s(message, sizeof(message), username, _TRUNCATE);
			strncat_s(message, sizeof(message), ": ", _TRUNCATE);
		}
	}

	/* Add formatted string to base message */
	strncat_s(message, sizeof(message), formatted_string, _TRUNCATE);

	/* Select syslog level */
	switch (event->EventType) {
		case EVENTLOG_ERROR_TYPE:
			loglevel = SYSLOG_ERR;
			*level = SYSLOG_BUILD(SyslogFacility, loglevel);
			break;
		case EVENTLOG_WARNING_TYPE:
			loglevel = SYSLOG_WARNING;
			*level = SYSLOG_BUILD(SyslogFacility, loglevel);
			break;
		case EVENTLOG_INFORMATION_TYPE:
			loglevel = SYSLOG_NOTICE;
			*level = SYSLOG_BUILD(SyslogFacility, loglevel);
			break;
		case EVENTLOG_AUDIT_SUCCESS:
            strncat_s(message, sizeof(message), "AUDIT_SUCCESS ", _TRUNCATE);
			loglevel = SYSLOG_NOTICE;
			*level = SYSLOG_BUILD(SyslogFacility, loglevel);
			break;
		case EVENTLOG_AUDIT_FAILURE:
            strncat_s(message, sizeof(message), "AUDIT_FAILURE ", _TRUNCATE);
			loglevel = SYSLOG_ERR;
			*level = SYSLOG_BUILD(SyslogFacility, loglevel);
			break;

		/* Everything else */
		case EVENTLOG_SUCCESS:
		default:
			loglevel = SYSLOG_NOTICE;
			*level = SYSLOG_BUILD(SyslogFacility, loglevel);
			break;
	}

	/* If event is not being ignored, make sure it is severe enough to be logged */
	if (SyslogLogLevel != 0)
		if (SyslogLogLevel < loglevel-1)
			return NULL;

	/* Add hostname for RFC compliance (RFC 3164) */
	/* if -a then use the fqdn bound to our IP address. If none, use the IP address */
	if (ProgramUseIPAddress == TRUE) {
		strcpy_s(hostname, HOSTNAME_SZ, ProgramHostName);
	} else {
		if (ExpandEnvironmentStrings("%COMPUTERNAME%", hostname, COUNT_OF(hostname)) == 0) {
			strcpy_s(hostname, COUNT_OF(hostname), "HOSTNAME_ERR");
			Log(LOG_ERROR|LOG_SYS, "Cannot expand %COMPUTERNAME%");
	    }
    }
	
	/* Query and Add timestamp from EventLog, add hostname, */
	/* and finally the message to the string */
	_snprintf_s(tstamped_message, sizeof(tstamped_message), _TRUNCATE,
		"%s %s %s",
		TimeToString(event->TimeGenerated),
		hostname,
		message
	);

	/* Return formatted message */
	return tstamped_message;
}
예제 #2
0
/* Process a given event */
DWORD ProcessEvent(EVT_HANDLE hEvent)
{
    EVT_HANDLE hProviderMetadata = NULL;
	PEVT_VARIANT eventInfo = NULL;
    LPWSTR pwsMessage = NULL;
    LPWSTR pwszPublisherName = NULL;
	ULONGLONG eventTime;
	ULONGLONG keyword;
    DWORD status = ERROR_SUCCESS;
	int event_id = 0;
	int winlevel = 0;
	int level = 0;

	WCHAR source[SOURCE_SZ];
	WCHAR hostname[HOSTNAME_SZ];
	WCHAR * formatted_string = NULL;
	WCHAR * tstamp = NULL;
	WCHAR * index = NULL;
	WCHAR defmsg[ERRMSG_SZ];
	WCHAR tstamped_message[SYSLOG_DEF_SZ];

    /* Get and store the publishers new Windows Events name */
	eventInfo = GetEventInfo(hEvent);
	if (eventInfo) {
		pwszPublisherName = (LPWSTR)eventInfo[0].StringVal;
	}
	else {
		return ERR_CONTINUE;
	}
	eventTime = eventInfo[1].FileTimeVal;
	event_id = eventInfo[2].UInt16Val;

	/* Check for the "Microsoft-Windows-" prefix in the publisher name */
	/* and remove it if found. Saves 18 characters in the message */
	if(wcsncmp(pwszPublisherName, L"Microsoft-Windows-", 18) == 0)
		wcsncpy_s(source, COUNT_OF(source), pwszPublisherName+18, _TRUNCATE);
	else
		wcsncpy_s(source, COUNT_OF(source), pwszPublisherName, _TRUNCATE);

	/* Format Event Timestamp */
	if ((tstamp = WinEventTimeToString(eventTime)) == NULL)
		tstamp = L"TIME_ERROR";

	/* Add hostname for RFC compliance (RFC 3164) */
	if (ProgramUseIPAddress == TRUE) {
		_snwprintf_s(hostname, HOSTNAME_SZ, _TRUNCATE, L"%S", ProgramHostName);
	} else {
		if (ExpandEnvironmentStringsW(L"%COMPUTERNAME%", hostname, COUNT_OF(hostname)) == 0) {
			wcscpy_s(hostname, COUNT_OF(hostname), L"HOSTNAME_ERR");
			Log(LOG_ERROR|LOG_SYS, "Cannot expand %COMPUTERNAME%");
		}
    }

	/* replace every space in source by underscores */
	index = source;
	while( *index ) {
		if( *index == L' ' ) {
			*index = L'_';
		}
		index++;
	}

	/* Add Timestamp and hostname then format source & event ID for consistency with Event Viewer */
    if(SyslogIncludeTag)
    {
        _snwprintf_s(tstamped_message, COUNT_OF(tstamped_message), _TRUNCATE, L"%s %s %S: %s: %i: ",
            tstamp,
            hostname,
            SyslogTag,
            source,
            event_id
        );
    }
    else
    {
        _snwprintf_s(tstamped_message, COUNT_OF(tstamped_message), _TRUNCATE, L"%s %s %s: %i: ",
            tstamp,
            hostname,
            source,
            event_id
        );
    }

	/* Get the handle to the provider's metadata that contains the message strings. */
	hProviderMetadata = EvtOpenPublisherMetadata(NULL, pwszPublisherName, NULL, 0, 0);
	if (NULL == hProviderMetadata) {
		if (LogInteractive)
			Log(LOG_ERROR|LOG_SYS, "OpenPublisherMetadata failed for Publisher: \"%S\"", source);
		return ERR_CONTINUE;
	}

	/* Get the message string from the event */
	pwsMessage = GetMessageString(hProviderMetadata, hEvent);
	if (pwsMessage == NULL) {
		Log(LOG_ERROR|LOG_SYS, "Error getting message string for event DETAILS: Publisher: %S EventID: %i", source, event_id);
		return ERR_CONTINUE;
	}

	/* Get string and strip whitespace */
	formatted_string = CollapseExpandMessageW(pwsMessage);

	/* Create a default message if resources or formatting didn't work */
	if (formatted_string == NULL) {
        if(SyslogIncludeTag)
        {
		    _snwprintf_s(defmsg, COUNT_OF(defmsg), _TRUNCATE,
                L"%S: (Facility: %u, Status: %s)",
                SyslogTag,
			    HRESULT_FACILITY(event_id),
			    FAILED(event_id) ? L"Failure" : L"Success"
		    );
        }
        else
        {
            _snwprintf_s(defmsg, COUNT_OF(defmsg), _TRUNCATE,
                L"(Facility: %u, Status: %s)",
			    HRESULT_FACILITY(event_id),
			    FAILED(event_id) ? L"Failure" : L"Success"
		    );
        }
		formatted_string = defmsg;
	}

	/* Get Event Error Level. In the case of Security Events,
	 * set Failures to Error instead of notice using the
	 * keyword attribute
	 */
	keyword = (EvtVarTypeNull == eventInfo[4].Type) ? 0 : eventInfo[4].UInt64Val;
	if ((keyword & WINEVENT_KEYWORD_AUDIT_FAILURE) != 0) {
        // Add AUDIT_FAILURE message for better parsing
        wcsncat_s(tstamped_message, COUNT_OF(tstamped_message), L"AUDIT_FAILURE ", _TRUNCATE);
		winlevel = WINEVENT_ERROR_LEVEL;
    }
	else
		winlevel = (int)eventInfo[3].ByteVal;

	/* Select syslog level */
	switch (winlevel) {
		case WINEVENT_CRITICAL_LEVEL:
			level = SYSLOG_BUILD(SyslogFacility, SYSLOG_CRIT);
			break;		
		case WINEVENT_ERROR_LEVEL:
			level = SYSLOG_BUILD(SyslogFacility, SYSLOG_ERR);
			break;
		case WINEVENT_WARNING_LEVEL:
			level = SYSLOG_BUILD(SyslogFacility, SYSLOG_WARNING);
			break;
		case WINEVENT_INFORMATION_LEVEL:
			level = SYSLOG_BUILD(SyslogFacility, SYSLOG_NOTICE);
			break;
		case WINEVENT_AUDIT_LEVEL:
            wcsncat_s(tstamped_message, COUNT_OF(tstamped_message), L"AUDIT_SUCCESS ", _TRUNCATE);
			level = SYSLOG_BUILD(SyslogFacility, SYSLOG_NOTICE);
			break;
		case WINEVENT_VERBOSE_LEVEL:
			level = SYSLOG_BUILD(SyslogFacility, SYSLOG_DEBUG);
			break;

		/* Everything else */
		default:
			level = SYSLOG_BUILD(SyslogFacility, SYSLOG_NOTICE);
			break;
	}

	/* Combine the message strings */
	wcsncat_s(tstamped_message, COUNT_OF(tstamped_message), formatted_string, _TRUNCATE);

	/* Send the event to the Syslog Server */
	/* Making sure it is severe enough to be logged */
	if (SyslogLogLevel == 0 || (SyslogLogLevel >= (DWORD)winlevel && winlevel > 0))
		if (SyslogSendW(tstamped_message, level))
			status = ERR_FAIL;

	/* Cleanup memory and open handles */
	if(pwsMessage)
		free(pwsMessage);
	if(eventInfo)
		free(eventInfo);

	if (hProviderMetadata)
		EvtClose(hProviderMetadata);
	if (hEvent)
		EvtClose(hEvent);

	return status;
}