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