xref: /illumos-gate/usr/src/cmd/praudit/prio.c (revision 7c478bd9)
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
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
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
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
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
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
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
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
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
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
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
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