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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * @(#)audit_path.c 2.7 92/02/16 SMI; SunOS CMW
28 * @(#)audit_path.c 4.2.1.2 91/05/08 SMI; BSM Module
29 *
30 * This code does the audit path processes. Part of this is still in
31 * audit.c and will be moved here when time permits.
32 *
33 * Note that audit debuging is enabled here. We will turn it off at
34 * beta shipment.
35 */
36
37#include <sys/types.h>
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/user.h>
41#include <sys/vnode.h>
42#include <sys/vfs.h>
43#include <sys/kmem.h>		/* for KM_SLEEP */
44#include <sys/proc.h>
45#include <sys/uio.h>
46#include <sys/file.h>
47#include <sys/stat.h>
48#include <sys/pathname.h>
49#include <sys/acct.h>
50#include <c2/audit.h>
51#include <c2/audit_kernel.h>
52#include <c2/audit_record.h>
53#include <sys/sysmacros.h>
54#include <sys/atomic.h>
55
56
57int
58au_token_size(m)
59	token_t *m;
60{
61	int i;
62
63	if (m == (token_t *)0)
64		return (0);
65
66	for (i = 0; m != (token_t *)0; m = m->next_buf)
67		i += m->len;
68	return (i);
69}
70
71token_t *
72au_set(cp, size)
73	caddr_t  cp;
74	uint_t    size;
75{
76	au_buff_t *head;
77	au_buff_t *tail;
78	au_buff_t *m;
79	uint_t	l;
80
81	head = NULL;
82	tail = NULL;	/* only to satisfy lint */
83
84	while (size) {
85		m = au_get_buff();
86		l = MIN(size, AU_BUFSIZE);
87		bcopy(cp, memtod(m, char *), l);
88		m->len = l;
89
90		if (head)
91			tail->next_buf = m;	/* tail set if head set */
92		else
93			head = m;
94		tail = m;
95		size -= l;
96		cp += l;
97	}
98
99	return (head);
100}
101
102token_t *
103au_append_token(chain, m)
104	token_t *chain;
105	token_t *m;
106{
107	token_t *mbp;
108
109	if (chain == (token_t *)0)
110		return (m);
111
112	if (m == (token_t *)0)
113		return (chain);
114
115	for (mbp = chain; mbp->next_buf != (token_t *)0; mbp = mbp->next_buf)
116		;
117	mbp->next_buf = m;
118	return (chain);
119}
120
121
122void
123audit_fixpath(struct audit_path *app, int len)
124{
125	int id;		/* index of where we are in destination string */
126	int is;		/* index of where we are in source string */
127	int cnt;	/* # of levels in audit_path */
128	int slashseen;	/* have we seen a slash */
129	char *s;	/* start of top-level string */
130	char c;
131
132	cnt = app->audp_cnt;
133	s = app->audp_sect[cnt - 1];
134	is = (app->audp_sect[cnt] - s) - len;
135	if (is <= 2)
136		is = 0;	/* catch leading // or ./ */
137	slashseen = (is > 0);
138	for (id = is; ; is++) {
139		if ((c = s[is]) == '\0') {
140			/* that's all folks, we've reached the end of input */
141			if (id > 1 && s[id-1] == '/') {
142				/* remove terminating / */
143				--id;
144			}
145			s[id++] = '\0';
146			break;
147		}
148		if (slashseen) {
149			/* previous character was a / */
150			if (c == '/') {
151				/* another slash, ignore it */
152				continue;
153			}
154		} else if (c == '/') {
155			/* we see a /, just copy it and try again */
156			slashseen = 1;
157			s[id++] = c;
158			continue;
159		}
160		if (c == '.') {
161			if ((c = s[is+1]) == '\0') {
162				/* XXX/. seen */
163				if (id > 1)
164					id--;
165				continue;
166			}
167			if (c == '/') {
168				/* XXX/./ seen */
169				is += 1;
170				continue;
171			}
172			if (c == '.' && (s[is+2] == '\0' || s[is+2] == '/')) {
173				/* XXX/.. or XXX/../ seen */
174				is++;
175				if (id == 0 && cnt > 1) {
176					char	*s_attr;
177					/* .. refers to attributed object */
178					app->audp_cnt = --cnt;
179					s_attr = s;
180					s = app->audp_sect[cnt - 1];
181					id = s_attr - s;
182					is += id;
183					id--;
184					slashseen = 0;
185					continue;
186				}
187				/* backup over previous component */
188				if (id > 0)
189					id--;
190				while (id > 0 && s[id - 1] != '/')
191					id--;
192				continue;
193			}
194		}
195		/* copy component name and terminating /, if any */
196		for (;;) {
197			c = s[is++];
198			if (c == '\0' || c == '/')
199				break;
200			s[id++] = c;
201		}
202		/* back up to before terminating '\0' or / */
203		slashseen = 0;
204		is -= 2;
205	}
206	/* fill empty attribute directory reference */
207	if (id == 1 && cnt > 1) {
208		s[0] = '.';
209		s[1] = '\0';
210		id = 2;
211	}
212	/* correct end pointer */
213	app->audp_sect[cnt] = s + id;
214}
215