jafs-library-20020725
[openafs.git] / src / JAVA / libjafs / User.c
1 /*
2  * Copyright (c) 2001-2002 International Business Machines Corp.
3  * All rights reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  * 
9  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
12  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
13  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
15  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
17  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
18  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20  */
21
22 #include "Internal.h"
23 #include "org_openafs_jafs_User.h"
24
25 #include <stdio.h>
26 #include <afs_ptsAdmin.h>
27 #include <afs_kasAdmin.h>
28 #include <kautils.h>
29 #include <afs_AdminPtsErrors.h>
30 #include <afs_AdminClientErrors.h>
31 #include <afs_AdminCommonErrors.h>
32 #include <prerror.h>
33
34 ///// definitions in Internal.c ////////////////////
35
36 extern jclass userCls;
37 extern jfieldID user_nameField;
38 extern jfieldID user_ptsField;
39 extern jfieldID user_kasField;
40 //pts fields
41 extern jfieldID user_nameUidField;
42 extern jfieldID user_ownerUidField;
43 extern jfieldID user_creatorUidField;
44 extern jfieldID user_listStatusField;
45 extern jfieldID user_listGroupsOwnedField;
46 extern jfieldID user_listMembershipField;
47 extern jfieldID user_groupCreationQuotaField;
48 extern jfieldID user_groupMembershipCountField;
49 extern jfieldID user_ownerField;
50 extern jfieldID user_creatorField;
51 // kas fields
52 extern jfieldID user_adminSettingField;
53 extern jfieldID user_tgsSettingField;
54 extern jfieldID user_encSettingField;
55 extern jfieldID user_cpwSettingField;
56 extern jfieldID user_rpwSettingField;
57 extern jfieldID user_userExpirationField;
58 extern jfieldID user_lastModTimeField;
59 extern jfieldID user_lastModNameField;
60 extern jfieldID user_lastChangePasswordTimeField;
61 extern jfieldID user_maxTicketLifetimeField;
62 extern jfieldID user_keyVersionField;
63 extern jfieldID user_encryptionKeyField;
64 extern jfieldID user_keyCheckSumField;
65 extern jfieldID user_daysToPasswordExpireField;
66 extern jfieldID user_failLoginCountField;
67 extern jfieldID user_lockTimeField;
68 extern jfieldID user_lockedUntilField;
69
70 extern jclass groupCls;
71 //extern jfieldID group_cellHandleField;
72 extern jfieldID group_nameField;
73 extern jfieldID group_cachedInfoField;
74
75 //////////////////////////////////////////////////////////////////
76
77 /**
78  * Creates the kas and pts entries for a new user.  Pass in 0 for the uid 
79  * if pts is to automatically assign the user id.
80  *
81  * env      the Java environment
82  * cls      the current Java class
83  * cellHandle    the handle of the cell to which the user belongs
84  * juserName      the name of the user to create
85  * jpassword      the password for the new user
86  * uid     the user id to assign to the user (0 to have one 
87  *                automatically assigned)
88  */
89 JNIEXPORT void JNICALL 
90 Java_org_openafs_jafs_User_create
91   (JNIEnv *env, jclass cls, jint cellHandle, jstring juserName, 
92    jstring jpassword, jint uid )
93 {
94   afs_status_t ast;
95   const char *userName;
96   const char *password;
97   kas_identity_p who = (kas_identity_p) malloc( sizeof(kas_identity_t) );
98   
99   if( !who ) {
100     throwAFSException( env, JAFSADMNOMEM );
101     return;    
102   }
103
104   // convert java strings
105   if( juserName != NULL ) {
106     userName = (*env)->GetStringUTFChars(env, juserName, 0);
107     if( !userName ) {
108       free( who );
109       throwAFSException( env, JAFSADMNOMEM );
110       return;    
111     }
112   } else {
113     userName = NULL;
114   }
115   if( jpassword != NULL ) {
116     password = (*env)->GetStringUTFChars(env, jpassword, 0);
117     if( !password ) {
118       free( who );
119       if( userName != NULL ) {
120         (*env)->ReleaseStringUTFChars(env, juserName, userName);
121       }
122       throwAFSException( env, JAFSADMNOMEM );
123       return;    
124     }
125   } else {
126     password = NULL;
127   }
128
129   // make sure the name is within the allowed bounds
130   if( userName != NULL && strlen( userName ) > KAS_MAX_NAME_LEN ) {
131     free( who );
132     // release converted java strings
133     if( userName != NULL ) {
134       (*env)->ReleaseStringUTFChars(env, juserName, userName);
135     }
136     if( password != NULL ) {
137       (*env)->ReleaseStringUTFChars(env, jpassword, password);
138     }
139     throwAFSException( env, ADMPTSUSERNAMETOOLONG  );
140     return;
141   }
142
143   // make sure name doesn't have ":" in it
144   if( userName != NULL && strchr( userName, ':' ) != (int) NULL ) {
145       free(who);
146       // release converted java strings
147       if( userName != NULL ) {
148         (*env)->ReleaseStringUTFChars(env, juserName, userName);
149       }
150       if( password != NULL ) {
151         (*env)->ReleaseStringUTFChars(env, jpassword, password);
152       }
153       throwAFSException( env, PRBADNAM );
154       return;
155   }
156
157   // make sure the id isn't negative
158   if( uid < 0 ) {
159       free(who);
160       // release converted java strings
161       if( userName != NULL ) {
162         (*env)->ReleaseStringUTFChars(env, juserName, userName);
163       }
164       if( password != NULL ) {
165         (*env)->ReleaseStringUTFChars(env, jpassword, password);
166       }
167       // use the "bad arg" error code even though it's an ID exception.  
168       // There isn't a bad user ID error code
169       throwAFSException( env, PRBADARG );
170       return;
171   }
172
173   if( userName != NULL ) {
174     internal_makeKasIdentity( userName, who );
175   }
176
177   // create the kas entry
178   if (!kas_PrincipalCreate( (void *) cellHandle, NULL, who, 
179                             password, &ast ) ) {
180     free(who);
181     // release converted java strings
182     if( userName != NULL ) {
183       (*env)->ReleaseStringUTFChars(env, juserName, userName);
184     }
185     if( password != NULL ) {
186       (*env)->ReleaseStringUTFChars(env, jpassword, password);
187     }
188     throwAFSException( env, ast );
189     return;
190   } 
191
192   // create the pts entry - if there's an error, make sure to delete 
193   // the kas entry 
194   if( !pts_UserCreate( (void *) cellHandle, userName, (int *) &uid, &ast ) ) {
195     afs_status_t ast_kd;
196     kas_PrincipalDelete( (void *) cellHandle, NULL, who, &ast_kd );
197     free( who );
198     // release converted java strings
199     if( userName != NULL ) {
200       (*env)->ReleaseStringUTFChars(env, juserName, userName);
201     }
202     if( password != NULL ) {
203       (*env)->ReleaseStringUTFChars(env, jpassword, password);
204     }
205     throwAFSException( env, ast );
206     return;
207   }
208
209   free( who );
210   // release converted java strings
211   if( userName != NULL ) {
212     (*env)->ReleaseStringUTFChars(env, juserName, userName);
213   }
214   if( password != NULL ) {
215     (*env)->ReleaseStringUTFChars(env, jpassword, password);
216   }
217
218 }
219
220 /**
221  * Deletes the pts and kas entry for a user.  Deletes this user from the 
222  * membership list of the groups to which it belonged, but does not delete 
223  * the groups owned by this user.
224  *
225  * env      the Java environment
226  * cls      the current Java class
227  * cellHandle    the handle of the cell to which the user belongs
228  * juserName      the name of the user to delete
229  */
230 JNIEXPORT void JNICALL 
231 Java_org_openafs_jafs_User_delete
232   (JNIEnv *env, jclass cls, jint cellHandle, jstring juserName )
233 {
234   afs_status_t ast;
235   const char *userName;
236   kas_identity_p who = (kas_identity_p) malloc( sizeof(kas_identity_t) );  
237   int kas;
238   
239   if( !who ) {
240     throwAFSException( env, JAFSADMNOMEM );
241     return;    
242   }
243
244   if( juserName != NULL ) {
245       userName = (*env)->GetStringUTFChars(env, juserName, 0);
246       if( !userName ) {
247         free( who );
248         throwAFSException( env, JAFSADMNOMEM );
249         return;    
250       }
251   } else {
252       userName = NULL;
253   }
254
255   // make sure the name is within the allowed bounds
256   if( userName != NULL && strlen( userName ) > KAS_MAX_NAME_LEN ) {
257     free( who );
258     if( userName != NULL ) {
259         (*env)->ReleaseStringUTFChars(env, juserName, userName);
260     }
261     throwAFSException( env, ADMPTSUSERNAMETOOLONG  );
262     return;
263   }
264
265   if( userName != NULL ) {
266       internal_makeKasIdentity( userName, who );
267   }
268
269   // delete the kas entry
270   if( !kas_PrincipalDelete( (void *) cellHandle, NULL, who, &ast ) ) {
271       if( ast != KANOENT ) {
272           free(who);
273           if( userName != NULL ) {
274               (*env)->ReleaseStringUTFChars(env, juserName, userName);
275           }
276           throwAFSException( env, ast );
277           return;
278       } else {
279           kas = FALSE;
280       }
281   }
282
283   //delete the pts entry
284   if( !pts_UserDelete( (void *) cellHandle, userName, &ast ) ) {
285       // throw exception if there was no such pts user only if there was 
286       // also no such kas user
287       if( (ast == ADMPTSFAILEDNAMETRANSLATE && !kas ) || 
288           ast != ADMPTSFAILEDNAMETRANSLATE ) {
289           free( who );
290           if( userName != NULL ) {
291               (*env)->ReleaseStringUTFChars(env, juserName, userName);
292           }
293           throwAFSException( env, ast );
294           return;
295       }
296   }
297
298   free( who );
299   // release converted java strings
300   if( userName != NULL ) {
301       (*env)->ReleaseStringUTFChars(env, juserName, userName);
302   }
303 }
304
305 /**
306  * Unlocks a user.
307  *
308  * env      the Java environment
309  * cls      the current Java class
310  * cellHandle    the handle of the cell to which the user belongs
311  * juserName      the name of the user to unlock
312  */
313 JNIEXPORT void JNICALL 
314 Java_org_openafs_jafs_User_unlock
315   (JNIEnv *env, jclass cls, jint cellHandle, jstring juserName )
316 {
317   afs_status_t ast;
318   const char *userName;
319   kas_identity_p who = (kas_identity_p) malloc( sizeof(kas_identity_t) );  
320   
321   if( !who ) {
322     throwAFSException( env, JAFSADMNOMEM );
323     return;    
324   }
325
326   // convert java strings
327   if( juserName != NULL ) {
328       userName = (*env)->GetStringUTFChars(env, juserName, 0);
329     if( !userName ) {
330         throwAFSException( env, JAFSADMNOMEM );
331         return;    
332     }
333   } else {
334       userName = NULL;
335   }
336
337   // make sure the name is within the allowed bounds
338   if( userName != NULL && strlen( userName ) > KAS_MAX_NAME_LEN ) {
339     free( who );
340     if( userName != NULL ) {
341         (*env)->ReleaseStringUTFChars(env, juserName, userName);
342     }
343     throwAFSException( env, ADMPTSUSERNAMETOOLONG  );
344     return;
345   }  
346
347   if( userName != NULL ) {
348     internal_makeKasIdentity( userName, who );
349   }
350
351   if( !kas_PrincipalUnlock( (void *) cellHandle, NULL, who, &ast ) ) {
352     free( who );
353     if( userName != NULL ) {
354         (*env)->ReleaseStringUTFChars(env, juserName, userName);
355     }
356     throwAFSException( env, ast );
357     return;
358   }
359
360   free( who );
361   // release converted java strings
362   if( userName != NULL ) {
363       (*env)->ReleaseStringUTFChars(env, juserName, userName);
364   }
365 }
366
367 /**
368  * Retrieve the information for the specified user and populate the
369  * given object
370  *
371  * env      the Java environment
372  * cellHandle    the handle of the cell to which the user belongs
373  * name      the name of the user for which to get the info
374  * user      the User object to populate with the info
375  */
376 void getUserInfoChar
377   (JNIEnv *env, int cellHandle, const char *name, jobject user)
378 {
379   jstring jowner;
380   jstring jcreator;
381   jstring jlastModName;
382   jstring jencryptionKey;
383   jboolean pts;
384   jboolean kas;
385   pts_UserEntry_t ptsEntry;
386   afs_status_t ast;
387   kas_identity_p who = (kas_identity_p) malloc( sizeof(kas_identity_t) );
388   kas_principalEntry_t kasEntry;
389   unsigned int lockedUntil;
390
391   if( !who ) {
392     throwAFSException( env, JAFSADMNOMEM );
393     return;    
394   }
395
396   // make sure the name is within the allowed bounds
397   if( name != NULL && strlen( name ) > KAS_MAX_NAME_LEN ) {
398     free( who );
399     throwAFSException( env, ADMPTSUSERNAMETOOLONG );
400     return;
401   }
402   
403   if( name != NULL ) {
404       internal_makeKasIdentity( name, who );
405   }
406
407   // get all the field ids, if you haven't done so already
408   if( userCls == 0 ) {
409     internal_getUserClass( env, user );
410   }
411
412   // get the pts entry
413   if ( !pts_UserGet( (void *) cellHandle, name, &ptsEntry, &ast ) ) {
414     // if the user has no pts ptsEntry
415     if( ast == ADMPTSFAILEDNAMETRANSLATE ) {
416         pts = FALSE;    
417     } else {
418         free( who );
419         throwAFSException( env, ast );
420         return;
421     }
422   } else {
423       pts = TRUE;
424   }
425   
426
427   // get the kas entry
428   if( !kas_PrincipalGet( (void *) cellHandle, NULL, who, &kasEntry, &ast ) ) {
429     // no kas entry
430     if( ast == KANOENT ) { 
431         if( !pts ) {
432             free( who );
433             throwAFSException( env, ast );
434             return;
435         } else {
436             kas = FALSE;
437         }
438     // other
439     } else {
440         free( who );
441         throwAFSException( env, ast );
442         return;
443     }
444   } else {
445       kas = TRUE;
446   }
447
448   // get the lock status
449   if( kas && !kas_PrincipalLockStatusGet( (void *) cellHandle, NULL, who, 
450                                           &lockedUntil, &ast ) ) {
451     free( who );
452     throwAFSException( env, ast );
453     return;
454   }
455
456   (*env)->SetBooleanField(env, user, user_ptsField, pts);
457   (*env)->SetBooleanField(env, user, user_kasField, kas);
458
459   // set the pts fields
460   if( pts ) {
461       (*env)->SetIntField(env, user, user_nameUidField, ptsEntry.nameUid);
462       (*env)->SetIntField(env, user, user_ownerUidField, ptsEntry.ownerUid);
463       (*env)->SetIntField(env, user, user_creatorUidField, 
464                           ptsEntry.creatorUid);
465       (*env)->SetIntField(env, user, user_groupCreationQuotaField, 
466                           ptsEntry.groupCreationQuota);
467       (*env)->SetIntField(env, user, user_groupMembershipCountField, 
468                           ptsEntry.groupMembershipCount);
469       
470       if( ptsEntry.listStatus == PTS_USER_OWNER_ACCESS ) {
471           (*env)->SetIntField(env, user, user_listStatusField, 
472                               org_openafs_jafs_User_USER_OWNER_ACCESS);
473       } else {
474           (*env)->SetIntField(env, user, user_listStatusField, 
475                               org_openafs_jafs_User_USER_ANYUSER_ACCESS);
476       }
477       if( ptsEntry.listGroupsOwned == PTS_USER_OWNER_ACCESS ) {
478           (*env)->SetIntField(env, user, user_listGroupsOwnedField, 
479                               org_openafs_jafs_User_USER_OWNER_ACCESS);
480       } else {
481           (*env)->SetIntField(env, user, user_listGroupsOwnedField, 
482                               org_openafs_jafs_User_USER_ANYUSER_ACCESS);
483       }
484       if( ptsEntry.listMembership == PTS_USER_OWNER_ACCESS ) {
485           (*env)->SetIntField(env, user, user_listMembershipField, 
486                               org_openafs_jafs_User_USER_OWNER_ACCESS);
487       } else {
488           (*env)->SetIntField(env, user, user_listMembershipField, 
489                               org_openafs_jafs_User_USER_ANYUSER_ACCESS);
490       }
491       
492       jowner = (*env)->NewStringUTF(env, ptsEntry.owner);
493       jcreator =  (*env)->NewStringUTF(env, ptsEntry.creator);
494       
495       (*env)->SetObjectField(env, user, user_ownerField, jowner);
496       (*env)->SetObjectField(env, user, user_creatorField, jcreator);
497
498   }
499
500   // set the kas fields
501   if( kas ) {
502       char *convertedKey;
503       int i;
504       if( kasEntry.adminSetting == KAS_ADMIN ) {
505           (*env)->SetIntField(env, user, user_adminSettingField, 
506                               org_openafs_jafs_User_ADMIN);
507       } else {
508           (*env)->SetIntField(env, user, user_adminSettingField, 
509                               org_openafs_jafs_User_NO_ADMIN);
510       }
511       if( kasEntry.tgsSetting == TGS ) {
512           (*env)->SetIntField(env, user, user_tgsSettingField, 
513                               org_openafs_jafs_User_GRANT_TICKETS);
514       } else {
515           (*env)->SetIntField(env, user, user_tgsSettingField, 
516                               org_openafs_jafs_User_NO_GRANT_TICKETS);
517       }
518       if( kasEntry.encSetting != NO_ENCRYPT ) {
519           (*env)->SetIntField(env, user, user_encSettingField, 
520                               org_openafs_jafs_User_ENCRYPT);
521       } else {
522           (*env)->SetIntField(env, user, user_encSettingField, 
523                               org_openafs_jafs_User_NO_ENCRYPT);
524       }
525       if( kasEntry.cpwSetting == CHANGE_PASSWORD ) {
526           (*env)->SetIntField(env, user, user_cpwSettingField, 
527                               org_openafs_jafs_User_CHANGE_PASSWORD);
528       } else {
529           (*env)->SetIntField(env, user, user_cpwSettingField, 
530                               org_openafs_jafs_User_NO_CHANGE_PASSWORD);
531       }
532       if( kasEntry.rpwSetting == REUSE_PASSWORD ) {
533           (*env)->SetIntField(env, user, user_rpwSettingField, 
534                               org_openafs_jafs_User_REUSE_PASSWORD);
535       } else {
536           (*env)->SetIntField(env, user, user_rpwSettingField, 
537                               org_openafs_jafs_User_NO_REUSE_PASSWORD);
538       }
539       (*env)->SetIntField(env, user, user_userExpirationField, 
540                           kasEntry.userExpiration);
541       (*env)->SetIntField(env, user, user_lastModTimeField, 
542                           kasEntry.lastModTime);
543       (*env)->SetIntField(env, user, user_lastChangePasswordTimeField, 
544                           kasEntry.lastChangePasswordTime);
545       (*env)->SetIntField(env, user, user_maxTicketLifetimeField, 
546                           kasEntry.maxTicketLifetime);
547       (*env)->SetIntField(env, user, user_keyVersionField, 
548                           kasEntry.keyVersion);
549       (*env)->SetLongField(env, user, user_keyCheckSumField, 
550                            (unsigned int) kasEntry.keyCheckSum);
551       (*env)->SetIntField(env, user, user_daysToPasswordExpireField, 
552                           kasEntry.daysToPasswordExpire);
553       (*env)->SetIntField(env, user, user_failLoginCountField, 
554                           kasEntry.failLoginCount);
555       (*env)->SetIntField(env, user, user_lockTimeField, kasEntry.lockTime);
556       (*env)->SetIntField(env, user, user_lockedUntilField, lockedUntil);
557       
558       jlastModName = (*env)->NewStringUTF(env, 
559                                           kasEntry.lastModPrincipal.principal);
560       (*env)->SetObjectField(env, user, user_lastModNameField, jlastModName);
561
562       convertedKey = (char *) malloc( sizeof(char *)*
563                                       (sizeof(kasEntry.key.key)*4+1) );
564       if( !convertedKey ) {
565         throwAFSException( env, JAFSADMNOMEM );
566         return;    
567       }
568       for( i = 0; i < sizeof(kasEntry.key.key); i++ ) {
569         sprintf( &(convertedKey[i*4]), "\\%0.3o", kasEntry.key.key[i] );
570       }
571       jencryptionKey =  (*env)->NewStringUTF(env, convertedKey);
572       (*env)->SetObjectField(env, user, user_encryptionKeyField, 
573                              jencryptionKey);
574       free( convertedKey );
575   }
576   free(who);
577 }
578
579 /**
580  * Fills in the information fields of the provided User.  
581  * Fills in values based on the current pts and kas information of the user.
582  *
583  * env      the Java environment
584  * cls      the current Java class
585  * cellHandle    the handle of the cell to which the user belongs
586  * jname     the name of the user for which to get the information
587  * user     the User object in which to fill in the 
588  *                 information
589  */
590 JNIEXPORT void JNICALL 
591 Java_org_openafs_jafs_User_getUserInfo
592   (JNIEnv *env, jclass cls, jint cellHandle, jstring jname, jobject user)
593 {
594   const char *name;
595
596   if( jname != NULL ) {
597       name = (*env)->GetStringUTFChars(env, jname, 0);
598     if( !name ) {
599         throwAFSException( env, JAFSADMNOMEM );
600         return;    
601     }
602   } else {
603       name = NULL;
604   }
605
606   getUserInfoChar( env, cellHandle, name, user );
607  
608   // get class fields if need be
609   if( userCls == 0 ) {
610     internal_getUserClass( env, user );
611   }
612   
613   // set name in case blank object
614   (*env)->SetObjectField(env, user, user_nameField, jname);
615   
616   if( name != NULL ) {
617       (*env)->ReleaseStringUTFChars(env, jname, name);
618   }      
619 }
620
621 /**
622  * Sets the information values of this AFS user to be the parameter values.  
623  * Sets both kas and pts fields.
624  *
625  * env      the Java environment
626  * cls      the current Java class
627  * cellHandle    the handle of the cell to which the user belongs
628  * jname     the name of the user for which to set the information
629  * user  the User object containing the desired 
630  *                 information
631  */
632 JNIEXPORT void JNICALL 
633 Java_org_openafs_jafs_User_setUserInfo
634   (JNIEnv *env, jclass cls, jint cellHandle, jstring jname, jobject user )
635 {
636   const char *name;
637   kas_identity_p who = (kas_identity_p) malloc( sizeof(kas_identity_t) );
638   pts_UserUpdateEntry_t ptsEntry;
639   afs_status_t ast;
640   kas_admin_t isAdmin;
641   kas_tgs_t grantTickets;
642   kas_enc_t canEncrypt;
643   kas_cpw_t canChangePassword;
644   kas_rpw_t passwordReuse;
645   unsigned int expirationDate;
646   unsigned int maxTicketLifetime;
647   unsigned int passwordExpires;
648   unsigned int failedPasswordAttempts;
649   unsigned int failedPasswordLockTime;
650   int kas;
651   int pts;
652
653   if( !who ) {
654     throwAFSException( env, JAFSADMNOMEM );
655     return;    
656   }
657
658   if( jname != NULL ) {
659       name = (*env)->GetStringUTFChars(env, jname, 0);
660     if( !name ) {
661         throwAFSException( env, JAFSADMNOMEM );
662         return;    
663     }
664   } else {
665       name = NULL;
666   }
667
668   // make sure the name is within the allowed bounds
669   if( name != NULL && strlen( name ) > KAS_MAX_NAME_LEN ) {
670     free( who );
671     (*env)->ReleaseStringUTFChars(env, jname, name);
672     throwAFSException( env, ADMPTSUSERNAMETOOLONG );
673     return;
674   }
675
676   if( name != NULL ) {
677       internal_makeKasIdentity( name, who );
678   }
679
680   // get class fields if need be
681   if( userCls == 0 ) {
682     internal_getUserClass( env, user );
683   }
684
685   kas = (*env)->GetBooleanField(env, user, user_kasField);
686   pts = (*env)->GetBooleanField(env, user, user_ptsField);
687
688   if( pts ) {
689       // set the pts fields: 
690       ptsEntry.flag = PTS_USER_UPDATE_GROUP_CREATE_QUOTA | 
691         PTS_USER_UPDATE_PERMISSIONS;
692       ptsEntry.groupCreationQuota = 
693         (*env)->GetIntField(env, user, user_groupCreationQuotaField);
694       if( (*env)->GetIntField(env, user, user_listStatusField) == 
695           org_openafs_jafs_User_USER_OWNER_ACCESS ) {
696           ptsEntry.listStatus = PTS_USER_OWNER_ACCESS;
697       } else {
698           ptsEntry.listStatus = PTS_USER_ANYUSER_ACCESS;
699       }
700       if( (*env)->GetIntField(env, user, user_listGroupsOwnedField) == 
701           org_openafs_jafs_User_USER_OWNER_ACCESS ) {
702           ptsEntry.listGroupsOwned = PTS_USER_OWNER_ACCESS;
703       } else {
704           ptsEntry.listGroupsOwned = PTS_USER_ANYUSER_ACCESS;
705       }
706       if( (*env)->GetIntField(env, user, user_listMembershipField) == 
707           org_openafs_jafs_User_USER_OWNER_ACCESS ) {
708           ptsEntry.listMembership = PTS_USER_OWNER_ACCESS;
709       } else {
710           ptsEntry.listMembership = PTS_USER_ANYUSER_ACCESS;
711       }
712       if( !pts_UserModify( (void *) cellHandle, name, &ptsEntry, &ast ) ) {
713           free( who );
714           if( name != NULL ) {
715               (*env)->ReleaseStringUTFChars(env, jname, name);
716           }
717           throwAFSException( env, ast );
718           return;    
719       }
720   }
721
722   if( kas ) {
723       // set the kas fields:
724       if( (*env)->GetIntField(env, user, user_adminSettingField) == 
725           org_openafs_jafs_User_ADMIN ) {
726           isAdmin = KAS_ADMIN;
727       } else {
728           isAdmin = NO_KAS_ADMIN;
729       }
730       if( (*env)->GetIntField(env, user, user_tgsSettingField) == 
731           org_openafs_jafs_User_GRANT_TICKETS ) {
732           grantTickets = TGS;
733       } else {
734           grantTickets = NO_TGS;
735       }
736       if( (*env)->GetIntField(env, user, user_encSettingField) == 
737           org_openafs_jafs_User_ENCRYPT ) {
738           canEncrypt = 0;
739       } else {
740           canEncrypt = NO_ENCRYPT;
741       }
742       if( (*env)->GetIntField(env, user, user_cpwSettingField) == 
743           org_openafs_jafs_User_CHANGE_PASSWORD ) {
744           canChangePassword = CHANGE_PASSWORD;
745       } else {
746           canChangePassword = NO_CHANGE_PASSWORD;
747       }
748       if( (*env)->GetIntField(env, user, user_rpwSettingField) == 
749           org_openafs_jafs_User_REUSE_PASSWORD ) {
750           passwordReuse = REUSE_PASSWORD;
751       } else {
752           passwordReuse = NO_REUSE_PASSWORD;
753       }
754       expirationDate = (*env)->GetIntField(env, user, 
755                                            user_userExpirationField);
756       maxTicketLifetime = (*env)->GetIntField(env, user, 
757                                               user_maxTicketLifetimeField);
758       passwordExpires = (*env)->GetIntField(env, user, 
759                                             user_daysToPasswordExpireField);
760       failedPasswordAttempts = (*env)->GetIntField(env, user, 
761                                                    user_failLoginCountField);
762       failedPasswordLockTime =  (*env)->GetIntField(env, user, 
763                                                     user_lockTimeField);
764       
765       if( !kas_PrincipalFieldsSet( (void *) cellHandle, NULL, who, &isAdmin, 
766                                    &grantTickets, &canEncrypt, 
767                                    &canChangePassword, &expirationDate, 
768                                    &maxTicketLifetime, &passwordExpires, 
769                                    &passwordReuse, &failedPasswordAttempts, 
770                                    &failedPasswordLockTime, &ast ) ) {
771           free( who );
772           if( name != NULL ) {
773               (*env)->ReleaseStringUTFChars(env, jname, name);
774           }
775           throwAFSException( env, ast );
776           return;    
777       }
778   }      
779
780   free( who );
781   if( name != NULL ) {
782       (*env)->ReleaseStringUTFChars(env, jname, name);
783   }
784 }
785
786 /**
787  * Renames the given user.  Does not update the info fields of the kas entry
788  *  -- the calling code is responsible for that.
789  *
790  * env      the Java environment
791  * cls      the current Java class
792  * cellHandle    the handle of the cell to which the user belongs
793  * joldName     the name of the user to rename
794  * jnewName     the new name for the user
795  */
796 JNIEXPORT void JNICALL 
797 Java_org_openafs_jafs_User_rename
798   (JNIEnv *env, jclass cls, jint cellHandle, jstring joldName, jstring jnewName)
799 {
800
801     const char *oldName;
802     const char *newName;
803     kas_identity_p whoOld = (kas_identity_p) malloc( sizeof(kas_identity_t) );
804     kas_identity_p whoNew = (kas_identity_p) malloc( sizeof(kas_identity_t) );
805     kas_principalEntry_t kasEntry;
806     pts_UserEntry_t ptsEntry;
807     afs_status_t ast;
808     int kas;
809
810     if( !whoOld || !whoNew ) {
811       if( whoOld ) {
812         free( whoOld );
813       }
814       if( whoNew ) {
815         free( whoNew );
816       } 
817       throwAFSException( env, JAFSADMNOMEM );
818       return;    
819     }
820
821     if( joldName != NULL ) {
822         oldName = (*env)->GetStringUTFChars(env, joldName, 0);
823         if( !oldName ) {
824             throwAFSException( env, JAFSADMNOMEM );
825             return;    
826         }
827     } else {
828         oldName = NULL;
829     }
830     if( jnewName != NULL ) {
831         newName = (*env)->GetStringUTFChars(env, jnewName, 0);
832         if( !newName ) {
833           if( oldName != NULL ) {
834             (*env)->ReleaseStringUTFChars(env, joldName, oldName);
835           }
836           throwAFSException( env, JAFSADMNOMEM );
837           return;    
838         }
839     } else {
840         newName = NULL;
841     }
842
843     // make sure the names are within the allowed bounds
844     if( oldName != NULL && strlen( oldName ) > KAS_MAX_NAME_LEN ) {
845         free( whoOld );
846         free( whoNew );
847         if( oldName != NULL ) {
848             (*env)->ReleaseStringUTFChars(env, joldName, oldName);
849         }
850         if( newName != NULL ) {
851             (*env)->ReleaseStringUTFChars(env, jnewName, newName);
852         }
853         throwAFSException( env, ADMPTSUSERNAMETOOLONG );
854         return;
855     }
856     if( newName != NULL && strlen( newName ) > KAS_MAX_NAME_LEN ) {
857         free( whoOld );
858         free( whoNew );
859         if( oldName != NULL ) {
860             (*env)->ReleaseStringUTFChars(env, joldName, oldName);
861         }
862         if( newName != NULL ) {
863             (*env)->ReleaseStringUTFChars(env, jnewName, newName);
864         }
865         throwAFSException( env, ADMPTSUSERNAMETOOLONG );
866         return;
867     }
868     
869     if( oldName != NULL ) {
870         internal_makeKasIdentity( oldName, whoOld );
871     }
872     if( newName != NULL ) {
873         internal_makeKasIdentity( newName, whoNew );
874     }
875
876     // retrieve the old kas info
877     if( !kas_PrincipalGet( (void *) cellHandle, NULL, whoOld, 
878                            &kasEntry, &ast ) ) {
879         if( ast != KANOENT ) {
880             free( whoOld );
881             free( whoNew );
882             if( oldName != NULL ) {
883                 (*env)->ReleaseStringUTFChars(env, joldName, oldName);
884             }
885             if( newName != NULL ) {
886                 (*env)->ReleaseStringUTFChars(env, jnewName, newName);
887             }
888             throwAFSException( env, ast );
889             return;
890         } else {
891             kas = FALSE;
892         }
893     } else {
894         kas = TRUE;
895     }   
896         
897     if( kas ) {
898         // create a new kas entry
899         // temporarily set the password equal to the new name
900         if (!kas_PrincipalCreate( (void *) cellHandle, NULL, whoNew, 
901                                   newName, &ast ) ) {       
902             free( whoOld );
903             free( whoNew );
904             if( oldName != NULL ) {
905                 (*env)->ReleaseStringUTFChars(env, joldName, oldName);
906             }
907             if( newName != NULL ) {
908                 (*env)->ReleaseStringUTFChars(env, jnewName, newName);
909             }
910             throwAFSException( env, ast );
911             return;
912         } 
913
914         // set the password 
915         ast = 0;
916         // For some reason kas_PrincipalKeySet doesn't set the return code 
917         // correctly.  It always returns 0.
918         // So instead of checking the return code, we see if there's an 
919         // error in the status variable.
920         kas_PrincipalKeySet( (void *) cellHandle, NULL, whoNew, 0, 
921                              &(kasEntry.key), &ast );
922         if( ast ) {
923             afs_status_t ast_kd;
924             kas_PrincipalDelete( (void *) cellHandle, NULL, whoNew, &ast_kd );
925             free( whoOld );
926             free( whoNew );
927             if( oldName != NULL ) {
928                 (*env)->ReleaseStringUTFChars(env, joldName, oldName);
929             }
930             if( newName != NULL ) {
931                 (*env)->ReleaseStringUTFChars(env, jnewName, newName);
932             }
933             throwAFSException( env, ast );
934             return;
935         }
936     }
937
938     // rename the pts entry
939     if( !pts_UserRename( (void *) cellHandle, oldName, newName, &ast ) ) {
940         // throw exception if there was no such pts user only if 
941         // there was also no such kas user
942         if( (ast == ADMPTSFAILEDNAMETRANSLATE && !kas ) || 
943             ast != ADMPTSFAILEDNAMETRANSLATE ) {
944             afs_status_t ast_kd;
945             if( kas ) {
946                 kas_PrincipalDelete( (void *) cellHandle, NULL, whoNew, 
947                                      &ast_kd );
948             }
949             free( whoOld );
950             free( whoNew );
951             if( oldName != NULL ) {
952                 (*env)->ReleaseStringUTFChars(env, joldName, oldName);
953             }
954             if( newName != NULL ) {
955                 (*env)->ReleaseStringUTFChars(env, jnewName, newName);
956             }
957             throwAFSException( env, ast );
958             return;
959         }
960     }
961
962     if( kas ) {
963         // delete the old kas entry
964         if( !kas_PrincipalDelete( (void *) cellHandle, NULL, whoOld, &ast ) ) {
965             free( whoOld );
966             free( whoNew );
967             if( oldName != NULL ) {
968                 (*env)->ReleaseStringUTFChars(env, joldName, oldName);
969             }
970             if( newName != NULL ) {
971                 (*env)->ReleaseStringUTFChars(env, jnewName, newName);
972             }
973             throwAFSException( env, ast );
974             return;
975         }
976     }    
977
978     free( whoOld );
979     free( whoNew );
980     if( oldName != NULL ) {
981         (*env)->ReleaseStringUTFChars(env, joldName, oldName);
982     }
983     if( newName != NULL ) {
984         (*env)->ReleaseStringUTFChars(env, jnewName, newName);
985     }
986 }
987
988 /**
989  * Sets the password of the given user.  Sets the key version to 0.
990  *
991  * env      the Java environment
992  * cls      the current Java class
993  * cellHandle    the handle of the cell to which the user belongs
994  * juserName     the name of the user for which to set the password
995  * jnewPassword     the new password for the user
996  */
997 JNIEXPORT void JNICALL 
998 Java_org_openafs_jafs_User_setPassword
999   (JNIEnv *env, jclass cls, jint cellHandle, jstring juserName,
1000    jstring jnewPassword)
1001 {
1002   afs_status_t ast;
1003   char *cellName;
1004   const char *userName;
1005   const char *newPassword;
1006   kas_encryptionKey_p newKey = 
1007     (kas_encryptionKey_p) malloc( sizeof(kas_encryptionKey_t) );
1008   kas_identity_p who = (kas_identity_p) malloc( sizeof(kas_identity_t) );
1009
1010   if( !who || !newKey ) {
1011     if( who ) {
1012       free( who );
1013     }
1014     if( newKey ) {
1015       free( newKey );
1016     }
1017     throwAFSException( env, JAFSADMNOMEM );
1018     return;    
1019   }
1020
1021   if( juserName != NULL ) {
1022       userName = (*env)->GetStringUTFChars(env, juserName, 0);
1023       if( !userName ) {
1024           throwAFSException( env, JAFSADMNOMEM );
1025           return;    
1026       }
1027   } else {
1028       userName = NULL;
1029   }
1030   if( jnewPassword != NULL ) {
1031       newPassword = (*env)->GetStringUTFChars(env, jnewPassword, 0);
1032       if( !newPassword ) {
1033           throwAFSException( env, JAFSADMNOMEM );
1034           return;    
1035       }
1036   } else {
1037       newPassword = NULL;
1038   }
1039
1040   // make sure the name is within the allowed bounds
1041   if( userName != NULL && strlen( userName ) > KAS_MAX_NAME_LEN ) {
1042     free(who);
1043     free( newKey );
1044     if( userName != NULL ) {
1045         (*env)->ReleaseStringUTFChars(env, juserName, userName);
1046     }
1047     if( newPassword != NULL ) {
1048         (*env)->ReleaseStringUTFChars(env, jnewPassword, newPassword);
1049     }
1050     throwAFSException( env, ADMPTSUSERNAMETOOLONG );
1051     return;
1052   }
1053
1054   if( !afsclient_CellNameGet( (void *) cellHandle, &cellName, &ast ) ) {
1055       free(who);
1056       free( newKey );
1057       if( userName != NULL ) {
1058           (*env)->ReleaseStringUTFChars(env, juserName, userName);
1059       }
1060       if( newPassword != NULL ) {
1061           (*env)->ReleaseStringUTFChars(env, jnewPassword, newPassword);
1062       }
1063       throwAFSException( env, ast );
1064       return;
1065   }
1066   
1067   if( !kas_StringToKey( cellName, newPassword, newKey, &ast ) ) {
1068       free(who);
1069       free( newKey );
1070       if( userName != NULL ) {
1071           (*env)->ReleaseStringUTFChars(env, juserName, userName);
1072       }
1073       if( newPassword != NULL ) {
1074           (*env)->ReleaseStringUTFChars(env, jnewPassword, newPassword);
1075       }
1076       throwAFSException( env, ast );
1077       return;
1078   }
1079
1080   if( userName != NULL ) {
1081       internal_makeKasIdentity( userName, who );
1082   }
1083
1084   ast = 0;
1085   // For some reason kas_PrincipalKeySet doesn't set the return code correctly.
1086   //  It always returns 0.
1087   // So instead of checking the return code, we see if there's an error 
1088   // in the status variable.
1089   kas_PrincipalKeySet( (void *) cellHandle, NULL, who, 0, newKey, &ast );
1090   if( ast ) {
1091     free( who );
1092     free( newKey );
1093     if( userName != NULL ) {
1094         (*env)->ReleaseStringUTFChars(env, juserName, userName);
1095     }
1096     if( newPassword != NULL ) {
1097         (*env)->ReleaseStringUTFChars(env, jnewPassword, newPassword);
1098     }
1099     throwAFSException( env, ast );
1100     return;
1101   }
1102
1103   free( who );
1104   free( newKey );
1105   if( userName != NULL ) {
1106       (*env)->ReleaseStringUTFChars(env, juserName, userName);
1107   }
1108   if( newPassword != NULL ) {
1109       (*env)->ReleaseStringUTFChars(env, jnewPassword, newPassword);
1110   }
1111
1112 }
1113
1114 /**
1115  * Begin the process of getting the groups to which the user belongs.  
1116  * Returns an iteration ID to be used by subsequent calls to 
1117  * getUserGroupsNext and getUserGroupsDone.  
1118  *
1119  * env      the Java environment
1120  * cls      the current Java class
1121  * cellHandle    the handle of the cell to which the user belongs
1122  * jname          the name of the user for which to get the groups
1123  * returns an iteration ID
1124  */
1125 JNIEXPORT jint JNICALL 
1126 Java_org_openafs_jafs_User_getUserGroupsBegin
1127   (JNIEnv *env, jclass cls, jint cellHandle, jstring jname)
1128 {
1129   const char *name;
1130   afs_status_t ast;
1131   void *iterationId;
1132
1133   if( jname != NULL ) {
1134       name = (*env)->GetStringUTFChars(env, jname, 0);
1135       if( !name ) {
1136           throwAFSException( env, JAFSADMNOMEM );
1137           return;    
1138       }
1139   } else {
1140       name = NULL;
1141   }
1142
1143   if( !pts_UserMemberListBegin( (void *) cellHandle, name, &iterationId, 
1144                                 &ast ) ) {
1145       if( name != NULL ) {
1146           (*env)->ReleaseStringUTFChars(env, jname, name);
1147       }
1148       throwAFSException( env, ast );
1149       return;
1150   }
1151
1152   if( name != NULL ) {
1153       (*env)->ReleaseStringUTFChars(env, jname, name);
1154   }
1155
1156   return (jint) iterationId;
1157
1158 }
1159
1160 /**
1161  * Returns the next group to which the user belongs.  Returns 
1162  * null if there are no more groups.
1163  *
1164  * env      the Java environment
1165  * cls      the current Java class
1166  * iterationId   the iteration ID of this iteration
1167  * returns the name of the next group
1168  */
1169 JNIEXPORT jstring JNICALL 
1170 Java_org_openafs_jafs_User_getUserGroupsNextString
1171   (JNIEnv *env, jclass cls, jint iterationId)
1172 {
1173   afs_status_t ast;
1174   char *groupName = (char *) malloc( sizeof(char)*PTS_MAX_NAME_LEN);
1175   jstring jgroup;
1176
1177   if( !groupName ) {
1178     throwAFSException( env, JAFSADMNOMEM );
1179     return;    
1180   }
1181
1182   if( !pts_UserMemberListNext( (void *) iterationId, groupName, &ast ) ) {
1183     free( groupName );
1184     if( ast == ADMITERATORDONE ) {
1185       return NULL;
1186     } else {
1187       throwAFSException( env, ast );
1188       return;
1189     }
1190   }
1191   
1192   jgroup = (*env)->NewStringUTF(env, groupName);
1193   free( groupName );
1194   return jgroup;
1195 }
1196
1197 /**
1198  * Fills the next group object of which the user belongs.  Returns 0 if there
1199  * are no more groups, != 0 otherwise.
1200  *
1201  * env      the Java environment
1202  * cls      the current Java class
1203  * cellHandle    the handle of the cell to which the users belong
1204  * iterationId   the iteration ID of this iteration
1205  * jgroupObject   a Group object to be populated with the values of the 
1206  *                   next group
1207  * returns 0 if there are no more users, != 0 otherwise
1208  */
1209 JNIEXPORT jint JNICALL 
1210 Java_org_openafs_jafs_User_getUserGroupsNext
1211   (JNIEnv *env, jclass cls, jint cellHandle, jint iterationId,
1212    jobject jgroupObject)
1213 {
1214   afs_status_t ast;
1215   char *groupName;
1216   jstring jgroup;
1217
1218   groupName = (char *) malloc( sizeof(char)*PTS_MAX_NAME_LEN);
1219
1220   if( !groupName ) {
1221     throwAFSException( env, JAFSADMNOMEM );
1222     return;    
1223   }
1224
1225   if( !pts_UserMemberListNext( (void *) iterationId, groupName, &ast ) ) {
1226     free( groupName );
1227     if( ast == ADMITERATORDONE ) {
1228       return 0;
1229     } else {
1230       throwAFSException( env, ast );
1231       return 0;
1232     }
1233   }
1234
1235   jgroup = (*env)->NewStringUTF(env, groupName);
1236
1237   if( groupCls == 0 ) {
1238     internal_getGroupClass( env, jgroupObject );
1239   }
1240
1241   (*env)->SetObjectField(env, jgroupObject, group_nameField, jgroup);
1242
1243   getGroupInfoChar( env, (void *) cellHandle, groupName, jgroupObject );
1244   (*env)->SetBooleanField( env, jgroupObject, group_cachedInfoField, TRUE );
1245
1246   free( groupName );
1247   return 1;
1248
1249 }
1250
1251 /**
1252  * Signals that the iteration is complete and will not be accessed anymore.
1253  *
1254  * env      the Java environment
1255  * cls      the current Java class
1256  * iterationId   the iteration ID of this iteration
1257  */
1258 JNIEXPORT void JNICALL 
1259 Java_org_openafs_jafs_User_getUserGroupsDone
1260   (JNIEnv *env, jclass cls, jint iterationId)
1261 {
1262   afs_status_t ast;
1263
1264   if( !pts_UserMemberListDone( (void *) iterationId, &ast ) ) {
1265     throwAFSException( env, ast );
1266     return;
1267   }
1268 }
1269
1270 /**
1271  * Returns the total number of groups owned by the user.  
1272  *
1273  * env      the Java environment
1274  * cls      the current Java class
1275  * cellHandle    the handle of the cell to which the user belongs
1276  * jname          the name of the user for which to get the groups
1277  * returns total number of groups owned by the user
1278  */
1279 JNIEXPORT jint JNICALL 
1280 Java_org_openafs_jafs_User_getGroupsOwnedCount
1281   (JNIEnv *env, jclass cls, jint cellHandle, jstring jname)
1282 {
1283   afs_status_t ast;
1284   void *iterationId;
1285   char *groupName;
1286   int i = 0;
1287
1288   iterationId = 
1289     (void *) Java_org_openafs_jafs_User_getGroupsOwnedBegin( env, cls, 
1290                                                                 cellHandle, 
1291                                                                 jname );
1292
1293   groupName = (char *) malloc( sizeof(char)*PTS_MAX_NAME_LEN);
1294
1295   if( !groupName ) {
1296     throwAFSException( env, JAFSADMNOMEM );
1297     return -1;    
1298   }
1299
1300   while ( pts_OwnedGroupListNext( (void *) iterationId, groupName, &ast ) ) 
1301     i++;
1302
1303   free( groupName );  
1304
1305   if( ast != ADMITERATORDONE ) {
1306     throwAFSException( env, ast );
1307     return -1;
1308   }
1309
1310   return i;
1311 }
1312
1313 /**
1314  * Begin the process of getting the groups that a user or group owns.  
1315  * Returns an iteration ID to be used by subsequent calls to 
1316  * getGroupsOwnedNext and getGroupsOwnedDone.  
1317  *
1318  * env      the Java environment
1319  * cls      the current Java class
1320  * cellHandle    the handle of the cell to which the user belongs
1321  * jname  the name of the user or group for which to get the groups
1322  * returns an iteration ID
1323  */
1324 JNIEXPORT jint JNICALL 
1325 Java_org_openafs_jafs_User_getGroupsOwnedBegin
1326   (JNIEnv *env, jclass cls, jint cellHandle, jstring jname)
1327 {
1328   const char *name;
1329   afs_status_t ast;
1330   void *iterationId;
1331
1332   if( jname != NULL ) {
1333       name = (*env)->GetStringUTFChars(env, jname, 0);
1334       if( !name ) {
1335           throwAFSException( env, JAFSADMNOMEM );
1336           return;    
1337       }
1338   } else {
1339       name = NULL;
1340   }
1341
1342   if( !pts_OwnedGroupListBegin( (void *) cellHandle, name, 
1343                                 &iterationId, &ast ) ) {
1344       if( jname != NULL ) {
1345           (*env)->ReleaseStringUTFChars(env, jname, name);
1346       }
1347       throwAFSException( env, ast );
1348       return;
1349   }
1350
1351   if( jname != NULL ) {
1352       (*env)->ReleaseStringUTFChars(env, jname, name);
1353   }
1354
1355   return (jint) iterationId;
1356
1357 }
1358
1359 /**
1360  * Returns the next group the user or group owns.  Returns null 
1361  * if there are no more groups.
1362  *
1363  * env      the Java environment
1364  * cls      the current Java class
1365  * iterationId   the iteration ID of this iteration
1366  * returns the name of the next group
1367  */
1368 JNIEXPORT jstring JNICALL 
1369 Java_org_openafs_jafs_User_getGroupsOwnedNextString
1370   (JNIEnv *env, jclass cls, jint iterationId)
1371 {
1372   afs_status_t ast;
1373   char *groupName = (char *) malloc( sizeof(char)*PTS_MAX_NAME_LEN);
1374   jstring jgroup;
1375
1376   if( !groupName ) {
1377     throwAFSException( env, JAFSADMNOMEM );
1378     return;    
1379   }
1380
1381   if( !pts_OwnedGroupListNext( (void *) iterationId, groupName, &ast ) ) {
1382     free( groupName );
1383     if( ast == ADMITERATORDONE ) {
1384       return NULL;
1385     } else {
1386       throwAFSException( env, ast );
1387       return;
1388     }
1389   }
1390   
1391   jgroup = (*env)->NewStringUTF(env, groupName);
1392   free( groupName );
1393   return jgroup;
1394
1395 }
1396
1397 /**
1398  * Fills the next group object that the user or group owns.  Returns 0 if 
1399  * there are no more groups, != 0 otherwise.
1400  *
1401  * env      the Java environment
1402  * cls      the current Java class
1403  * cellHandle    the handle of the cell to which the users belong
1404  * iterationId   the iteration ID of this iteration
1405  * jgroupObject   a Group object to be populated with the values of the 
1406  *                   next group
1407  * returns 0 if there are no more users, != 0 otherwise
1408  */
1409 JNIEXPORT jint JNICALL 
1410 Java_org_openafs_jafs_User_getGroupsOwnedNext
1411   (JNIEnv *env, jclass cls, jint cellHandle, jint iterationId, 
1412    jobject jgroupObject)
1413 {
1414   afs_status_t ast;
1415   char *groupName;
1416   jstring jgroup;
1417
1418   groupName = (char *) malloc( sizeof(char)*PTS_MAX_NAME_LEN);
1419
1420   if( !groupName ) {
1421     throwAFSException( env, JAFSADMNOMEM );
1422     return;    
1423   }
1424
1425   if( !pts_OwnedGroupListNext( (void *) iterationId, groupName, &ast ) ) {
1426     free( groupName );
1427     if( ast == ADMITERATORDONE ) {
1428       return 0;
1429     } else {
1430       throwAFSException( env, ast );
1431       return 0;
1432     }
1433   }
1434
1435   jgroup = (*env)->NewStringUTF(env, groupName);
1436
1437   if( groupCls == 0 ) {
1438     internal_getGroupClass( env, jgroupObject );
1439   }
1440
1441   (*env)->SetObjectField(env, jgroupObject, group_nameField, jgroup);
1442
1443   getGroupInfoChar( env, (void *) cellHandle, groupName, jgroupObject );
1444   (*env)->SetBooleanField( env, jgroupObject, group_cachedInfoField, TRUE );
1445
1446   free( groupName );
1447   return 1;
1448
1449 }
1450
1451 /**
1452  * Signals that the iteration is complete and will not be accessed anymore.
1453  *
1454  * env      the Java environment
1455  * cls      the current Java class
1456  * iterationId   the iteration ID of this iteration
1457  */
1458 JNIEXPORT void JNICALL 
1459 Java_org_openafs_jafs_User_getGroupsOwnedDone
1460   (JNIEnv *env, jclass cls, jint iterationId)
1461 {
1462   afs_status_t ast;
1463
1464   if( !pts_OwnedGroupListDone( (void *) iterationId, &ast ) ) {
1465     throwAFSException( env, ast );
1466     return;
1467   }
1468   
1469 }
1470
1471 // reclaim global memory being used by this portion
1472 JNIEXPORT void JNICALL
1473 Java_org_openafs_jafs_User_reclaimUserMemory
1474   (JNIEnv *env, jclass cls)
1475 {
1476   if( userCls ) {
1477       (*env)->DeleteGlobalRef(env, userCls);
1478       userCls = 0;
1479   }
1480
1481 }
1482
1483
1484