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 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * ident	"%Z%%M%	%I%	%E% SMI"
27  */
28 package com.sun.audit;
29 
30 import java.util.Stack;
31 import java.io.Serializable;
32 
33 public class AuditSession implements Serializable
34 {
35 	// LD_LIBRARY_PATH determines directory for libadt_jni.so.
36 	// When you get an UnsatisfiedLinkError, and have determined
37 	// the path is right, the problem is probably in the library
38 	// itself, but Java doesn't say what it is.  Set up a cc
39 	// command to link the library to see what the actual error
40 	// is.
41 
42 	static private boolean library_loaded = false;
43 	static {
44 		try {
45 			System.loadLibrary("adt_jni");
46 			library_loaded = true;
47 		} catch (Exception ex) {
48 			library_loaded = false;
49 		} catch (java.lang.UnsatisfiedLinkError ul) {
50 			library_loaded = false;
51 		}
52 	}
53 	private native boolean bsmAuditOn();
54 	private native byte[] startSession(
55 	    byte[] context, long flags)
56 	    throws Error;
57 	private native byte[] dupSession(
58 	    byte[] source)
59 	    throws Error;
60 	private native void endSession(byte[] sessionHandle)
61 	    throws Error;
62 	private native String getSessionId(byte[] sessionHandle)
63 	    throws Error;
64 	private native byte[] exportSessionData(byte[] sessionHandle)
65 	    throws Error;
66 	private native void sessionAttr(byte[] sessionHandle,
67 	    int euid, int egid, int ruid, int rgid,
68             String hostname, int context)
69 	    throws Error;
70 //TSOL only
71 //	private native void setSL(byte[] sessionHandle, String label);
72 //end TSOL
73 
74 	private byte[] sh;  // current session handle
75 
76 	private Stack stateStack = new Stack();  // for push/pop
77 
78 	boolean AuditIsOn = true;		// Underlying BSM state
79 	boolean ValidSession = true;		// Session object state
80 
81 	// Create an audit session.
82 	// The fixed length of 8 corresponds to a 64 bit pointer;
83 	// valid overkill on 32 bit systems.
84 	// Even if bsmAuditOn returns false, need to create a session.
85 
86 	public AuditSession(byte[] context) {
87 
88 		if (!library_loaded) {
89 			ValidSession = false;
90 			AuditIsOn = false;
91 			sh = new byte[8];  // NULL pointer in C
92 			return;
93 		}
94 		AuditIsOn = bsmAuditOn();
95 		try {
96 			sh = startSession(context, 0);
97 		}
98 		catch (java.lang.Exception e) {
99 			ValidSession = false;
100 			sh = new byte[8];
101 		}
102 		catch (java.lang.Error e) {
103 			ValidSession = false;
104 			sh = new byte[8];
105 			throw e;
106 		}
107 	}
108 
109 	// getSession() is for use by AuditEvent, not much use to caller of
110 	// AuditSession "package protected"  == not public
111 	//
112 	// If you think you need this C pointer (sh), see
113 	// exportSession() and the "context" parameter to
114 	// startSession() for a way to pass an audit thread from one
115 	// process to another or from one language to another.
116 
117 	byte[] getSession() {
118 		return sh;
119 	}
120 
121 	public String getSessionId() throws Exception {
122 		String	sessionId;
123 
124 		if (ValidSession) {
125 			try {
126 				sessionId = getSessionId(sh);
127 			}
128 			catch (Exception e) {
129 				sessionId = null;
130 				throw e;
131 			}
132 			catch (Error e) {
133 				sessionId = null;
134 				throw e;
135 			}
136 		} else {
137 			sessionId = null;
138 		}
139 		return sessionId;
140 	}
141 
142 	// auditOn: The return value does not reveal whether or
143 	// auditing is on, but whether or not the current audit
144 	// session was created ok.
145 
146 	public boolean auditOn() {
147 		return (ValidSession);
148 	}
149 
150 	public void finalize() {
151 		byte[]	state;
152 
153 		while (!stateStack.empty()) {
154 			state = (byte[])stateStack.pop();
155 			endSession(state);
156 		}
157 		endSession(sh);
158 	}
159 
160 	// Returns export data even if auditing is off.  If the
161 	// session is invalid (no jni library, memory error in
162 	// startSession), returns null.
163 	//
164 	// If you use exportSession(), it is important that you first
165 	// call setUser() even when auditOn() returns false; otherwise
166 	// the exported session will result in remote processes being
167 	// unable to generate an valid audit trail.
168 
169 	public byte[] exportSession() throws Exception {
170 		byte[]	exportedData;
171 
172 		if (ValidSession) {
173 			try {
174 				exportedData = exportSessionData(sh);
175 			}
176 			catch (java.lang.Exception e) {
177 				throw e;
178 			}
179 		} else {
180 			exportedData = null;
181 		}
182 		return exportedData;
183 	}
184 
185 	// ADT_NEW, ADT_UPDATE and ADT_USER are the only valid values
186 	// for the context input to setUser().  If the user has
187 	// completed initial authentication, use ADT_NEW; if the user
188 	// is to change ids, such as to a role or to root, use
189 	// ADT_UPDATE.  If the process audit context is already set,
190 	// use ADT_USER.
191 
192 	// If a uid or gid is unknown (e.g., unrecognized login id)
193 	// then use ADT_NO_ATTRIB for the uid/gid.
194 	//
195 	// For ADT_UPDATE only, use ADT_NO_CHANGE for any uid or gid
196 	// that you don't wish to change.
197 
198 	public static final int ADT_NEW = 0;
199 	public static final int ADT_UPDATE = 1;
200 	public static final int ADT_USER = 2;
201 	public static final int ADT_NO_ATTRIB = -1;
202 	public static final int ADT_NO_CHANGE = -2;
203 
204 	public void setUser(int euid, int egid, int ruid, int rgid,
205 			     String hostname, int context) {
206 
207 		if (ValidSession) {
208 			try {
209 				sessionAttr(sh, euid, egid, ruid, rgid,
210 				    hostname, context);
211 			}
212 			catch (java.lang.Error e) {
213 				throw e;
214 			}
215 		}
216 	}
217 
218 	// pushState duplicates the session handle, puts the source
219 	// handle on a stack, and makes the duplicate the current
220 	// handle dupSession throws an out of memory error to be
221 	// caught higher up.
222 
223 	public void pushState() throws Exception {
224 		byte[]		copy;
225 		int		i;
226 
227 		copy = dupSession(sh);
228 		stateStack.push(sh);
229 		sh = copy;
230 	}
231 
232 	// popState frees the current handle and pops a handle off a
233 	// stack to become the new current handle.
234 	// As with pushState, it lets the caller deal with any exceptions.
235 
236 	public void popState() throws Exception {
237 
238 		endSession(sh);
239 		sh = (byte[])stateStack.pop();
240 	}
241 //TSOL -- stub for base Solaris; should be called even if auditOn is
242 //false.
243 	public void setLabel(String label) throws Exception {
244 	//	if (ValidSession)
245 	//		setSL(sh, label);
246 	}
247 //end TSOL
248 }
249