Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / JAVA / classes / org / openafs / jafs / Token.java
1 /*
2 * @(#)Token.java 1.2 05/06/2002
3 *
4 * Copyright (c) 2001 International Business Machines Corp.
5 * All rights reserved.
6 *
7 * This software has been released under the terms of the IBM Public
8 * License. For details, see the LICENSE file in the top-level source
9 * directory or online at http://www.openafs.org/dl/license10.html
10 *
11 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
12 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
13 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
15 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 */
23
24 package org.openafs.jafs;
25
26 import java.io.Serializable;
27
28 /**
29 * An abstract representation of an AFS authentication token. It conveniently
30 * maintains the handle associated with token and the cell to which the token
31 * is authenticated.
32 * <BR><BR>
33 *
34 * Constructing a <code>Token</code> object results in an immediate attempt to
35 * authenticate the user within the specified cell. If this attempt fails, an
36 * <code>{@link AFSException}</code> will be thrown. Therefore, if the
37 * construction of the object succeeds without an exception, then the
38 * <code>Token</code> is considered authenticated.
39 *
40 * The construction of a <code>Token</code> object acts as an entry point
41 * for authentication into the AFS system. Thus, when you construct a
42 * <code>{@link Cell}</code> object, you must pass in an instance of a
43 * <code>Token</code> that has been authenticated within the AFS cell that
44 * <code><I>Cell</I></code> is intended to represent. You will only be
45 * allowed to perform actions that the user, used to authenticate
46 * <code>Token</code>, is authorized to perform. You must construct a
47 * <code>Token</code> object before constructing a <code>Cell</code> object,
48 * which is required by all other objects within this package either directly
49 * or indirectly.<BR><BR>
50 *
51 * If an error occurs during a method call, an
52 * <code>AFSException</code> will be thrown. This class is the Java
53 * equivalent of errors thrown by AFS; see {@link AFSException}
54 * for a complete description.<BR><BR>
55 *
56 * <!--Example of how to use class-->
57 * The following is a simple example of how to construct and use a
58 * <code>Token</code> object. It shows how to construct a <code>Cell</code>
59 * using a <code>Token</code>. See {@link Cell} for a more detailed example
60 * of constructing and using a <code>Cell</code> object.<BR><BR>
61 *
62 * <PRE>
63 * import org.openafs.jafs.AFSException;
64 * import org.openafs.jafs.Cell;
65 * import org.openafs.jafs.Token;
66 * ...
67 * public class ...
68 * {
69 * ...
70 * private Cell cell;
71 * private Token token;
72 * ...
73 * public static void main(String[] args) throws Exception
74 * {
75 * String username = arg[0];
76 * String password = arg[1];
77 * String cellName = arg[2];
78 * String serverName = arg[3];
79 *
80 * token = new Token(username, password, cellName);
81 * cell = new Cell(token);
82 * ...
83 * }
84 * ...
85 * }
86 * </PRE>
87 *
88 */
89
90 public class Token implements Serializable, Comparable
91 {
92 public static int ANYUSER_PAG_ID;
93
94 protected long tokenHandle;
95 protected int pagID = -1;
96 protected int errno;
97
98 protected String cellName;
99 protected String username;
100 private String password;
101
102 private boolean hasInitialized = false;
103
104 /**
105 * Load the native libraries <code>libjafs</code> and
106 * <code>libjafs</code>.
107 */
108 static
109 {
110 try {
111 Class.forName("org.openafs.jafs.AFSLibraryLoader");
112 try {
113 initializeAdminClient();
114 } catch (Exception e) {
115 System.err.println(e);
116 }
117 } catch (ClassNotFoundException e) {
118 /* Most likely running on a client, do nothing */
119 }
120 }
121
122 /**
123 * Constructs a new <CODE>Token</CODE> object instance given
124 * the name of the AFS cell it represents and the username and password
125 * of the user to be Tokend for
126 * administrative access.
127 *
128 * @param username the name of the user to Token with
129 * @param password the password of that user
130 * @param cellName the name of the cell to Token into
131 * @param login if true, automatically login upon construction
132 * @exception AFSException If an error occurs in the native code
133 */
134 protected Token( String username, String password, String cellName,
135 boolean automaticallyLogin )
136 throws AFSException
137 {
138 this.username = username;
139 this.password = password;
140 this.cellName = cellName;
141
142 /* By default lets authenticate the user using libafsauthent.a */
143 if (automaticallyLogin) login();
144 }
145
146 /**
147 * Constructs a new <CODE>Token</CODE> object instance given the
148 * name of the AFS cell it represents; the token for administrative
149 * access will be extracted from the kernel cache manager if possible.
150 *
151 * @param cellName the name of the cell to Token into
152 * @exception AFSException If an error occurs in the native code
153 */
154 public Token(String cellName)
155 throws AFSException
156 {
157 this(null, null, cellName);
158 }
159
160 /**
161 * Constructs a new <CODE>Token</CODE> object instance given
162 * the name of the AFS cell it represents and the username and password
163 * of the user to be Tokend for
164 * administrative access.
165 *
166 * @param username the name of the user to Token with
167 * @param password the password of that user
168 * @param cellName the name of the cell to Token into
169 * @exception AFSException If an error occurs in the native code
170 */
171 public Token( String username, String password, String cellName )
172 throws AFSException
173 {
174 this.username = username;
175 this.password = password;
176 this.cellName = cellName;
177
178 //System.out.println(username + ", " + cellName);
179 /* By default lets authenticate the user using libafsauthent.a */
180 login();
181 }
182
183 /**
184 * Returns the name of the AFS cell that this <code>Token</code> was
185 * authenticated against.
186 *
187 * @exception AFSException If an error occurs in the native code
188 * @return the name of the AFS cell associated with this <code>Token</code>.
189 */
190 public String getCellName()
191 {
192 return cellName;
193 }
194
195 /**
196 * Returns the username of user to whom this token belongs.
197 *
198 * @exception AFSException If an error occurs in the native code
199 * @return the username of the user represented by this Token
200 */
201 public String getUsername()
202 {
203 return username;
204 }
205
206 /**
207 * Returns a token handle that can be used to prove this authentication
208 * later.
209 *
210 * @exception AFSException If an error occurs in the native code
211 * @return a token representing the authentication
212 */
213 protected long getHandle()
214 {
215 return tokenHandle;
216 }
217
218 /**
219 * Closes the given currently open token.
220 *
221 * @exception AFSException If an error occurs in the native code
222 */
223 public void close() throws AFSException
224 {
225 close(tokenHandle);
226 }
227
228 /**
229 * Gets the expiration time for a given token.
230 *
231 * @return a long representing the UTC time for the token expiration
232 * @exception AFSException If an error occurs in the native code
233 */
234 public long getExpiration() throws AFSException
235 {
236 return getExpiration(tokenHandle);
237 }
238
239 /**
240 * Authenticates a user in kas, and binds that authentication
241 * to the current process.
242 *
243 * @exception AFSException If an error occurs in the native code
244 */
245 public void klog() throws AFSException
246 {
247 if (!hasInitialized) {
248 initializeUserSpace();
249 hasInitialized = true;
250 }
251 if (pagID > -1) {
252 relog(pagID);
253 } else {
254 pagID = klog(username, password, cellName, pagID);
255 }
256 }
257
258 /**
259 * Authenticates a user in KAS, and binds that authentication
260 * to the current process.
261 *
262 * @exception AFSException If an error occurs in the native code
263 */
264 public void login() throws AFSException
265 {
266 this.tokenHandle = this.getToken(cellName, username, password);
267 //System.out.println("Token handle -> " + tokenHandle);
268 }
269
270 /**
271 * Initialize the user space AFS client (libjafs).
272 *
273 * <P> The user space client must be initialized prior to any
274 * user space related methods, including: klog, unlog, relog,
275 * and shutdown.
276 *
277 * @exception AFSException If an error occurs in the native code
278 */
279 protected static void initializeUserSpace() throws AFSException
280 {
281 try {
282 Token.initUserSpace();
283 } catch (AFSException e) {
284 System.err.println(e.getMessage());
285 }
286 try {
287 Runtime.getRuntime().addShutdownHook(new AFSShutdownHandler());
288 } catch (Exception e) {
289 System.err.println("Could not register shutdown hook: " + e.toString());
290 }
291 }
292
293 /////////////// custom override methods ////////////////////
294
295 /**
296 * Compares two ACL objects respective to their paths and does not
297 * factor any other attribute. Alphabetic case is significant in
298 * comparing names.
299 *
300 * @param acl The ACL object to be compared to this ACL
301 * instance
302 *
303 * @return Zero if the argument is equal to this ACL's path, a
304 * value less than zero if this ACL's path is
305 * lexicographically less than the argument, or a value greater
306 * than zero if this ACL's path is lexicographically
307 * greater than the argument
308 */
309 public int compareTo(Token token)
310 {
311 return this.toString().compareTo(token.toString());
312 }
313
314 /**
315 * Comparable interface method.
316 *
317 * @see #compareTo(Token)
318 */
319 public int compareTo(Object obj)
320 {
321 return compareTo((Token)obj);
322 }
323
324 /**
325 * Tests whether two <code>Cell</code> objects are equal, based on their
326 * names. Does not test whether the objects are actually the same
327 * representational instance of the AFS cell.
328 *
329 * @param otherCell the <code>Cell</code> to test
330 * @return whether the specifed user is the same as this user
331 */
332 public boolean equals( Token token )
333 {
334 return this.toString().equals( token.toString() );
335 }
336
337 /**
338 * Returns the name of this <CODE>Cell</CODE>
339 *
340 * @return the name of this <CODE>Cell</CODE>
341 */
342 public String toString()
343 {
344 return username + "@" + cellName + ":" + tokenHandle;
345 }
346
347 /////////////// native methods found in *Token.c ////////////////////
348
349 /**
350 * Initialize the user space library.
351 *
352 * @exception AFSException If an error occurs in the native code
353 */
354 private static native void initUserSpace() throws AFSException;
355
356 /**
357 * Initialize the administrative library.
358 *
359 * @exception AFSException If an error occurs in the native code
360 */
361 protected static native void initializeAdminClient() throws AFSException;
362
363 /**
364 * Returns a token handle that can be used to prove this authentication
365 * later.
366 *
367 * @param cellName the name of the cell in which to Token this user
368 * @param userName the name of the user to Token
369 * @param password the password of the user
370 * @exception AFSException If an error occurs in the native code
371 * @return a token representing the authentication
372 */
373 protected native long getToken( String cellName, String username,
374 String password )
375 throws AFSException;
376
377 /**
378 * Closes the given currently open token.
379 *
380 * @param tokenHandle the token to close
381 * @exception AFSException If an error occurs in the native code
382 */
383 protected native void close( long tokenHandle ) throws AFSException;
384
385 /**
386 * Gets the expiration time for a given token.
387 *
388 * @param tokenHandle a token handle previously returned by a call
389 * to {@link #getToken}
390 * @see #getToken
391 * @return a long representing the UTC time for the token expiration
392 * @exception AFSException If an error occurs in the native code
393 */
394 protected native long getExpiration( long tokenHandle )
395 throws AFSException;
396
397 /**
398 * Authenticates a user in KAS, and binds that authentication
399 * to the current thread or native process.
400 *
401 * @param username the login to authenticate
402 * (expected as username@cellname)
403 * @param password the password of the login
404 * @param cellName the name of the cell to authenticate into
405 * @param id the existing pag (or 0)
406 *
407 * @return the assigned pag
408 * @exception AFSException If an error occurs in the native code
409 */
410 protected native int klog(String username, String password,
411 String cellName, int id)
412 throws AFSException;
413
414 /**
415 * Authenticates a user in KAS by a previously acquired PAG ID, and binds
416 * that authentication to the current thread or native process.
417 *
418 * <P> This method does not require the user's username and password to
419 * fully authenticate their request. Rather it utilizes the user's PAG ID
420 * to recapture the user's existing credentials.
421 *
422 * <P> This method is called by the public <code>klog</code> method, which
423 * internally manages the PAG ID. Additionally, an application needs only
424 * call <code>klog</code>, this reduces the amount of complexity and ensures
425 * that <code>relog</code> is never called before a <code>klog</code>.
426 *
427 * @param int User's current PAG (process authentication group) ID
428 * @exception AFSException If an error occurs in the native code
429 */
430 protected native void relog(int id) throws AFSException;
431
432 /**
433 * Manually discards all AFS credentials associated with the bound user.
434 *
435 * @exception AFSException If an error occurs in the native code
436 */
437 public native void unlog() throws AFSException;
438
439 /**
440 * Inform the native library that the application is
441 * shutting down and will be unloading.
442 *
443 * <p> The library will make a call informing the file server that it will
444 * no longer be available for callbacks.
445 */
446 protected static native void shutdown();
447
448 /**
449 * Reclaims all memory being saved by the authentication portion of
450 * the native library.
451 * This method should be called when no more authentications are expected.
452 */
453 protected static native void reclaimAuthMemory();
454 }
455
456 /*=======================================================================*/
457 /**
458 * Class that loads the native libraries required for direct communication with
459 * AFS. Since the Token class is serializable the function of loading the
460 * native libraries must be performed in a non-serialized class, one that will
461 * not be included in any client side application packages.
462 *
463 * @version 1.0, 06/13/2001
464 */
465 class AFSLibraryLoader
466 {
467 static
468 {
469 System.loadLibrary("jafs");
470 System.loadLibrary("jafsadm");
471 }
472 }
473 /*=======================================================================*/
474 /**
475 * Class that handles graceful AFS application shutdown procedures by
476 * instructing the native library to inform the file system server that
477 * it is shutting down.
478 *
479 * @version 1.0, 06/13/2001
480 */
481 class AFSShutdownHandler extends Thread
482 {
483 public AFSShutdownHandler() {}
484
485 /**
486 * This is the execution method satisfying the interface requirement as a
487 * stand alone runnable thread.
488 *
489 * <p> This method will automatically be invoked by the Thread instantiator.
490 *
491 * @see Token#shutdown()
492 */
493 public void run()
494 {
495 System.out.println("Shutting down Java AFS library...");
496 org.openafs.jafs.Token.shutdown();
497 }
498 }
499 /*=======================================================================*/
500
501
502
503
504
505
506
507