4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
37 #include <sys/types.h>
40 #include <bsm/audit.h>
41 #include <bsm/audit_record.h>
42 #include <bsm/libbsm.h>
47 extern void init_tokens(void); /* shared with auditreduce */
49 static int check_inputs(int flags
, const char *separator
);
50 static void checkpoint_progress(pr_context_t
*context
);
51 static int print_audit_common(pr_context_t
*context
, int flags
,
52 const char *separator
);
53 static int token_processing(pr_context_t
*context
);
55 static int initdone
= 0;
58 * This source is shared outside of praudit; the following lint directive
59 * is needed to suppress praudit lint warnings about unused functions, for
60 * functions which are only invoked outside praudit.
66 * ----------------------------------------------------------------------
67 * check_inputs() - check input flags and delimiter.
70 * -1 - invalid inputs. errno is set to EINVAL
71 * ----------------------------------------------------------------------
74 check_inputs(int flags
, const char *separator
)
76 if ((flags
& PRF_RAWM
) && (flags
& PRF_SHORTM
)) {
81 /* Ignore the delimiter when XML is specified */
82 if (!(flags
& PRF_XMLM
) && (strlen(separator
) >= SEP_SIZE
)) {
91 * ----------------------------------------------------------------------
92 * print_audit_xml_prolog_buf() - print the XML prolog.
94 * -1 - output buffer too small. errno is set to ENOSPC
95 * ----------------------------------------------------------------------
98 print_audit_xml_prolog_buf(char *out_buf
, const int out_buf_len
)
100 if (xml_prolog_len
> out_buf_len
) {
105 (void) snprintf(out_buf
, out_buf_len
, "%s%s%s%s", prolog1
, prolog_xsl
,
112 * ----------------------------------------------------------------------
113 * print_audit_xml_ending_buf() - print the XML ending.
115 * -1 - output buffer too small. errno is set to ENOSPC
116 * ----------------------------------------------------------------------
119 print_audit_xml_ending_buf(char *out_buf
, const int out_buf_len
)
121 if (xml_end_len
> out_buf_len
) {
126 (void) snprintf(out_buf
, out_buf_len
, "%s", xml_ending
);
131 * ----------------------------------------------------------------------
132 * print_prolog() - print the XML prolog.
133 * ----------------------------------------------------------------------
136 print_audit_xml_prolog(void)
138 (void) printf("%s%s%s%s", prolog1
, prolog_xsl
, prolog2
, xml_start
);
142 * ----------------------------------------------------------------------
143 * print_ending() - print the XML ending.
144 * ----------------------------------------------------------------------
147 print_audit_xml_ending(void)
149 (void) printf("%s", xml_ending
);
153 * ----------------------------------------------------------------------
154 * checkpoint_progress() - If starting a new file or header token,
155 * checkpoint as needed to mark progress.
156 * ----------------------------------------------------------------------
159 checkpoint_progress(pr_context_t
*context
)
161 int tokenid
= context
->tokenid
;
163 if (is_file_token(tokenid
) || is_header_token(tokenid
)) {
164 if (context
->data_mode
== BUFMODE
) {
165 context
->inbuf_last
= context
->audit_adr
->adr_now
- 1;
166 context
->outbuf_last
= context
->outbuf_p
;
168 context
->audit_rec_start
= context
->audit_adr
->adr_now
- 1;
169 if (is_file_token(tokenid
)) {
170 context
->audit_rec_len
= 11;
176 * ----------------------------------------------------------------------
177 * print_audit_buf() - display contents of audit trail file
179 * Parses the binary audit data from the specified input
180 * buffer, and formats as requested to the specified output
184 * in_buf, - address and length of binary audit input.
186 * out_buf, - address and length of output buffer to
187 * out_buf_len copy formatted audit data to.
188 * flags - formatting flags as defined in praudit.h
189 * separator - field delimiter (or NULL if the default
190 * delimiter of comma is to be used).
192 * return codes: 0 - success
194 * ----------------------------------------------------------------------
197 print_audit_buf(char **in_buf
, int *in_buf_len
, char **out_buf
,
198 int *out_buf_len
, const int flags
, const char *separator
)
201 pr_context_t
*context
;
203 if ((retstat
= check_inputs(flags
, separator
)) != 0)
206 if ((context
= (pr_context_t
*)malloc(sizeof (pr_context_t
))) == NULL
) {
211 /* Init internal pointers and lengths... */
212 context
->data_mode
= BUFMODE
;
213 context
->inbuf_last
= context
->inbuf_start
= *in_buf
;
214 context
->inbuf_totalsize
= *in_buf_len
;
216 context
->pending_flag
= 0;
217 context
->current_rec
= 0;
219 context
->outbuf_last
= context
->outbuf_start
=
220 context
->outbuf_p
= *out_buf
;
221 context
->outbuf_remain_len
= *out_buf_len
;
224 * get an adr pointer to the audit input buf
226 context
->audit_adr
= (adr_t
*)malloc(sizeof (adr_t
));
227 (void) adrm_start(context
->audit_adr
, *in_buf
);
228 context
->audit_rec_start
= NULL
;
229 context
->audit_rec_len
= 0;
231 retstat
= print_audit_common(context
, flags
, separator
);
233 /* Check for and handle partial results as needed */
235 *in_buf
= context
->inbuf_last
;
236 *in_buf_len
= context
->inbuf_totalsize
-
237 (context
->inbuf_last
- context
->inbuf_start
);
239 /* Return size of output */
240 *out_buf_len
= context
->outbuf_last
- context
->outbuf_start
;
241 if (*out_buf_len
> 0) {
242 /* null-terminate the output */
243 *(context
->outbuf_last
) = '\0';
244 *out_buf_len
= *out_buf_len
+ 1;
247 /* Return size of output */
248 *out_buf_len
= context
->outbuf_p
- context
->outbuf_start
+ 1;
249 *(context
->outbuf_p
) = '\0'; /* null-terminate the output */
252 (void) free(context
->audit_adr
);
253 (void) free(context
);
258 * ----------------------------------------------------------------------
259 * print_audit() - display contents of audit trail file
261 * Parses the binary audit data from the file mapped as stdin,
262 * and formats as requested to file mapped as stdout.
264 * flags - formatting flags as defined in praudit.h
265 * separator - field delimiter (or NULL if the default
266 * delimiter of comma is to be used).
268 * return codes: -1 - error
270 * ----------------------------------------------------------------------
273 print_audit(const int flags
, const char *separator
)
276 pr_context_t
*context
;
278 if ((retstat
= check_inputs(flags
, separator
)) != 0)
281 if ((context
= (pr_context_t
*)malloc(sizeof (pr_context_t
))) == NULL
) {
287 * get an adr pointer to the current audit file (stdin)
289 context
->audit_adr
= malloc(sizeof (adr_t
));
290 context
->audit_adrf
= malloc(sizeof (adrf_t
));
292 adrf_start(context
->audit_adrf
, context
->audit_adr
, stdin
);
294 context
->data_mode
= FILEMODE
;
295 context
->audit_rec_start
= NULL
;
296 context
->audit_rec_len
= 0;
298 context
->pending_flag
= 0;
299 context
->current_rec
= 0;
301 retstat
= print_audit_common(context
, flags
, separator
);
303 (void) free(context
->audit_adr
);
304 (void) free(context
->audit_adrf
);
305 (void) free(context
);
310 * ----------------------------------------------------------------------
311 * print_audit_common() - common routine for print_audit* functions.
313 * Parses the binary audit data, and formats as requested.
314 * The context parameter defines whether the source of the
315 * audit data is a buffer, or a file mapped to stdin, and
316 * whether the output is to a buffer or a file mapped to
320 * context - defines the context of the request, including
321 * info about the source and output.
322 * flags - formatting flags as defined in praudit.h
323 * separator - field delimiter (or NULL if the default
324 * delimiter of comma is to be used).
326 * return codes: -1 - error
328 * ----------------------------------------------------------------------
331 print_audit_common(pr_context_t
*context
, const int flags
,
332 const char *separator
)
341 context
->format
= flags
;
343 /* start with default delimiter of comma */
344 (void) strlcpy(context
->SEPARATOR
, ",", SEP_SIZE
);
345 if (separator
!= NULL
) {
346 if (strlen(separator
) < SEP_SIZE
) {
347 (void) strlcpy(context
->SEPARATOR
, separator
, SEP_SIZE
);
351 while ((retstat
== 0) && pr_input_remaining(context
, 1)) {
352 if (pr_adr_char(context
, (char *)&(context
->tokenid
), 1) == 0) {
353 retstat
= token_processing(context
);
359 * For buffer processing, if the entire input buffer was processed
360 * successfully, but the last record in the buffer was incomplete
361 * (according to the length from its header), then reflect an
362 * "incomplete input" error (which will cause partial results to be
365 if ((context
->data_mode
== BUFMODE
) && (retstat
== 0) &&
366 (context
->audit_adr
->adr_now
< (context
->audit_rec_start
+
367 context
->audit_rec_len
))) {
373 * If there was a last record that didn't get officially closed
376 if ((retstat
== 0) && (context
->format
& PRF_XMLM
) &&
377 (context
->current_rec
)) {
378 retstat
= do_newline(context
, 1);
380 retstat
= close_tag(context
, context
->current_rec
);
387 * -----------------------------------------------------------------------
389 * Calls the routine corresponding to the token id
390 * passed in the parameter from the token table, tokentable
391 * return codes : -1 - error
393 * -----------------------------------------------------------------------
396 token_processing(pr_context_t
*context
)
400 int tokenid
= context
->tokenid
;
402 if ((tokenid
> 0) && (tokenid
<= MAXTOKEN
) &&
403 (tokentable
[tokenid
].func
!= NOFUNC
)) {
405 * First check if there's a previous record that needs to be
406 * closed off now; then checkpoint our progress as needed.
408 if ((retstat
= check_close_rec(context
, tokenid
)) != 0)
410 checkpoint_progress(context
);
412 /* print token name */
413 if (context
->format
& PRF_XMLM
) {
414 retstat
= open_tag(context
, tokenid
);
416 if (!(context
->format
& PRF_RAWM
) &&
417 (tokentable
[tokenid
].t_name
!= NULL
)) {
418 uval
.uvaltype
= PRA_STRING
;
420 gettext(tokentable
[tokenid
].t_name
);
422 uval
.uvaltype
= PRA_BYTE
;
423 uval
.char_val
= tokenid
;
425 retstat
= pa_print(context
, &uval
, 0);
428 retstat
= (*tokentable
[tokenid
].func
)(context
);
431 * For XML, close the token tag. Header tokens wrap the
432 * entire record, so they only get closed later implicitly;
433 * here, just make sure the header open tag gets finished.
435 if ((retstat
== 0) && (context
->format
& PRF_XMLM
)) {
436 if (!is_header_token(tokenid
))
437 retstat
= close_tag(context
, tokenid
);
439 retstat
= finish_open_tag(context
);
443 /* here if token id is not in table */
444 (void) fprintf(stderr
, gettext("praudit: No code associated with "
445 "token id %d\n"), tokenid
);