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