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