Commit | Line | Data |
---|---|---|
805e021f CE |
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 |