1 /*
2 * CDDL HEADER START
3 *
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
7 * with the License.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <sys/varargs.h>
32 #include <bsm/audit.h>
33 #include <bsm/libbsm.h>
34 #include <bsm/audit_record.h>
35
36 #include "praudit.h"
37
38
39 /*
40 * pr_adr_char - pull out characters
41 */
42 int
pr_adr_char(pr_context_t * context,char * cp,int count)43 pr_adr_char(pr_context_t *context, char *cp, int count)
44 {
45 int err;
46 adr_t *adr = context->audit_adr;
47 adrf_t *adrf = context->audit_adrf;
48
49 if (context->data_mode == FILEMODE) {
50 err = adrf_char(adrf, cp, count);
51 if (err) {
52 errno = EIO;
53 return (-1);
54 } else
55 return (0);
56 }
57
58 /* adrm routines don't return error, so check before calling */
59 if (!pr_input_remaining(context, (sizeof (char) * count))) {
60 errno = EIO;
61 return (-1);
62 }
63
64 adrm_char(adr, cp, count);
65 return (0);
66 }
67
68 /*
69 * pr_adr_short - pull out shorts
70 */
71 int
pr_adr_short(pr_context_t * context,short * sp,int count)72 pr_adr_short(pr_context_t *context, short *sp, int count)
73 {
74 int err;
75 adr_t *adr = context->audit_adr;
76 adrf_t *adrf = context->audit_adrf;
77
78 if (context->data_mode == FILEMODE) {
79 err = adrf_short(adrf, sp, count);
80 if (err) {
81 errno = EIO;
82 return (-1);
83 } else
84 return (0);
85 }
86
87 /* adrm routines don't return error, so check before calling */
88 if (!pr_input_remaining(context, (sizeof (short) * count))) {
89 errno = EIO;
90 return (-1);
91 }
92
93 adrm_short(adr, sp, count);
94 return (0);
95 }
96
97 /*
98 * pr_adr_int32 - pull out int32
99 */
100 int
pr_adr_int32(pr_context_t * context,int32_t * lp,int count)101 pr_adr_int32(pr_context_t *context, int32_t *lp, int count)
102 {
103 int err;
104 adr_t *adr = context->audit_adr;
105 adrf_t *adrf = context->audit_adrf;
106
107 if (context->data_mode == FILEMODE) {
108 err = adrf_int32(adrf, lp, count);
109 if (err) {
110 errno = EIO;
111 return (-1);
112 } else
113 return (0);
114 }
115
116 /* adrm routines don't return error, so check before calling */
117 if (!pr_input_remaining(context, (sizeof (int32_t) * count))) {
118 errno = EIO;
119 return (-1);
120 }
121
122 adrm_int32(adr, lp, count);
123 return (0);
124 }
125
126 int
pr_adr_int64(pr_context_t * context,int64_t * lp,int count)127 pr_adr_int64(pr_context_t *context, int64_t *lp, int count)
128 {
129 int err;
130 adr_t *adr = context->audit_adr;
131 adrf_t *adrf = context->audit_adrf;
132
133 if (context->data_mode == FILEMODE) {
134 err = adrf_int64(adrf, lp, count);
135 if (err) {
136 errno = EIO;
137 return (-1);
138 } else
139 return (0);
140 }
141
142 /* adrm routines don't return error, so check before calling */
143 if (!pr_input_remaining(context, (sizeof (int64_t) * count))) {
144 errno = EIO;
145 return (-1);
146 }
147
148 adrm_int64(adr, lp, count);
149 return (0);
150 }
151
152 int
pr_adr_u_int32(pr_context_t * context,uint32_t * cp,int count)153 pr_adr_u_int32(pr_context_t *context, uint32_t *cp, int count)
154 {
155 return (pr_adr_int32(context, (int32_t *)cp, count));
156 }
157
158 int
pr_adr_u_char(pr_context_t * context,uchar_t * cp,int count)159 pr_adr_u_char(pr_context_t *context, uchar_t *cp, int count)
160 {
161 return (pr_adr_char(context, (char *)cp, count));
162 }
163
164 int
pr_adr_u_int64(pr_context_t * context,uint64_t * lp,int count)165 pr_adr_u_int64(pr_context_t *context, uint64_t *lp, int count)
166 {
167 return (pr_adr_int64(context, (int64_t *)lp, count));
168 }
169
170 int
pr_adr_u_short(pr_context_t * context,ushort_t * sp,int count)171 pr_adr_u_short(pr_context_t *context, ushort_t *sp, int count)
172 {
173 return (pr_adr_short(context, (short *)sp, count));
174 }
175
176 int
pr_putchar(pr_context_t * context,char c)177 pr_putchar(pr_context_t *context, char c)
178 {
179 if (context->data_mode == FILEMODE) {
180 (void) putchar(c);
181 return (0);
182 }
183 /* Buffer-based output processing otherwise... */
184
185 /* Need at least room for char + null-byte */
186 if (context->outbuf_remain_len < 2) {
187 /* no space left */
188 errno = ENOSPC;
189 return (-1);
190 }
191
192 *(context->outbuf_p) = c;
193 context->outbuf_p += 1;
194 context->outbuf_remain_len -= 1;
195
196 return (0);
197 }
198
199 int
pr_printf(pr_context_t * context,const char * fmt,...)200 pr_printf(pr_context_t *context, const char *fmt, ...)
201 {
202 int addlen;
203 va_list ap;
204
205 va_start(ap, fmt);
206
207 if (context->data_mode == FILEMODE) {
208 (void) vprintf(fmt, ap);
209 va_end(ap);
210 return (0);
211 }
212 /* Buffer-based output processing otherwise... */
213
214 if (context->outbuf_remain_len < 2) {
215 /* no space at all left */
216 va_end(ap);
217 errno = ENOSPC;
218 return (-1);
219 }
220
221 /* Attempt to tack on this string */
222 addlen = vsnprintf(context->outbuf_p, context->outbuf_remain_len - 1,
223 fmt, ap);
224 va_end(ap);
225 if (addlen < 0) {
226 /* output error */
227 errno = EPERM;
228 return (-1);
229 }
230 if (addlen >= context->outbuf_remain_len - 1) {
231 /* not enough space; bail out */
232 errno = ENOSPC;
233 return (-1);
234 }
235
236 /*
237 * vsnprintf was successful; update pointers and counters
238 * as needed. If no bytes were written, treat it as a no-op
239 * and don't need to update anything.
240 */
241 if (addlen >= 1) {
242 context->outbuf_remain_len -= addlen;
243 context->outbuf_p += addlen;
244 }
245
246 return (0);
247 }
248
249
250 /*
251 * pr_input_remaining - Check whether size bytes (or more) are remaining in
252 * the inbuf.
253 * returns 1 - there are enough bytes remaining
254 * 0 - not enough bytes left
255 */
256 int
pr_input_remaining(pr_context_t * context,size_t size)257 pr_input_remaining(pr_context_t *context, size_t size)
258 {
259 adr_t *adr = context->audit_adr;
260
261 /* no-op if not doing buf mode */
262 if (context->data_mode != BUFMODE)
263 return (1);
264
265 if ((adr_count(adr) + size) > context->inbuf_totalsize)
266 return (0);
267 else
268 return (1);
269 }
270