xref: /titanic_44/usr/src/cmd/praudit/printaudit.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <dirent.h>
30*7c478bd9Sstevel@tonic-gate #include <locale.h>
31*7c478bd9Sstevel@tonic-gate #include <libintl.h>
32*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
33*7c478bd9Sstevel@tonic-gate #include <strings.h>
34*7c478bd9Sstevel@tonic-gate #include <stdio.h>
35*7c478bd9Sstevel@tonic-gate #include <unistd.h>
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #include <bsm/audit.h>
41*7c478bd9Sstevel@tonic-gate #include <bsm/audit_record.h>
42*7c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #include "praudit.h"
45*7c478bd9Sstevel@tonic-gate #include "toktable.h"
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate extern void	init_tokens(void);	/* shared with auditreduce */
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate static int	check_inputs(int flags, const char *separator);
50*7c478bd9Sstevel@tonic-gate static void	checkpoint_progress(pr_context_t *context);
51*7c478bd9Sstevel@tonic-gate static int	print_audit_common(pr_context_t *context, int flags,
52*7c478bd9Sstevel@tonic-gate     const char *separator);
53*7c478bd9Sstevel@tonic-gate static int	token_processing(pr_context_t *context);
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate static int	initdone = 0;
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate /*
58*7c478bd9Sstevel@tonic-gate  * This source is shared outside of praudit; the following lint directive
59*7c478bd9Sstevel@tonic-gate  * is needed to suppress praudit lint warnings about unused functions, for
60*7c478bd9Sstevel@tonic-gate  * functions which are only invoked outside praudit.
61*7c478bd9Sstevel@tonic-gate  */
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate /*
66*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
67*7c478bd9Sstevel@tonic-gate  * check_inputs() - check input flags and delimiter.
68*7c478bd9Sstevel@tonic-gate  *		Returns:
69*7c478bd9Sstevel@tonic-gate  *		    0 - successful
70*7c478bd9Sstevel@tonic-gate  *		   -1 - invalid inputs. errno is set to EINVAL
71*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
72*7c478bd9Sstevel@tonic-gate  */
73*7c478bd9Sstevel@tonic-gate static int
check_inputs(int flags,const char * separator)74*7c478bd9Sstevel@tonic-gate check_inputs(int flags, const char *separator)
75*7c478bd9Sstevel@tonic-gate {
76*7c478bd9Sstevel@tonic-gate 	if ((flags & PRF_RAWM) && (flags & PRF_SHORTM)) {
77*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
78*7c478bd9Sstevel@tonic-gate 		return (-1);
79*7c478bd9Sstevel@tonic-gate 	}
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 	/* Ignore the delimiter when XML is specified */
82*7c478bd9Sstevel@tonic-gate 	if (!(flags & PRF_XMLM) && (strlen(separator) >= SEP_SIZE)) {
83*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
84*7c478bd9Sstevel@tonic-gate 		return (-1);
85*7c478bd9Sstevel@tonic-gate 	}
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	return (0);
88*7c478bd9Sstevel@tonic-gate }
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate /*
91*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
92*7c478bd9Sstevel@tonic-gate  * print_audit_xml_prolog_buf() - print the XML prolog.
93*7c478bd9Sstevel@tonic-gate  *		    0 - successful
94*7c478bd9Sstevel@tonic-gate  *		   -1 - output buffer too small. errno is set to ENOSPC
95*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
96*7c478bd9Sstevel@tonic-gate  */
97*7c478bd9Sstevel@tonic-gate int
print_audit_xml_prolog_buf(char * out_buf,const int out_buf_len)98*7c478bd9Sstevel@tonic-gate print_audit_xml_prolog_buf(char *out_buf, const int out_buf_len)
99*7c478bd9Sstevel@tonic-gate {
100*7c478bd9Sstevel@tonic-gate 	if (xml_prolog_len > out_buf_len) {
101*7c478bd9Sstevel@tonic-gate 		errno = ENOSPC;
102*7c478bd9Sstevel@tonic-gate 		return (-1);
103*7c478bd9Sstevel@tonic-gate 	}
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 	(void) snprintf(out_buf, out_buf_len, "%s%s%s%s", prolog1, prolog_xsl,
106*7c478bd9Sstevel@tonic-gate 	    prolog2, xml_start);
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	return (0);
109*7c478bd9Sstevel@tonic-gate }
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate /*
112*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
113*7c478bd9Sstevel@tonic-gate  * print_audit_xml_ending_buf() - print the XML ending.
114*7c478bd9Sstevel@tonic-gate  *		    0 - successful
115*7c478bd9Sstevel@tonic-gate  *		   -1 - output buffer too small. errno is set to ENOSPC
116*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
117*7c478bd9Sstevel@tonic-gate  */
118*7c478bd9Sstevel@tonic-gate int
print_audit_xml_ending_buf(char * out_buf,const int out_buf_len)119*7c478bd9Sstevel@tonic-gate print_audit_xml_ending_buf(char *out_buf, const int out_buf_len)
120*7c478bd9Sstevel@tonic-gate {
121*7c478bd9Sstevel@tonic-gate 	if (xml_end_len > out_buf_len) {
122*7c478bd9Sstevel@tonic-gate 		errno = ENOSPC;
123*7c478bd9Sstevel@tonic-gate 		return (-1);
124*7c478bd9Sstevel@tonic-gate 	}
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 	(void) snprintf(out_buf, out_buf_len, "%s", xml_ending);
127*7c478bd9Sstevel@tonic-gate 	return (0);
128*7c478bd9Sstevel@tonic-gate }
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate /*
131*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
132*7c478bd9Sstevel@tonic-gate  * print_prolog() - print the XML prolog.
133*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
134*7c478bd9Sstevel@tonic-gate  */
135*7c478bd9Sstevel@tonic-gate void
print_audit_xml_prolog(void)136*7c478bd9Sstevel@tonic-gate print_audit_xml_prolog(void)
137*7c478bd9Sstevel@tonic-gate {
138*7c478bd9Sstevel@tonic-gate 	(void) printf("%s%s%s%s", prolog1, prolog_xsl, prolog2, xml_start);
139*7c478bd9Sstevel@tonic-gate }
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate /*
142*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
143*7c478bd9Sstevel@tonic-gate  * print_ending() - print the XML ending.
144*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
145*7c478bd9Sstevel@tonic-gate  */
146*7c478bd9Sstevel@tonic-gate void
print_audit_xml_ending(void)147*7c478bd9Sstevel@tonic-gate print_audit_xml_ending(void)
148*7c478bd9Sstevel@tonic-gate {
149*7c478bd9Sstevel@tonic-gate 	(void) printf("%s", xml_ending);
150*7c478bd9Sstevel@tonic-gate }
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate /*
153*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
154*7c478bd9Sstevel@tonic-gate  * checkpoint_progress() - If starting a new file or header token,
155*7c478bd9Sstevel@tonic-gate  *      checkpoint as needed to mark progress.
156*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
157*7c478bd9Sstevel@tonic-gate  */
158*7c478bd9Sstevel@tonic-gate static void
checkpoint_progress(pr_context_t * context)159*7c478bd9Sstevel@tonic-gate checkpoint_progress(pr_context_t *context)
160*7c478bd9Sstevel@tonic-gate {
161*7c478bd9Sstevel@tonic-gate 	int	tokenid = context->tokenid;
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	if (is_file_token(tokenid) || is_header_token(tokenid)) {
164*7c478bd9Sstevel@tonic-gate 		if (context->data_mode == BUFMODE) {
165*7c478bd9Sstevel@tonic-gate 			context->inbuf_last = context->audit_adr->adr_now - 1;
166*7c478bd9Sstevel@tonic-gate 			context->outbuf_last = context->outbuf_p;
167*7c478bd9Sstevel@tonic-gate 		}
168*7c478bd9Sstevel@tonic-gate 		context->audit_rec_start = context->audit_adr->adr_now - 1;
169*7c478bd9Sstevel@tonic-gate 		if (is_file_token(tokenid)) {
170*7c478bd9Sstevel@tonic-gate 			context->audit_rec_len = 11;
171*7c478bd9Sstevel@tonic-gate 		}
172*7c478bd9Sstevel@tonic-gate 	}
173*7c478bd9Sstevel@tonic-gate }
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate /*
176*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
177*7c478bd9Sstevel@tonic-gate  * print_audit_buf() - display contents of audit trail file
178*7c478bd9Sstevel@tonic-gate  *
179*7c478bd9Sstevel@tonic-gate  *		   Parses the binary audit data from the specified input
180*7c478bd9Sstevel@tonic-gate  *		   buffer, and formats as requested to the specified output
181*7c478bd9Sstevel@tonic-gate  *		   buffer.
182*7c478bd9Sstevel@tonic-gate  *
183*7c478bd9Sstevel@tonic-gate  *	inputs:
184*7c478bd9Sstevel@tonic-gate  *		   in_buf, -	address and length of binary audit input.
185*7c478bd9Sstevel@tonic-gate  *		   in_buf_len
186*7c478bd9Sstevel@tonic-gate  *		   out_buf, -	address and length of output buffer to
187*7c478bd9Sstevel@tonic-gate  *		   out_buf_len	copy formatted audit data to.
188*7c478bd9Sstevel@tonic-gate  *		   flags -	formatting flags as defined in praudit.h
189*7c478bd9Sstevel@tonic-gate  *		   separator -	field delimiter (or NULL if the default
190*7c478bd9Sstevel@tonic-gate  *				delimiter of comma is to be used).
191*7c478bd9Sstevel@tonic-gate  *
192*7c478bd9Sstevel@tonic-gate  * return codes:    0 - success
193*7c478bd9Sstevel@tonic-gate  *		ENOSPC...
194*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
195*7c478bd9Sstevel@tonic-gate  */
196*7c478bd9Sstevel@tonic-gate int
print_audit_buf(char ** in_buf,int * in_buf_len,char ** out_buf,int * out_buf_len,const int flags,const char * separator)197*7c478bd9Sstevel@tonic-gate print_audit_buf(char **in_buf, int *in_buf_len, char **out_buf,
198*7c478bd9Sstevel@tonic-gate     int *out_buf_len, const int flags, const char *separator)
199*7c478bd9Sstevel@tonic-gate {
200*7c478bd9Sstevel@tonic-gate 	int	retstat = 0;
201*7c478bd9Sstevel@tonic-gate 	pr_context_t	*context;
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 	if ((retstat = check_inputs(flags, separator)) != 0)
204*7c478bd9Sstevel@tonic-gate 		return (retstat);
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	if ((context = (pr_context_t *)malloc(sizeof (pr_context_t))) == NULL) {
207*7c478bd9Sstevel@tonic-gate 		errno = EPERM;
208*7c478bd9Sstevel@tonic-gate 		return (-1);
209*7c478bd9Sstevel@tonic-gate 	}
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 	/* Init internal pointers and lengths... */
212*7c478bd9Sstevel@tonic-gate 	context->data_mode = BUFMODE;
213*7c478bd9Sstevel@tonic-gate 	context->inbuf_last = context->inbuf_start = *in_buf;
214*7c478bd9Sstevel@tonic-gate 	context->inbuf_totalsize = *in_buf_len;
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	context->pending_flag = 0;
217*7c478bd9Sstevel@tonic-gate 	context->current_rec = 0;
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	context->outbuf_last = context->outbuf_start =
220*7c478bd9Sstevel@tonic-gate 	    context->outbuf_p = *out_buf;
221*7c478bd9Sstevel@tonic-gate 	context->outbuf_remain_len = *out_buf_len;
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	/*
224*7c478bd9Sstevel@tonic-gate 	 * get an adr pointer to the audit input buf
225*7c478bd9Sstevel@tonic-gate 	 */
226*7c478bd9Sstevel@tonic-gate 	context->audit_adr = (adr_t *)malloc(sizeof (adr_t));
227*7c478bd9Sstevel@tonic-gate 	(void) adrm_start(context->audit_adr, *in_buf);
228*7c478bd9Sstevel@tonic-gate 	context->audit_rec_start = NULL;
229*7c478bd9Sstevel@tonic-gate 	context->audit_rec_len = 0;
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	retstat = print_audit_common(context, flags, separator);
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	/* Check for and handle partial results as needed */
234*7c478bd9Sstevel@tonic-gate 	if (retstat != 0) {
235*7c478bd9Sstevel@tonic-gate 		*in_buf = context->inbuf_last;
236*7c478bd9Sstevel@tonic-gate 		*in_buf_len = context->inbuf_totalsize -
237*7c478bd9Sstevel@tonic-gate 		    (context->inbuf_last - context->inbuf_start);
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 		/* Return size of output */
240*7c478bd9Sstevel@tonic-gate 		*out_buf_len = context->outbuf_last - context->outbuf_start;
241*7c478bd9Sstevel@tonic-gate 		if (*out_buf_len > 0) {
242*7c478bd9Sstevel@tonic-gate 			/* null-terminate the output */
243*7c478bd9Sstevel@tonic-gate 			*(context->outbuf_last) = '\0';
244*7c478bd9Sstevel@tonic-gate 			*out_buf_len = *out_buf_len + 1;
245*7c478bd9Sstevel@tonic-gate 		}
246*7c478bd9Sstevel@tonic-gate 	} else {
247*7c478bd9Sstevel@tonic-gate 		/* Return size of output */
248*7c478bd9Sstevel@tonic-gate 		*out_buf_len = context->outbuf_p - context->outbuf_start + 1;
249*7c478bd9Sstevel@tonic-gate 		*(context->outbuf_p) = '\0';	/* null-terminate the output */
250*7c478bd9Sstevel@tonic-gate 	}
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 	(void) free(context->audit_adr);
253*7c478bd9Sstevel@tonic-gate 	(void) free(context);
254*7c478bd9Sstevel@tonic-gate 	return (retstat);
255*7c478bd9Sstevel@tonic-gate }
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate /*
258*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
259*7c478bd9Sstevel@tonic-gate  * print_audit() - display contents of audit trail file
260*7c478bd9Sstevel@tonic-gate  *
261*7c478bd9Sstevel@tonic-gate  *		   Parses the binary audit data from the file mapped as stdin,
262*7c478bd9Sstevel@tonic-gate  *		   and formats as requested to file mapped as stdout.
263*7c478bd9Sstevel@tonic-gate  *	inputs:
264*7c478bd9Sstevel@tonic-gate  *		   flags -	formatting flags as defined in praudit.h
265*7c478bd9Sstevel@tonic-gate  *		   separator -	field delimiter (or NULL if the default
266*7c478bd9Sstevel@tonic-gate  *				delimiter of comma is to be used).
267*7c478bd9Sstevel@tonic-gate  *
268*7c478bd9Sstevel@tonic-gate  * return codes:   -1 - error
269*7c478bd9Sstevel@tonic-gate  *		    0 - successful
270*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
271*7c478bd9Sstevel@tonic-gate  */
272*7c478bd9Sstevel@tonic-gate int
print_audit(const int flags,const char * separator)273*7c478bd9Sstevel@tonic-gate print_audit(const int flags, const char *separator)
274*7c478bd9Sstevel@tonic-gate {
275*7c478bd9Sstevel@tonic-gate 	int	retstat = 0;
276*7c478bd9Sstevel@tonic-gate 	pr_context_t	*context;
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	if ((retstat = check_inputs(flags, separator)) != 0)
279*7c478bd9Sstevel@tonic-gate 		return (retstat);
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	if ((context = (pr_context_t *)malloc(sizeof (pr_context_t))) == NULL) {
282*7c478bd9Sstevel@tonic-gate 		errno = EPERM;
283*7c478bd9Sstevel@tonic-gate 		return (-1);
284*7c478bd9Sstevel@tonic-gate 	}
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	/*
287*7c478bd9Sstevel@tonic-gate 	 * get an adr pointer to the current audit file (stdin)
288*7c478bd9Sstevel@tonic-gate 	 */
289*7c478bd9Sstevel@tonic-gate 	context->audit_adr = malloc(sizeof (adr_t));
290*7c478bd9Sstevel@tonic-gate 	context->audit_adrf = malloc(sizeof (adrf_t));
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	adrf_start(context->audit_adrf, context->audit_adr, stdin);
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	context->data_mode = FILEMODE;
295*7c478bd9Sstevel@tonic-gate 	context->audit_rec_start = NULL;
296*7c478bd9Sstevel@tonic-gate 	context->audit_rec_len = 0;
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	context->pending_flag = 0;
299*7c478bd9Sstevel@tonic-gate 	context->current_rec = 0;
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate 	retstat = print_audit_common(context, flags, separator);
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	(void) free(context->audit_adr);
304*7c478bd9Sstevel@tonic-gate 	(void) free(context->audit_adrf);
305*7c478bd9Sstevel@tonic-gate 	(void) free(context);
306*7c478bd9Sstevel@tonic-gate 	return (retstat);
307*7c478bd9Sstevel@tonic-gate }
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate /*
310*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
311*7c478bd9Sstevel@tonic-gate  * print_audit_common() - common routine for print_audit* functions.
312*7c478bd9Sstevel@tonic-gate  *
313*7c478bd9Sstevel@tonic-gate  *		   Parses the binary audit data, and formats as requested.
314*7c478bd9Sstevel@tonic-gate  *		   The context parameter defines whether the source of the
315*7c478bd9Sstevel@tonic-gate  *		   audit data is a buffer, or a file mapped to stdin, and
316*7c478bd9Sstevel@tonic-gate  *		   whether the output is to a buffer or a file mapped to
317*7c478bd9Sstevel@tonic-gate  *		   stdout.
318*7c478bd9Sstevel@tonic-gate  *
319*7c478bd9Sstevel@tonic-gate  *	inputs:
320*7c478bd9Sstevel@tonic-gate  *		   context -	defines the context of the request, including
321*7c478bd9Sstevel@tonic-gate  *				info about the source and output.
322*7c478bd9Sstevel@tonic-gate  *		   flags -	formatting flags as defined in praudit.h
323*7c478bd9Sstevel@tonic-gate  *		   separator -	field delimiter (or NULL if the default
324*7c478bd9Sstevel@tonic-gate  *				delimiter of comma is to be used).
325*7c478bd9Sstevel@tonic-gate  *
326*7c478bd9Sstevel@tonic-gate  * return codes:   -1 - error
327*7c478bd9Sstevel@tonic-gate  *		    0 - successful
328*7c478bd9Sstevel@tonic-gate  * ----------------------------------------------------------------------
329*7c478bd9Sstevel@tonic-gate  */
330*7c478bd9Sstevel@tonic-gate static int
print_audit_common(pr_context_t * context,const int flags,const char * separator)331*7c478bd9Sstevel@tonic-gate print_audit_common(pr_context_t *context, const int flags,
332*7c478bd9Sstevel@tonic-gate     const char *separator)
333*7c478bd9Sstevel@tonic-gate {
334*7c478bd9Sstevel@tonic-gate 	int	retstat = 0;
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 	if (!initdone) {
337*7c478bd9Sstevel@tonic-gate 		init_tokens();
338*7c478bd9Sstevel@tonic-gate 		initdone++;
339*7c478bd9Sstevel@tonic-gate 	}
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	context->format = flags;
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 	/* start with default delimiter of comma */
344*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(context->SEPARATOR, ",", SEP_SIZE);
345*7c478bd9Sstevel@tonic-gate 	if (separator != NULL) {
346*7c478bd9Sstevel@tonic-gate 		if (strlen(separator) < SEP_SIZE) {
347*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(context->SEPARATOR, separator, SEP_SIZE);
348*7c478bd9Sstevel@tonic-gate 		}
349*7c478bd9Sstevel@tonic-gate 	}
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 	while ((retstat == 0) && pr_input_remaining(context, 1)) {
352*7c478bd9Sstevel@tonic-gate 		if (pr_adr_char(context, (char *)&(context->tokenid), 1) == 0) {
353*7c478bd9Sstevel@tonic-gate 			retstat = token_processing(context);
354*7c478bd9Sstevel@tonic-gate 		} else
355*7c478bd9Sstevel@tonic-gate 			break;
356*7c478bd9Sstevel@tonic-gate 	}
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 	/*
359*7c478bd9Sstevel@tonic-gate 	 * For buffer processing, if the entire input buffer was processed
360*7c478bd9Sstevel@tonic-gate 	 * successfully, but the last record in the buffer was incomplete
361*7c478bd9Sstevel@tonic-gate 	 * (according to the length from its header), then reflect an
362*7c478bd9Sstevel@tonic-gate 	 * "incomplete input" error (which will cause partial results to be
363*7c478bd9Sstevel@tonic-gate 	 * returned).
364*7c478bd9Sstevel@tonic-gate 	 */
365*7c478bd9Sstevel@tonic-gate 	if ((context->data_mode == BUFMODE) && (retstat == 0) &&
366*7c478bd9Sstevel@tonic-gate 	    (context->audit_adr->adr_now < (context->audit_rec_start +
367*7c478bd9Sstevel@tonic-gate 	    context->audit_rec_len))) {
368*7c478bd9Sstevel@tonic-gate 		retstat = -1;
369*7c478bd9Sstevel@tonic-gate 		errno = EIO;
370*7c478bd9Sstevel@tonic-gate 	}
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	/*
373*7c478bd9Sstevel@tonic-gate 	 * If there was a last record that didn't get officially closed
374*7c478bd9Sstevel@tonic-gate 	 * off, do it now.
375*7c478bd9Sstevel@tonic-gate 	 */
376*7c478bd9Sstevel@tonic-gate 	if ((retstat == 0) && (context->format & PRF_XMLM) &&
377*7c478bd9Sstevel@tonic-gate 	    (context->current_rec)) {
378*7c478bd9Sstevel@tonic-gate 		retstat = do_newline(context, 1);
379*7c478bd9Sstevel@tonic-gate 		if (retstat == 0)
380*7c478bd9Sstevel@tonic-gate 			retstat = close_tag(context, context->current_rec);
381*7c478bd9Sstevel@tonic-gate 	}
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	return (retstat);
384*7c478bd9Sstevel@tonic-gate }
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate /*
387*7c478bd9Sstevel@tonic-gate  * -----------------------------------------------------------------------
388*7c478bd9Sstevel@tonic-gate  * token_processing:
389*7c478bd9Sstevel@tonic-gate  *		  Calls the routine corresponding to the token id
390*7c478bd9Sstevel@tonic-gate  *		  passed in the parameter from the token table, tokentable
391*7c478bd9Sstevel@tonic-gate  * return codes : -1 - error
392*7c478bd9Sstevel@tonic-gate  *		:  0 - successful
393*7c478bd9Sstevel@tonic-gate  * -----------------------------------------------------------------------
394*7c478bd9Sstevel@tonic-gate  */
395*7c478bd9Sstevel@tonic-gate static int
token_processing(pr_context_t * context)396*7c478bd9Sstevel@tonic-gate token_processing(pr_context_t *context)
397*7c478bd9Sstevel@tonic-gate {
398*7c478bd9Sstevel@tonic-gate 	uval_t	uval;
399*7c478bd9Sstevel@tonic-gate 	int	retstat;
400*7c478bd9Sstevel@tonic-gate 	int	tokenid = context->tokenid;
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	if ((tokenid > 0) && (tokenid <= MAXTOKEN) &&
403*7c478bd9Sstevel@tonic-gate 	    (tokentable[tokenid].func != NOFUNC)) {
404*7c478bd9Sstevel@tonic-gate 		/*
405*7c478bd9Sstevel@tonic-gate 		 * First check if there's a previous record that needs to be
406*7c478bd9Sstevel@tonic-gate 		 * closed off now; then checkpoint our progress as needed.
407*7c478bd9Sstevel@tonic-gate 		 */
408*7c478bd9Sstevel@tonic-gate 		if ((retstat = check_close_rec(context, tokenid)) != 0)
409*7c478bd9Sstevel@tonic-gate 			return (retstat);
410*7c478bd9Sstevel@tonic-gate 		checkpoint_progress(context);
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate 		/* print token name */
413*7c478bd9Sstevel@tonic-gate 		if (context->format & PRF_XMLM) {
414*7c478bd9Sstevel@tonic-gate 			retstat = open_tag(context, tokenid);
415*7c478bd9Sstevel@tonic-gate 		} else {
416*7c478bd9Sstevel@tonic-gate 			if (!(context->format & PRF_RAWM) &&
417*7c478bd9Sstevel@tonic-gate 			    (tokentable[tokenid].t_name != (char *)0)) {
418*7c478bd9Sstevel@tonic-gate 				uval.uvaltype = PRA_STRING;
419*7c478bd9Sstevel@tonic-gate 				uval.string_val =
420*7c478bd9Sstevel@tonic-gate 				    gettext(tokentable[tokenid].t_name);
421*7c478bd9Sstevel@tonic-gate 			} else {
422*7c478bd9Sstevel@tonic-gate 				uval.uvaltype = PRA_BYTE;
423*7c478bd9Sstevel@tonic-gate 				uval.char_val = tokenid;
424*7c478bd9Sstevel@tonic-gate 			}
425*7c478bd9Sstevel@tonic-gate 			retstat = pa_print(context, &uval, 0);
426*7c478bd9Sstevel@tonic-gate 		}
427*7c478bd9Sstevel@tonic-gate 		if (retstat == 0)
428*7c478bd9Sstevel@tonic-gate 			retstat = (*tokentable[tokenid].func)(context);
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 		/*
431*7c478bd9Sstevel@tonic-gate 		 * For XML, close the token tag. Header tokens wrap the
432*7c478bd9Sstevel@tonic-gate 		 * entire record, so they only get closed later implicitly;
433*7c478bd9Sstevel@tonic-gate 		 * here, just make sure the header open tag gets finished.
434*7c478bd9Sstevel@tonic-gate 		 */
435*7c478bd9Sstevel@tonic-gate 		if ((retstat == 0) && (context->format & PRF_XMLM)) {
436*7c478bd9Sstevel@tonic-gate 			if (!is_header_token(tokenid))
437*7c478bd9Sstevel@tonic-gate 				retstat = close_tag(context, tokenid);
438*7c478bd9Sstevel@tonic-gate 			else
439*7c478bd9Sstevel@tonic-gate 				retstat = finish_open_tag(context);
440*7c478bd9Sstevel@tonic-gate 		}
441*7c478bd9Sstevel@tonic-gate 		return (retstat);
442*7c478bd9Sstevel@tonic-gate 	}
443*7c478bd9Sstevel@tonic-gate 	/* here if token id is not in table */
444*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("praudit: No code associated with "
445*7c478bd9Sstevel@tonic-gate 	    "token id %d\n"), tokenid);
446*7c478bd9Sstevel@tonic-gate 	return (0);
447*7c478bd9Sstevel@tonic-gate }
448