xref: /titanic_44/usr/src/cmd/krb5/kadmin/gui/native/Kadmin.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <jni.h>
29 #include <kadm5/admin.h>
30 #include <adm_err.h>
31 #include <sys/signal.h>
32 #include <netdb.h>
33 #include <iconv.h>
34 #include <langinfo.h>
35 
36 static int Principal_to_kadmin(JNIEnv *, jobject, int, krb5_principal *,
37 	kadm5_principal_ent_rec *, long *, char **, char **);
38 static int kadmin_to_Principal(kadm5_principal_ent_rec *, JNIEnv *, jobject,
39 	const char *, char *);
40 static int Policy_to_kadmin(JNIEnv *, jobject, int, kadm5_policy_ent_rec *,
41 	long *);
42 static int kadmin_to_Policy(kadm5_policy_ent_rec *, JNIEnv *, jobject);
43 static int edit_comments(kadm5_principal_ent_rec *, krb5_principal, char *);
44 static int format_comments(kadm5_principal_ent_rec *, long *, char *);
45 static int extract_comments(kadm5_principal_ent_rec *, char **);
46 static int set_password(krb5_principal, char *);
47 static void handle_error(JNIEnv *, int);
48 static char *qualify(char *name);
49 
50 static void *server_handle = NULL;
51 static char *cur_realm = NULL;
52 
53 static iconv_t cd = (iconv_t)-1;
54 
55 static char *
56 qualify(char *name)
57 {
58 	char *fullname;
59 	int len;
60 
61 	if (strchr(name, '@') != NULL)
62 		return (strdup(name));
63 	len = strlen(name) + strlen(cur_realm) + 2;
64 	fullname = malloc(len);
65 	if (fullname)
66 		snprintf(fullname, len, "%s@%s", name, cur_realm);
67 	return (fullname);
68 }
69 
70 
71 /*
72  * Class:     Kadmin
73  * Method:    sessionInit
74  * Signature:
75  * (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
76  */
77 /*ARGSUSED*/
78 JNIEXPORT jboolean JNICALL
79 Java_Kadmin_sessionInit(JNIEnv *env, jobject obj, jstring name,
80 	jstring passwd, jstring realm, jstring server, jint port)
81 {
82 	const char *cname = NULL, *cpasswd = NULL;
83 	const char *crealm = NULL, *cserver = NULL;
84 	int cport = 749;
85 	kadm5_config_params params;
86 	kadm5_ret_t ret;
87 	char *ka_service = NULL;
88 	char *ka_name = NULL;
89 	char *codeset;
90 	int len;
91 
92 	if (server_handle != NULL)
93 		kadm5_destroy(server_handle);
94 
95 	if (cd == (iconv_t)-1) {
96 		codeset = nl_langinfo(CODESET);
97 		/* fprintf(stderr, "codeset returned %s\n", codeset);  XXX */
98 		if (strcmp("UTF-8", codeset) != 0)
99 			cd = iconv_open("UTF-8", codeset);
100 	}
101 
102 	/* Get hold of string arguments */
103 	cname = (*env)->GetStringUTFChars(env, name, NULL);
104 	if (!cname) {
105 		ret = KADM_JNI_STRING;
106 		goto err;
107 	}
108 	cpasswd = (*env)->GetStringUTFChars(env, passwd, NULL);
109 	if (!cpasswd) {
110 		ret = KADM_JNI_STRING;
111 		goto err;
112 	}
113 	crealm = (*env)->GetStringUTFChars(env, realm, NULL);
114 	if (!crealm) {
115 		ret = KADM_JNI_STRING;
116 		goto err;
117 	}
118 	if (cur_realm)
119 		free(cur_realm);
120 	cur_realm = strdup(crealm);
121 	cserver = (*env)->GetStringUTFChars(env, server, NULL);
122 	if (!cserver) {
123 		ret = KADM_JNI_STRING;
124 		goto err;
125 	}
126 	if (port != 0)
127 		cport = port;
128 	else {
129 		/*
130 		 * Look for a services map entry
131 		 * Note that this will be in network byte order,
132 		 * and that the API requires native byte order.
133 		 */
134 		struct servent *rec = getservbyname("kerberos-adm", NULL);
135 		if (rec)
136 			cport = (int)ntohs((uint16_t)rec->s_port);
137 	}
138 
139 	/*
140 	 * Build kadm5_config_params with realm name and server name
141 	 */
142 	memset((char *)&params, 0, sizeof (params));
143 	params.realm = (char *)crealm;
144 	params.admin_server = (char *)cserver;
145 	params.mask = KADM5_CONFIG_REALM | KADM5_CONFIG_ADMIN_SERVER;
146 	params.kadmind_port = cport;
147 	params.mask |= KADM5_CONFIG_KADMIND_PORT;
148 	len = strlen("kadmin") + strlen(cserver) + 2;
149 	ka_service = malloc(len);
150 	if (!ka_service) {
151 		ret = KADM_ENOMEM;
152 		goto err;
153 	}
154 	snprintf(ka_service, len, "%s@%s", "kadmin", cserver);
155 	ka_name = qualify((char *)cname);
156 	if (!ka_name) {
157 		ret = KADM_ENOMEM;
158 		goto err;
159 	}
160 
161 	ret = kadm5_init_with_password(ka_name, (char *)cpasswd,
162 				ka_service, &params, KADM5_STRUCT_VERSION,
163 				KADM5_API_VERSION_2, &server_handle);
164 
165 	/* Release string arguments and variables */
166 	if (cname)
167 		(*env)->ReleaseStringUTFChars(env, name, cname);
168 	if (cpasswd)
169 		(*env)->ReleaseStringUTFChars(env, passwd, cpasswd);
170 	if (crealm)
171 		(*env)->ReleaseStringUTFChars(env, realm, crealm);
172 	if (cserver)
173 		(*env)->ReleaseStringUTFChars(env, server, cserver);
174 	if (ka_name)
175 		free(ka_name);
176 	if (ka_service)
177 		free(ka_service);
178 
179 err:
180 	if (ret) {
181 		handle_error(env, ret);
182 		return (JNI_FALSE);
183 	}
184 	return (JNI_TRUE);
185 }
186 
187 /*
188  * Class:     Kadmin
189  * Method:    sessionExit
190  * Signature: ()V
191  */
192 /*ARGSUSED*/
193 JNIEXPORT void JNICALL
194 Java_Kadmin_sessionExit(JNIEnv *env, jobject obj)
195 {
196 	kadm5_ret_t ret;
197 
198 	/*
199 	 * Use persistant handle to close
200 	 */
201 	ret = kadm5_destroy(server_handle);
202 	if (ret)
203 		handle_error(env, ret);
204 	server_handle = NULL;
205 	if (cur_realm) {
206 		free(cur_realm);
207 		cur_realm = NULL;
208 	}
209 }
210 
211 /*
212  * Class:     Kadmin
213  * Method:    getPrivs
214  * Signature: ()I
215  */
216 /*ARGSUSED*/
217 JNIEXPORT jint JNICALL
218 Java_Kadmin_getPrivs(JNIEnv *env, jobject obj)
219 {
220 	long privs = 0;
221 	kadm5_ret_t ret;
222 
223 	/*
224 	 * Get ACL for this user
225 	 */
226 	ret = kadm5_get_privs(server_handle, &privs);
227 	if (ret)
228 		handle_error(env, ret);
229 	return (privs);
230 }
231 
232 static int
233 charcmp(const void *a, const void *b)
234 {
235 	char    **sa = (char **)a;
236 	char    **sb = (char **)b;
237 
238 	return (strcmp(*sa, *sb));
239 }
240 
241 /*
242  * Class:     Kadmin
243  * Method:    getPrincipalList
244  * Signature: ()[Ljava/lang/String;
245  */
246 /*ARGSUSED*/
247 JNIEXPORT jobjectArray JNICALL
248 Java_Kadmin_getPrincipalList(JNIEnv *env,
249 	jobject obj)
250 {
251 	jclass stringclass;
252 	jobjectArray plist;
253 	jstring s;
254 	char **princs;
255 	int i, count;
256 	kadm5_ret_t ret;
257 
258 	/*
259 	 * Get the list
260 	 */
261 	ret = kadm5_get_principals(server_handle, NULL, &princs, &count);
262 	if (ret) {
263 		handle_error(env, ret);
264 		return (NULL);
265 	}
266 	qsort(princs, count, sizeof (princs[0]), charcmp);
267 
268 	/*
269 	 * Create and populate a Java String array
270 	 */
271 	stringclass = (*env)->FindClass(env, "java/lang/String");
272 	if (!stringclass) {
273 		handle_error(env, KADM_JNI_CLASS);
274 		return (NULL);
275 	}
276 	plist = (*env)->NewObjectArray(env, count, stringclass, NULL);
277 	if (!plist) {
278 		handle_error(env, KADM_JNI_ARRAY);
279 		return (NULL);
280 	}
281 	for (i = 0; i < count; i++) {
282 		s = (*env)->NewStringUTF(env, princs[i]);
283 		if (!s) {
284 			handle_error(env, KADM_JNI_NEWSTRING);
285 			return (NULL);
286 		}
287 		(*env)->SetObjectArrayElement(env, plist, i, s);
288 	}
289 	kadm5_free_name_list(server_handle, princs, count);
290 	return (plist);
291 }
292 
293 
294 /*
295  * Class:     Kadmin
296  * Method:    getPrincipalList2
297  * Signature: ()Ljava/lang/String;
298  */
299 /*ARGSUSED*/
300 JNIEXPORT jstring JNICALL
301 Java_Kadmin_getPrincipalList2(JNIEnv *env, jobject obj)
302 {
303 	jstring plist;
304 	char **princs;
305 	char *princlist = NULL;
306 	int i, count, n, used = 0, size = 0;
307 	kadm5_ret_t ret;
308 
309 	/*
310 	 * Get the list
311 	 */
312 	ret = kadm5_get_principals(server_handle, NULL, &princs, &count);
313 	if (ret) {
314 		handle_error(env, ret);
315 		return (NULL);
316 	}
317 	qsort(princs, count, sizeof (princs[0]), charcmp);
318 
319 	/*
320 	 * Build one large C string to hold list
321 	 */
322 	used = 0;
323 	princlist = malloc(size += 2048);
324 	if (!princlist)
325 		return (NULL);
326 	for (i = 0; i < count; i++) {
327 		n = strlen(princs[i]);
328 		if (used + n + 2 > size) {
329 			princlist = realloc(princlist, size += 2048);
330 			if (!princlist)
331 				return (NULL);
332 		}
333 		strncpy(&princlist[used], princs[i], n);
334 		used += n + 1;
335 		princlist[used-1] = ' ';
336 		princlist[used] = '\0';
337 	}
338 
339 	/*
340 	 * Create a Java String
341 	 */
342 	plist = (*env)->NewStringUTF(env, princlist);
343 	free(princlist);
344 	kadm5_free_name_list(server_handle, princs, count);
345 	return (plist);
346 }
347 
348 
349 /*
350  * Class:     Kadmin
351  * Method:    loadPrincipal
352  * Signature: (Ljava/lang/String;LPrincipal;)Z
353  */
354 /*ARGSUSED*/
355 JNIEXPORT jboolean JNICALL
356 Java_Kadmin_loadPrincipal(JNIEnv *env, jobject obj, jstring name, jobject prin)
357 {
358 	const char *cname;
359 	char *fullname;
360 	char *comments = NULL;
361 	kadm5_principal_ent_rec pr_rec;
362 	kadm5_ret_t ret;
363 	long mask = KADM5_PRINCIPAL_NORMAL_MASK | KADM5_TL_DATA;
364 	krb5_principal kprin = NULL;
365 	krb5_context context;
366 
367 	cname = (*env)->GetStringUTFChars(env, name, NULL);
368 	if (!cname) {
369 		handle_error(env, KADM_JNI_STRING);
370 		return (JNI_FALSE);
371 	}
372 	fullname = qualify((char *)cname);
373 	if (!fullname) {
374 		handle_error(env, KADM_JNI_STRING);
375 		return (JNI_FALSE);
376 	}
377 
378 	/*
379 	 * Get the principal
380 	 */
381 	ret = krb5_init_context(&context);
382 	if (ret) {
383 		handle_error(env, ret);
384 		return (JNI_FALSE);
385 	}
386 	ret = krb5_parse_name(context, fullname, &kprin);
387 	if (ret) {
388 		handle_error(env, ret);
389 		return (JNI_FALSE);
390 	}
391 	memset((char *)&pr_rec, 0, sizeof (pr_rec));
392 	ret = kadm5_get_principal(server_handle, kprin, &pr_rec, mask);
393 	if (ret) {
394 		handle_error(env, ret);
395 		return (JNI_FALSE);
396 	}
397 
398 	/*
399 	 * Pull the comments out of the tl_data array
400 	 */
401 	ret = extract_comments(&pr_rec, &comments);
402 	if (ret) {
403 		handle_error(env, ret);
404 		return (JNI_FALSE);
405 	}
406 
407 	/*
408 	 * Fill in our Principal object
409 	 */
410 	ret = kadmin_to_Principal(&pr_rec, env, prin, cname, comments);
411 	if (ret) {
412 		handle_error(env, ret);
413 		return (JNI_FALSE);
414 	}
415 
416 	kadm5_free_principal_ent(server_handle, &pr_rec);
417 	krb5_free_principal(context, kprin);
418 	(*env)->ReleaseStringUTFChars(env, name, cname);
419 	free(fullname);
420 
421 	return (JNI_TRUE);
422 }
423 
424 /*
425  * Class:     Kadmin
426  * Method:    savePrincipal
427  * Signature: (LPrincipal;)Z
428  */
429 /*ARGSUSED*/
430 JNIEXPORT jboolean JNICALL
431 Java_Kadmin_savePrincipal(JNIEnv *env, jobject obj, jobject prin)
432 {
433 	kadm5_principal_ent_rec pr_rec;
434 	long mask;
435 	char *pw = NULL;
436 	char *comments = NULL;
437 	kadm5_ret_t ret;
438 	krb5_principal kprin = NULL;
439 
440 	/*
441 	 * Convert principal object to the kadmin API structure
442 	 */
443 	memset((char *)&pr_rec, 0, sizeof (pr_rec));
444 	ret = Principal_to_kadmin(env, prin, 0, &kprin, &pr_rec, &mask,
445 					&pw, &comments);
446 	if (ret) {
447 		handle_error(env, ret);
448 		return (JNI_FALSE);
449 	}
450 
451 	/*
452 	 * Save the principal
453 	 */
454 	ret = kadm5_modify_principal(server_handle, &pr_rec, mask);
455 	if (ret) {
456 		handle_error(env, ret);
457 		ret = JNI_FALSE;
458 		goto out;
459 	}
460 
461 	/*
462 	 * Handle any comments with read-modify-write
463 	 */
464 	ret = edit_comments(&pr_rec, kprin, comments);
465 	if (ret) {
466 		handle_error(env, ret);
467 		ret = JNI_FALSE;
468 		goto out;
469 	}
470 
471 	/*
472 	 * Set the password if changed
473 	 */
474 	ret = set_password(kprin, pw);
475 	if (ret) {
476 		handle_error(env, ret);
477 		ret = JNI_FALSE;
478 		goto out;
479 	}
480 	ret = JNI_TRUE;
481 
482 out:
483 	kadm5_free_principal_ent(server_handle, &pr_rec);
484 	return (ret);
485 }
486 
487 /*
488  * Class:     Kadmin
489  * Method:    createPrincipal
490  * Signature: (LPrincipal;)Z
491  */
492 /*ARGSUSED*/
493 JNIEXPORT jboolean JNICALL
494 Java_Kadmin_createPrincipal(JNIEnv *env, jobject obj, jobject prin)
495 {
496 	kadm5_principal_ent_rec pr_rec;
497 	long mask;
498 	char *pw = NULL;
499 	char *comments = NULL;
500 	kadm5_ret_t ret;
501 	krb5_principal kprin = NULL;
502 
503 	/*
504 	 * Convert principal object to the kadmin API structure
505 	 */
506 	memset((char *)&pr_rec, 0, sizeof (pr_rec));
507 	ret = Principal_to_kadmin(env, prin, 1, &kprin, &pr_rec, &mask,
508 					&pw, &comments);
509 	if (ret) {
510 		handle_error(env, ret);
511 		return (JNI_FALSE);
512 	}
513 
514 	/*
515 	 * Create the new principal
516 	 */
517 	ret = kadm5_create_principal(server_handle, &pr_rec, mask, pw);
518 	if (ret) {
519 		handle_error(env, ret);
520 		ret = JNI_FALSE;
521 		goto out;
522 	}
523 
524 	/*
525 	 * Handle any comments with read-modify-write
526 	 */
527 	ret = edit_comments(&pr_rec, kprin, comments);
528 	if (ret) {
529 		handle_error(env, ret);
530 		ret = JNI_FALSE;
531 		goto out;
532 	}
533 
534 	ret = JNI_TRUE;
535 out:
536 	kadm5_free_principal_ent(server_handle, &pr_rec);
537 	return (ret);
538 }
539 
540 /*
541  * Class:     Kadmin
542  * Method:    deletePrincipal
543  * Signature: (Ljava/lang/String;)Z
544  */
545 /*ARGSUSED*/
546 JNIEXPORT jboolean JNICALL
547 Java_Kadmin_deletePrincipal(JNIEnv *env, jobject obj, jstring name)
548 {
549 	kadm5_ret_t ret;
550 	const char *cname;
551 	char *fullname;
552 	krb5_principal kprin = NULL;
553 	krb5_context context;
554 
555 	/*
556 	 * Get name and call the delete function
557 	 */
558 	cname = (*env)->GetStringUTFChars(env, name, NULL);
559 	if (!cname) {
560 		handle_error(env, KADM_JNI_STRING);
561 		return (JNI_FALSE);
562 	}
563 	fullname = qualify((char *)cname);
564 	if (!fullname) {
565 		handle_error(env, KADM_JNI_STRING);
566 		return (JNI_FALSE);
567 	}
568 
569 	ret = krb5_init_context(&context);
570 	if (ret) {
571 		handle_error(env, ret);
572 		return (JNI_FALSE);
573 	}
574 	ret = krb5_parse_name(context, fullname, &kprin);
575 	if (ret) {
576 		handle_error(env, ret);
577 		return (JNI_FALSE);
578 	}
579 	ret = kadm5_delete_principal(server_handle, kprin);
580 	if (ret) {
581 		handle_error(env, ret);
582 		return (JNI_FALSE);
583 	}
584 
585 	krb5_free_principal(context, kprin);
586 	(*env)->ReleaseStringUTFChars(env, name, cname);
587 	free(fullname);
588 
589 	return (JNI_TRUE);
590 }
591 
592 /*
593  * Class:     Kadmin
594  * Method:    getPolicyList
595  * Signature: ()[Ljava/lang/String;
596  */
597 /*ARGSUSED*/
598 JNIEXPORT jobjectArray JNICALL
599 Java_Kadmin_getPolicyList(JNIEnv *env, jobject obj)
600 {
601 	jclass stringclass;
602 	jobjectArray plist;
603 	jstring s;
604 	char **pols;
605 	int i, count;
606 	kadm5_ret_t ret;
607 
608 	/*
609 	 * Get the list
610 	 */
611 	ret = kadm5_get_policies(server_handle, NULL, &pols, &count);
612 	if (ret) {
613 		handle_error(env, ret);
614 		return (NULL);
615 	}
616 	qsort(pols, count, sizeof (pols[0]), charcmp);
617 
618 	/*
619 	 * Create and populate a Java String array
620 	 */
621 	stringclass = (*env)->FindClass(env, "java/lang/String");
622 	if (!stringclass) {
623 		handle_error(env, KADM_JNI_CLASS);
624 		return (NULL);
625 	}
626 	plist = (*env)->NewObjectArray(env, count, stringclass, NULL);
627 	if (!plist) {
628 		handle_error(env, KADM_JNI_ARRAY);
629 		return (NULL);
630 	}
631 	for (i = 0; i < count; i++) {
632 		s = (*env)->NewStringUTF(env, pols[i]);
633 		if (!s) {
634 			handle_error(env, KADM_JNI_NEWSTRING);
635 			return (NULL);
636 		}
637 		(*env)->SetObjectArrayElement(env, plist, i, s);
638 	}
639 	kadm5_free_name_list(server_handle, pols, count);
640 	return (plist);
641 }
642 
643 /*
644  * Class:     Kadmin
645  * Method:    loadPolicy
646  * Signature: (Ljava/lang/String;LPolicy;)Z
647  */
648 /*ARGSUSED*/
649 JNIEXPORT jboolean JNICALL
650 Java_Kadmin_loadPolicy(JNIEnv *env, jobject obj, jstring name, jobject pol)
651 {
652 	const char *cname;
653 	kadm5_policy_ent_rec po_rec;
654 	kadm5_ret_t ret;
655 
656 	cname = (*env)->GetStringUTFChars(env, name, NULL);
657 	if (!cname) {
658 		handle_error(env, KADM_JNI_STRING);
659 		return (JNI_FALSE);
660 	}
661 
662 	ret = kadm5_get_policy(server_handle, (char *)cname, &po_rec);
663 	if (ret) {
664 		handle_error(env, ret);
665 		return (JNI_FALSE);
666 	}
667 
668 	ret = kadmin_to_Policy(&po_rec, env, pol);
669 	if (ret) {
670 		handle_error(env, ret);
671 		return (JNI_FALSE);
672 	}
673 
674 	kadm5_free_policy_ent(server_handle, &po_rec);
675 	(*env)->ReleaseStringUTFChars(env, name, cname);
676 
677 	return (JNI_TRUE);
678 }
679 
680 /*
681  * Class:     Kadmin
682  * Method:    savePolicy
683  * Signature: (LPolicy;)Z
684  */
685 /*ARGSUSED*/
686 JNIEXPORT jboolean JNICALL
687 Java_Kadmin_savePolicy(JNIEnv *env, jobject obj, jobject pol)
688 {
689 	kadm5_policy_ent_rec po_rec;
690 	kadm5_ret_t ret;
691 	long mask;
692 
693 	ret = Policy_to_kadmin(env, pol, 0, &po_rec, &mask);
694 	if (ret) {
695 		handle_error(env, ret);
696 		return (JNI_FALSE);
697 	}
698 
699 	ret = kadm5_modify_policy(server_handle, &po_rec, mask);
700 	if (ret) {
701 		handle_error(env, ret);
702 		return (JNI_FALSE);
703 	}
704 
705 	return (JNI_TRUE);
706 }
707 
708 /*
709  * Class:     Kadmin
710  * Method:    createPolicy
711  * Signature: (LPolicy;)Z
712  */
713 /*ARGSUSED*/
714 JNIEXPORT jboolean JNICALL
715 Java_Kadmin_createPolicy(JNIEnv * env, jobject obj, jobject pol)
716 {
717 	kadm5_policy_ent_rec po_rec;
718 	kadm5_ret_t ret;
719 	long mask;
720 
721 	ret = Policy_to_kadmin(env, pol, 1, &po_rec, &mask);
722 	if (ret) {
723 		handle_error(env, ret);
724 		return (JNI_FALSE);
725 	}
726 
727 	ret = kadm5_create_policy(server_handle, &po_rec, mask);
728 	if (ret) {
729 		handle_error(env, ret);
730 		return (JNI_FALSE);
731 	}
732 
733 	return (JNI_TRUE);
734 }
735 
736 /*
737  * Class:     Kadmin
738  * Method:    deletePolicy
739  * Signature: (Ljava/lang/String;)Z
740  */
741 /*ARGSUSED*/
742 JNIEXPORT jboolean JNICALL
743 Java_Kadmin_deletePolicy(JNIEnv * env, jobject obj, jstring name)
744 {
745 	const char *cname;
746 	kadm5_ret_t ret;
747 
748 	cname = (*env)->GetStringUTFChars(env, name, NULL);
749 	if (!cname) {
750 		handle_error(env, KADM_JNI_STRING);
751 		return (JNI_FALSE);
752 	}
753 
754 	ret = kadm5_delete_policy(server_handle, (char *)cname);
755 	if (ret) {
756 		handle_error(env, ret);
757 		return (JNI_FALSE);
758 	}
759 	return (JNI_TRUE);
760 }
761 
762 #ifdef needtoknowmore
763 /*
764  * Class:     Kadmin
765  * Method:    loadDefaults
766  * Signature: (LConfig;)Z
767  */
768 /*ARGSUSED*/
769 JNIEXPORT jboolean JNICALL
770 Java_Kadmin_loadDefaults(JNIEnv *env, jobject obj, jobject config)
771 {
772 	/*
773 	 *
774 	 */
775 	return (JNI_TRUE);
776 }
777 
778 /*
779  * Class:     Kadmin
780  * Method:    saveDefaults
781  * Signature: (LConfig;)Z
782  */
783 /*ARGSUSED*/
784 JNIEXPORT jboolean JNICALL
785 Java_Kadmin_saveDefaults(JNIEnv *env, jobject obj, jobject config)
786 {
787 	/*
788 	 *
789 	 */
790 	return (JNI_TRUE);
791 }
792 #endif
793 
794 static int
795 Principal_to_kadmin(JNIEnv *env, jobject prin, int new, krb5_principal *kprin,
796 	kadm5_principal_ent_rec *p, long *mask, char **pw, char **comments)
797 {
798 	jstring s;
799 	jclass prcl, dateclass, intclass;
800 	jfieldID f;
801 	jmethodID mid;
802 	jobject obj;
803 	const char *str;
804 	jlong l;
805 	jint i;
806 	jboolean b;
807 	kadm5_ret_t ret;
808 	krb5_context context;
809 	jfieldID flagsID;
810 	jobject flagsObj;
811 	jclass flagsClass;
812 	char *fullname;
813 
814 	*mask = 0;
815 
816 	prcl = (*env)->GetObjectClass(env, prin);
817 	if (!prcl)
818 		return (KADM_JNI_CLASS);
819 	dateclass = (*env)->FindClass(env, "java/util/Date");
820 	if (!dateclass)
821 		return (KADM_JNI_CLASS);
822 	intclass = (*env)->FindClass(env, "java/lang/Integer");
823 	if (!intclass)
824 		return (KADM_JNI_CLASS);
825 
826 	f = (*env)->GetFieldID(env, prcl, "PrName", "Ljava/lang/String;");
827 	if (!f)
828 		return (KADM_JNI_FIELD);
829 	obj = (*env)->GetObjectField(env, prin, f);
830 	if (!obj)
831 		return (KADM_JNI_OFIELD);
832 	s = (jstring)obj;
833 	str = (*env)->GetStringUTFChars(env, s, NULL);
834 	if (!str)
835 		return (KADM_JNI_STRING);
836 	fullname = qualify((char *)str);
837 	if (!fullname)
838 		return (KADM_ENOMEM);
839 	ret = krb5_init_context(&context);
840 	if (ret)
841 		return (ret);
842 	ret = krb5_parse_name(context, fullname, kprin);
843 	if (ret)
844 		return (ret);
845 	p->principal = *kprin;
846 	(*env)->ReleaseStringUTFChars(env, s, str);
847 	if (new)
848 		*mask |= KADM5_PRINCIPAL;
849 
850 	f = (*env)->GetFieldID(env, prcl, "PrExpireTime", "Ljava/util/Date;");
851 	if (!f)
852 		return (KADM_JNI_FIELD);
853 	obj = (*env)->GetObjectField(env, prin, f);
854 	if (!obj)
855 		return (KADM_JNI_OFIELD);
856 	mid = (*env)->GetMethodID(env, dateclass, "getTime", "()J");
857 	if (!mid)
858 		return (KADM_JNI_METHOD);
859 	l = (*env)->CallLongMethod(env, obj, mid);
860 	p->princ_expire_time = (long)(l / 1000LL);
861 	*mask |= KADM5_PRINC_EXPIRE_TIME;
862 
863 	f = (*env)->GetFieldID(env, prcl, "Policy", "Ljava/lang/String;");
864 	if (!f)
865 		return (KADM_JNI_FIELD);
866 	obj = (*env)->GetObjectField(env, prin, f);
867 	if (!obj)
868 		return (KADM_JNI_OFIELD);
869 	s = (jstring)obj;
870 	str = (*env)->GetStringUTFChars(env, s, NULL);
871 	if (!str)
872 		return (KADM_JNI_STRING);
873 	p->policy = strdup(str);
874 	if (!p->policy)
875 		return (KADM_ENOMEM);
876 	(*env)->ReleaseStringUTFChars(env, s, str);
877 	if (strlen(p->policy))
878 		*mask |= KADM5_POLICY;
879 	else if (!new)
880 		*mask |= KADM5_POLICY_CLR;
881 
882 	f = (*env)->GetFieldID(env, prcl, "PwExpireTime", "Ljava/util/Date;");
883 	if (!f)
884 		return (KADM_JNI_FIELD);
885 	obj = (*env)->GetObjectField(env, prin, f);
886 	if (obj) {
887 		mid = (*env)->GetMethodID(env, dateclass, "getTime", "()J");
888 		if (!mid)
889 			return (KADM_JNI_METHOD);
890 		l = (*env)->CallLongMethod(env, obj, mid);
891 		p->pw_expiration = (long)(l / 1000LL);
892 		*mask |= KADM5_PW_EXPIRATION;
893 	}
894 
895 	f = (*env)->GetFieldID(env, prcl, "MaxLife", "Ljava/lang/Integer;");
896 	if (!f)
897 		return (KADM_JNI_FIELD);
898 	obj = (*env)->GetObjectField(env, prin, f);
899 	if (!obj)
900 		return (KADM_JNI_OFIELD);
901 	mid = (*env)->GetMethodID(env, intclass, "intValue", "()I");
902 	if (!mid)
903 		return (KADM_JNI_METHOD);
904 	i = (*env)->CallIntMethod(env, obj, mid);
905 	p->max_life = i;
906 	*mask |= KADM5_MAX_LIFE;
907 
908 	f = (*env)->GetFieldID(env, prcl, "MaxRenew", "Ljava/lang/Integer;");
909 	if (!f)
910 		return (KADM_JNI_FIELD);
911 	obj = (*env)->GetObjectField(env, prin, f);
912 	if (!obj)
913 		return (KADM_JNI_OFIELD);
914 	mid = (*env)->GetMethodID(env, intclass, "intValue", "()I");
915 	if (!mid)
916 		return (KADM_JNI_METHOD);
917 	i = (*env)->CallIntMethod(env, obj, mid);
918 	p->max_renewable_life = i;
919 	*mask |= KADM5_MAX_RLIFE;
920 
921 	/*
922 	 * Comments: because of API rules on the TL_DATA entries,
923 	 * which say that a load-modify-write is always necessary,
924 	 * we will only deal with comments if they are newly changed.
925 	 */
926 	f = (*env)->GetFieldID(env, prcl, "newComments", "Z");
927 	if (!f)
928 		return (KADM_JNI_FIELD);
929 	b = (*env)->GetBooleanField(env, prin, f);
930 	if (b == JNI_TRUE) {
931 
932 		f = (*env)->GetFieldID(env, prcl, "Comments",
933 				"Ljava/lang/String;");
934 		if (!f)
935 			return (KADM_JNI_FIELD);
936 		obj = (*env)->GetObjectField(env, prin, f);
937 		if (!obj)
938 			return (KADM_JNI_OFIELD);
939 		s = (jstring)obj;
940 		str = (*env)->GetStringUTFChars(env, s, NULL);
941 		if (!str)
942 			return (KADM_JNI_STRING);
943 		*comments = strdup(str);
944 		if (!*comments)
945 			return (KADM_ENOMEM);
946 		(*env)->ReleaseStringUTFChars(env, s, str);
947 	}
948 
949 	f = (*env)->GetFieldID(env, prcl, "Kvno", "Ljava/lang/Integer;");
950 	if (!f)
951 		return (KADM_JNI_FIELD);
952 	obj = (*env)->GetObjectField(env, prin, f);
953 	if (!obj)
954 		return (KADM_JNI_OFIELD);
955 	mid = (*env)->GetMethodID(env, intclass, "intValue", "()I");
956 	if (!mid)
957 		return (KADM_JNI_METHOD);
958 	i = (*env)->CallIntMethod(env, obj, mid);
959 	p->kvno = i;
960 	*mask |= KADM5_KVNO;
961 
962 	/*
963 	 * Get the Principal.flags field id
964 	 */
965 	flagsID = (*env)->GetFieldID(env, prcl, "flags",
966 				    "LFlags;");
967 	if (!f)
968 		return (KADM_JNI_FIELD);
969 
970 	/*
971 	 * Get the Principal.Flags object
972 	 */
973 	flagsObj = (*env)->GetObjectField(env, prin, flagsID);
974 	if (!obj)
975 		return (KADM_JNI_OFIELD);
976 
977 	/*
978 	 * Get the Flags object's class
979 	 */
980 	flagsClass = (*env)->GetObjectClass(env, flagsObj);
981 	if (!flagsClass)
982 		return (KADM_JNI_CLASS);
983 
984 	/*
985 	 * Now get the Flags.flags field's value
986 	 */
987 	f = (*env)->GetFieldID(env, flagsClass, "flags", "I");
988 	if (!f)
989 		return (KADM_JNI_FIELD);
990 
991 	i = (*env)->GetIntField(env, flagsObj, f);
992 	p->attributes = i & ~65536;
993 
994 	*mask |= KADM5_ATTRIBUTES;
995 
996 	f = (*env)->GetFieldID(env, prcl, "PrPasswd", "Ljava/lang/String;");
997 	if (!f)
998 		return (KADM_JNI_FIELD);
999 	obj = (*env)->GetObjectField(env, prin, f);
1000 	if (!obj)
1001 		return (KADM_JNI_OFIELD);
1002 	s = (jstring)obj;
1003 	str = (*env)->GetStringUTFChars(env, s, NULL);
1004 	if (!str)
1005 		return (KADM_JNI_STRING);
1006 	*pw = strdup(str);
1007 	if (!*pw)
1008 		return (KADM_ENOMEM);
1009 	(*env)->ReleaseStringUTFChars(env, s, str);
1010 
1011 	free(fullname);
1012 	return (0);
1013 }
1014 
1015 static int
1016 kadmin_to_Principal(kadm5_principal_ent_rec *p, JNIEnv *env, jobject prin,
1017 		const char *prname, char *comments)
1018 {
1019 	jstring s;
1020 	jclass prcl, dateclass, intclass;
1021 	jfieldID f;
1022 	jmethodID mid;
1023 	jobject obj;
1024 	int i;
1025 	kadm5_ret_t ret;
1026 	krb5_context context;
1027 	char *ptr;
1028 	char *cstr;
1029 
1030 	jfieldID flagsID;
1031 	jobject flagsObj;
1032 	jclass flagsClass;
1033 
1034 	prcl = (*env)->GetObjectClass(env, prin);
1035 	if (!prcl)
1036 		return (KADM_JNI_CLASS);
1037 	dateclass = (*env)->FindClass(env, "java/util/Date");
1038 	if (!dateclass)
1039 		return (KADM_JNI_CLASS);
1040 	intclass = (*env)->FindClass(env, "java/lang/Integer");
1041 	if (!intclass)
1042 		return (KADM_JNI_CLASS);
1043 
1044 	f = (*env)->GetFieldID(env, prcl, "PrName", "Ljava/lang/String;");
1045 	if (!f)
1046 		return (KADM_JNI_FIELD);
1047 	s = (*env)->NewStringUTF(env, prname);
1048 	if (!s)
1049 		return (KADM_JNI_NEWSTRING);
1050 	(*env)->SetObjectField(env, prin, f, s);
1051 
1052 	f = (*env)->GetFieldID(env, prcl, "PrExpireTime", "Ljava/util/Date;");
1053 	if (!f)
1054 		return (KADM_JNI_FIELD);
1055 	mid = (*env)->GetMethodID(env, dateclass, "setTime", "(J)V");
1056 	if (!mid)
1057 		return (KADM_JNI_METHOD);
1058 	obj = (*env)->GetObjectField(env, prin, f);
1059 	if (!obj)
1060 		return (KADM_JNI_OFIELD);
1061 	(*env)->CallVoidMethod(env, obj, mid,
1062 			(jlong) (p->princ_expire_time * 1000LL));
1063 
1064 	f = (*env)->GetFieldID(env, prcl, "Policy", "Ljava/lang/String;");
1065 	if (!f)
1066 		return (KADM_JNI_FIELD);
1067 	cstr = strdup(p->policy ? p->policy : "");
1068 	if (!cstr)
1069 		return (KADM_ENOMEM);
1070 	s = (*env)->NewStringUTF(env, cstr);
1071 	if (!s)
1072 		return (KADM_JNI_NEWSTRING);
1073 	(*env)->SetObjectField(env, prin, f, s);
1074 	free(cstr);
1075 
1076 	f = (*env)->GetFieldID(env, prcl, "LastPwChange", "Ljava/util/Date;");
1077 	if (!f)
1078 		return (KADM_JNI_FIELD);
1079 	mid = (*env)->GetMethodID(env, dateclass, "setTime", "(J)V");
1080 	if (!mid)
1081 		return (KADM_JNI_METHOD);
1082 	obj = (*env)->GetObjectField(env, prin, f);
1083 	if (!obj)
1084 		return (KADM_JNI_OFIELD);
1085 	(*env)->CallVoidMethod(env, obj, mid,
1086 			(jlong) (p->last_pwd_change * 1000LL));
1087 
1088 	f = (*env)->GetFieldID(env, prcl, "PwExpireTime", "Ljava/util/Date;");
1089 	if (!f)
1090 		return (KADM_JNI_FIELD);
1091 	mid = (*env)->GetMethodID(env, dateclass, "setTime", "(J)V");
1092 	if (!mid)
1093 		return (KADM_JNI_METHOD);
1094 	obj = (*env)->GetObjectField(env, prin, f);
1095 	if (!obj)
1096 		return (KADM_JNI_OFIELD);
1097 	(*env)->CallVoidMethod(env, obj, mid,
1098 			(jlong) (p->pw_expiration * 1000LL));
1099 
1100 	f = (*env)->GetFieldID(env, prcl, "MaxLife", "Ljava/lang/Integer;");
1101 	if (!f)
1102 		return (KADM_JNI_FIELD);
1103 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1104 	if (!mid)
1105 		return (KADM_JNI_METHOD);
1106 	obj = (*env)->NewObject(env, intclass, mid, (jint) p->max_life);
1107 	if (!obj)
1108 		return (KADM_JNI_OBJECT);
1109 	(*env)->SetObjectField(env, prin, f, obj);
1110 
1111 	f = (*env)->GetFieldID(env, prcl, "MaxRenew", "Ljava/lang/Integer;");
1112 	if (!f)
1113 		return (KADM_JNI_FIELD);
1114 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1115 	if (!mid)
1116 		return (KADM_JNI_METHOD);
1117 	obj = (*env)->NewObject(env, intclass, mid,
1118 			(jint) p->max_renewable_life);
1119 	if (!obj)
1120 		return (KADM_JNI_OBJECT);
1121 	(*env)->SetObjectField(env, prin, f, obj);
1122 
1123 	f = (*env)->GetFieldID(env, prcl, "ModTime", "Ljava/util/Date;");
1124 	if (!f)
1125 		return (KADM_JNI_FIELD);
1126 	mid = (*env)->GetMethodID(env, dateclass, "setTime", "(J)V");
1127 	if (!mid)
1128 		return (KADM_JNI_METHOD);
1129 	obj = (*env)->GetObjectField(env, prin, f);
1130 	if (!obj)
1131 		return (KADM_JNI_OFIELD);
1132 	(*env)->CallVoidMethod(env, obj, mid,
1133 			(jlong) (p->mod_date * 1000LL));
1134 
1135 	ret = krb5_init_context(&context);
1136 	if (ret)
1137 		return (ret);
1138 	ret = krb5_unparse_name(context, p->mod_name, &ptr);
1139 	if (ret)
1140 		return (ret);
1141 	f = (*env)->GetFieldID(env, prcl, "ModName", "Ljava/lang/String;");
1142 	if (!f)
1143 		return (KADM_JNI_FIELD);
1144 	s = (*env)->NewStringUTF(env, ptr);
1145 	if (!s)
1146 		return (KADM_JNI_NEWSTRING);
1147 	(*env)->SetObjectField(env, prin, f, s);
1148 	krb5_xfree(ptr);
1149 
1150 	f = (*env)->GetFieldID(env, prcl, "LastSuccess", "Ljava/util/Date;");
1151 	if (!f)
1152 		return (KADM_JNI_FIELD);
1153 	mid = (*env)->GetMethodID(env, dateclass, "setTime", "(J)V");
1154 	if (!mid)
1155 		return (KADM_JNI_METHOD);
1156 	obj = (*env)->GetObjectField(env, prin, f);
1157 	if (!obj)
1158 		return (KADM_JNI_OFIELD);
1159 	(*env)->CallVoidMethod(env, obj, mid,
1160 			(jlong) (p->last_success * 1000LL));
1161 
1162 	f = (*env)->GetFieldID(env, prcl, "LastFailure", "Ljava/util/Date;");
1163 	if (!f)
1164 		return (KADM_JNI_FIELD);
1165 	mid = (*env)->GetMethodID(env, dateclass, "setTime", "(J)V");
1166 	if (!mid)
1167 		return (KADM_JNI_METHOD);
1168 	obj = (*env)->GetObjectField(env, prin, f);
1169 	if (!obj)
1170 		return (KADM_JNI_OFIELD);
1171 	(*env)->CallVoidMethod(env, obj, mid,
1172 			(jlong) (p->last_failed * 1000LL));
1173 
1174 	f = (*env)->GetFieldID(env, prcl, "NumFailures", "Ljava/lang/Integer;");
1175 	if (!f)
1176 		return (KADM_JNI_FIELD);
1177 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1178 	if (!mid)
1179 		return (KADM_JNI_METHOD);
1180 	obj = (*env)->NewObject(env, intclass, mid,
1181 			(jint) p->fail_auth_count);
1182 	if (!obj)
1183 		return (KADM_JNI_OBJECT);
1184 	(*env)->SetObjectField(env, prin, f, obj);
1185 
1186 	f = (*env)->GetFieldID(env, prcl, "Comments", "Ljava/lang/String;");
1187 	if (!f)
1188 		return (KADM_JNI_FIELD);
1189 	cstr = strdup(comments ? comments : "");
1190 	if (!cstr)
1191 		return (KADM_ENOMEM);
1192 	s = (*env)->NewStringUTF(env, cstr);
1193 	if (!s)
1194 		return (KADM_JNI_NEWSTRING);
1195 	(*env)->SetObjectField(env, prin, f, s);
1196 	free(cstr);
1197 
1198 	f = (*env)->GetFieldID(env, prcl, "Kvno", "Ljava/lang/Integer;");
1199 	if (!f)
1200 		return (KADM_JNI_FIELD);
1201 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1202 	if (!mid)
1203 		return (KADM_JNI_METHOD);
1204 	obj = (*env)->NewObject(env, intclass, mid, p->kvno);
1205 	if (!obj)
1206 		return (KADM_JNI_OBJECT);
1207 	(*env)->SetObjectField(env, prin, f, obj);
1208 
1209 	f = (*env)->GetFieldID(env, prcl, "Mkvno", "Ljava/lang/Integer;");
1210 	if (!f)
1211 		return (KADM_JNI_FIELD);
1212 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1213 	if (!mid)
1214 		return (KADM_JNI_METHOD);
1215 	obj = (*env)->NewObject(env, intclass, mid, p->mkvno);
1216 	if (!obj)
1217 		return (KADM_JNI_OBJECT);
1218 	(*env)->SetObjectField(env, prin, f, obj);
1219 
1220 	i = p->attributes;
1221 
1222 	/*
1223 	 * Get the Principal.flags field id
1224 	 */
1225 	flagsID = (*env)->GetFieldID(env, prcl, "flags",
1226 				    "LFlags;");
1227 	if (!f)
1228 		return (KADM_JNI_FIELD);
1229 
1230 	/*
1231 	 * Get the Principal.Flags object
1232 	 */
1233 	flagsObj = (*env)->GetObjectField(env, prin, flagsID);
1234 	if (!obj)
1235 		return (KADM_JNI_OFIELD);
1236 
1237 	/*
1238 	 * Get the Flags object's class
1239 	 */
1240 	flagsClass = (*env)->GetObjectClass(env, flagsObj);
1241 
1242 	/*
1243 	 * Now set the Flags.flags field's value
1244 	 */
1245 	f = (*env)->GetFieldID(env, flagsClass, "flags", "I");
1246 	if (!f)
1247 		return (KADM_JNI_FIELD);
1248 	(*env)->SetIntField(env, flagsObj, f, i);
1249 
1250 	return (0);
1251 }
1252 
1253 static int
1254 Policy_to_kadmin(JNIEnv *env, jobject pol, int new,
1255 	kadm5_policy_ent_rec *p, long *mask)
1256 {
1257 	jstring s;
1258 	jclass pocl, intclass;
1259 	jfieldID f;
1260 	jmethodID mid;
1261 	jobject obj;
1262 	const char *str;
1263 	int i;
1264 
1265 	*mask = 0;
1266 
1267 	pocl = (*env)->GetObjectClass(env, pol);
1268 	if (!pocl)
1269 		return (KADM_JNI_CLASS);
1270 	intclass = (*env)->FindClass(env, "java/lang/Integer");
1271 	if (!intclass)
1272 		return (KADM_JNI_CLASS);
1273 
1274 	f = (*env)->GetFieldID(env, pocl, "PolicyName", "Ljava/lang/String;");
1275 	if (!f)
1276 		return (KADM_JNI_FIELD);
1277 	obj = (*env)->GetObjectField(env, pol, f);
1278 	if (!obj)
1279 		return (KADM_JNI_OFIELD);
1280 	s = (jstring)obj;
1281 	str = (*env)->GetStringUTFChars(env, s, NULL);
1282 	if (!str)
1283 		return (KADM_JNI_STRING);
1284 	p->policy = strdup(str);
1285 	if (!p->policy)
1286 		return (KADM_ENOMEM);
1287 	if (new)
1288 		*mask |= KADM5_POLICY;
1289 	(*env)->ReleaseStringUTFChars(env, s, str);
1290 
1291 	f = (*env)->GetFieldID(env, pocl, "PwMinLife", "Ljava/lang/Integer;");
1292 	if (!f)
1293 		return (KADM_JNI_FIELD);
1294 	obj = (*env)->GetObjectField(env, pol, f);
1295 	if (!obj)
1296 		return (KADM_JNI_OFIELD);
1297 	mid = (*env)->GetMethodID(env, intclass, "intValue", "()I");
1298 	if (!mid)
1299 		return (KADM_JNI_METHOD);
1300 	i = (*env)->CallIntMethod(env, obj, mid);
1301 	p->pw_min_life = i;
1302 	*mask |= KADM5_PW_MIN_LIFE;
1303 
1304 	f = (*env)->GetFieldID(env, pocl, "PwMaxLife", "Ljava/lang/Integer;");
1305 	if (!f)
1306 		return (KADM_JNI_FIELD);
1307 	obj = (*env)->GetObjectField(env, pol, f);
1308 	if (!obj)
1309 		return (KADM_JNI_OFIELD);
1310 	mid = (*env)->GetMethodID(env, intclass, "intValue", "()I");
1311 	if (!mid)
1312 		return (KADM_JNI_METHOD);
1313 	i = (*env)->CallIntMethod(env, obj, mid);
1314 	p->pw_max_life = i;
1315 	*mask |= KADM5_PW_MAX_LIFE;
1316 
1317 	f = (*env)->GetFieldID(env, pocl, "PwMinLength", "Ljava/lang/Integer;");
1318 	if (!f)
1319 		return (KADM_JNI_FIELD);
1320 	obj = (*env)->GetObjectField(env, pol, f);
1321 	if (!obj)
1322 		return (KADM_JNI_OFIELD);
1323 	mid = (*env)->GetMethodID(env, intclass, "intValue", "()I");
1324 	if (!mid)
1325 		return (KADM_JNI_METHOD);
1326 	i = (*env)->CallIntMethod(env, obj, mid);
1327 	p->pw_min_length = i;
1328 	*mask |= KADM5_PW_MIN_LENGTH;
1329 
1330 	f = (*env)->GetFieldID(env, pocl, "PwMinClasses",
1331 				"Ljava/lang/Integer;");
1332 	if (!f)
1333 		return (KADM_JNI_FIELD);
1334 	obj = (*env)->GetObjectField(env, pol, f);
1335 	if (!obj)
1336 		return (KADM_JNI_OFIELD);
1337 	mid = (*env)->GetMethodID(env, intclass, "intValue", "()I");
1338 	if (!mid)
1339 		return (KADM_JNI_METHOD);
1340 	i = (*env)->CallIntMethod(env, obj, mid);
1341 	p->pw_min_classes = i;
1342 	*mask |= KADM5_PW_MIN_CLASSES;
1343 
1344 	f = (*env)->GetFieldID(env, pocl, "PwSaveCount", "Ljava/lang/Integer;");
1345 	if (!f)
1346 		return (KADM_JNI_FIELD);
1347 	obj = (*env)->GetObjectField(env, pol, f);
1348 	if (!obj)
1349 		return (KADM_JNI_OFIELD);
1350 	mid = (*env)->GetMethodID(env, intclass, "intValue", "()I");
1351 	if (!mid)
1352 		return (KADM_JNI_METHOD);
1353 	i = (*env)->CallIntMethod(env, obj, mid);
1354 	p->pw_history_num = i;
1355 	*mask |= KADM5_PW_HISTORY_NUM;
1356 
1357 	return (0);
1358 }
1359 
1360 static int
1361 kadmin_to_Policy(kadm5_policy_ent_rec *p, JNIEnv *env, jobject pol)
1362 {
1363 	jstring s;
1364 	jclass pocl, intclass;
1365 	jfieldID f;
1366 	jmethodID mid;
1367 	jobject obj;
1368 
1369 	pocl = (*env)->GetObjectClass(env, pol);
1370 	if (!pocl)
1371 		return (KADM_JNI_CLASS);
1372 	intclass = (*env)->FindClass(env, "java/lang/Integer");
1373 	if (!intclass)
1374 		return (KADM_JNI_CLASS);
1375 
1376 	f = (*env)->GetFieldID(env, pocl, "PolicyName", "Ljava/lang/String;");
1377 	if (!f)
1378 		return (KADM_JNI_FIELD);
1379 	s = (*env)->NewStringUTF(env, p->policy);
1380 	if (!s)
1381 		return (KADM_JNI_NEWSTRING);
1382 	(*env)->SetObjectField(env, pol, f, s);
1383 
1384 	f = (*env)->GetFieldID(env, pocl, "PwMinLife", "Ljava/lang/Integer;");
1385 	if (!f)
1386 		return (KADM_JNI_FIELD);
1387 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1388 	if (!mid)
1389 		return (KADM_JNI_METHOD);
1390 	obj = (*env)->NewObject(env, intclass, mid, p->pw_min_life);
1391 	if (!obj)
1392 		return (KADM_JNI_OBJECT);
1393 	(*env)->SetObjectField(env, pol, f, obj);
1394 
1395 	f = (*env)->GetFieldID(env, pocl, "PwMaxLife", "Ljava/lang/Integer;");
1396 	if (!f)
1397 		return (KADM_JNI_FIELD);
1398 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1399 	if (!mid)
1400 		return (KADM_JNI_METHOD);
1401 	obj = (*env)->NewObject(env, intclass, mid, p->pw_max_life);
1402 	if (!obj)
1403 		return (KADM_JNI_OBJECT);
1404 	(*env)->SetObjectField(env, pol, f, obj);
1405 
1406 	f = (*env)->GetFieldID(env, pocl, "PwMinLength", "Ljava/lang/Integer;");
1407 	if (!f)
1408 		return (KADM_JNI_FIELD);
1409 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1410 	if (!mid)
1411 		return (KADM_JNI_METHOD);
1412 	obj = (*env)->NewObject(env, intclass, mid, p->pw_min_length);
1413 	if (!obj)
1414 		return (KADM_JNI_OBJECT);
1415 	(*env)->SetObjectField(env, pol, f, obj);
1416 
1417 	f = (*env)->GetFieldID(env, pocl, "PwMinClasses",
1418 				"Ljava/lang/Integer;");
1419 	if (!f)
1420 		return (KADM_JNI_FIELD);
1421 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1422 	if (!mid)
1423 		return (KADM_JNI_METHOD);
1424 	obj = (*env)->NewObject(env, intclass, mid, p->pw_min_classes);
1425 	if (!obj)
1426 		return (KADM_JNI_OBJECT);
1427 	(*env)->SetObjectField(env, pol, f, obj);
1428 
1429 	f = (*env)->GetFieldID(env, pocl, "PwSaveCount", "Ljava/lang/Integer;");
1430 	if (!f)
1431 		return (KADM_JNI_FIELD);
1432 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1433 	if (!mid)
1434 		return (KADM_JNI_METHOD);
1435 	obj = (*env)->NewObject(env, intclass, mid, p->pw_history_num);
1436 	if (!obj)
1437 		return (KADM_JNI_OBJECT);
1438 	(*env)->SetObjectField(env, pol, f, obj);
1439 
1440 	f = (*env)->GetFieldID(env, pocl, "RefCount", "Ljava/lang/Integer;");
1441 	if (!f)
1442 		return (KADM_JNI_FIELD);
1443 	mid = (*env)->GetMethodID(env, intclass, "<init>", "(I)V");
1444 	if (!mid)
1445 		return (KADM_JNI_METHOD);
1446 	obj = (*env)->NewObject(env, intclass, mid, p->policy_refcnt);
1447 	if (!obj)
1448 		return (KADM_JNI_OBJECT);
1449 	(*env)->SetObjectField(env, pol, f, obj);
1450 
1451 	return (0);
1452 }
1453 
1454 #define	SUNSOFT_COMMENTS	256
1455 
1456 /*
1457  * The new principal has been saved; now we do a load-modify-store
1458  * to get the comments into the TL_DATA array.
1459  */
1460 static int
1461 edit_comments(kadm5_principal_ent_rec *p, krb5_principal kprin, char *comments)
1462 {
1463 	long mask = KADM5_PRINCIPAL | KADM5_TL_DATA;
1464 	kadm5_ret_t ret;
1465 
1466 	if (!comments || !strlen(comments))
1467 		return (0);
1468 
1469 	ret = kadm5_get_principal(server_handle, kprin, p, mask);
1470 	if (ret)
1471 		return (ret);
1472 
1473 	mask = 0;
1474 	ret = format_comments(p, &mask, comments);
1475 	if (ret)
1476 		return (ret);
1477 
1478 	if (mask) {
1479 		ret = kadm5_modify_principal(server_handle, p, mask);
1480 		if (ret)
1481 			return (ret);
1482 	}
1483 
1484 	return (0);
1485 }
1486 
1487 /*
1488  * Put the comments into TL_DATA.
1489  */
1490 static int
1491 format_comments(kadm5_principal_ent_rec *p, long *mask, char *comments)
1492 {
1493 	krb5_tl_data *t, *t1, *tdp;
1494 	char *s;
1495 
1496 	if (!comments || !strlen(comments))
1497 		return (0);
1498 	tdp = malloc(sizeof (krb5_tl_data));
1499 	if (!tdp)
1500 		return (KADM_ENOMEM);
1501 	s = strdup(comments);
1502 	if (!s)
1503 		return (KADM_ENOMEM);
1504 
1505 	/*
1506 	 * Search for existing comments field, or find next-to-last
1507 	 */
1508 	for (t = t1 = p->tl_data; t; t1 = t, t = t->tl_data_next)
1509 		if (t->tl_data_type == SUNSOFT_COMMENTS)
1510 			break;
1511 	if (t) {
1512 		t->tl_data_length = strlen(comments);
1513 		free(t->tl_data_contents);
1514 		t->tl_data_contents = (krb5_octet *)s;
1515 	} else {
1516 		tdp->tl_data_next = NULL;
1517 		tdp->tl_data_type = SUNSOFT_COMMENTS;
1518 		tdp->tl_data_length = strlen(comments)+1;
1519 		tdp->tl_data_contents = (krb5_octet *)s;
1520 		if (t1)
1521 			t1->tl_data_next = tdp;
1522 		else
1523 			p->tl_data = tdp;
1524 		p->n_tl_data++;
1525 	}
1526 	*mask |= KADM5_TL_DATA;
1527 	return (0);
1528 }
1529 
1530 /*
1531  * The principal has been loaded, so we pluck the comments out of TL_DATA.
1532  */
1533 static int
1534 extract_comments(kadm5_principal_ent_rec *p, char **comments)
1535 {
1536 	krb5_tl_data *t;
1537 	char *s;
1538 
1539 	/*
1540 	 * Search for existing comments field, or find next-to-last
1541 	 */
1542 	if (!p->n_tl_data)
1543 		return (0);
1544 	for (t = p->tl_data; t; t = t->tl_data_next)
1545 		if (t->tl_data_type == SUNSOFT_COMMENTS)
1546 			break;
1547 	if (t && t->tl_data_length) {
1548 		s = strdup((char *)t->tl_data_contents);
1549 		if (!s)
1550 			return (KADM_ENOMEM);
1551 		s[t->tl_data_length] = 0;
1552 		*comments = s;
1553 	}
1554 	return (0);
1555 }
1556 
1557 /*
1558  * Set password for the modified principal
1559  */
1560 static int
1561 set_password(krb5_principal kprin, char *pw)
1562 {
1563 	kadm5_ret_t ret;
1564 
1565 	if (!pw || !strlen(pw))
1566 		return (0);
1567 	ret = kadm5_chpass_principal(server_handle, kprin, pw);
1568 	if (ret)
1569 		return (ret);
1570 	return (0);
1571 }
1572 
1573 static void
1574 handle_error(JNIEnv *env, int error)
1575 {
1576 	char *s;
1577 	char    from[BUFSIZ], to[BUFSIZ];
1578 	char    *tptr;
1579 	const char  *fptr;
1580 	size_t  ileft, oleft, ret;
1581 
1582 	s = (char *)error_message(error);
1583 	/* fprintf(stderr, "Kadmin: %s (%d)\n", s, error); XXX */
1584 	if (cd != (iconv_t)-1) {
1585 		ileft = strlen(s);
1586 		strncpy(from, s, ileft);
1587 		fptr = from;
1588 		oleft = BUFSIZ;
1589 		tptr = to;
1590 		ret = iconv(cd, &fptr, &ileft, &tptr, &oleft);
1591 		if (ret != (size_t)-1) {
1592 			to[BUFSIZ-oleft] = '\0';
1593 			s = to;
1594 		/* fprintf(stderr, "Kadmin: %s (%d)\n", s, error); XXX */
1595 		}
1596 	}
1597 	(*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/Exception"),
1598 			(const char *)s);
1599 }
1600