/* * Token printing for each token type . */ static int print_tokens(FILE *fp) { u_char *buf; tokenstr_t tok; int reclen; int bytesread; /* Allow tail -f | praudit to work. */ if (partial) { u_char type = 0; /* Record must begin with a header token. */ do { type = fgetc(fp); } while(type != AUT_HEADER32); ungetc(type, fp); } while ((reclen = au_read_rec(fp, &buf)) != -1) { bytesread = 0; while (bytesread < reclen) { /* Is this an incomplete record? */ if (-1 == au_fetch_tok(&tok, buf + bytesread, reclen - bytesread)) break; au_print_flags_tok(stdout, &tok, del, oflags); bytesread += tok.len; if (oneline) { if (!(oflags & AU_OFLAG_XML)) printf("%s", del); } else printf("\n"); } free(buf); if (oneline) printf("\n"); fflush(stdout); } return (0); }
/* * Checks the presence of "auditregex" in auditpipe(4) after the * corresponding system call has been triggered. */ static bool get_records(const char *auditregex, FILE *pipestream) { uint8_t *buff; tokenstr_t token; ssize_t size = 1024; char membuff[size]; char del[] = ","; int reclen, bytes = 0; FILE *memstream; /* * Open a stream on 'membuff' (address to memory buffer) for storing * the audit records in the default mode.'reclen' is the length of the * available records from auditpipe which is passed to the functions * au_fetch_tok(3) and au_print_flags_tok(3) for further use. */ ATF_REQUIRE((memstream = fmemopen(membuff, size, "w")) != NULL); ATF_REQUIRE((reclen = au_read_rec(pipestream, &buff)) != -1); /* * Iterate through each BSM token, extracting the bits that are * required to start processing the token sequences. */ while (bytes < reclen) { if (au_fetch_tok(&token, buff + bytes, reclen - bytes) == -1) { perror("au_read_rec"); atf_tc_fail("Incomplete Audit Record"); } /* Print the tokens as they are obtained, in the default form */ au_print_flags_tok(memstream, &token, del, AU_OFLAG_NONE); bytes += token.len; } free(buff); ATF_REQUIRE_EQ(0, fclose(memstream)); return (atf_utils_grep_string("%s", membuff, auditregex)); }
int main(int argc, char** argv){ // User configurable section starts here FILE* output = stdout; FILE* errors = stderr; char* delimiter = ","; int raw = 1; // Convert raw to string int shortForm = 0; // Use long form char* auditPipe = "/dev/auditpipe"; u_int dataFlow = 0x00000001 | 0x00000002 | 0x00000010 | 0x00000020 | 0x00000080 | 0x40000000; // Class defined in /etc/security/audit_class // Events in class defined in /etc/security/audit_event // User configurable section ends here // Open the audit trail FILE* auditFile; int auditFileDescriptor; auditFile = fopen(auditPipe, "r"); if(auditFile == NULL){ fprintf(stderr, "Unable to open audit pipe: %s\n", auditPipe); perror("Error "); exit(1); } auditFileDescriptor = fileno(auditFile); // Configure the audit pipe int ioctlReturn; int mode = AUDITPIPE_PRESELECT_MODE_LOCAL; ioctlReturn = ioctl(auditFileDescriptor, AUDITPIPE_SET_PRESELECT_MODE, &mode); if(ioctlReturn == -1){ fprintf(stderr, "Unable to set the audit pipe mode to local.\n"); perror("Error "); } int queueLength; ioctlReturn = ioctl(auditFileDescriptor, AUDITPIPE_GET_QLIMIT_MAX, &queueLength); if(ioctlReturn == -1){ fprintf(stderr, "Unable to get the maximum queue length of the audit pipe.\n"); perror("Error "); } ioctlReturn = ioctl(auditFileDescriptor, AUDITPIPE_SET_QLIMIT, &queueLength); if(ioctlReturn == -1){ fprintf(stderr, "Unable to set the queue length of the audit pipe.\n"); perror("Error "); } u_int attributableEventsMask = dataFlow; ioctlReturn = ioctl(auditFileDescriptor, AUDITPIPE_SET_PRESELECT_FLAGS, &attributableEventsMask); if(ioctlReturn == -1){ fprintf(stderr, "Unable to set the attributable events preselection mask.\n"); perror("Error "); } u_int nonAttributableEventsMask = dataFlow; ioctlReturn = ioctl(auditFileDescriptor, AUDITPIPE_SET_PRESELECT_NAFLAGS, &nonAttributableEventsMask); if(ioctlReturn == -1){ fprintf(stderr, "Unable to set the non-attributable events preselection mask.\n"); perror("Error "); } // fprintf(output, "Provenance collection has started.\n"); // Start processing audit records u_char* buffer; int remainingRecords = 1; int recordLength; int recordBalance; int processedLength; int tokenCount; int fetchToken; tokenstr_t token; while(remainingRecords){ // Read an audit record // Note: au_read_rec() man page incorrectly states return // value is 0 on success (rather than number of bytes // read in record) recordLength = au_read_rec(auditFile, &buffer); if(recordLength == -1){ remainingRecords = 0; break; } recordBalance = recordLength; processedLength = 0; tokenCount = 0; while(recordBalance){ // Extract a token from the record fetchToken = au_fetch_tok(&token, buffer + processedLength, recordBalance); if(fetchToken == -1){ // fprintf(errors, "Error fetching token.\n"); break; } // Print the long form of the token as a string au_print_tok(output, &token, delimiter, raw, shortForm); fprintf(output, "\n"); tokenCount++; processedLength += token.len; recordBalance -= token.len; } free(buffer); // fprintf(output, "\n"); } fclose(auditFile); fprintf(output, "Provenance collection has ended.\n"); }