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