jafs-library-20020725
[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 int 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 
148    * the name of the AFS cell it represents and the username and password 
149    * of the user to be Tokend for 
150    * administrative access.
151    *
152    * @param username    the name of the user to Token with
153    * @param password    the password of that user
154    * @param cellName    the name of the cell to Token into
155    * @exception AFSException  If an error occurs in the native code
156    */
157   public Token( String username, String password, String cellName ) 
158       throws AFSException
159   {
160     this.username = username;
161     this.password = password;
162     this.cellName = cellName;
163
164 System.out.println(username + ", " + cellName);
165     /* By default lets authenticate the user using libafsauthent.a */
166     login();
167   }
168
169   /**
170    * Returns the name of the AFS cell that this <code>Token</code> was
171    * authenticated against.
172    *
173    * @exception AFSException  If an error occurs in the native code
174    * @return the name of the AFS cell associated with this <code>Token</code>.
175    */
176   public String getCellName()
177   {
178     return cellName;
179   }
180
181   /**
182    * Returns the username of user to whom this token belongs.
183    *
184    * @exception AFSException  If an error occurs in the native code
185    * @return the username of the user represented by this Token
186    */
187   public String getUsername()
188   {
189     return username;
190   }
191
192   /**
193    * Returns a token handle that can be used to prove this authentication 
194    * later.
195    *
196    * @exception AFSException  If an error occurs in the native code
197    * @return a token representing the authentication
198    */
199   protected int getHandle()
200   {
201     return tokenHandle;
202   }
203
204   /**
205    * Closes the given currently open token.
206    *
207    * @exception AFSException  If an error occurs in the native code
208    */
209   public void close() throws AFSException
210   {
211     close(tokenHandle);
212   }
213
214   /**
215    *  Gets the expiration time for a given token.
216    *
217    * @return a long representing the UTC time for the token expiration
218    * @exception AFSException  If an error occurs in the native code
219    */
220   public long getExpiration() throws AFSException
221   {
222     return getExpiration(tokenHandle);
223   }
224
225   /**
226    * Authenticates a user in kas, and binds that authentication
227    * to the current process.
228    *
229    * @exception AFSException  If an error occurs in the native code
230    */
231   public void klog() throws AFSException
232   {
233     if (!hasInitialized) {
234       initializeUserSpace();
235       hasInitialized = true;
236     }
237     if (pagID > -1) {
238       relog(pagID);
239     } else {
240       pagID = klog(username, password, cellName, pagID);
241     }
242   }
243
244   /**
245    * Authenticates a user in KAS, and binds that authentication
246    * to the current process.
247    *
248    * @exception AFSException  If an error occurs in the native code
249    */
250   public void login() throws AFSException
251   {
252     this.tokenHandle = this.getToken(cellName, username, password);
253 System.out.println("Token handle -> " + tokenHandle);
254   }
255
256   /**
257    * Initialize the user space AFS client (libjafs).
258    *
259    * <P> The user space client must be initialized prior to any
260    * user space related methods, including: klog, unlog, relog,
261    * and shutdown.
262    *
263    * @exception AFSException  If an error occurs in the native code
264    */
265   protected static void initializeUserSpace() throws AFSException
266   {
267     try {
268       Token.initUserSpace();
269     } catch (AFSException e) {
270       System.err.println(e.getMessage());
271     }
272     try {
273         Runtime.getRuntime().addShutdownHook(new AFSShutdownHandler());
274     } catch (Exception e) {
275         System.err.println("Could not register shutdown hook: " + e.toString());
276     }
277   }
278
279   /////////////// custom override methods ////////////////////
280
281   /**
282    * Compares two ACL objects respective to their paths and does not
283    * factor any other attribute.    Alphabetic case is significant in 
284    * comparing names.
285    *
286    * @param     acl    The ACL object to be compared to this ACL
287    *                   instance
288    * 
289    * @return    Zero if the argument is equal to this ACL's path, a
290    *            value less than zero if this ACL's path is
291    *            lexicographically less than the argument, or a value greater
292    *            than zero if this ACL's path is lexicographically
293    *            greater than the argument
294    */
295   public int compareTo(Token token)
296   {
297     return this.toString().compareTo(token.toString());
298   }
299
300   /**
301    * Comparable interface method.
302    *
303    * @see #compareTo(Token)
304    */
305   public int compareTo(Object obj)
306   {
307     return compareTo((Token)obj);
308   }
309
310   /**
311    * Tests whether two <code>Cell</code> objects are equal, based on their 
312    * names.  Does not test whether the objects are actually the same
313    * representational instance of the AFS cell.
314    *
315    * @param otherCell   the <code>Cell</code> to test
316    * @return whether the specifed user is the same as this user
317    */
318   public boolean equals( Token token )
319   {
320     return this.toString().equals( token.toString() );
321   }
322
323   /**
324    * Returns the name of this <CODE>Cell</CODE>
325    *
326    * @return the name of this <CODE>Cell</CODE>
327    */
328   public String toString()
329   {
330     return username + "@" + cellName + ":" + tokenHandle;
331   }
332
333   /////////////// native methods found in *Token.c ////////////////////
334
335   /**
336    * Initialize the user space library.
337    *
338    * @exception AFSException  If an error occurs in the native code
339    */
340   private static native void initUserSpace() throws AFSException;
341
342   /**
343    * Initialize the administrative library.
344    *
345    * @exception AFSException  If an error occurs in the native code
346    */
347   protected static native void initializeAdminClient() throws AFSException;
348
349   /**
350    * Returns a token handle that can be used to prove this authentication 
351    * later.
352    *
353    * @param cellName    the name of the cell in which to Token this user
354    * @param userName    the name of the user to Token
355    * @param password    the password of the user
356    * @exception AFSException  If an error occurs in the native code
357    * @return a token representing the authentication
358    */
359   protected native int getToken( String cellName, String username, 
360                                  String password ) 
361         throws AFSException;
362
363   /**
364    * Closes the given currently open token.
365    *
366    * @param tokenHandle   the token to close
367    * @exception AFSException  If an error occurs in the native code
368    */
369   protected native void close( int tokenHandle ) throws AFSException;
370
371   /**
372    *  Gets the expiration time for a given token.
373    *
374    * @param tokenHandle    a token handle previously returned by a call 
375    *                       to {@link #getToken}
376    * @see #getToken
377    * @return a long representing the UTC time for the token expiration
378    * @exception AFSException  If an error occurs in the native code
379    */
380   protected native long getExpiration( int tokenHandle )
381       throws AFSException;
382
383   /**
384    * Authenticates a user in KAS, and binds that authentication
385    * to the current thread or native process.
386    *
387    * @param username         the login to authenticate 
388    *                         (expected as username@cellname)
389    * @param password         the password of the login
390    * @param cellName         the name of the cell to authenticate into
391    * @param id               the existing pag (or 0)
392    *
393    * @return the assigned pag
394    * @exception AFSException  If an error occurs in the native code
395    */
396   protected native int klog(String username, String password, 
397                             String cellName, int id) 
398         throws AFSException;
399
400   /**
401    * Authenticates a user in KAS by a previously acquired PAG ID, and binds 
402    * that authentication to the current thread or native process.
403    *
404    * <P> This method does not require the user's username and password to
405    * fully authenticate their request.  Rather it utilizes the user's PAG ID
406    * to recapture the user's existing credentials.
407    *
408    * <P> This method is called by the public <code>klog</code> method, which
409    * internally manages the PAG ID. Additionally, an application needs only
410    * call <code>klog</code>, this reduces the amount of complexity and ensures
411    * that <code>relog</code> is never called before a <code>klog</code>.
412    *
413    * @param int User's current PAG (process authentication group) ID
414    * @exception AFSException  If an error occurs in the native code
415    */
416   protected native void relog(int id) throws AFSException;
417
418   /**
419    * Manually discards all AFS credentials associated with the bound user.
420    *
421    * @exception AFSException  If an error occurs in the native code
422    */
423   public native void unlog() throws AFSException;
424
425   /**
426    * Inform the native library that the application is 
427    * shutting down and will be unloading.
428    *
429    * <p> The library will make a call informing the file server that it will 
430    * no longer be available for callbacks.
431    */
432   protected static native void shutdown();
433
434   /**
435    * Reclaims all memory being saved by the authentication portion of 
436    * the native library.
437    * This method should be called when no more authentications are expected.
438    */
439   protected static native void reclaimAuthMemory();
440 }
441
442 /*=======================================================================*/
443 /**
444  * Class that loads the native libraries required for direct communication with
445  * AFS. Since the Token class is serializable the function of loading the 
446  * native libraries must be performed in a non-serialized class, one that will
447  * not be included in any client side application packages.
448  *                                                                             
449  * @version 1.0, 06/13/2001
450  */
451 class AFSLibraryLoader
452 {
453   static
454   {
455     System.loadLibrary("jafs");
456     System.loadLibrary("jafsadm");
457   }
458 }
459 /*=======================================================================*/
460 /**
461  * Class that handles graceful AFS application shutdown procedures by
462  * instructing the native library to inform the file system server that
463  * it is shutting down.
464  *                                                                             
465  * @version 1.0, 06/13/2001
466  */
467 class AFSShutdownHandler extends Thread
468 {
469   public AFSShutdownHandler() {}
470
471   /**
472    * This is the execution method satisfying the interface requirement as a 
473    * stand alone runnable thread.
474    *
475    * <p> This method will automatically be invoked by the Thread instantiator.
476    *
477    * @see Token#shutdown()
478    */
479   public void run() 
480   {
481     System.out.println("Shutting down Java AFS library...");
482     org.openafs.jafs.Token.shutdown();
483   }
484 }
485 /*=======================================================================*/
486
487
488
489
490
491
492
493