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 <stdio.h> 30 #include <stdlib.h> 31 #include <ctype.h> 32 #include <strings.h> 33 #include <pwd.h> 34 #include <shadow.h> 35 #include <netdb.h> 36 #include <mp.h> 37 #include <rpcsvc/nis.h> 38 #include <rpc/key_prot.h> 39 #include <nsswitch.h> 40 #include <ns_sldap.h> 41 42 extern char *crypt(); 43 extern long random(); 44 extern char *getpassphrase(); 45 extern char *program_name; 46 static const char *CRED_TABLE = "cred.org_dir"; 47 48 #define ROOTKEY_FILE "/etc/.rootkey" 49 50 #ifndef MAXHOSTNAMELEN 51 #define MAXHOSTNAMELEN 256 52 #endif 53 54 #define PK_FILES 1 55 #define PK_YP 2 56 #define PK_NISPLUS 3 57 #define PK_LDAP 4 58 59 #define LDAP_BINDDN_DEFAULT "cn=Directory Manager" 60 #define PROMPTGET_SUCCESS 1 61 #define PROMPTGET_FAIL -1 62 #define PROMPTGET_MEMORY_FAIL -2 63 #define PASSWD_UNMATCHED -3 64 65 #define FREE_CREDINFO(s) \ 66 if ((s)) { (void) memset((s), 0, strlen((s))); } 67 68 69 /* ************************ switch functions *************************** */ 70 71 /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */ 72 #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE} 73 74 static struct __nsw_lookup lookup_files = {"files", DEF_ACTION, NULL, NULL}, 75 lookup_nis = {"nis", DEF_ACTION, NULL, &lookup_files}; 76 static struct __nsw_switchconfig publickey_default = 77 {0, "publickey", 2, &lookup_nis}; 78 79 static int get_ldap_bindDN(char **); 80 static int get_ldap_bindPassword(char **); 81 82 /* 83 * Prompt the users for a ldap bind DN. If users do not enter a value but just 84 * simply hit the return key, the default bindDN "cn=Directory Manager" 85 * will be used. 86 */ 87 static int 88 get_ldap_bindDN(char **ret_bindDN) { 89 90 char bindDN[BUFSIZ]; 91 char prompt[BUFSIZ]; 92 int blen, pos; 93 94 /* set the initial value for bindDN buffer */ 95 (void) memset(bindDN, 0, BUFSIZ); 96 97 (void) snprintf(prompt, BUFSIZ, 98 "\nThe LDAP bind DN and password are required for this update.\n" 99 "If you are not sure what values to enter, please contact your\n" 100 "LDAP administrator.\n\nPlease enter LDAP bind DN [%s]: ", 101 LDAP_BINDDN_DEFAULT); 102 103 printf(prompt); 104 105 if (fgets(bindDN, sizeof (bindDN), stdin) == NULL) { 106 (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ); 107 } 108 109 blen = strlen(bindDN); 110 111 /* Check if the buffer ends with a newline */ 112 if ((blen > 0) && (bindDN[blen - 1] == '\n')) { 113 bindDN[blen - 1] = '\0'; 114 blen -= 1; 115 } 116 117 /* Remove the white spaces */ 118 if (blen > 0) { 119 for (pos = blen - 1; pos >= 0; pos--) { 120 if (isspace(bindDN[pos])) 121 bindDN[pos] = '\0'; 122 else 123 break; 124 } 125 } 126 127 /* Use the default bindDN, if the buffer contains no characters */ 128 if (strlen(bindDN) == 0) 129 (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ); 130 131 if ((*ret_bindDN = (char *)malloc(strlen(bindDN)+1)) == NULL) { 132 (void) memset(bindDN, 0, BUFSIZ); 133 return (PROMPTGET_MEMORY_FAIL); 134 } 135 136 (void) strlcpy(*ret_bindDN, bindDN, strlen(bindDN)+1); 137 138 /* Clean up and erase the credential info */ 139 (void) memset(bindDN, 0, BUFSIZ); 140 141 return (PROMPTGET_SUCCESS); 142 } 143 144 145 /* 146 * Prompt the user for a ldap bind password. 147 */ 148 static int 149 get_ldap_bindPassword(char **ret_bindPass) { 150 151 char bindPassword[BUFSIZ]; 152 char prompt[BUFSIZ]; 153 char *bindPass = NULL; 154 155 /* set the initial value for bindPassword buffer */ 156 (void) memset(bindPassword, 0, BUFSIZ); 157 *ret_bindPass = NULL; 158 159 (void) snprintf(prompt, BUFSIZ, 160 "Please enter LDAP bind password: "); 161 162 bindPass = getpassphrase(prompt); 163 164 if (bindPass == NULL) 165 return (PROMPTGET_FAIL); 166 167 (void) strlcpy(bindPassword, bindPass, BUFSIZ); 168 169 /* clean the static buffer returned from getpassphrase call */ 170 (void) memset(bindPass, 0, strlen(bindPass)); 171 bindPass = NULL; 172 173 /* 174 * Re-enter the bind passowrd and compare it with the one 175 * from previous entered. 176 */ 177 (void) snprintf(prompt, BUFSIZ, 178 "Re-enter LDAP bind password to confirm: "); 179 180 bindPass = getpassphrase(prompt); 181 182 if (bindPass == NULL) { 183 (void) memset(bindPassword, 0, BUFSIZ); 184 return (PASSWD_UNMATCHED); 185 } 186 187 if (strcmp(bindPass, bindPassword) != 0) { 188 (void) memset(bindPassword, 0, BUFSIZ); 189 (void) memset(bindPass, 0, strlen(bindPass)); 190 return (PASSWD_UNMATCHED); 191 } else { 192 (void) memset(bindPass, 0, strlen(bindPass)); 193 if ((*ret_bindPass = (char *)malloc(strlen(bindPassword)+1)) 194 == NULL) { 195 (void) memset(bindPassword, 0, BUFSIZ); 196 return (PROMPTGET_MEMORY_FAIL); 197 } 198 199 (void) strlcpy(*ret_bindPass, bindPassword, 200 strlen(bindPassword)+1); 201 202 /* Clean up and erase the credential info */ 203 (void) memset(bindPassword, 0, BUFSIZ); 204 205 return (PROMPTGET_SUCCESS); 206 } 207 } 208 209 210 211 char * 212 switch_policy_str(struct __nsw_switchconfig *conf) 213 { 214 struct __nsw_lookup *look; 215 static char policy[256]; /* 256 is enough for (nis, files...etc) */ 216 int previous = 0; 217 218 memset((char *)policy, 0, 256); 219 220 for (look = conf->lookups; look; look = look->next) { 221 if (previous) 222 strcat(policy, " "); 223 strcat(policy, look->service_name); 224 previous = 1; 225 } 226 return (policy); 227 } 228 229 int 230 no_switch_policy(struct __nsw_switchconfig *conf) 231 { 232 return (conf == NULL || conf->lookups == NULL); 233 } 234 235 int 236 is_switch_policy(struct __nsw_switchconfig *conf, char *target) 237 { 238 return (conf && 239 conf->lookups && 240 strcmp(conf->lookups->service_name, target) == 0 && 241 conf->lookups->next == NULL); 242 } 243 244 char * 245 first_and_only_switch_policy(char *policy, 246 struct __nsw_switchconfig *default_conf, 247 char *head_msg) 248 { 249 struct __nsw_switchconfig *conf; 250 enum __nsw_parse_err perr; 251 int policy_correct = 1; 252 char *target_service = 0; 253 int use_default = 0; 254 255 if (default_conf == 0) 256 default_conf = &publickey_default; 257 258 conf = __nsw_getconfig(policy, &perr); 259 if (no_switch_policy(conf)) { 260 use_default = 1; 261 conf = default_conf; 262 } 263 264 target_service = conf->lookups->service_name; 265 266 if (conf->lookups->next != NULL) { 267 policy_correct = 0; 268 if (use_default) { 269 (void) fprintf(stderr, 270 "\n%s\n There is no publickey entry in %s.\n", 271 head_msg, __NSW_CONFIG_FILE); 272 (void) fprintf(stderr, 273 "The default publickey policy is \"publickey: %s\".\n", 274 switch_policy_str(default_conf)); 275 } else 276 (void) fprintf(stderr, 277 "\n%s\nThe publickey entry in %s is \"publickey: %s\".\n", 278 head_msg, __NSW_CONFIG_FILE, 279 switch_policy_str(conf)); 280 } 281 282 if (policy_correct == 0) 283 (void) fprintf(stderr, 284 "I cannot figure out which publickey database you want to update.\n"); 285 if (!use_default && conf) 286 __nsw_freeconfig(conf); 287 288 if (policy_correct) 289 return (target_service); 290 else 291 return (0); 292 } 293 294 295 296 int 297 check_switch_policy(char *policy, char *target_service, 298 struct __nsw_switchconfig *default_conf, 299 char *head_msg, char *tail_msg) 300 { 301 struct __nsw_switchconfig *conf; 302 enum __nsw_parse_err perr; 303 int policy_correct = 1; 304 305 if (default_conf == 0) 306 default_conf = &publickey_default; 307 308 conf = __nsw_getconfig(policy, &perr); 309 if (no_switch_policy(conf)) { 310 if (!is_switch_policy(default_conf, target_service)) { 311 (void) fprintf(stderr, 312 "\n%s\nThere is no publickey entry in %s.\n", 313 head_msg, __NSW_CONFIG_FILE); 314 (void) fprintf(stderr, 315 "The default publickey policy is \"publickey: %s\".\n", 316 switch_policy_str(default_conf)); 317 policy_correct = 0; 318 } 319 } else if (!is_switch_policy(conf, target_service)) { 320 (void) fprintf(stderr, 321 "\n%s\nThe publickey entry in %s is \"publickey: %s\".\n", 322 head_msg, __NSW_CONFIG_FILE, 323 switch_policy_str(conf)); 324 policy_correct = 0; 325 } 326 /* should we exit ? */ 327 if (policy_correct == 0) 328 (void) fprintf(stderr, 329 "It should be \"publickey: %s\"%s\n\n", 330 target_service, tail_msg); 331 if (conf) 332 __nsw_freeconfig(conf); 333 334 return (policy_correct); 335 } 336 337 int 338 get_pk_source(char *pk_service) 339 { 340 int db = 0, got_from_switch = 0; 341 342 /* No service specified, try to figure out from switch */ 343 if (pk_service == 0) { 344 pk_service = first_and_only_switch_policy("publickey", 0, 345 "ERROR:"); 346 if (pk_service == 0) 347 return (0); 348 (void) fprintf(stdout, 349 "Updating %s publickey database.\n", 350 pk_service); 351 got_from_switch = 1; 352 } 353 354 if (strcmp(pk_service, "ldap") == 0) 355 db = PK_LDAP; 356 else if (strcmp(pk_service, "nisplus") == 0) 357 db = PK_NISPLUS; 358 else if (strcmp(pk_service, "nis") == 0) 359 db = PK_YP; 360 else if (strcmp(pk_service, "files") == 0) 361 db = PK_FILES; 362 else return (0); 363 364 /* 365 * If we didn't get service name from switch, check switch 366 * and print warning about it source of publickeys if not unique 367 */ 368 if (got_from_switch == 0) 369 check_switch_policy("publickey", pk_service, 0, "WARNING:", 370 db == PK_FILES ? "" : 371 "; add 'files' if you want the 'nobody' key."); 372 373 374 return (db); /* all passed */ 375 } 376 377 378 /* ***************************** keylogin stuff *************************** */ 379 int 380 keylogin(char *netname, char *secret) 381 { 382 struct key_netstarg netst; 383 384 netst.st_pub_key[0] = 0; 385 memcpy(netst.st_priv_key, secret, HEXKEYBYTES); 386 netst.st_netname = netname; 387 388 #ifdef NFS_AUTH 389 nra.authtype = AUTH_DES; /* only revoke DES creds */ 390 nra.uid = getuid(); /* use the real uid */ 391 if (_nfssys(NFS_REVAUTH, &nra) < 0) { 392 perror("Warning: NFS credentials not destroyed"); 393 err = 1; 394 } 395 #endif 396 397 398 /* do actual key login */ 399 if (key_setnet(&netst) < 0) { 400 (void) fprintf(stderr, 401 "Could not set %s's secret key\n", netname); 402 (void) fprintf(stderr, "May be the keyserv is down?\n"); 403 return (0); 404 } 405 406 return (1); 407 } 408 409 /* 410 * XXX unused routine. 411 * Can not locate any routine that is using this write_rootkey() 412 * function. There are 2 other write_rootkey() routines defined in chkey.c 413 * and in cmd/rpcsvc/nis/utils/nisaddcred/makedhextcred.c. 414 * 415 * write unencrypted secret key into root key file 416 */ 417 void 418 write_rootkey(char *secret) 419 { 420 char sbuf[HEXKEYBYTES+2]; 421 int fd, len; 422 423 strcpy(sbuf, secret); 424 strcat(sbuf, "\n"); 425 len = strlen(sbuf); 426 sbuf[len] = '\0'; 427 unlink(ROOTKEY_FILE); 428 if ((fd = open(ROOTKEY_FILE, O_WRONLY+O_CREAT, 0600)) != -1) { 429 write(fd, sbuf, len+1); 430 close(fd); 431 (void) fprintf(stdout, "Wrote secret key into %s\n", 432 ROOTKEY_FILE); 433 } else { 434 (void) fprintf(stderr, "Could not open %s for update\n", 435 ROOTKEY_FILE); 436 perror(ROOTKEY_FILE); 437 } 438 } 439 440 /* ****************************** nisplus stuff ************************* */ 441 /* most of it gotten from nisaddcred */ 442 443 444 /* Check that someone else don't have the same auth information already */ 445 static 446 nis_error 447 auth_exists(char *princname, char *auth_name, char *auth_type, char *domain) 448 { 449 char sname[NIS_MAXNAMELEN+MAXHOSTNAMELEN+64]; 450 nis_result *res; 451 nis_error status; 452 char *foundprinc; 453 454 (void) sprintf(sname, "[auth_name=%s,auth_type=%s],%s.%s", 455 auth_name, auth_type, CRED_TABLE, domain); 456 if (sname[strlen(sname)-1] != '.') 457 strcat(sname, "."); 458 /* Don't want FOLLOW_PATH here */ 459 res = nis_list(sname, 460 MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS, 461 NULL, NULL); 462 463 status = res->status; 464 switch (res->status) { 465 case NIS_NOTFOUND: 466 break; 467 case NIS_TRYAGAIN : 468 (void) fprintf(stderr, 469 "%s: NIS+ server busy, try again later.\n", 470 program_name); 471 exit(1); 472 case NIS_PERMISSION : 473 (void) fprintf(stderr, 474 "%s: insufficient permission to look up old credentials.\n", 475 program_name); 476 exit(1); 477 case NIS_SUCCESS: 478 foundprinc = ENTRY_VAL(res->objects.objects_val, 0); 479 if (nis_dir_cmp(foundprinc, princname) != SAME_NAME) { 480 (void) fprintf(stderr, 481 "%s: %s credentials with auth_name '%s' already belong to '%s'.\n", 482 program_name, auth_type, auth_name, foundprinc); 483 exit(1); 484 } 485 break; 486 default: 487 (void) fprintf(stderr, 488 "%s: error looking at cred table, NIS+ error: %s\n", 489 program_name, nis_sperrno(res->status)); 490 exit(1); 491 } 492 nis_freeresult(res); 493 return (status); 494 } 495 496 /* Returns 0 if check fails; 1 if successful. */ 497 static int 498 sanity_checks(nis_princ, netname, domain) 499 char *nis_princ, 500 *netname, 501 *domain; 502 { 503 char netdomainaux[MAXHOSTNAMELEN+1]; 504 char *princdomain, *netdomain; 505 int len; 506 507 /* Sanity check 0. Do we have a nis+ principal name to work with? */ 508 if (nis_princ == NULL) { 509 (void) fprintf(stderr, 510 "%s: you must create a \"LOCAL\" credential for '%s' first.\n", 511 program_name, netname); 512 (void) fprintf(stderr, "\tSee nisaddcred(1).\n"); 513 return (0); 514 } 515 516 /* Sanity check 0.5. NIS+ principal names must be dotted. */ 517 len = strlen(nis_princ); 518 if (nis_princ[len-1] != '.') { 519 (void) fprintf(stderr, 520 "%s: invalid principal name: '%s' (forgot ending dot?).\n", 521 program_name, nis_princ); 522 return (0); 523 } 524 525 /* Sanity check 1. We only deal with one type of netnames. */ 526 if (strncmp(netname, "unix", 4) != 0) { 527 (void) fprintf(stderr, 528 "%s: unrecognized netname type: '%s'.\n", 529 program_name, netname); 530 return (0); 531 } 532 533 /* Sanity check 2. Should only add DES cred in home domain. */ 534 princdomain = nis_domain_of(nis_princ); 535 if (strcasecmp(princdomain, domain) != 0) { 536 (void) fprintf(stderr, 537 "%s: domain of principal '%s' does not match destination domain '%s'.\n", 538 program_name, nis_princ, domain); 539 (void) fprintf(stderr, 540 "Should only add DES credential of principal in its home domain\n"); 541 return (0); 542 } 543 544 /* 545 * Sanity check 3: Make sure netname's domain same as principal's 546 * and don't have extraneous dot at the end. 547 */ 548 netdomain = (char *)strchr(netname, '@'); 549 if (! netdomain || netname[strlen(netname)-1] == '.') { 550 (void) fprintf(stderr, "%s: invalid netname: '%s'. \n", 551 program_name, netname); 552 return (0); 553 } 554 netdomain++; /* skip '@' */ 555 /* make sure we don't run into buffer overflow */ 556 if (strlen(netdomain) > sizeof (netdomainaux)) 557 return (0); 558 strcpy(netdomainaux, netdomain); 559 if (netdomainaux[strlen(netdomainaux)-1] != '.') 560 strcat(netdomainaux, "."); 561 562 if (strcasecmp(princdomain, netdomainaux) != 0) { 563 (void) fprintf(stderr, 564 "%s: domain of netname %s should be same as that of principal %s\n", 565 program_name, netname, nis_princ); 566 return (0); 567 } 568 569 /* Another principal owns same credentials? (exits if that happens) */ 570 (void) auth_exists(nis_princ, netname, "DES", domain); 571 572 return (1); /* all passed */ 573 } 574 575 576 /* 577 * Similar to nis_local_principal in "nis_subr.c" except 578 * this gets the results from the MASTER_ONLY and no FOLLOW_PATH. 579 * We only want the master because we'll be making updates there, 580 * and also the replicas may not have seen the 'nisaddacred local' 581 * that may have just occurred. 582 * Returns NULL if not found. 583 */ 584 char * 585 get_nisplus_principal(directory, uid) 586 char *directory; 587 uid_t uid; 588 { 589 nis_result *res; 590 char buf[NIS_MAXNAMELEN + 1]; 591 int status; 592 static char principal_name[NIS_MAXNAMELEN + 1]; 593 594 if (uid == 0) 595 return (nis_local_host()); 596 597 /* buf is enough to hold the string, no buffer overflow */ 598 (void) sprintf(buf, "[auth_name=%d,auth_type=LOCAL],%s.%s", 599 uid, CRED_TABLE, directory); 600 601 if (buf[strlen(buf)-1] != '.') 602 strcat(buf, "."); 603 604 res = nis_list(buf, 605 MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS, 606 NULL, NULL); 607 608 if (res == NULL) { 609 (void) fprintf(stderr, 610 "%s: unable to get result from NIS+ server.", 611 program_name); 612 exit(1); 613 } 614 switch (res->status) { 615 case NIS_SUCCESS: 616 if (res->objects.objects_len > 1) { 617 /* 618 * More than one principal with same uid? 619 * something wrong with cred table. Should be unique 620 * Warn user and continue. 621 */ 622 (void) fprintf(stderr, 623 "%s: LOCAL entry for %d in directory %s not unique", 624 program_name, uid, directory); 625 } 626 /* make sure we don't run into buffer overflow */ 627 if (strlen(ENTRY_VAL(res->objects.objects_val, 0)) > 628 sizeof (principal_name)) 629 return (NULL); 630 strcpy(principal_name, 631 ENTRY_VAL(res->objects.objects_val, 0)); 632 nis_freeresult(res); 633 return (principal_name); 634 635 case NIS_NOTFOUND: 636 nis_freeresult(res); 637 return (NULL); 638 639 case NIS_TRYAGAIN : 640 (void) fprintf(stderr, 641 "%s: NIS+ server busy, try again later.\n", 642 program_name); 643 exit(1); 644 645 case NIS_PERMISSION : 646 (void) fprintf(stderr, 647 "%s: insufficient permission to update credentials.\n", 648 program_name); 649 exit(1); 650 651 default: 652 (void) fprintf(stderr, 653 "%s: error talking to server, NIS+ error: %s.\n", 654 program_name, nis_sperrno(res->status)); 655 exit(1); 656 } 657 return (NULL); 658 } 659 660 661 662 /* Check whether this principal already has this type of credentials */ 663 static nis_error 664 cred_exists(char *nisprinc, char *flavor, char *domain) 665 { 666 char sname[NIS_MAXNAMELEN+MAXHOSTNAMELEN+64]; 667 nis_result *res; 668 nis_error status; 669 670 (void) sprintf(sname, "[cname=\"%s\",auth_type=%s],%s.%s", 671 nisprinc, flavor, CRED_TABLE, domain); 672 if (sname[strlen(sname)-1] != '.') 673 strcat(sname, "."); 674 675 /* Don't want FOLLOW_PATH here */ 676 res = nis_list(sname, 677 MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS, 678 NULL, NULL); 679 680 status = res->status; 681 switch (status) { 682 case NIS_NOTFOUND: 683 break; 684 case NIS_TRYAGAIN: 685 (void) fprintf(stderr, 686 "%s: NIS+ server busy, try again later.\n", 687 program_name); 688 exit(1); 689 case NIS_PERMISSION: 690 (void) fprintf(stderr, 691 "%s: insufficient permission to look at credentials table\n", 692 program_name); 693 exit(1); 694 case NIS_SUCCESS: 695 case NIS_S_SUCCESS: 696 break; 697 default: 698 (void) fprintf(stderr, 699 "%s: error looking at cred table, NIS+ error: %s\n", 700 program_name, nis_sperrno(res->status)); 701 exit(1); 702 } 703 nis_freeresult(res); 704 return (status); 705 } 706 707 708 /* Returns 0 if operation fails; 1 if successful. */ 709 static 710 int 711 modify_cred_obj(obj, domain) 712 char *domain; 713 nis_object *obj; 714 { 715 int status = 0; 716 char sname[NIS_MAXNAMELEN+1]; 717 nis_result *res; 718 719 (void) sprintf(sname, "%s.%s", CRED_TABLE, domain); 720 res = nis_modify_entry(sname, obj, 0); 721 switch (res->status) { 722 case NIS_TRYAGAIN : 723 (void) fprintf(stderr, 724 "%s: NIS+ server busy, try again later.\n", 725 program_name); 726 exit(1); 727 case NIS_PERMISSION : 728 (void) fprintf(stderr, 729 "%s: insufficient permission to update credentials.\n", 730 program_name); 731 exit(1); 732 case NIS_SUCCESS : 733 status = 1; 734 break; 735 default: 736 (void) fprintf(stderr, 737 "%s: error modifying credential, NIS+ error: %s.\n", 738 program_name, nis_sperrno(res->status)); 739 exit(1); 740 } 741 nis_freeresult(res); 742 return (status); 743 } 744 745 746 static 747 int 748 add_cred_obj(obj, domain) 749 char *domain; 750 nis_object *obj; 751 { 752 int status = 0; 753 char sname[NIS_MAXNAMELEN+1]; 754 nis_result *res; 755 756 /* Assume check for cred_exists performed already */ 757 758 (void) sprintf(sname, "%s.%s", CRED_TABLE, domain); 759 res = nis_add_entry(sname, obj, 0); 760 switch (res->status) { 761 case NIS_TRYAGAIN : 762 (void) fprintf(stderr, 763 "%s: NIS+ server busy, try again later.\n", 764 program_name); 765 exit(1); 766 case NIS_PERMISSION : 767 (void) fprintf(stderr, 768 "%s: insufficient permission to update credentials.\n", 769 program_name); 770 exit(1); 771 case NIS_SUCCESS : 772 status = 1; 773 break; 774 default: 775 (void) fprintf(stderr, 776 "%s: error creating credential, NIS+ error: %s.\n", 777 program_name, nis_sperrno(res->status)); 778 exit(1); 779 } 780 nis_freeresult(res); 781 return (status); 782 } 783 784 nis_object * 785 init_entry() 786 { 787 static nis_object obj; 788 static entry_col cred_data[10]; 789 entry_obj *eo; 790 791 memset((char *)(&obj), 0, sizeof (obj)); 792 memset((char *)(cred_data), 0, sizeof (entry_col) * 10); 793 794 obj.zo_name = "cred"; 795 obj.zo_group = ""; 796 obj.zo_ttl = 43200; 797 obj.zo_data.zo_type = NIS_ENTRY_OBJ; 798 eo = &(obj.EN_data); 799 eo->en_type = "cred_tbl"; 800 eo->en_cols.en_cols_val = cred_data; 801 eo->en_cols.en_cols_len = 5; 802 cred_data[4].ec_flags |= EN_CRYPT; 803 return (&obj); 804 } 805 806 807 static char *attrFilter[] = { 808 "objectclass", 809 "nispublickey", 810 "nissecretkey", 811 (char *)NULL 812 }; 813 814 815 /* Determines if there is a NisKeyObject objectclass in a given entry */ 816 static int 817 ldap_keyobj_exist(ns_ldap_entry_t *entry) 818 { 819 char **fattrs; 820 821 fattrs = __ns_ldap_getAttr(entry, "objectClass"); 822 823 if (fattrs == NULL) 824 return (1); 825 826 while (*fattrs) { 827 if (strcasecmp("NisKeyObject", *fattrs) == 0) 828 return (1); 829 fattrs++; 830 } 831 832 return (0); 833 } 834 835 836 static char *keyAttrs[] = { 837 "nispublickey", 838 "nissecretkey", 839 NULL 840 }; 841 842 /* 843 * Replace or append new attribute value(s) to an attribute. 844 * Don't care about memory leaks, because program is short running. 845 */ 846 847 static int 848 ldap_attr_mod(ns_ldap_entry_t *entry, 849 char *mechname, 850 char *public, 851 ns_ldap_attr_t **pkeyattrs, 852 char *crypt, 853 ns_ldap_attr_t **ckeyattrs) 854 { 855 char **alist[2]; 856 char *keys[2]; 857 858 char *mechfilter; 859 int mechfilterlen; 860 int q = 0; 861 int i, j; 862 int keycount[] = {0, 0}; 863 ns_ldap_attr_t *attrs; 864 865 keys[0] = public; 866 keys[1] = crypt; 867 868 mechfilter = (char *)malloc(strlen(mechname) + 3); 869 if (mechfilter == NULL) 870 return (0); 871 sprintf(mechfilter, "{%s}", mechname); 872 mechfilterlen = strlen(mechfilter); 873 874 for (q = 0; keyAttrs[q] != NULL; q++) { 875 int found = 0; 876 877 for (i = 0; i < entry->attr_count; i++) { 878 int rep = 0; 879 ns_ldap_attr_t *attr = entry->attr_pair[i]; 880 char *name = attr->attrname; 881 int count = 0; 882 883 if (strcasecmp(keyAttrs[q], name) == 0) { 884 found++; 885 count = attr->value_count; 886 alist[q] = (char **)malloc(sizeof (char *) * (count + 1)); 887 if (alist[q] == NULL) 888 return (0); 889 alist[q][attr->value_count] = NULL; 890 for (j = 0; j < attr->value_count; j++) { 891 char *val = attr->attrvalue[j]; 892 if (strncasecmp(val, mechfilter, 893 mechfilterlen) == 0) { 894 /* Replace entry */ 895 rep++; 896 alist[q][j] = keys[q]; 897 } else 898 alist[q][j] = val; 899 ++keycount[q]; 900 } 901 if (!rep) { 902 /* Add entry to list */ 903 alist[q] = (char **)realloc(alist[q], 904 sizeof (char *) * (count + 2)); 905 if (alist[q] == NULL) 906 return (0); 907 alist[q][attr->value_count + 1] = NULL; 908 alist[q][attr->value_count] = keys[q]; 909 ++keycount[q]; 910 } 911 } 912 } 913 if (!found) { 914 /* Attribute does not exist, add entry anyways */ 915 alist[q] = (char **)malloc(sizeof (char *) * 2); 916 if (alist[q] == NULL) 917 return (0); 918 alist[q][0] = keys[q]; 919 alist[q][1] = NULL; 920 ++keycount[q]; 921 } 922 } 923 if ((attrs = (ns_ldap_attr_t *)calloc(1, 924 sizeof (ns_ldap_attr_t))) == NULL) 925 return (0); 926 attrs->attrname = "nisPublicKey"; 927 attrs->attrvalue = alist[0]; 928 attrs->value_count = keycount[0]; 929 *pkeyattrs = attrs; 930 931 if ((attrs = (ns_ldap_attr_t *)calloc(1, 932 sizeof (ns_ldap_attr_t))) == NULL) 933 return (0); 934 attrs->attrname = "nisSecretKey"; 935 attrs->attrvalue = alist[1]; 936 attrs->value_count = keycount[1]; 937 *ckeyattrs = attrs; 938 return (1); 939 } 940 941 942 /* 943 * Do the actual Add or update of attributes in attrs. 944 * The parameter 'update4host' is a flag that tells the function which 945 * DN and password should be used to bind to ldap. If it is an update 946 * for a host (update4host > 0), the two parameters "bindDN" and 947 * "bindPasswd" would be used to bind as the directory manager, 948 * otherwise "dn" and "passwd" would be used to bind as an individual 949 * user. 950 */ 951 static void 952 update_ldap_attr(const char *dn, 953 ns_ldap_attr_t **attrs, 954 const char *passwd, 955 int add, 956 int update4host, 957 const char *bindDN, 958 const char *bindPasswd) 959 { 960 int ldaprc; 961 int authstried = 0; 962 char *msg; 963 char *ldap_pw; 964 char **certpath = NULL; 965 ns_auth_t **app; 966 ns_auth_t **authpp = NULL; 967 ns_auth_t *authp = NULL; 968 ns_cred_t *credp; 969 ns_ldap_error_t *errorp = NULL; 970 int status; 971 972 if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL) { 973 fprintf(stderr, "Can not allocate cred buffer.\n"); 974 goto out; 975 } 976 977 /* 978 * if this is an update for host, use the bindDN from the 979 * command prompt, otherwise use user's DN directly. 980 */ 981 if (update4host) 982 credp->cred.unix_cred.userID = strdup(bindDN); 983 else 984 credp->cred.unix_cred.userID = strdup(dn); 985 986 if (credp->cred.unix_cred.userID == NULL) { 987 fprintf(stderr, "Memory allocation failure (userID)\n"); 988 goto out; 989 } 990 991 if (update4host) { 992 credp->cred.unix_cred.passwd = strdup(bindPasswd); 993 } else { 994 if (passwd) 995 credp->cred.unix_cred.passwd = strdup(passwd); 996 else { 997 /* Make sure a valid password is received. */ 998 status = get_ldap_bindPassword(&ldap_pw); 999 1000 if (status != PROMPTGET_SUCCESS) { 1001 if (!ldap_pw) 1002 free(ldap_pw); 1003 goto out; 1004 } 1005 credp->cred.unix_cred.passwd = ldap_pw; 1006 } 1007 } 1008 1009 if (credp->cred.unix_cred.passwd == NULL) { 1010 fprintf(stderr, "Memory allocation failure (passwd)\n"); 1011 goto out; 1012 } 1013 1014 /* get host certificate path, if one is configured */ 1015 if (__ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P, 1016 (void ***)&certpath, &errorp) != NS_LDAP_SUCCESS) 1017 goto out; 1018 1019 if (certpath && *certpath) 1020 credp->hostcertpath = *certpath; 1021 1022 /* Load the service specific authentication method */ 1023 if (__ns_ldap_getServiceAuthMethods("keyserv", &authpp, &errorp) != 1024 NS_LDAP_SUCCESS) 1025 goto out; 1026 1027 /* 1028 * if authpp is null, there is no serviceAuthenticationMethod 1029 * try default authenticationMethod 1030 */ 1031 if (authpp == NULL) { 1032 if (__ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp, 1033 &errorp) != NS_LDAP_SUCCESS) 1034 goto out; 1035 } 1036 1037 /* 1038 * if authpp is still null, then can not authenticate, log 1039 * error message and return error 1040 */ 1041 if (authpp == NULL) { 1042 fprintf(stderr, "No LDAP authentication method configured.\n" 1043 " configured.\n"); 1044 goto out; 1045 } 1046 1047 /* 1048 * Walk the array and try all authentication methods in order except 1049 * for "none". 1050 */ 1051 for (app = authpp; *app; app++) { 1052 authp = *app; 1053 /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */ 1054 if (authp->type == NS_LDAP_AUTH_NONE) 1055 continue; 1056 authstried++; 1057 credp->auth.type = authp->type; 1058 credp->auth.tlstype = authp->tlstype; 1059 credp->auth.saslmech = authp->saslmech; 1060 credp->auth.saslopt = authp->saslopt; 1061 1062 if (add == TRUE) 1063 ldaprc = __ns_ldap_addAttr("publickey", dn, 1064 (const ns_ldap_attr_t * const *)attrs, 1065 credp, NULL, &errorp); 1066 else 1067 ldaprc = __ns_ldap_repAttr("publickey", dn, 1068 (const ns_ldap_attr_t * const *)attrs, 1069 credp, NULL, &errorp); 1070 if (ldaprc == NS_LDAP_SUCCESS) { 1071 /* clean up ns_cred_t structure in memory */ 1072 if (credp != NULL) 1073 (void) __ns_ldap_freeCred(&credp); 1074 return; 1075 } 1076 1077 /* XXX add checking for cases of authentication errors */ 1078 if ((ldaprc == NS_LDAP_INTERNAL) && 1079 ((errorp->status == LDAP_INAPPROPRIATE_AUTH) || 1080 (errorp->status == LDAP_INVALID_CREDENTIALS))) { 1081 fprintf(stderr, "LDAP authentication failed.\n"); 1082 goto out; 1083 } 1084 } 1085 if (authstried == 0) 1086 fprintf(stderr, "No legal authentication method configured.\n"); 1087 1088 out: 1089 /* clean up ns_cred_t structure in memory */ 1090 if (credp != NULL) { 1091 (void) __ns_ldap_freeCred(&credp); 1092 } 1093 1094 if (errorp) { 1095 __ns_ldap_err2str(errorp->status, &msg); 1096 fprintf(stderr, "LDAP error: %s.\n", msg); 1097 } 1098 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 1099 exit(1); 1100 } 1101 1102 1103 /* 1104 * Update LDAP nisplublickey entry with new key information via SLDAP. 1105 * Free and clean up memory that stores credential data soon after 1106 * they are not used or an error comes up. 1107 */ 1108 int 1109 ldap_update(char *mechname, 1110 char *netname, 1111 char *public, 1112 char *crypt, 1113 char *passwd) 1114 { 1115 char *netnamecpy; 1116 char *id; 1117 char *domain; 1118 char *dn; 1119 char *db; 1120 char *filter; 1121 ns_ldap_error_t *errorp; 1122 char *pkeyatval, *ckeyatval; 1123 ns_ldap_result_t *res; 1124 ns_ldap_attr_t *pattrs, *cattrs; 1125 int update4host = FALSE; 1126 char *bindDN = NULL; 1127 char *bindPasswd = NULL; 1128 int status; 1129 1130 /* Generate DN */ 1131 if ((netnamecpy = strdup(netname)) == NULL) 1132 return (0); 1133 if (((id = strchr(netnamecpy, '.')) == NULL) || 1134 ((domain = strchr(netnamecpy, '@')) == NULL)) 1135 return (0); 1136 else { 1137 *domain++ = '\0'; 1138 *id++ = '\0'; 1139 1140 id = strdup(id); 1141 if (id == NULL) { 1142 free(netnamecpy); 1143 fprintf(stderr, "LDAP memory error (id)\n"); 1144 return (0); 1145 } 1146 domain = strdup(domain); 1147 if (domain == NULL) { 1148 free(netnamecpy); 1149 free(id); 1150 fprintf(stderr, "LDAP memory error (domain)\n"); 1151 return (0); 1152 } 1153 free(netnamecpy); 1154 } 1155 1156 if (isdigit(*id)) { 1157 /* We be user. */ 1158 __ns_ldap_uid2dn(id, &dn, NULL, &errorp); 1159 if (dn == NULL) { 1160 fprintf(stderr, "Could not obtain LDAP dn\n"); 1161 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 1162 program_name); 1163 exit(1); 1164 } 1165 db = "passwd"; 1166 filter = (char *)malloc(strlen(id) + 13); 1167 if (filter) 1168 sprintf(filter, "(uidnumber=%s)", id); 1169 else { 1170 fprintf(stderr, "Can not allocate filter buffer.\n"); 1171 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 1172 program_name); 1173 exit(1); 1174 } 1175 } else { 1176 /* We be host. */ 1177 update4host = TRUE; 1178 1179 __ns_ldap_host2dn(id, NULL, &dn, NULL, &errorp); 1180 if (dn == NULL) { 1181 fprintf(stderr, "Could not obtain LDAP dn\n"); 1182 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 1183 program_name); 1184 exit(1); 1185 } 1186 1187 db = "hosts"; 1188 filter = (char *)malloc(strlen(id) + 6); 1189 if (filter) 1190 sprintf(filter, "(cn=%s)", id); 1191 else { 1192 fprintf(stderr, "Can not allocate filter buffer.\n"); 1193 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 1194 program_name); 1195 exit(1); 1196 } 1197 1198 /* Prompt for ldap bind DN for entry udpates */ 1199 status = get_ldap_bindDN(&bindDN); 1200 1201 if (status != PROMPTGET_SUCCESS) { 1202 FREE_CREDINFO(bindDN); 1203 fprintf(stderr, 1204 "Failed to get a valid LDAP bind DN.\n" 1205 "%s: key-pair(s) unchanged.\n", 1206 program_name); 1207 exit(1); 1208 } 1209 1210 /* Prompt for ldap bind password */ 1211 status = get_ldap_bindPassword(&bindPasswd); 1212 1213 if (status != PROMPTGET_SUCCESS) { 1214 FREE_CREDINFO(bindPasswd); 1215 FREE_CREDINFO(bindDN); 1216 1217 fprintf(stderr, 1218 "Failed to get a valid LDAP bind password." 1219 "\n%s: key-pair(s) unchanged.\n", 1220 program_name); 1221 exit(1); 1222 } 1223 } 1224 1225 /* Construct attribute values */ 1226 pkeyatval = (char *)malloc(strlen(mechname) + strlen(public) + 3); 1227 if (pkeyatval == NULL) { 1228 FREE_CREDINFO(bindPasswd); 1229 FREE_CREDINFO(bindDN); 1230 fprintf(stderr, "LDAP memory error (pkeyatval)\n"); 1231 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 1232 exit(1); 1233 } 1234 sprintf(pkeyatval, "{%s}%s", mechname, public); 1235 ckeyatval = (char *)malloc(strlen(mechname) + strlen(crypt) + 3); 1236 if (ckeyatval == NULL) { 1237 FREE_CREDINFO(pkeyatval); 1238 FREE_CREDINFO(bindPasswd); 1239 FREE_CREDINFO(bindDN); 1240 fprintf(stderr, "LDAP memory error (pkeyatval)\n"); 1241 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 1242 exit(1); 1243 } 1244 sprintf(ckeyatval, "{%s}%s", mechname, crypt); 1245 1246 /* Does entry exist? */ 1247 if ((__ns_ldap_list(db, filter, NULL, (const char **)attrFilter, 1248 NULL, 0, &res, &errorp, 1249 NULL, NULL) == NS_LDAP_SUCCESS) && res == NULL) { 1250 FREE_CREDINFO(ckeyatval); 1251 FREE_CREDINFO(pkeyatval); 1252 FREE_CREDINFO(bindPasswd); 1253 FREE_CREDINFO(bindDN); 1254 fprintf(stderr, "LDAP entry does not exist.\n"); 1255 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 1256 exit(1); 1257 } 1258 1259 /* Entry exists, modify attributes for public and secret keys */ 1260 1261 /* Is there a NisKeyObject in entry? */ 1262 if (!ldap_keyobj_exist(&res->entry[0])) { 1263 /* Add NisKeyObject objectclass and the keys */ 1264 char **newattr; 1265 ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */ 1266 1267 /* set objectclass */ 1268 newattr = (char **)calloc(2, sizeof (char *)); 1269 newattr[0] = "NisKeyObject"; 1270 newattr[1] = NULL; 1271 if ((attrs[0] = (ns_ldap_attr_t *)calloc(1, 1272 sizeof (ns_ldap_attr_t))) == NULL) { 1273 FREE_CREDINFO(ckeyatval); 1274 FREE_CREDINFO(pkeyatval); 1275 FREE_CREDINFO(bindPasswd); 1276 FREE_CREDINFO(bindDN); 1277 fprintf(stderr, "Memory allocation failed\n"); 1278 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 1279 program_name); 1280 exit(1); 1281 } 1282 attrs[0]->attrname = "objectClass"; 1283 attrs[0]->attrvalue = newattr; 1284 attrs[0]->value_count = 1; 1285 1286 /* set publickey */ 1287 newattr = (char **)calloc(2, sizeof (char *)); 1288 newattr[0] = pkeyatval; 1289 newattr[1] = NULL; 1290 if ((attrs[1] = (ns_ldap_attr_t *)calloc(1, 1291 sizeof (ns_ldap_attr_t))) == NULL) { 1292 FREE_CREDINFO(ckeyatval); 1293 FREE_CREDINFO(pkeyatval); 1294 FREE_CREDINFO(bindPasswd); 1295 FREE_CREDINFO(bindDN); 1296 fprintf(stderr, "Memory allocation failed\n"); 1297 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 1298 program_name); 1299 exit(1); 1300 } 1301 attrs[1]->attrname = "nisPublicKey"; 1302 attrs[1]->attrvalue = newattr; 1303 attrs[1]->value_count = 1; 1304 1305 /* set privatekey */ 1306 newattr = (char **)calloc(2, sizeof (char *)); 1307 newattr[0] = ckeyatval; 1308 newattr[1] = NULL; 1309 if ((attrs[2] = (ns_ldap_attr_t *)calloc(1, 1310 sizeof (ns_ldap_attr_t))) == NULL) { 1311 FREE_CREDINFO(ckeyatval); 1312 FREE_CREDINFO(pkeyatval); 1313 FREE_CREDINFO(bindPasswd); 1314 FREE_CREDINFO(bindDN); 1315 fprintf(stderr, "Memory allocation failed\n"); 1316 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 1317 program_name); 1318 exit(1); 1319 } 1320 attrs[2]->attrname = "nisSecretKey"; 1321 attrs[2]->attrvalue = newattr; 1322 attrs[2]->value_count = 1; 1323 1324 /* terminator */ 1325 attrs[3] = NULL; 1326 1327 update_ldap_attr(dn, attrs, passwd, TRUE, update4host, 1328 bindDN, bindPasswd); 1329 } else { 1330 /* object class already exists, replace keys */ 1331 ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */ 1332 1333 if (!ldap_attr_mod(&res->entry[0], mechname, 1334 pkeyatval, &pattrs, 1335 ckeyatval, &cattrs)) { 1336 FREE_CREDINFO(ckeyatval); 1337 FREE_CREDINFO(pkeyatval); 1338 FREE_CREDINFO(bindPasswd); 1339 FREE_CREDINFO(bindDN); 1340 fprintf(stderr, 1341 "Could not generate LDAP attribute list.\n"); 1342 fprintf(stderr, 1343 "%s: key-pair(s) unchanged.\n", program_name); 1344 exit(1); 1345 } 1346 1347 attrs[0] = pattrs; 1348 attrs[1] = cattrs; 1349 attrs[2] = NULL; 1350 1351 update_ldap_attr(dn, attrs, passwd, FALSE, update4host, 1352 bindDN, bindPasswd); 1353 } 1354 1355 FREE_CREDINFO(ckeyatval); 1356 FREE_CREDINFO(pkeyatval); 1357 FREE_CREDINFO(bindPasswd); 1358 FREE_CREDINFO(bindDN); 1359 1360 return (0); 1361 } 1362 1363 1364 /* Returns 0 if successful; -1 if failure. (expected by setpublicmap). */ 1365 1366 int 1367 nisplus_update(char *netname, char *public, char *secret, nis_name nis_princ) 1368 { 1369 nis_object *obj = init_entry(); 1370 char *domain, *netdomain; 1371 char netdomainaux[MAXHOSTNAMELEN + 1]; 1372 int status, addition; 1373 1374 /* 1375 * we take the domain given in the netname & the principal 1376 * name if they match otherwise the local domain. 1377 */ 1378 1379 netdomain = (char *)strchr(netname, '@'); 1380 if (! netdomain) { 1381 (void) fprintf(stderr, "%s: invalid netname: '%s'. \n", 1382 program_name, netname); 1383 return (0); 1384 } 1385 netdomain++; /* skip '@' */ 1386 /* make sure we don't run into buffer overflow */ 1387 if (strlen(netdomain) > sizeof (netdomainaux)) 1388 return (0); 1389 strcpy(netdomainaux, netdomain); 1390 if (netdomainaux[strlen(netdomainaux) - 1] != '.') 1391 strcat(netdomainaux, "."); 1392 1393 domain = nis_domain_of(nis_princ); 1394 if (strcasecmp(domain, netdomainaux) != 0) 1395 domain = nis_local_directory(); 1396 1397 if (sanity_checks(nis_princ, netname, domain) == 0) 1398 return (-1); 1399 1400 addition = (cred_exists(nis_princ, "DES", domain) == NIS_NOTFOUND); 1401 1402 /* Now we have a key pair, build up the cred entry */ 1403 ENTRY_VAL(obj, 0) = nis_princ; 1404 ENTRY_LEN(obj, 0) = strlen(nis_princ) + 1; 1405 1406 ENTRY_VAL(obj, 1) = "DES"; 1407 ENTRY_LEN(obj, 1) = 4; 1408 1409 ENTRY_VAL(obj, 2) = netname; 1410 ENTRY_LEN(obj, 2) = strlen(netname) + 1; 1411 1412 ENTRY_VAL(obj, 3) = public; 1413 ENTRY_LEN(obj, 3) = strlen(public) + 1; 1414 1415 ENTRY_VAL(obj, 4) = secret; 1416 ENTRY_LEN(obj, 4) = strlen(secret) + 1; 1417 1418 if (addition) { 1419 obj->zo_owner = nis_princ; 1420 obj->zo_group = nis_local_group(); 1421 obj->zo_domain = domain; 1422 /* owner: r, group: rmcd */ 1423 obj->zo_access = ((NIS_READ_ACC<<16)| 1424 (NIS_READ_ACC|NIS_MODIFY_ACC|NIS_CREATE_ACC| 1425 NIS_DESTROY_ACC)<<8); 1426 status = add_cred_obj(obj, domain); 1427 } else { 1428 obj->EN_data.en_cols.en_cols_val[3].ec_flags |= EN_MODIFIED; 1429 obj->EN_data.en_cols.en_cols_val[4].ec_flags |= EN_MODIFIED; 1430 status = modify_cred_obj(obj, domain); 1431 } 1432 1433 return (status == 1 ? 0 : -1); 1434 } 1435