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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * ldapaddent.c 27 * 28 * Utility to add /etc files into LDAP. 29 * Can also be used to dump entries from a ldap container in /etc format. 30 */ 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <libintl.h> 35 #include <strings.h> 36 #include <sys/param.h> 37 #include <ctype.h> 38 #include <sys/types.h> 39 #include <sys/socket.h> 40 #include <netinet/in.h> 41 #include <arpa/inet.h> 42 #include <locale.h> 43 #include <syslog.h> 44 45 #undef opaque 46 47 #include <nss_dbdefs.h> 48 #include <netdb.h> 49 #include <rpc/rpcent.h> 50 #include <grp.h> 51 #include <pwd.h> 52 #include <project.h> 53 #include <shadow.h> 54 #include <sys/systeminfo.h> 55 #include "ns_internal.h" 56 #include "ldapaddent.h" 57 #include "standalone.h" 58 59 #define OP_ADD 0 60 #define OP_DUMP 3 61 62 static struct ttypelist_t { 63 char *ttype; /* type tag */ 64 int (*genent)(char *, int(*)()); 65 /* routine to turn line into ldap entries */ 66 void (*dump)(ns_ldap_result_t *); 67 /* routine to print ldap containers */ 68 int (*filedbmline)(); /* routine to turn file line into dbm line */ 69 char *objclass; /* Objectclass for the servicetype */ 70 char *sortattr; /* Sort attr for enumeration */ 71 } *tt; 72 73 char parse_err_msg [PARSE_ERR_MSG_LEN]; 74 int continue_onerror = 0; /* do not exit on error */ 75 76 static int get_basedn(char *service, char **basedn); 77 static int check_ipaddr(char *addr, char **newaddr); 78 static int check_projname(char *addr); 79 80 extern int optind; 81 extern char *optarg; 82 83 extern char *__nis_quote_key(const char *, char *, int); 84 85 static char *inputbasedn = NULL; 86 static char *databasetype = NULL; 87 static int exit_val = 0; 88 static unsigned nent_add = 0; 89 static FILE *etcf = 0; 90 static ns_cred_t authority; 91 unsigned flags = 0; 92 93 static void 94 perr(ns_ldap_error_t *e) 95 { 96 if (e) 97 (void) fprintf(stderr, "%d: %s\n", 98 e->status, e->message); 99 } 100 101 102 static int 103 ascii_to_int(char *str) 104 { 105 int i; 106 char *c = str; 107 108 if (c == NULL || *c == '\0') 109 return (-1); 110 111 while (c != '\0' && *c == ' ') 112 c++; 113 if (*c == '\0') 114 return (-1); 115 116 for (i = 0; i < strlen(c); i++) 117 if (!isdigit(c[i])) 118 return (-1); 119 120 return (atoi(c)); 121 } 122 123 /* 124 * Internet network address interpretation routine. 125 * The library routines call this routine to interpret 126 * network numbers. 127 */ 128 static in_addr_t 129 encode_network(const char *cp) 130 { 131 in_addr_t val; 132 int base; 133 ptrdiff_t n; 134 char c; 135 in_addr_t parts[4], *pp = parts; 136 int i; 137 138 again: 139 val = 0; base = 10; 140 if (*cp == '0') { 141 if (*++cp == 'x' || *cp == 'X') 142 base = 16, cp++; 143 else 144 base = 8; 145 } 146 while ((c = *cp) != NULL) { 147 if (isdigit(c)) { 148 if ((c - '0') >= base) 149 break; 150 val = (val * base) + (c - '0'); 151 cp++; 152 continue; 153 } 154 if (base == 16 && isxdigit(c)) { 155 val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); 156 cp++; 157 continue; 158 } 159 break; 160 } 161 if (*cp == '.') { 162 if (pp >= parts + 4) 163 return ((in_addr_t)-1); 164 *pp++ = val, cp++; 165 goto again; 166 } 167 if (*cp && !isspace(*cp)) 168 return ((in_addr_t)-1); 169 *pp++ = val; 170 n = pp - parts; 171 if (n > 4) 172 return ((in_addr_t)-1); 173 for (val = 0, i = 0; i < n; i++) { 174 val <<= 8; 175 val |= parts[i] & 0xff; 176 } 177 for (/* no init */; i < 4; i++) 178 val <<= 8; 179 return (val); 180 } 181 182 static void 183 replace_tab2space(char *str) 184 { 185 int i = 0; 186 187 while ((str) && (str[i])) { 188 if (str[i] == '\t') 189 str[i] = ' '; 190 i++; 191 } 192 } 193 194 static int 195 blankline(char *line) 196 { 197 char *p; 198 199 for (p = line; *p; p++) 200 if (*p != ' ' && *p != '\t') 201 return (0); 202 return (1); 203 } 204 205 /* 206 * check whether the token <tok> is a triplet, 207 * i. e. <tok> := (<hostname>,<username>,<domainname>) 208 * where <hostname>, <username>, <domainname> are IA5String 209 * <tok> supposes to contain NO spaces and start with '(' 210 */ 211 static int 212 is_triplet(char *tok) 213 { 214 char *s; 215 return (strchr(++tok, '(') == NULL && /* no more '(' */ 216 (s = strchr(tok, ')')) != NULL && /* find ')' */ 217 !*++s && /* ')' ends token */ 218 (tok = strchr(tok, ',')) != NULL && /* host up to ',' */ 219 (tok = strchr(++tok, ',')) != NULL && /* user up to ',' */ 220 strchr(++tok, ',') == NULL); /* no more ',' */ 221 } 222 223 static void 224 line_buf_expand(struct line_buf *line) 225 { 226 line->alloc += BUFSIZ; 227 line->str = (char *)realloc(line->str, line->alloc); 228 229 if (line->str == NULL) { 230 (void) fprintf(stderr, 231 gettext("line_buf_expand: out of memory\n")); 232 exit(1); 233 } 234 } 235 236 static void 237 line_buf_init(struct line_buf *line) 238 { 239 (void) memset((char *)line, 0, sizeof (*line)); 240 line_buf_expand(line); 241 } 242 243 static int 244 __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value) 245 { 246 ns_ldap_attr_t *a; 247 char *v; 248 249 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); 250 if (a == NULL) 251 return (NS_LDAP_MEMORY); 252 a->attrname = strdup(attrname); 253 if (a->attrname == NULL) { 254 free(a); 255 return (NS_LDAP_MEMORY); 256 } 257 a->attrvalue = (char **)calloc(1, sizeof (char **)); 258 if (a->attrvalue == NULL) { 259 free(a->attrname); 260 free(a); 261 return (NS_LDAP_MEMORY); 262 } 263 a->value_count = 1; 264 a->attrvalue[0] = NULL; 265 v = strdup(value); 266 if (v == NULL) { 267 free(a->attrname); 268 free(a->attrvalue); 269 free(a); 270 return (NS_LDAP_MEMORY); 271 } 272 a->attrvalue[0] = v; 273 e->attr_pair[e->attr_count] = a; 274 e->attr_count++; 275 return (NS_LDAP_SUCCESS); 276 } 277 278 static int 279 __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv) 280 { 281 ns_ldap_attr_t *a; 282 char *v; 283 char **av; 284 int i, j; 285 286 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); 287 if (a == NULL) 288 return (NS_LDAP_MEMORY); 289 a->attrname = strdup(attrname); 290 if (a->attrname == NULL) { 291 free(a); 292 return (NS_LDAP_MEMORY); 293 } 294 295 for (i = 0, av = argv; *av != NULL; av++, i++) 296 ; 297 298 a->attrvalue = (char **)calloc(i, sizeof (char **)); 299 300 if (a->attrvalue == NULL) { 301 free(a->attrname); 302 free(a); 303 return (NS_LDAP_MEMORY); 304 } 305 a->value_count = i; 306 for (j = 0; j < i; j++) { 307 v = strdup(argv[j]); 308 if (v == NULL) { 309 free(a->attrname); 310 free(a->attrvalue); 311 free(a); 312 return (NS_LDAP_MEMORY); 313 } 314 a->attrvalue[j] = v; 315 } 316 e->attr_pair[e->attr_count] = a; 317 e->attr_count++; 318 return (NS_LDAP_SUCCESS); 319 } 320 321 static ns_ldap_entry_t * 322 __s_mk_entry(char **objclass, int max_attr) 323 { 324 ns_ldap_entry_t *e; 325 e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t)); 326 if (e == NULL) 327 return (NULL); 328 e->attr_pair = (ns_ldap_attr_t **)calloc(max_attr+1, 329 sizeof (ns_ldap_attr_t *)); 330 if (e->attr_pair == NULL) { 331 free(e); 332 return (NULL); 333 } 334 e->attr_count = 0; 335 if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) { 336 free(e->attr_pair); 337 free(e); 338 return (NULL); 339 } 340 return (e); 341 } 342 343 static void 344 ldap_freeEntry(ns_ldap_entry_t *ep) 345 { 346 int j, k = 0; 347 348 if (ep == NULL) 349 return; 350 351 if (ep->attr_pair == NULL) { 352 free(ep); 353 return; 354 } 355 for (j = 0; j < ep->attr_count; j++) { 356 if (ep->attr_pair[j] == NULL) 357 continue; 358 if (ep->attr_pair[j]->attrname) 359 free(ep->attr_pair[j]->attrname); 360 if (ep->attr_pair[j]->attrvalue) { 361 for (k = 0; (k < ep->attr_pair[j]->value_count) && 362 (ep->attr_pair[j]->attrvalue[k]); k++) { 363 free(ep->attr_pair[j]->attrvalue[k]); 364 } 365 free(ep->attr_pair[j]->attrvalue); 366 } 367 free(ep->attr_pair[j]); 368 } 369 free(ep->attr_pair); 370 free(ep); 371 } 372 373 static int 374 addentry(void *entry, int mod) 375 { 376 int result = 0; 377 ns_ldap_error_t *eres = NULL; 378 int rc = 1; 379 380 381 /* adds entry into the LDAP tree */ 382 if (mod) 383 result = __ns_ldap_addTypedEntry(databasetype, inputbasedn, 384 entry, 0, &authority, NS_LDAP_FOLLOWREF | NS_LDAP_KEEP_CONN, 385 &eres); 386 else 387 result = __ns_ldap_addTypedEntry(databasetype, inputbasedn, 388 entry, 1, &authority, NS_LDAP_FOLLOWREF | NS_LDAP_KEEP_CONN, 389 &eres); 390 /* 391 * Return 0 on success 392 * LDAP_ALREADY_EXISTS if entry exists already 393 * 1 for all other non-fatal errors. 394 * Exit on fatal errors. 395 */ 396 switch (result) { 397 case NS_LDAP_SUCCESS: 398 nent_add++; 399 rc = 0; 400 break; 401 402 case NS_LDAP_OP_FAILED: 403 (void) fprintf(stderr, gettext("operation failed.\n")); 404 rc = 1; 405 break; 406 407 case NS_LDAP_INVALID_PARAM: 408 (void) fprintf(stderr, 409 gettext("invalid parameter(s) passed.\n")); 410 rc = 1; 411 break; 412 413 case NS_LDAP_NOTFOUND: 414 (void) fprintf(stderr, gettext("entry not found.\n")); 415 rc = 1; 416 break; 417 418 case NS_LDAP_MEMORY: 419 (void) fprintf(stderr, 420 gettext("internal memory allocation error.\n")); 421 exit(1); 422 break; 423 424 case NS_LDAP_CONFIG: 425 (void) fprintf(stderr, 426 gettext("LDAP Configuration problem.\n")); 427 perr(eres); 428 exit(1); 429 break; 430 431 case NS_LDAP_PARTIAL: 432 (void) fprintf(stderr, 433 gettext("partial result returned\n")); 434 perr(eres); 435 rc = 1; 436 break; 437 438 case NS_LDAP_INTERNAL: 439 if (eres->status == LDAP_ALREADY_EXISTS || 440 eres->status == LDAP_NO_SUCH_OBJECT) 441 rc = eres->status; 442 else if (eres->status == LDAP_INSUFFICIENT_ACCESS) { 443 (void) fprintf(stderr, 444 gettext("The user does not have permission" 445 " to add/modify entries\n")); 446 perr(eres); 447 exit(1); 448 } else { 449 rc = 1; 450 perr(eres); 451 } 452 break; 453 } 454 455 if (eres) 456 (void) __ns_ldap_freeError(&eres); 457 return (rc); 458 } 459 460 /* 461 * usage(char *msg) 462 * Display usage message to STDERR. 463 */ 464 static void 465 usage(char *msg) { 466 467 if (msg) 468 (void) fprintf(stderr, "%s\n", msg); 469 470 (void) fprintf(stderr, gettext( 471 "usage: ldapaddent [-cpv] [-a authenticationMethod] [-b baseDN]\n" 472 "-D bindDN [-w bindPassword] [-j passwdFile] [-f filename]\n" 473 "database\n" 474 "\n" 475 "usage: ldapaddent [-cpv] -asasl/GSSAPI [-b baseDN] [-f filename]\n" 476 "database\n" 477 "\n" 478 "usage: ldapaddent -d [-v] [-a authenticationMethod] [-D bindDN]\n" 479 "[-w bindPassword] [-j passwdFile] database\n" 480 "\n" 481 "usage: ldapaddent [-cpv] -h LDAP_server[:serverPort] [-M domainName]\n" 482 "[-N profileName] [-P certifPath] [-a authenticationMethod]\n" 483 "[-b baseDN] -D bindDN [-w bindPassword] [-f filename]\n" 484 "[-j passwdFile] database\n" 485 "\n" 486 "usage: ldapaddent [-cpv] -h LDAP_server[:serverPort] [-M domainName]\n" 487 "[-N profileName] [-P certifPath] -asasl/GSSAPI [-b baseDN]\n" 488 "[-f filename] database\n" 489 "\n" 490 "usage: ldapaddent -d [-v] -h LDAP_server[:serverPort]" 491 " [-M domainName]\n" 492 "[-N profileName] [-P certifPath] [-a authenticationMethod]\n" 493 "[-b baseDN] -D bindDN [-w bindPassword] [-j passwdFile]\n" 494 "database\n")); 495 exit(1); 496 } 497 498 /* 499 * Determine if the given string is an IP address (IPv4 or IPv6). 500 * If so, it's converted to the preferred form (rfc2373) and 501 * *newaddr will point to the new address. 502 * 503 * Returns -2 : inet_ntop error 504 * -1 : not an IP address 505 * 0 : unsupported IP address (future use) 506 * AF_INET : IPv4 507 * AF_INET6 : IPv6 508 */ 509 static int 510 check_ipaddr(char *addr, char **newaddr) { 511 ipaddr_t addr_ipv4 = 0; 512 in6_addr_t addr_ipv6; 513 514 /* IPv6 */ 515 if (inet_pton(AF_INET6, addr, &addr_ipv6) == 1) { 516 if (newaddr == NULL) 517 return (AF_INET6); 518 519 /* Convert IPv4-mapped IPv6 address to IPv4 */ 520 if (IN6_IS_ADDR_V4MAPPED(&addr_ipv6) || 521 IN6_IS_ADDR_V4COMPAT(&addr_ipv6)) { 522 IN6_V4MAPPED_TO_IPADDR(&addr_ipv6, addr_ipv4); 523 if ((*newaddr = calloc(1, INET_ADDRSTRLEN)) == NULL) { 524 (void) fprintf(stderr, 525 gettext("out of memory\n")); 526 exit(1); 527 } 528 if (inet_ntop(AF_INET, &addr_ipv4, *newaddr, 529 INET_ADDRSTRLEN)) 530 return (AF_INET6); 531 free(*newaddr); 532 return (-2); 533 } 534 535 /* Processing general IPv6 addresses */ 536 if ((*newaddr = calloc(1, INET6_ADDRSTRLEN)) == NULL) { 537 (void) fprintf(stderr, gettext("out of memory\n")); 538 exit(1); 539 } 540 if (inet_ntop(AF_INET6, &addr_ipv6, *newaddr, INET6_ADDRSTRLEN)) 541 return (AF_INET6); 542 free(*newaddr); 543 return (-2); 544 } 545 546 /* Processing IPv4 addresses of the type d.d.d.d. */ 547 if (inet_pton(AF_INET, addr, &addr_ipv4) == 1) { 548 if (newaddr == NULL) 549 return (AF_INET); 550 if ((*newaddr = calloc(1, INET_ADDRSTRLEN)) == NULL) { 551 (void) fprintf(stderr, gettext("out of memory\n")); 552 exit(1); 553 } 554 if (inet_ntop(AF_INET, &addr_ipv4, *newaddr, INET_ADDRSTRLEN)) 555 return (AF_INET); 556 free(*newaddr); 557 return (-2); 558 } 559 560 /* Processing IPv4 addresses d.d.d , d.d and d */ 561 if (inet_addr(addr) != (in_addr_t)-1) { 562 if (newaddr == NULL) 563 return (AF_INET); 564 if ((*newaddr = strdup(addr)) == NULL) { 565 (void) fprintf(stderr, gettext("out of memory\n")); 566 exit(1); 567 } 568 return (AF_INET); 569 } 570 571 return (-1); 572 } 573 574 /* 575 * Verifies that project name meets the restrictions defined by project(4). 576 */ 577 static int 578 check_projname(char *addr) 579 { 580 int i; 581 if (addr == NULL || *addr == '\0') 582 return (-1); 583 584 for (i = 0; i < strlen(addr); i++) { 585 if (!isalpha(addr[i]) && 586 !isdigit(addr[i]) && 587 addr[i] != '_' && 588 addr[i] != '-' && 589 addr[i] != '.') 590 return (-1); 591 } 592 593 return (0); 594 } 595 596 static int 597 genent_hosts(char *line, int (*cback)()) 598 { 599 char buf[BUFSIZ+1]; 600 char *t, *comment; 601 entry_col ecol[4]; 602 char *cname, *pref_addr; 603 int ctr = 0, retval = 1; 604 int rc = GENENT_OK, af; 605 606 struct hostent data; 607 char *alias; 608 609 /* 610 * don't clobber our argument 611 */ 612 if (strlen(line) >= sizeof (buf)) { 613 (void) strlcpy(parse_err_msg, gettext("line too long"), 614 PARSE_ERR_MSG_LEN); 615 return (GENENT_PARSEERR); 616 } 617 (void) strcpy(buf, line); 618 619 /* 620 * clear column data 621 */ 622 (void) memset((char *)ecol, 0, sizeof (ecol)); 623 624 /* 625 * comment (col 3) 626 * All leading spaces will be deleted from the comment 627 */ 628 ecol[3].ec_value.ec_value_val = ""; 629 ecol[3].ec_value.ec_value_len = 0; 630 comment = t = strchr(buf, '#'); 631 if (comment) { 632 do { 633 ++comment; 634 } while (*comment != '\0' && isspace(*comment)); 635 if (*comment != '\0') { 636 *--comment = '#'; 637 ecol[3].ec_value.ec_value_val = strdup(comment); 638 ecol[3].ec_value.ec_value_len = strlen(comment)+1; 639 } 640 641 *t = '\0'; 642 } 643 644 /* 645 * addr(col 2) 646 */ 647 if ((t = strtok(buf, " \t")) == 0) { 648 (void) strlcpy(parse_err_msg, gettext("no host"), 649 PARSE_ERR_MSG_LEN); 650 return (GENENT_PARSEERR); 651 } 652 653 af = check_ipaddr(t, &pref_addr); 654 if (af == -2) { 655 (void) strlcpy(parse_err_msg, gettext("Internal error"), 656 PARSE_ERR_MSG_LEN); 657 } else if (af == -1) { 658 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 659 gettext("Invalid IP address: %s"), t); 660 } else if (flags & F_VERBOSE) { 661 if ((strncasecmp(t, pref_addr, strlen(t))) != 0) { 662 (void) fprintf(stdout, 663 gettext("IP address %s converted to %s\n"), 664 t, pref_addr); 665 } 666 } 667 668 if (af < 0) { 669 (void) fprintf(stderr, "%s\n", parse_err_msg); 670 if (continue_onerror == 0) 671 return (GENENT_CBERR); 672 else 673 return (rc); 674 } 675 676 ecol[2].ec_value.ec_value_val = pref_addr; 677 ecol[2].ec_value.ec_value_len = strlen(pref_addr)+1; 678 679 /* 680 * cname (col 0) 681 */ 682 if ((t = strtok(NULL, " \t")) == 0) { 683 (void) strlcpy(parse_err_msg, gettext("no cname"), 684 PARSE_ERR_MSG_LEN); 685 return (GENENT_PARSEERR); 686 } 687 ecol[0].ec_value.ec_value_val = t; 688 ecol[0].ec_value.ec_value_len = strlen(t)+1; 689 cname = t; 690 691 692 /* build entry */ 693 if ((data.h_addr_list = (char **)calloc(2, sizeof (char **))) == NULL) { 694 (void) fprintf(stderr, gettext("out of memory\n")); 695 exit(1); 696 } 697 data.h_addr_list[0] = strdup(ecol[2].ec_value.ec_value_val); 698 data.h_addr_list[1] = NULL; 699 700 free(pref_addr); 701 data.h_name = strdup(ecol[0].ec_value.ec_value_val); 702 703 /* 704 * name (col 1) 705 */ 706 707 data.h_aliases = NULL; 708 709 do { 710 /* 711 * don't clobber comment in canonical entry 712 */ 713 714 /* This call to AddEntry may move out of the loop */ 715 /* This is because we have to call the function just once */ 716 if (t != cname && strcasecmp(t, cname) == 0) 717 continue; 718 if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) 719 continue; 720 721 ecol[1].ec_value.ec_value_val = t; 722 ecol[1].ec_value.ec_value_len = strlen(t)+1; 723 724 ctr++; 725 alias = strdup(ecol[1].ec_value.ec_value_val); 726 if ((data.h_aliases = (char **)realloc(data.h_aliases, 727 ctr * sizeof (char **))) == NULL) { 728 (void) fprintf(stderr, gettext("out of memory\n")); 729 exit(1); 730 } 731 data.h_aliases[ctr-1] = alias; 732 } while (t = strtok(NULL, " \t")); 733 734 /* 735 * End the list of all the aliases by NULL 736 * If there is some comment, it will be stored as the last entry 737 * in the list of the host aliases 738 */ 739 if ((data.h_aliases = (char **)realloc(data.h_aliases, 740 (ecol[3].ec_value.ec_value_len != 0 ? 741 ctr + 2 : ctr + 1) * sizeof (char **))) == NULL) { 742 (void) fprintf(stderr, gettext("out of memory\n")); 743 exit(1); 744 } 745 746 if (ecol[3].ec_value.ec_value_len != 0) { 747 data.h_aliases[ctr++] = ecol[3].ec_value.ec_value_val; 748 } 749 data.h_aliases[ctr] = NULL; 750 751 if (flags & F_VERBOSE) 752 (void) fprintf(stdout, 753 gettext("Adding entry : cn=%s+ipHostNumber=%s\n"), 754 data.h_name, data.h_addr_list[0]); 755 756 retval = (*cback)(&data, 0); 757 758 if (ecol[3].ec_value.ec_value_len != 0) { 759 free(ecol[3].ec_value.ec_value_val); 760 } 761 762 if (retval == LDAP_ALREADY_EXISTS) { 763 if (continue_onerror) 764 (void) fprintf(stderr, 765 gettext("Entry: cn=%s+ipHostNumber=%s " 766 "already Exists -skipping it\n"), 767 data.h_name, data.h_addr_list[0]); 768 else { 769 rc = GENENT_CBERR; 770 (void) fprintf(stderr, 771 gettext("Entry: cn=%s+ipHostNumber=%s" 772 " already Exists\n"), 773 data.h_name, data.h_addr_list[0]); 774 } 775 } else if (retval) 776 rc = GENENT_CBERR; 777 778 free(data.h_name); 779 free(data.h_aliases); 780 free(data.h_addr_list); 781 782 return (rc); 783 } 784 785 786 787 static void 788 dump_hosts(ns_ldap_result_t *res) 789 { 790 ns_ldap_attr_t *attrptr = NULL, 791 *cn = NULL, 792 *iphostnumber = NULL, 793 *desc = NULL; 794 int i, j; 795 char *name; /* host name */ 796 797 if (res == NULL || res->entry == NULL) 798 return; 799 for (i = 0; i < res->entry->attr_count; i++) { 800 attrptr = res->entry->attr_pair[i]; 801 if (strcasecmp(attrptr->attrname, "cn") == 0) 802 cn = attrptr; 803 else if (strcasecmp(attrptr->attrname, "iphostnumber") == 0) 804 iphostnumber = attrptr; 805 else if (strcasecmp(attrptr->attrname, "description") == 0) { 806 desc = attrptr; 807 } 808 } 809 /* sanity check */ 810 if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL || 811 iphostnumber == NULL || iphostnumber->attrvalue == NULL || 812 iphostnumber->attrvalue[0] == NULL) 813 return; 814 815 if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL) 816 return; 817 818 /* ip host/ipnode number */ 819 if (strlen(iphostnumber->attrvalue[0]) <= INET_ADDRSTRLEN) 820 /* IPV4 or IPV6 but <= NET_ADDRSTRLEN */ 821 (void) fprintf(stdout, "%-18s", iphostnumber->attrvalue[0]); 822 else 823 /* IPV6 */ 824 (void) fprintf(stdout, "%-48s", iphostnumber->attrvalue[0]); 825 826 /* host/ipnode name */ 827 (void) fprintf(stdout, "%s ", name); 828 829 /* aliases */ 830 for (j = 0; j < cn->value_count; j++) { 831 if (cn->attrvalue[j]) { 832 if (strcasecmp(name, cn->attrvalue[j]) == 0) 833 /* skip host name */ 834 continue; 835 (void) fprintf(stdout, "%s ", cn->attrvalue[j]); 836 } 837 } 838 839 /* description */ 840 if (desc != NULL && desc->attrvalue != NULL && 841 desc->attrvalue[0] != NULL) { 842 (void) fprintf(stdout, "#%s", desc->attrvalue[0]); 843 } 844 845 /* end of line */ 846 (void) fprintf(stdout, "\n"); 847 } 848 849 /* 850 * /etc/rpc 851 */ 852 853 static int 854 genent_rpc(char *line, int (*cback)()) 855 { 856 char buf[BUFSIZ+1]; 857 char *t; 858 entry_col ecol[4]; 859 char *cname; 860 861 struct rpcent data; 862 char *alias; 863 int ctr = 0; 864 int retval = 1; 865 int rc = GENENT_OK; 866 867 /* 868 * don't clobber our argument 869 */ 870 if (strlen(line) >= sizeof (buf)) { 871 (void) strlcpy(parse_err_msg, gettext("line too long"), 872 PARSE_ERR_MSG_LEN); 873 return (GENENT_PARSEERR); 874 } 875 (void) strcpy(buf, line); 876 877 /* 878 * clear column data 879 */ 880 (void) memset((char *)ecol, 0, sizeof (ecol)); 881 882 /* 883 * comment (col 3) 884 */ 885 t = strchr(buf, '#'); 886 if (t) { 887 *t++ = 0; 888 ecol[3].ec_value.ec_value_val = t; 889 ecol[3].ec_value.ec_value_len = strlen(t)+1; 890 } else { 891 ecol[3].ec_value.ec_value_val = 0; 892 ecol[3].ec_value.ec_value_len = 0; 893 } 894 895 /* 896 * cname(col 0) 897 */ 898 if ((t = strtok(buf, " \t")) == 0) { 899 (void) strlcpy(parse_err_msg, gettext("no number"), 900 PARSE_ERR_MSG_LEN); 901 return (GENENT_PARSEERR); 902 } 903 ecol[0].ec_value.ec_value_val = t; 904 ecol[0].ec_value.ec_value_len = strlen(t)+1; 905 cname = t; 906 907 /* 908 * number (col 2) 909 */ 910 if ((t = strtok(NULL, " \t")) == 0) { 911 (void) strlcpy(parse_err_msg, gettext("no number"), 912 PARSE_ERR_MSG_LEN); 913 return (GENENT_PARSEERR); 914 } 915 ecol[2].ec_value.ec_value_val = t; 916 ecol[2].ec_value.ec_value_len = strlen(t)+1; 917 918 919 /* 920 * build entry 921 */ 922 923 data.r_name = strdup(ecol[0].ec_value.ec_value_val); 924 if (ecol[2].ec_value.ec_value_val != NULL && 925 ecol[2].ec_value.ec_value_val[0] != '\0') { 926 927 data.r_number = ascii_to_int(ecol[2].ec_value.ec_value_val); 928 if (data.r_number == -1) { 929 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 930 gettext("invalid program number: %s"), 931 ecol[2].ec_value.ec_value_val); 932 return (GENENT_PARSEERR); 933 } 934 } else 935 data.r_number = -1; 936 937 /* 938 * name (col 1) 939 */ 940 t = cname; 941 data.r_aliases = NULL; 942 do { 943 944 /* 945 * don't clobber comment in canonical entry 946 */ 947 if (t != cname && strcasecmp(t, cname) == 0) 948 continue; 949 if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) 950 continue; 951 952 ecol[1].ec_value.ec_value_val = t; 953 ecol[1].ec_value.ec_value_len = strlen(t)+1; 954 955 ctr++; 956 alias = strdup(ecol[1].ec_value.ec_value_val); 957 if ((data.r_aliases = (char **)realloc(data.r_aliases, 958 ctr * sizeof (char **))) == NULL) { 959 (void) fprintf(stderr, gettext("out of memory\n")); 960 exit(1); 961 } 962 data.r_aliases[ctr-1] = alias; 963 964 965 /* 966 * only put comment in canonical entry 967 */ 968 ecol[3].ec_value.ec_value_val = 0; 969 ecol[3].ec_value.ec_value_len = 0; 970 971 } while (t = strtok(NULL, " \t")); 972 973 /* End the list of all the aliases by NULL */ 974 if ((data.r_aliases = (char **)realloc(data.r_aliases, 975 (ctr + 1) * sizeof (char **))) == NULL) { 976 (void) fprintf(stderr, gettext("out of memory\n")); 977 exit(1); 978 } 979 data.r_aliases[ctr] = NULL; 980 981 if (flags & F_VERBOSE) 982 (void) fprintf(stdout, 983 gettext("Adding entry : %s\n"), data.r_name); 984 985 retval = (*cback)(&data, 0); 986 987 if (retval == LDAP_ALREADY_EXISTS) { 988 if (continue_onerror) 989 (void) fprintf(stderr, 990 gettext("Entry: %s - already Exists," 991 " skipping it.\n"), data.r_name); 992 else { 993 rc = GENENT_CBERR; 994 (void) fprintf(stderr, 995 gettext("Entry: %s - already Exists\n"), 996 data.r_name); 997 } 998 } else if (retval) 999 rc = GENENT_CBERR; 1000 1001 free(data.r_name); 1002 free(data.r_aliases); 1003 1004 return (rc); 1005 } 1006 1007 1008 1009 static void 1010 dump_rpc(ns_ldap_result_t *res) 1011 { 1012 ns_ldap_attr_t *attrptr = NULL, *cn = NULL, *rpcnumber = NULL; 1013 int i, j; 1014 char *name; /* rpc name */ 1015 1016 if (res == NULL || res->entry == NULL) 1017 return; 1018 for (i = 0; i < res->entry->attr_count; i++) { 1019 attrptr = res->entry->attr_pair[i]; 1020 if (strcasecmp(attrptr->attrname, "cn") == 0) 1021 cn = attrptr; 1022 else if (strcasecmp(attrptr->attrname, "oncRpcNumber") == 0) 1023 rpcnumber = attrptr; 1024 } 1025 /* sanity check */ 1026 if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL || 1027 rpcnumber == NULL || rpcnumber->attrvalue == NULL || 1028 rpcnumber->attrvalue[0] == NULL) 1029 return; 1030 1031 if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL) 1032 return; 1033 1034 /* rpc name */ 1035 if (strlen(name) < 8) 1036 (void) fprintf(stdout, "%s\t\t", name); 1037 else 1038 (void) fprintf(stdout, "%s\t", name); 1039 1040 /* rpc number */ 1041 (void) fprintf(stdout, "%-8s", rpcnumber->attrvalue[0]); 1042 1043 1044 /* aliases */ 1045 for (j = 0; j < cn->value_count; j++) { 1046 if (cn->attrvalue[j]) { 1047 if (strcasecmp(name, cn->attrvalue[j]) == 0) 1048 /* skip rpc name */ 1049 continue; 1050 (void) fprintf(stdout, "%s ", cn->attrvalue[j]); 1051 } 1052 } 1053 1054 /* end of line */ 1055 (void) fprintf(stdout, "\n"); 1056 1057 } 1058 1059 /* 1060 * /etc/protocols 1061 * 1062 */ 1063 1064 static int 1065 genent_protocols(char *line, int (*cback)()) 1066 { 1067 char buf[BUFSIZ+1]; 1068 char *t; 1069 entry_col ecol[4]; 1070 char *cname; 1071 1072 struct protoent data; 1073 char *alias; 1074 int ctr = 0; 1075 int retval = 1; 1076 int rc = GENENT_OK; 1077 1078 /* 1079 * don't clobber our argument 1080 */ 1081 if (strlen(line) >= sizeof (buf)) { 1082 (void) strlcpy(parse_err_msg, gettext("line too long"), 1083 PARSE_ERR_MSG_LEN); 1084 return (GENENT_PARSEERR); 1085 } 1086 (void) strcpy(buf, line); 1087 1088 /* 1089 * clear column data 1090 */ 1091 (void) memset((char *)ecol, 0, sizeof (ecol)); 1092 1093 /* 1094 * comment (col 3) 1095 */ 1096 t = strchr(buf, '#'); 1097 if (t) { 1098 *t++ = 0; 1099 ecol[3].ec_value.ec_value_val = t; 1100 ecol[3].ec_value.ec_value_len = strlen(t)+1; 1101 } else { 1102 ecol[3].ec_value.ec_value_val = 0; 1103 ecol[3].ec_value.ec_value_len = 0; 1104 } 1105 1106 /* 1107 * cname(col 0) 1108 */ 1109 if ((t = strtok(buf, " \t")) == 0) { 1110 (void) strlcpy(parse_err_msg, gettext("no number"), 1111 PARSE_ERR_MSG_LEN); 1112 return (GENENT_PARSEERR); 1113 } 1114 ecol[0].ec_value.ec_value_val = t; 1115 ecol[0].ec_value.ec_value_len = strlen(t)+1; 1116 cname = t; 1117 1118 /* 1119 * number (col 2) 1120 */ 1121 if ((t = strtok(NULL, " \t")) == 0) { 1122 (void) strlcpy(parse_err_msg, gettext("no number"), 1123 PARSE_ERR_MSG_LEN); 1124 return (GENENT_PARSEERR); 1125 } 1126 ecol[2].ec_value.ec_value_val = t; 1127 ecol[2].ec_value.ec_value_len = strlen(t)+1; 1128 1129 1130 /* 1131 * build entry 1132 */ 1133 data.p_name = strdup(ecol[0].ec_value.ec_value_val); 1134 1135 if (ecol[2].ec_value.ec_value_val != NULL && 1136 ecol[2].ec_value.ec_value_val[0] != '\0') { 1137 1138 data.p_proto = ascii_to_int(ecol[2].ec_value.ec_value_val); 1139 if (data.p_proto == -1) { 1140 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 1141 gettext("invalid protocol number: %s"), 1142 ecol[2].ec_value.ec_value_val); 1143 return (GENENT_PARSEERR); 1144 } 1145 } else 1146 data.p_proto = -1; 1147 1148 /* 1149 * name (col 1) 1150 */ 1151 t = cname; 1152 ctr = 0; 1153 data.p_aliases = NULL; 1154 1155 do { 1156 /* 1157 * don't clobber comment in canonical entry 1158 */ 1159 if (t != cname && strcasecmp(t, cname) == 0) 1160 continue; 1161 if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) 1162 continue; 1163 1164 ecol[1].ec_value.ec_value_val = t; 1165 ecol[1].ec_value.ec_value_len = strlen(t)+1; 1166 1167 ctr++; 1168 alias = strdup(ecol[1].ec_value.ec_value_val); 1169 if ((data.p_aliases = (char **)realloc(data.p_aliases, 1170 ctr * sizeof (char **))) == NULL) { 1171 (void) fprintf(stderr, gettext("out of memory\n")); 1172 exit(1); 1173 } 1174 data.p_aliases[ctr-1] = alias; 1175 1176 /* 1177 * only put comment in canonical entry 1178 */ 1179 ecol[3].ec_value.ec_value_val = 0; 1180 ecol[3].ec_value.ec_value_len = 0; 1181 1182 } while (t = strtok(NULL, " \t")); 1183 1184 /* End the list of all the aliases by NULL */ 1185 if ((data.p_aliases = (char **)realloc(data.p_aliases, 1186 (ctr + 1) * sizeof (char **))) == NULL) { 1187 (void) fprintf(stderr, gettext("out of memory\n")); 1188 exit(1); 1189 } 1190 data.p_aliases[ctr] = NULL; 1191 1192 if (flags & F_VERBOSE) 1193 (void) fprintf(stdout, 1194 gettext("Adding entry : %s\n"), data.p_name); 1195 1196 retval = (*cback)(&data, 0); 1197 1198 if (retval == LDAP_ALREADY_EXISTS) { 1199 if (continue_onerror) 1200 (void) fprintf(stderr, 1201 gettext("Entry: %s - already Exists," 1202 " skipping it.\n"), data.p_name); 1203 else { 1204 rc = GENENT_CBERR; 1205 (void) fprintf(stderr, 1206 gettext("Entry: %s - already Exists\n"), 1207 data.p_name); 1208 } 1209 } else if (retval) 1210 rc = GENENT_CBERR; 1211 1212 free(data.p_name); 1213 free(data.p_aliases); 1214 1215 return (rc); 1216 } 1217 1218 1219 static void 1220 dump_protocols(ns_ldap_result_t *res) 1221 { 1222 ns_ldap_attr_t *attrptr = NULL, *cn = NULL, *protocolnumber = NULL; 1223 int i, j; 1224 char *name, *cp; 1225 1226 if (res == NULL || res->entry == NULL) 1227 return; 1228 for (i = 0; i < res->entry->attr_count; i++) { 1229 attrptr = res->entry->attr_pair[i]; 1230 if (strcasecmp(attrptr->attrname, "cn") == 0) 1231 cn = attrptr; 1232 else if (strcasecmp(attrptr->attrname, "ipProtocolNumber") 1233 == 0) 1234 protocolnumber = attrptr; 1235 } 1236 /* sanity check */ 1237 if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL || 1238 protocolnumber == NULL || protocolnumber->attrvalue == NULL || 1239 protocolnumber->attrvalue[0] == NULL) 1240 return; 1241 1242 if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL) 1243 return; 1244 1245 /* protocol name */ 1246 if (strlen(name) < 8) 1247 (void) fprintf(stdout, "%s\t\t", name); 1248 else 1249 (void) fprintf(stdout, "%s\t", name); 1250 1251 /* protocol number */ 1252 (void) fprintf(stdout, "%-16s", protocolnumber->attrvalue[0]); 1253 1254 /* aliases */ 1255 for (j = 0; j < cn->value_count; j++) { 1256 if (cn->attrvalue[j]) { 1257 if (strcasecmp(name, cn->attrvalue[j]) == 0) { 1258 if (cn->value_count > 1) 1259 /* Do not replicate */ 1260 continue; 1261 /* 1262 * Replicate name in uppercase as an aliase 1263 */ 1264 for (cp = cn->attrvalue[j]; *cp; cp++) 1265 *cp = toupper(*cp); 1266 } 1267 (void) fprintf(stdout, "%s ", cn->attrvalue[j]); 1268 } 1269 } 1270 1271 /* end of line */ 1272 (void) fprintf(stdout, "\n"); 1273 1274 } 1275 1276 1277 1278 1279 1280 /* 1281 * /etc/networks 1282 * 1283 */ 1284 1285 static int 1286 genent_networks(char *line, int (*cback)()) 1287 { 1288 char buf[BUFSIZ+1]; 1289 char *t; 1290 entry_col ecol[4]; 1291 char *cname; 1292 1293 struct netent data; 1294 char *alias; 1295 int ctr = 0; 1296 int retval = 1; 1297 int enet; 1298 int rc = GENENT_OK; 1299 1300 /* 1301 * don't clobber our argument 1302 */ 1303 if (strlen(line) >= sizeof (buf)) { 1304 (void) strlcpy(parse_err_msg, gettext("line too long"), 1305 PARSE_ERR_MSG_LEN); 1306 return (GENENT_PARSEERR); 1307 } 1308 (void) strcpy(buf, line); 1309 1310 /* 1311 * clear column data 1312 */ 1313 (void) memset((char *)ecol, 0, sizeof (ecol)); 1314 1315 /* 1316 * comment (col 3) 1317 */ 1318 t = strchr(buf, '#'); 1319 if (t) { 1320 *t++ = 0; 1321 ecol[3].ec_value.ec_value_val = t; 1322 ecol[3].ec_value.ec_value_len = strlen(t)+1; 1323 } else { 1324 ecol[3].ec_value.ec_value_val = 0; 1325 ecol[3].ec_value.ec_value_len = 0; 1326 } 1327 1328 /* 1329 * cname(col 0) 1330 */ 1331 if ((t = strtok(buf, " \t")) == 0) { 1332 (void) strlcpy(parse_err_msg, gettext("no number"), 1333 PARSE_ERR_MSG_LEN); 1334 return (GENENT_PARSEERR); 1335 } 1336 ecol[0].ec_value.ec_value_val = t; 1337 ecol[0].ec_value.ec_value_len = strlen(t)+1; 1338 cname = t; 1339 1340 /* 1341 * number (col 2) 1342 */ 1343 if ((t = strtok(NULL, " \t")) == 0) { 1344 (void) strlcpy(parse_err_msg, gettext("no number"), 1345 PARSE_ERR_MSG_LEN); 1346 return (GENENT_PARSEERR); 1347 } 1348 ecol[2].ec_value.ec_value_val = t; 1349 ecol[2].ec_value.ec_value_len = strlen(t)+1; 1350 1351 1352 /* 1353 * build entry 1354 */ 1355 1356 data.n_name = strdup(ecol[0].ec_value.ec_value_val); 1357 /* 1358 * data.n_net is an unsigned field, 1359 * assign -1 to it, make no sense. 1360 * Use enet here to avoid lint warning. 1361 */ 1362 enet = encode_network(ecol[2].ec_value.ec_value_val); 1363 1364 if (enet == -1 && continue_onerror == 0) { 1365 (void) fprintf(stderr, gettext("Invalid network number\n")); 1366 if (continue_onerror == 0) 1367 return (GENENT_CBERR); 1368 } else 1369 data.n_net = enet; 1370 1371 /* 1372 * name (col 1) 1373 */ 1374 t = cname; 1375 data.n_aliases = NULL; 1376 1377 do { 1378 /* 1379 * don't clobber comment in canonical entry 1380 */ 1381 if (t != cname && strcasecmp(t, cname) == 0) 1382 continue; 1383 if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) 1384 continue; 1385 1386 ecol[1].ec_value.ec_value_val = t; 1387 ecol[1].ec_value.ec_value_len = strlen(t)+1; 1388 1389 ctr++; 1390 alias = strdup(ecol[1].ec_value.ec_value_val); 1391 if ((data.n_aliases = (char **)realloc(data.n_aliases, 1392 ctr * sizeof (char **))) == NULL) { 1393 (void) fprintf(stderr, gettext("out of memory\n")); 1394 exit(1); 1395 } 1396 data.n_aliases[ctr-1] = alias; 1397 1398 /* 1399 * only put comment in canonical entry 1400 */ 1401 ecol[3].ec_value.ec_value_val = 0; 1402 ecol[3].ec_value.ec_value_len = 0; 1403 1404 } while (t = strtok(NULL, " \t")); 1405 1406 /* End the list of all the aliases by NULL */ 1407 if ((data.n_aliases = (char **)realloc(data.n_aliases, 1408 (ctr + 1) * sizeof (char **))) == NULL) { 1409 (void) fprintf(stderr, gettext("out of memory\n")); 1410 exit(1); 1411 } 1412 data.n_aliases[ctr] = NULL; 1413 1414 if (flags & F_VERBOSE) 1415 (void) fprintf(stdout, 1416 gettext("Adding entry : %s\n"), data.n_name); 1417 1418 retval = (*cback)(&data, 0); 1419 1420 if (retval == LDAP_ALREADY_EXISTS) { 1421 if (continue_onerror) 1422 (void) fprintf(stderr, 1423 gettext("Entry: %s - already Exists," 1424 " skipping it.\n"), data.n_name); 1425 else { 1426 rc = GENENT_CBERR; 1427 (void) fprintf(stderr, 1428 gettext("Entry: %s - already Exists\n"), 1429 data.n_name); 1430 } 1431 } else if (retval) 1432 rc = GENENT_CBERR; 1433 1434 free(data.n_name); 1435 free(data.n_aliases); 1436 1437 return (rc); 1438 } 1439 1440 1441 static void 1442 dump_networks(ns_ldap_result_t *res) 1443 { 1444 ns_ldap_attr_t *attrptr = NULL, *cn = NULL, *networknumber = NULL; 1445 int i, j; 1446 char *name; 1447 1448 if (res == NULL || res->entry == NULL) 1449 return; 1450 for (i = 0; i < res->entry->attr_count; i++) { 1451 attrptr = res->entry->attr_pair[i]; 1452 if (strcasecmp(attrptr->attrname, "cn") == 0) 1453 cn = attrptr; 1454 else if (strcasecmp(attrptr->attrname, "ipNetworkNumber") 1455 == 0) 1456 networknumber = attrptr; 1457 } 1458 /* sanity check */ 1459 if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL || 1460 networknumber == NULL || networknumber->attrvalue == NULL || 1461 networknumber->attrvalue[0] == NULL) 1462 return; 1463 1464 /* 1465 * cn can be a MUST attribute(RFC 2307) or MAY attribute(2307bis). 1466 * If the canonical name can not be found (2307bis), use the 1st 1467 * value as the official name. 1468 */ 1469 1470 /* network name */ 1471 if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL) 1472 name = cn->attrvalue[0]; 1473 1474 if (strlen(name) < 8) 1475 (void) fprintf(stdout, "%s\t\t", name); 1476 else 1477 (void) fprintf(stdout, "%s\t", name); 1478 1479 /* network number */ 1480 (void) fprintf(stdout, "%-16s", networknumber->attrvalue[0]); 1481 1482 /* aliases */ 1483 for (j = 0; j < cn->value_count; j++) { 1484 if (cn->attrvalue[j]) { 1485 if (strcasecmp(name, cn->attrvalue[j]) == 0) 1486 /* skip name */ 1487 continue; 1488 (void) fprintf(stdout, "%s ", cn->attrvalue[j]); 1489 } 1490 } 1491 1492 /* end of line */ 1493 (void) fprintf(stdout, "\n"); 1494 1495 } 1496 1497 1498 1499 1500 /* 1501 * /etc/services 1502 * 1503 */ 1504 1505 static int 1506 genent_services(char *line, int (*cback)()) 1507 { 1508 char buf[BUFSIZ+1]; 1509 char *t, *p; 1510 entry_col ecol[5]; 1511 char *cname; 1512 1513 struct servent data; 1514 char *alias; 1515 int ctr = 0; 1516 int retval = 1; 1517 int rc = GENENT_OK; 1518 1519 /* 1520 * don't clobber our argument 1521 */ 1522 if (strlen(line) >= sizeof (buf)) { 1523 (void) strlcpy(parse_err_msg, gettext("line too long"), 1524 PARSE_ERR_MSG_LEN); 1525 return (GENENT_PARSEERR); 1526 } 1527 (void) strcpy(buf, line); 1528 1529 /* 1530 * clear column data 1531 */ 1532 (void) memset((char *)ecol, 0, sizeof (ecol)); 1533 1534 /* 1535 * comment (col 4) 1536 */ 1537 t = strchr(buf, '#'); 1538 if (t) { 1539 *t++ = 0; 1540 ecol[4].ec_value.ec_value_val = t; 1541 ecol[4].ec_value.ec_value_len = strlen(t)+1; 1542 } else { 1543 ecol[4].ec_value.ec_value_val = 0; 1544 ecol[4].ec_value.ec_value_len = 0; 1545 } 1546 1547 /* 1548 * cname(col 0) 1549 */ 1550 if ((t = strtok(buf, " \t")) == 0) { 1551 (void) strlcpy(parse_err_msg, gettext("no port"), 1552 PARSE_ERR_MSG_LEN); 1553 return (GENENT_PARSEERR); 1554 } 1555 ecol[0].ec_value.ec_value_val = t; 1556 ecol[0].ec_value.ec_value_len = strlen(t)+1; 1557 cname = t; 1558 1559 /* 1560 * port (col 3) 1561 */ 1562 if ((t = strtok(NULL, " \t")) == 0) { 1563 (void) strlcpy(parse_err_msg, gettext("no protocol"), 1564 PARSE_ERR_MSG_LEN); 1565 return (GENENT_PARSEERR); 1566 } 1567 if ((p = strchr(t, '/')) == 0) { 1568 (void) strlcpy(parse_err_msg, gettext("bad port/proto"), 1569 PARSE_ERR_MSG_LEN); 1570 return (GENENT_PARSEERR); 1571 } 1572 *(p++) = 0; 1573 ecol[3].ec_value.ec_value_val = t; 1574 ecol[3].ec_value.ec_value_len = strlen(t)+1; 1575 1576 /* 1577 * proto (col 2) 1578 */ 1579 ecol[2].ec_value.ec_value_val = p; 1580 ecol[2].ec_value.ec_value_len = strlen(p)+1; 1581 1582 1583 /* 1584 * build entry 1585 */ 1586 1587 data.s_name = strdup(ecol[0].ec_value.ec_value_val); 1588 data.s_proto = strdup(ecol[2].ec_value.ec_value_val); 1589 1590 if (ecol[3].ec_value.ec_value_val != NULL && 1591 ecol[3].ec_value.ec_value_val[0] != '\0') { 1592 1593 data.s_port = ascii_to_int(ecol[3].ec_value.ec_value_val); 1594 if (data.s_port == -1) { 1595 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 1596 gettext("invalid port number: %s"), 1597 ecol[3].ec_value.ec_value_val); 1598 return (GENENT_PARSEERR); 1599 } 1600 } else 1601 data.s_port = -1; 1602 1603 /* 1604 * name (col 1) 1605 */ 1606 t = cname; 1607 data.s_aliases = NULL; 1608 1609 do { 1610 /* 1611 * don't clobber comment in canonical entry 1612 */ 1613 if (t != cname && strcasecmp(t, cname) == 0) 1614 continue; 1615 if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) 1616 continue; 1617 1618 ecol[1].ec_value.ec_value_val = t; 1619 ecol[1].ec_value.ec_value_len = strlen(t)+1; 1620 1621 ctr++; 1622 alias = strdup(ecol[1].ec_value.ec_value_val); 1623 if ((data.s_aliases = (char **)realloc(data.s_aliases, 1624 ctr * sizeof (char **))) == NULL) { 1625 (void) fprintf(stderr, gettext("out of memory\n")); 1626 exit(1); 1627 } 1628 data.s_aliases[ctr-1] = alias; 1629 1630 /* 1631 * only put comment in canonical entry 1632 */ 1633 ecol[4].ec_value.ec_value_val = 0; 1634 ecol[4].ec_value.ec_value_len = 0; 1635 1636 } while (t = strtok(NULL, " \t")); 1637 1638 /* End the list of all the aliases by NULL */ 1639 if ((data.s_aliases = (char **)realloc(data.s_aliases, 1640 (ctr + 1) * sizeof (char **))) == NULL) { 1641 (void) fprintf(stderr, gettext("out of memory\n")); 1642 exit(1); 1643 } 1644 data.s_aliases[ctr] = NULL; 1645 1646 if (flags & F_VERBOSE) 1647 (void) fprintf(stdout, 1648 gettext("Adding entry : %s\n"), line); 1649 1650 retval = (*cback)(&data, 0); 1651 1652 if (retval == LDAP_ALREADY_EXISTS) { 1653 if (continue_onerror) 1654 (void) fprintf(stderr, gettext( 1655 "Entry: cn=%s+ipServiceProtocol=%s" 1656 " already Exists, skipping it.\n"), 1657 data.s_name, data.s_proto); 1658 else { 1659 rc = GENENT_CBERR; 1660 (void) fprintf(stderr, 1661 gettext("Entry: cn=%s+ipServiceProtocol=%s" 1662 " - already Exists\n"), 1663 data.s_name, data.s_proto); 1664 } 1665 } else if (retval) 1666 rc = GENENT_CBERR; 1667 1668 free(data.s_name); 1669 free(data.s_proto); 1670 free(data.s_aliases); 1671 1672 return (rc); 1673 } 1674 1675 1676 1677 static void 1678 dump_services(ns_ldap_result_t *res) 1679 { 1680 ns_ldap_attr_t *attrptr = NULL, *cn = NULL, *port = NULL; 1681 ns_ldap_attr_t *protocol = NULL; 1682 int i, j, len; 1683 char *name; /* service name */ 1684 1685 /* 1686 * cn can have multiple values.(service name and its aliases) 1687 * In order to support RFC 2307, section 5.5, ipserviceprotocol can 1688 * have multiple values too. 1689 * The output format should look like 1690 * 1691 * test 2345/udp mytest 1692 * test 2345/tcp mytest 1693 */ 1694 if (res == NULL || res->entry == NULL) 1695 return; 1696 for (i = 0; i < res->entry->attr_count; i++) { 1697 attrptr = res->entry->attr_pair[i]; 1698 if (strcasecmp(attrptr->attrname, "cn") == 0) 1699 cn = attrptr; 1700 else if (strcasecmp(attrptr->attrname, "ipServicePort") == 0) 1701 port = attrptr; 1702 else if (strcasecmp(attrptr->attrname, 1703 "ipServiceProtocol") == 0) 1704 protocol = attrptr; 1705 } 1706 /* sanity check */ 1707 if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL || 1708 port == NULL || port->attrvalue == NULL || 1709 port->attrvalue[0] == NULL || protocol == NULL || 1710 protocol->attrvalue == NULL || protocol->attrvalue[0] == NULL) 1711 return; 1712 1713 if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL) 1714 return; 1715 for (i = 0; i < protocol->value_count; i++) { 1716 if (protocol->attrvalue[i] == NULL) 1717 return; 1718 /* service name */ 1719 (void) fprintf(stdout, "%-16s", name); 1720 1721 /* port & protocol */ 1722 (void) fprintf(stdout, "%s/%s%n", port->attrvalue[0], 1723 protocol->attrvalue[i], &len); 1724 1725 if (len < 8) 1726 (void) fprintf(stdout, "\t\t"); 1727 else 1728 (void) fprintf(stdout, "\t"); 1729 1730 /* aliases */ 1731 for (j = 0; j < cn->value_count; j++) { 1732 if (cn->attrvalue[j]) { 1733 if (strcasecmp(name, cn->attrvalue[j]) == 0) 1734 /* skip service name */ 1735 continue; 1736 (void) fprintf(stdout, "%s ", cn->attrvalue[j]); 1737 } 1738 } 1739 1740 /* end of line */ 1741 (void) fprintf(stdout, "\n"); 1742 } 1743 } 1744 1745 1746 /* 1747 * /etc/group 1748 */ 1749 1750 static int 1751 genent_group(char *line, int (*cback)()) 1752 { 1753 char buf[BIGBUF+1]; 1754 char *s, *t; 1755 entry_col ecol[5]; 1756 1757 struct group data; 1758 int ctr = 0; 1759 int retval = 1; 1760 int rc = GENENT_OK; 1761 1762 /* 1763 * don't clobber our argument 1764 */ 1765 if (strlen(line) >= sizeof (buf)) { 1766 (void) strlcpy(parse_err_msg, gettext("line too long"), 1767 PARSE_ERR_MSG_LEN); 1768 return (GENENT_PARSEERR); 1769 } 1770 (void) strcpy(buf, line); 1771 t = buf; 1772 1773 /* ignore empty entries */ 1774 if (*t == '\0') 1775 return (GENENT_OK); 1776 1777 /* 1778 * clear column data 1779 */ 1780 (void) memset((char *)ecol, 0, sizeof (ecol)); 1781 1782 /* 1783 * name (col 0) 1784 */ 1785 if ((s = strchr(t, ':')) == 0) { 1786 (void) strlcpy(parse_err_msg, gettext("no passwd"), 1787 PARSE_ERR_MSG_LEN); 1788 return (GENENT_PARSEERR); 1789 } 1790 *s++ = 0; 1791 ecol[0].ec_value.ec_value_val = t; 1792 ecol[0].ec_value.ec_value_len = strlen(t)+1; 1793 t = s; 1794 1795 /* 1796 * passwd (col 1) 1797 */ 1798 if ((s = strchr(t, ':')) == 0) { 1799 (void) strlcpy(parse_err_msg, gettext("no gid"), 1800 PARSE_ERR_MSG_LEN); 1801 return (GENENT_PARSEERR); 1802 } 1803 *s++ = 0; 1804 ecol[1].ec_value.ec_value_val = t; 1805 ecol[1].ec_value.ec_value_len = strlen(t)+1; 1806 t = s; 1807 1808 1809 /* 1810 * gid (col 2) 1811 */ 1812 if ((s = strchr(t, ':')) == 0 || s == t) { 1813 (void) strlcpy(parse_err_msg, gettext("no members"), 1814 PARSE_ERR_MSG_LEN); 1815 return (GENENT_PARSEERR); 1816 } 1817 *s++ = 0; 1818 ecol[2].ec_value.ec_value_val = t; 1819 ecol[2].ec_value.ec_value_len = strlen(t)+1; 1820 t = s; 1821 1822 /* 1823 * members (col 3) 1824 */ 1825 ecol[3].ec_value.ec_value_val = t; 1826 ecol[3].ec_value.ec_value_len = strlen(t)+1; 1827 1828 1829 /* 1830 * build entry 1831 */ 1832 data.gr_name = strdup(ecol[0].ec_value.ec_value_val); 1833 data.gr_passwd = strdup(ecol[1].ec_value.ec_value_val); 1834 if (ecol[2].ec_value.ec_value_val != NULL && 1835 ecol[2].ec_value.ec_value_val[0] != '\0') { 1836 1837 data.gr_gid = ascii_to_int(ecol[2].ec_value.ec_value_val); 1838 if (data.gr_gid == (uid_t)-1) { 1839 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 1840 gettext("invalid group id: %s"), 1841 ecol[2].ec_value.ec_value_val); 1842 return (GENENT_PARSEERR); 1843 } 1844 } else 1845 data.gr_gid = (uid_t)-1; 1846 1847 data.gr_mem = NULL; 1848 1849 /* Compute maximum amount of members */ 1850 s = t; 1851 while (s = strchr(s, ',')) { 1852 s++; 1853 ctr++; 1854 } 1855 1856 /* Allocate memory for all members */ 1857 data.gr_mem = calloc(ctr + 2, sizeof (char **)); 1858 if (data.gr_mem == NULL) { 1859 (void) fprintf(stderr, gettext("out of memory\n")); 1860 exit(1); 1861 } 1862 1863 ctr = 0; 1864 while (s = strchr(t, ',')) { 1865 1866 *s++ = 0; 1867 ecol[3].ec_value.ec_value_val = t; 1868 t = s; 1869 /* Send to server only non empty member names */ 1870 if (strlen(ecol[3].ec_value.ec_value_val) != 0) 1871 data.gr_mem[ctr++] = ecol[3].ec_value.ec_value_val; 1872 } 1873 1874 /* Send to server only non empty member names */ 1875 if (strlen(t) != 0) 1876 data.gr_mem[ctr++] = t; 1877 1878 /* Array of members completed, finished by NULL, see calloc() */ 1879 1880 if (flags & F_VERBOSE) 1881 (void) fprintf(stdout, 1882 gettext("Adding entry : %s\n"), data.gr_name); 1883 1884 retval = (*cback)(&data, 0); 1885 1886 if (retval == LDAP_ALREADY_EXISTS) { 1887 if (continue_onerror) 1888 (void) fprintf(stderr, 1889 gettext("Entry: %s - already Exists," 1890 " skipping it.\n"), data.gr_name); 1891 else { 1892 rc = GENENT_CBERR; 1893 (void) fprintf(stderr, 1894 gettext("Entry: %s - already Exists\n"), 1895 data.gr_name); 1896 } 1897 } else if (retval) 1898 rc = GENENT_CBERR; 1899 1900 free(data.gr_name); 1901 free(data.gr_passwd); 1902 free(data.gr_mem); 1903 1904 return (rc); 1905 } 1906 1907 static void 1908 dump_group(ns_ldap_result_t *res) 1909 { 1910 char **value = NULL; 1911 char pnam[256]; 1912 int attr_count = 0; 1913 1914 value = __ns_ldap_getAttr(res->entry, "cn"); 1915 if (value && value[0]) 1916 (void) fprintf(stdout, "%s:", value[0]); 1917 value = __ns_ldap_getAttr(res->entry, "userPassword"); 1918 if (value == NULL || value[0] == NULL) 1919 (void) fprintf(stdout, "*:"); 1920 else { 1921 (void) strcpy(pnam, value[0]); 1922 if (strncasecmp(value[0], "{crypt}", 7) == 0) 1923 (void) fprintf(stdout, "%s:", (pnam+7)); 1924 else 1925 (void) fprintf(stdout, "*:"); 1926 } 1927 value = __ns_ldap_getAttr(res->entry, "gidNumber"); 1928 if (value && value[0]) 1929 (void) fprintf(stdout, "%s:", value[0]); 1930 1931 value = __ns_ldap_getAttr(res->entry, "memberUid"); 1932 if (value != NULL && value[0] != NULL) { 1933 while (value[attr_count] != NULL) { 1934 if (value[attr_count+1] == NULL) 1935 (void) fprintf(stdout, "%s", value[attr_count]); 1936 else 1937 (void) fprintf(stdout, "%s,", 1938 value[attr_count]); 1939 attr_count++; 1940 } 1941 (void) fprintf(stdout, "\n"); 1942 } 1943 else 1944 (void) fprintf(stdout, "\n"); 1945 } 1946 1947 1948 1949 1950 1951 /* 1952 * /etc/ethers 1953 */ 1954 1955 static int 1956 genent_ethers(char *line, int (*cback)()) 1957 { 1958 char buf[BUFSIZ+1]; 1959 char *t; 1960 entry_col ecol[3]; 1961 int retval = 1; 1962 struct _ns_ethers data; 1963 int rc = GENENT_OK; 1964 1965 /* 1966 * don't clobber our argument 1967 */ 1968 if (strlen(line) >= sizeof (buf)) { 1969 (void) strlcpy(parse_err_msg, gettext("line too long"), 1970 PARSE_ERR_MSG_LEN); 1971 return (GENENT_PARSEERR); 1972 } 1973 (void) strcpy(buf, line); 1974 1975 /* 1976 * clear column data 1977 */ 1978 (void) memset((char *)ecol, 0, sizeof (ecol)); 1979 1980 /* 1981 * comment (col 2) 1982 */ 1983 t = strchr(buf, '#'); 1984 if (t) { 1985 *t++ = 0; 1986 ecol[2].ec_value.ec_value_val = t; 1987 ecol[2].ec_value.ec_value_len = strlen(t)+1; 1988 } else { 1989 ecol[2].ec_value.ec_value_val = 0; 1990 ecol[2].ec_value.ec_value_len = 0; 1991 } 1992 1993 /* 1994 * addr(col 0) 1995 */ 1996 if ((t = strtok(buf, " \t")) == 0) { 1997 (void) strlcpy(parse_err_msg, gettext("no name"), 1998 PARSE_ERR_MSG_LEN); 1999 return (GENENT_PARSEERR); 2000 } 2001 ecol[0].ec_value.ec_value_val = t; 2002 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2003 2004 /* 2005 * name(col 1) 2006 */ 2007 if ((t = strtok(NULL, " \t")) == 0) { 2008 (void) strlcpy(parse_err_msg, 2009 gettext("no white space allowed in name"), 2010 PARSE_ERR_MSG_LEN); 2011 return (GENENT_PARSEERR); 2012 } 2013 ecol[1].ec_value.ec_value_val = t; 2014 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2015 2016 2017 /* 2018 * build entry 2019 */ 2020 2021 data.ether = strdup(ecol[0].ec_value.ec_value_val); 2022 data.name = strdup(ecol[1].ec_value.ec_value_val); 2023 2024 2025 if (flags & F_VERBOSE) 2026 (void) fprintf(stdout, 2027 gettext("Adding entry : %s\n"), data.name); 2028 2029 retval = (*cback)(&data, 0); 2030 2031 if (retval == LDAP_ALREADY_EXISTS) { 2032 if (continue_onerror) 2033 (void) fprintf(stderr, 2034 gettext("Entry: %s - already Exists," 2035 " skipping it.\n"), data.name); 2036 else { 2037 rc = GENENT_CBERR; 2038 (void) fprintf(stderr, 2039 gettext("Entry: %s - already Exists\n"), 2040 data.name); 2041 } 2042 } else if (retval) 2043 rc = GENENT_CBERR; 2044 2045 free(data.ether); 2046 free(data.name); 2047 2048 return (rc); 2049 } 2050 2051 2052 static void 2053 dump_ethers(ns_ldap_result_t *res) 2054 { 2055 char **value = NULL; 2056 2057 value = __ns_ldap_getAttr(res->entry, "macAddress"); 2058 if (value && value[0]) 2059 (void) fprintf(stdout, "%s", value[0]); 2060 else 2061 return; 2062 value = __ns_ldap_getAttr(res->entry, "cn"); 2063 if (value && value[0]) 2064 (void) fprintf(stdout, " %s\n", value[0]); 2065 } 2066 2067 static int 2068 genent_aliases(char *line, int (*cback)()) 2069 { 2070 char buf[BUFSIZ+1]; 2071 char *t, *aliases; 2072 char *cname; 2073 int ctr = 0; 2074 int retval = 1; 2075 int i; 2076 2077 struct _ns_alias data; 2078 char *alias; 2079 int rc = GENENT_OK; 2080 2081 /* 2082 * don't clobber our argument 2083 */ 2084 if (strlen(line) >= sizeof (buf)) { 2085 (void) strlcpy(parse_err_msg, gettext("line too long"), 2086 PARSE_ERR_MSG_LEN); 2087 return (GENENT_PARSEERR); 2088 } 2089 2090 (void) strcpy(buf, line); 2091 2092 if ((t = strchr(buf, ':')) == 0) { 2093 (void) strlcpy(parse_err_msg, gettext("no alias name"), 2094 PARSE_ERR_MSG_LEN); 2095 return (GENENT_PARSEERR); 2096 } 2097 2098 t[0] = '\0'; 2099 if (++t == '\0') { 2100 (void) strlcpy(parse_err_msg, gettext("no alias value"), 2101 PARSE_ERR_MSG_LEN); 2102 return (GENENT_PARSEERR); 2103 } 2104 2105 cname = buf; 2106 aliases = t; 2107 2108 /* build entry */ 2109 data.alias = strdup(cname); 2110 if (!data.alias) { 2111 (void) fprintf(stderr, gettext("out of memory\n")); 2112 exit(1); 2113 } 2114 2115 data.member = NULL; 2116 t = strtok(aliases, ","); 2117 do { 2118 ctr++; 2119 while (t[0] == ' ') 2120 t++; 2121 alias = strdup(t); 2122 if ((alias == NULL) || 2123 ((data.member = (char **)realloc(data.member, 2124 (ctr + 1) * sizeof (char **))) == NULL)) { 2125 (void) fprintf(stderr, gettext("out of memory\n")); 2126 exit(1); 2127 } 2128 data.member[ctr-1] = alias; 2129 2130 } while (t = strtok(NULL, ",")); 2131 2132 data.member[ctr] = NULL; 2133 2134 if (flags & F_VERBOSE) 2135 (void) fprintf(stdout, 2136 gettext("Adding entry : %s\n"), data.alias); 2137 2138 retval = (*cback)(&data, 0); 2139 2140 if (retval == LDAP_ALREADY_EXISTS) { 2141 if (continue_onerror) 2142 (void) fprintf(stderr, 2143 gettext("Entry: %s - already Exists," 2144 " skipping it.\n"), data.alias); 2145 else { 2146 rc = GENENT_CBERR; 2147 (void) fprintf(stderr, 2148 gettext("Entry: %s - already Exists\n"), 2149 data.alias); 2150 } 2151 } else if (retval) 2152 rc = GENENT_CBERR; 2153 2154 free(data.alias); 2155 i = 0; 2156 while (data.member[i]) 2157 free(data.member[i++]); 2158 free(data.member); 2159 2160 return (rc); 2161 } 2162 2163 2164 static void 2165 dump_aliases(ns_ldap_result_t *res) 2166 { 2167 2168 char **value = NULL; 2169 int attr_count = 0; 2170 2171 value = __ns_ldap_getAttr(res->entry, "mail"); 2172 if (value && value[0]) 2173 (void) fprintf(stdout, "%s:", value[0]); 2174 value = __ns_ldap_getAttr(res->entry, "mgrpRFC822MailMember"); 2175 if (value != NULL) 2176 while (value[attr_count] != NULL) { 2177 (void) fprintf(stdout, "%s,", value[attr_count]); 2178 attr_count++; 2179 } 2180 (void) fprintf(stdout, "\n"); 2181 2182 } 2183 2184 /* 2185 * /etc/publickey 2186 */ 2187 2188 static char *h_errno2str(int h_errno); 2189 2190 static int 2191 genent_publickey(char *line, int (*cback)()) 2192 { 2193 char buf[BUFSIZ+1], tmpbuf[BUFSIZ+1], cname[BUFSIZ+1]; 2194 char *t, *p, *tmppubkey, *tmpprivkey; 2195 entry_col ecol[3]; 2196 int buflen, uid, retval = 1, errnum = 0; 2197 struct passwd *pwd; 2198 char auth_type[BUFSIZ+1], *dot; 2199 keylen_t keylen; 2200 algtype_t algtype; 2201 struct _ns_pubkey data; 2202 struct hostent *hp; 2203 struct in_addr in; 2204 struct in6_addr in6; 2205 char abuf[INET6_ADDRSTRLEN]; 2206 2207 /* 2208 * don't clobber our argument 2209 */ 2210 if (strlen(line) >= sizeof (buf)) { 2211 (void) strlcpy(parse_err_msg, gettext("line too long"), 2212 PARSE_ERR_MSG_LEN); 2213 return (GENENT_PARSEERR); 2214 } 2215 (void) strcpy(buf, line); 2216 2217 /* 2218 * clear column data 2219 */ 2220 (void) memset((char *)ecol, 0, sizeof (ecol)); 2221 2222 if ((t = strtok(buf, " \t")) == 0) { 2223 (void) strlcpy(parse_err_msg, gettext("no cname"), 2224 PARSE_ERR_MSG_LEN); 2225 return (GENENT_PARSEERR); 2226 } 2227 2228 /* 2229 * Special case: /etc/publickey usually has an entry 2230 * for principal "nobody". We skip it. 2231 */ 2232 if (strcmp(t, "nobody") == 0) 2233 return (GENENT_OK); 2234 2235 /* 2236 * cname (col 0) 2237 */ 2238 if (strncmp(t, "unix.", 5)) { 2239 (void) strlcpy(parse_err_msg, gettext("bad cname"), 2240 PARSE_ERR_MSG_LEN); 2241 return (GENENT_PARSEERR); 2242 } 2243 (void) strcpy(tmpbuf, &(t[5])); 2244 if ((p = strchr(tmpbuf, '@')) == 0) { 2245 (void) strlcpy(parse_err_msg, gettext("bad cname"), 2246 PARSE_ERR_MSG_LEN); 2247 return (GENENT_PARSEERR); 2248 } 2249 *(p++) = 0; 2250 if (isdigit(*tmpbuf)) { 2251 2252 uid = atoi(tmpbuf); 2253 /* 2254 * don't generate entries for uids without passwd entries 2255 */ 2256 if ((pwd = getpwuid(uid)) == 0) { 2257 (void) fprintf(stderr, 2258 gettext("can't map uid %d to username, skipping\n"), 2259 uid); 2260 return (GENENT_OK); 2261 } 2262 (void) strcpy(cname, pwd->pw_name); 2263 data.hostcred = NS_HOSTCRED_FALSE; 2264 } else { 2265 if ((hp = getipnodebyname(tmpbuf, AF_INET6, 2266 AI_ALL | AI_V4MAPPED, &errnum)) == NULL) { 2267 (void) fprintf(stderr, 2268 gettext("can't map hostname %s to hostaddress, " 2269 "errnum %d %s skipping\n"), tmpbuf, errnum, 2270 h_errno2str(errnum)); 2271 return (GENENT_OK); 2272 } 2273 (void) memcpy((char *)&in6.s6_addr, hp->h_addr_list[0], 2274 hp->h_length); 2275 if (IN6_IS_ADDR_V4MAPPED(&in6) || 2276 IN6_IS_ADDR_V4COMPAT(&in6)) { 2277 IN6_V4MAPPED_TO_INADDR(&in6, &in); 2278 if (inet_ntop(AF_INET, (const void *)&in, abuf, 2279 INET6_ADDRSTRLEN) == NULL) { 2280 (void) fprintf(stderr, 2281 gettext("can't convert IPV4 address of" 2282 " hostname %s to string, " 2283 "skipping\n"), tmpbuf); 2284 return (GENENT_OK); 2285 } 2286 } else { 2287 if (inet_ntop(AF_INET6, (const void *)&in6, abuf, 2288 INET6_ADDRSTRLEN) == NULL) { 2289 (void) fprintf(stderr, 2290 gettext("can't convert IPV6 address of" 2291 " hostname %s to string, " 2292 "skipping\n"), tmpbuf); 2293 return (GENENT_OK); 2294 } 2295 } 2296 data.hostcred = NS_HOSTCRED_TRUE; 2297 /* 2298 * tmpbuf could be an alias, use hp->h_name instead. 2299 * hp->h_name is in FQDN format, so extract 1st field. 2300 */ 2301 if ((dot = strchr(hp->h_name, '.')) != NULL) 2302 *dot = '\0'; 2303 (void) snprintf(cname, sizeof (cname), 2304 "%s+ipHostNumber=%s", hp->h_name, abuf); 2305 if (dot) 2306 *dot = '.'; 2307 } 2308 2309 ecol[0].ec_value.ec_value_val = cname; 2310 ecol[0].ec_value.ec_value_len = strlen(cname)+1; 2311 2312 /* 2313 * public_data (col 1) 2314 */ 2315 if ((t = strtok(NULL, " \t")) == 0) { 2316 (void) strlcpy(parse_err_msg, gettext("no private_data"), 2317 PARSE_ERR_MSG_LEN); 2318 return (GENENT_PARSEERR); 2319 } 2320 if ((p = strchr(t, ':')) == 0) { 2321 (void) strlcpy(parse_err_msg, gettext("bad public_data"), 2322 PARSE_ERR_MSG_LEN); 2323 return (GENENT_PARSEERR); 2324 } 2325 *(p++) = 0; 2326 ecol[1].ec_value.ec_value_val = t; 2327 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2328 keylen = (strlen(t) / 2) * 8; 2329 2330 /* 2331 * private_data (col 2) and algtype extraction 2332 */ 2333 if (*p == ':') 2334 p++; 2335 t = p; 2336 if (!(t = strchr(t, ':'))) { 2337 (void) fprintf(stderr, 2338 gettext("WARNING: No algorithm type data found " 2339 "in publickey file, assuming 0\n")); 2340 algtype = 0; 2341 } else { 2342 *t = '\0'; 2343 t++; 2344 algtype = atoi(t); 2345 } 2346 ecol[2].ec_value.ec_value_val = p; 2347 ecol[2].ec_value.ec_value_len = strlen(p)+1; 2348 2349 /* 2350 * auth_type (col 1) 2351 */ 2352 if (AUTH_DES_KEY(keylen, algtype)) 2353 /* 2354 * {DES} and {DH192-0} means same thing. 2355 * However, nisplus uses "DES" and ldap uses "DH192-0" 2356 * internally. 2357 * See newkey(1M), __nis_mechalias2authtype() which is 2358 * called by __nis_keyalg2authtype() and getkey_ldap_g() 2359 */ 2360 (void) strlcpy(auth_type, "DH192-0", BUFSIZ+1); 2361 else if (!(__nis_keyalg2authtype(keylen, algtype, auth_type, 2362 MECH_MAXATNAME))) { 2363 (void) fprintf(stderr, 2364 gettext("Could not convert algorithm type to " 2365 "corresponding auth type string\n")); 2366 return (GENENT_ERR); 2367 } 2368 2369 /* 2370 * build entry 2371 */ 2372 data.name = strdup(ecol[0].ec_value.ec_value_val); 2373 if (data.name == NULL) { 2374 (void) fprintf(stderr, gettext("out of memory\n")); 2375 exit(1); 2376 } 2377 2378 buflen = sizeof (auth_type) + strlen(ecol[1].ec_value.ec_value_val) + 3; 2379 if ((tmppubkey = (char *)malloc(buflen)) == NULL) { 2380 (void) fprintf(stderr, gettext("out of memory\n")); 2381 exit(1); 2382 } 2383 (void) snprintf(tmppubkey, buflen, "{%s}%s", auth_type, 2384 ecol[1].ec_value.ec_value_val); 2385 data.pubkey = tmppubkey; 2386 2387 buflen = sizeof (auth_type) + strlen(ecol[2].ec_value.ec_value_val) + 3; 2388 if ((tmpprivkey = (char *)malloc(buflen)) == NULL) { 2389 (void) fprintf(stderr, gettext("out of memory\n")); 2390 exit(1); 2391 } 2392 2393 (void) snprintf(tmpprivkey, buflen, "{%s}%s", auth_type, 2394 ecol[2].ec_value.ec_value_val); 2395 data.privkey = tmpprivkey; 2396 2397 retval = (*cback)(&data, 1); 2398 if (retval != NS_LDAP_SUCCESS) { 2399 if (retval == LDAP_NO_SUCH_OBJECT) { 2400 if (data.hostcred == NS_HOSTCRED_TRUE) 2401 (void) fprintf(stdout, 2402 gettext("Cannot add publickey entry"" (%s)," 2403 " add host entry first\n"), 2404 tmpbuf); 2405 else 2406 (void) fprintf(stdout, 2407 gettext("Cannot add publickey entry (%s), " 2408 "add passwd entry first\n"), 2409 data.name); 2410 } 2411 if (continue_onerror == 0) 2412 return (GENENT_CBERR); 2413 } 2414 2415 free(data.name); 2416 free(data.pubkey); 2417 free(data.privkey); 2418 return (GENENT_OK); 2419 } 2420 2421 static void 2422 dump_publickey(ns_ldap_result_t *res, char *container) 2423 { 2424 char **value = NULL; 2425 char buf[BUFSIZ]; 2426 char domainname[BUFSIZ]; 2427 char *pubptr, *prvptr; 2428 2429 if (res == NULL) 2430 return; 2431 2432 if (sysinfo(SI_SRPC_DOMAIN, domainname, BUFSIZ) < 0) { 2433 (void) fprintf(stderr, 2434 gettext("could not obtain domainname\n")); 2435 exit(1); 2436 } 2437 2438 /* 2439 * Retrieve all the attributes, but don't print 2440 * until we have all the required ones. 2441 */ 2442 2443 if (strcmp(container, "passwd") == 0) 2444 value = __ns_ldap_getAttr(res->entry, "uidNumber"); 2445 else 2446 value = __ns_ldap_getAttr(res->entry, "cn"); 2447 2448 if (value && value[0]) 2449 (void) snprintf(buf, sizeof (buf), "unix.%s@%s", 2450 value[0], domainname); 2451 else 2452 return; 2453 2454 value = __ns_ldap_getAttr(res->entry, "nisPublickey"); 2455 if (value != NULL && value[0] != NULL) { 2456 if ((pubptr = strchr(value[0], '}')) == NULL) 2457 return; 2458 } 2459 2460 value = __ns_ldap_getAttr(res->entry, "nisSecretkey"); 2461 if (value != NULL && value[0] != NULL) 2462 if ((prvptr = strchr(value[0], '}')) == NULL) 2463 return; 2464 2465 /* print the attributes, algorithm type is always 0 */ 2466 (void) fprintf(stdout, "%s %s:%s:0\n", buf, ++pubptr, ++prvptr); 2467 } 2468 2469 2470 2471 /* 2472 * /etc/netmasks 2473 */ 2474 2475 static int 2476 genent_netmasks(char *line, int (*cback)()) 2477 { 2478 char buf[BUFSIZ+1]; 2479 char *t; 2480 entry_col ecol[3]; 2481 int retval; 2482 2483 struct _ns_netmasks data; 2484 2485 2486 /* 2487 * don't clobber our argument 2488 */ 2489 if (strlen(line) >= sizeof (buf)) { 2490 (void) strlcpy(parse_err_msg, gettext("line too long"), 2491 PARSE_ERR_MSG_LEN); 2492 return (GENENT_PARSEERR); 2493 } 2494 (void) strcpy(buf, line); 2495 2496 /* 2497 * clear column data 2498 */ 2499 (void) memset((char *)ecol, 0, sizeof (ecol)); 2500 2501 /* 2502 * comment (col 2) 2503 */ 2504 t = strchr(buf, '#'); 2505 if (t) { 2506 *t++ = 0; 2507 ecol[2].ec_value.ec_value_val = t; 2508 ecol[2].ec_value.ec_value_len = strlen(t)+1; 2509 } else { 2510 ecol[2].ec_value.ec_value_val = 0; 2511 ecol[2].ec_value.ec_value_len = 0; 2512 } 2513 2514 /* 2515 * addr(col 0) 2516 */ 2517 if ((t = strtok(buf, " \t")) == 0) { 2518 (void) strlcpy(parse_err_msg, gettext("no mask"), 2519 PARSE_ERR_MSG_LEN); 2520 return (GENENT_PARSEERR); 2521 } 2522 ecol[0].ec_value.ec_value_val = t; 2523 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2524 2525 /* 2526 * mask (col 1) 2527 */ 2528 if ((t = strtok(NULL, " \t")) == 0) { 2529 (void) strlcpy(parse_err_msg, gettext("no mask"), 2530 PARSE_ERR_MSG_LEN); 2531 return (GENENT_PARSEERR); 2532 } 2533 ecol[1].ec_value.ec_value_val = t; 2534 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2535 2536 /* build entry */ 2537 data.netnumber = ecol[0].ec_value.ec_value_val; 2538 data.netmask = ecol[1].ec_value.ec_value_val; 2539 2540 if (flags & F_VERBOSE) 2541 (void) fprintf(stdout, 2542 gettext("Adding entry : %s\n"), data.netnumber); 2543 2544 retval = (*cback)(&data, 1); 2545 if (retval != NS_LDAP_SUCCESS) { 2546 if (retval == LDAP_NO_SUCH_OBJECT) 2547 (void) fprintf(stdout, 2548 gettext("Cannot add netmask entry (%s), " 2549 "add network entry first\n"), data.netnumber); 2550 if (continue_onerror == 0) 2551 return (GENENT_CBERR); 2552 } 2553 2554 return (GENENT_OK); 2555 } 2556 2557 static void 2558 dump_netmasks(ns_ldap_result_t *res) 2559 { 2560 char **value = NULL; 2561 2562 value = __ns_ldap_getAttr(res->entry, "ipNetworkNumber"); 2563 if (value && value[0]) 2564 (void) fprintf(stdout, "%s", value[0]); 2565 value = __ns_ldap_getAttr(res->entry, "ipNetmaskNumber"); 2566 if (value && value[0]) 2567 (void) fprintf(stdout, " %s\n", value[0]); 2568 } 2569 2570 2571 /* 2572 * /etc/netgroup 2573 * column data format is: 2574 * col 0: netgroup name (or cname) 2575 * col 1: netgroup member, if this is a triplet 2576 * col 2: netgroup member, if not a triplet 2577 * col 3: comment 2578 */ 2579 2580 static int 2581 genent_netgroup(char *line, int (*cback)()) 2582 { 2583 char buf[BIGBUF+1]; /* netgroup entries tend to be big */ 2584 char *t; 2585 char *cname = NULL; 2586 entry_col ecol[4]; 2587 char *netg_tmp = NULL, *triplet_tmp = NULL; 2588 int netgcount = 0, tripletcount = 0, retval = 1, i; 2589 struct _ns_netgroups data; 2590 int rc = GENENT_OK; 2591 2592 /* don't clobber our argument */ 2593 if (strlen(line) >= sizeof (buf)) { 2594 (void) strlcpy(parse_err_msg, gettext("line too long"), 2595 PARSE_ERR_MSG_LEN); 2596 return (GENENT_PARSEERR); 2597 } 2598 (void) strcpy(buf, line); 2599 2600 /* clear column data */ 2601 (void) memset((char *)ecol, 0, sizeof (ecol)); 2602 2603 /* 2604 * process 1st minimal entry, to validate that there is no 2605 * parsing error. 2606 * start with comment(col 3) 2607 */ 2608 t = strchr(buf, '#'); 2609 if (t) { 2610 *t++ = 0; 2611 ecol[3].ec_value.ec_value_val = t; 2612 ecol[3].ec_value.ec_value_len = strlen(t)+1; 2613 } else { 2614 ecol[3].ec_value.ec_value_val = ""; 2615 ecol[3].ec_value.ec_value_len = 0; 2616 } 2617 2618 ecol[1].ec_value.ec_value_val = NULL; 2619 ecol[2].ec_value.ec_value_val = NULL; 2620 2621 /* cname (col 0) */ 2622 if ((t = strtok(buf, " \t")) == 0) { 2623 (void) strlcpy(parse_err_msg, gettext("no cname"), 2624 PARSE_ERR_MSG_LEN); 2625 return (GENENT_PARSEERR); 2626 } 2627 2628 ecol[0].ec_value.ec_value_val = t; 2629 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2630 cname = t; 2631 2632 /* addr(col 1 and 2) */ 2633 if ((t = strtok(NULL, " \t")) == 0) { 2634 (void) strlcpy(parse_err_msg, 2635 gettext("no members for netgroup"), PARSE_ERR_MSG_LEN); 2636 return (GENENT_PARSEERR); 2637 } 2638 2639 if (*t == '(') { 2640 /* if token starts with '(' it must be a valid triplet */ 2641 if (is_triplet(t)) { 2642 ecol[1].ec_value.ec_value_val = t; 2643 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2644 } else { 2645 (void) strlcpy(parse_err_msg, 2646 gettext("invalid triplet"), PARSE_ERR_MSG_LEN); 2647 return (GENENT_PARSEERR); 2648 } 2649 } else { 2650 ecol[2].ec_value.ec_value_val = t; 2651 ecol[2].ec_value.ec_value_len = strlen(t)+1; 2652 } 2653 2654 /* 2655 * now build entry. 2656 * start by clearing entry data 2657 */ 2658 (void) memset((struct _ns_netgroups *)&data, 0, sizeof (data)); 2659 2660 data.name = strdup(ecol[0].ec_value.ec_value_val); 2661 2662 if (ecol[1].ec_value.ec_value_val != NULL) { 2663 if ((data.triplet = calloc(1, sizeof (char **))) == NULL) { 2664 (void) fprintf(stderr, 2665 gettext("out of memory\n")); 2666 exit(1); 2667 } 2668 data.triplet[tripletcount++] = 2669 strdup(ecol[1].ec_value.ec_value_val); 2670 } else if (ecol[2].ec_value.ec_value_val != NULL) { 2671 if ((data.netgroup = calloc(1, sizeof (char **))) 2672 == NULL) { 2673 (void) fprintf(stderr, 2674 gettext("out of memory\n")); 2675 exit(1); 2676 } 2677 data.netgroup[netgcount++] = 2678 strdup(ecol[2].ec_value.ec_value_val); 2679 } 2680 2681 /* 2682 * we now have a valid entry (at least 1 netgroup name and 2683 * 1 netgroup member), proceed with the rest of the line 2684 */ 2685 while (rc == GENENT_OK && (t = strtok(NULL, " \t"))) { 2686 2687 /* if next token is equal to netgroup name, ignore */ 2688 if (t != cname && strcasecmp(t, cname) == 0) 2689 continue; 2690 if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) 2691 continue; 2692 2693 if (*t == '(') { 2694 if (is_triplet(t)) { 2695 /* skip a triplet if it is added already */ 2696 for (i = 0; i < tripletcount && 2697 strcmp(t, data.triplet[i]); i++) 2698 ; 2699 if (i < tripletcount) 2700 continue; 2701 2702 tripletcount++; 2703 triplet_tmp = strdup(t); 2704 if ((data.triplet = (char **)realloc( 2705 data.triplet, 2706 tripletcount * sizeof (char **))) == NULL) { 2707 (void) fprintf(stderr, 2708 gettext("out of memory\n")); 2709 exit(1); 2710 } 2711 data.triplet[tripletcount-1] = triplet_tmp; 2712 } else { 2713 (void) strlcpy(parse_err_msg, 2714 gettext("invalid triplet"), 2715 PARSE_ERR_MSG_LEN); 2716 rc = GENENT_PARSEERR; 2717 } 2718 } else { 2719 /* skip a netgroup if it is added already */ 2720 for (i = 0; i < netgcount && 2721 strcmp(t, data.netgroup[i]); i++) 2722 ; 2723 if (i < netgcount) 2724 continue; 2725 2726 netgcount++; 2727 netg_tmp = strdup(t); 2728 if ((data.netgroup = (char **)realloc(data.netgroup, 2729 netgcount * sizeof (char **))) == NULL) { 2730 (void) fprintf(stderr, 2731 gettext("out of memory\n")); 2732 exit(1); 2733 } 2734 data.netgroup[netgcount-1] = netg_tmp; 2735 } 2736 } 2737 2738 /* End the list with NULL */ 2739 if ((data.triplet = (char **)realloc(data.triplet, 2740 (tripletcount + 1) * sizeof (char **))) == NULL) { 2741 (void) fprintf(stderr, gettext("out of memory\n")); 2742 exit(1); 2743 } 2744 data.triplet[tripletcount] = NULL; 2745 if ((data.netgroup = (char **)realloc(data.netgroup, 2746 (netgcount + 1) * sizeof (char **))) == NULL) { 2747 (void) fprintf(stderr, gettext("out of memory\n")); 2748 exit(1); 2749 } 2750 data.netgroup[netgcount] = NULL; 2751 2752 if (rc == GENENT_OK) { 2753 if (flags & F_VERBOSE) 2754 (void) fprintf(stdout, 2755 gettext("Adding entry : %s\n"), data.name); 2756 2757 retval = (*cback)(&data, 0); 2758 2759 if (retval == LDAP_ALREADY_EXISTS) { 2760 if (continue_onerror) 2761 (void) fprintf(stderr, gettext( 2762 "Entry: %s - already Exists," 2763 " skipping it.\n"), data.name); 2764 else { 2765 rc = GENENT_CBERR; 2766 (void) fprintf(stderr, 2767 gettext("Entry: %s - already Exists\n"), 2768 data.name); 2769 } 2770 } else if (retval) 2771 rc = GENENT_CBERR; 2772 } 2773 2774 /* release memory allocated by strdup() */ 2775 for (i = 0; i < tripletcount; i++) { 2776 free(data.triplet[i]); 2777 } 2778 for (i = 0; i < netgcount; i++) { 2779 free(data.netgroup[i]); 2780 } 2781 2782 free(data.name); 2783 free(data.triplet); 2784 free(data.netgroup); 2785 2786 return (rc); 2787 } 2788 2789 static void 2790 dump_netgroup(ns_ldap_result_t *res) 2791 { 2792 char **value = NULL; 2793 int attr_count = 0; 2794 2795 value = __ns_ldap_getAttr(res->entry, "cn"); 2796 if ((value != NULL) && (value[0] != NULL)) 2797 (void) fprintf(stdout, "%s", value[0]); 2798 else 2799 return; 2800 value = __ns_ldap_getAttr(res->entry, "nisNetgroupTriple"); 2801 if (value != NULL) 2802 while (value[attr_count] != NULL) { 2803 (void) fprintf(stdout, " %s", value[attr_count]); 2804 attr_count++; 2805 } 2806 attr_count = 0; 2807 value = __ns_ldap_getAttr(res->entry, "memberNisNetgroup"); 2808 if (value != NULL) 2809 while (value[attr_count] != NULL) { 2810 (void) fprintf(stdout, " %s", value[attr_count]); 2811 attr_count++; 2812 } 2813 (void) fprintf(stdout, "\n"); 2814 2815 } 2816 2817 static int 2818 genent_automount(char *line, int (*cback)()) 2819 { 2820 char buf[BUFSIZ+1]; 2821 char *t, *s; 2822 entry_col ecol[2]; 2823 struct _ns_automount data; 2824 int retval = 1; 2825 int rc = GENENT_OK; 2826 2827 /* 2828 * don't clobber our argument 2829 */ 2830 if (strlen(line) >= sizeof (buf)) { 2831 (void) strlcpy(parse_err_msg, gettext("line too long"), 2832 PARSE_ERR_MSG_LEN); 2833 return (GENENT_PARSEERR); 2834 } 2835 2836 /* replace every tabspace with single space */ 2837 replace_tab2space(line); 2838 (void) strcpy(buf, line); 2839 2840 /* 2841 * clear column data 2842 */ 2843 (void) memset((char *)ecol, 0, sizeof (ecol)); 2844 2845 /* 2846 * key (col 0) 2847 */ 2848 t = buf; 2849 while (t[0] == ' ') 2850 t++; 2851 2852 if ((s = strchr(t, ' ')) == 0) { 2853 return (GENENT_PARSEERR); 2854 } 2855 *s++ = 0; 2856 2857 ecol[0].ec_value.ec_value_val = t; 2858 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2859 t = s; 2860 2861 while (t[0] == ' ') 2862 t++; 2863 2864 /* 2865 * mapentry (col 1) 2866 */ 2867 2868 ecol[1].ec_value.ec_value_val = t; 2869 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2870 2871 data.mapname = strdup(databasetype); 2872 data.key = strdup(ecol[0].ec_value.ec_value_val); 2873 data.value = strdup(ecol[1].ec_value.ec_value_val); 2874 2875 if (flags & F_VERBOSE) 2876 (void) fprintf(stdout, 2877 gettext("Adding entry : %s\n"), data.key); 2878 2879 retval = (*cback)(&data, 0); 2880 2881 if (retval == LDAP_ALREADY_EXISTS) { 2882 if (continue_onerror) 2883 (void) fprintf(stderr, 2884 gettext("Entry: %s - already Exists," 2885 " skipping it.\n"), data.key); 2886 else { 2887 rc = GENENT_CBERR; 2888 (void) fprintf(stderr, 2889 gettext("Entry: %s - already Exists\n"), 2890 data.key); 2891 } 2892 } else if (retval) 2893 rc = GENENT_CBERR; 2894 2895 free(data.mapname); 2896 free(data.key); 2897 free(data.value); 2898 return (rc); 2899 } 2900 2901 static void 2902 dump_automount(ns_ldap_result_t *res) 2903 { 2904 char **value = NULL; 2905 2906 if (res == NULL) 2907 return; 2908 2909 value = __ns_ldap_getAttr(res->entry, "automountKey"); 2910 if (value != NULL) { 2911 (void) fprintf(stdout, "%s", value[0]); 2912 value = __ns_ldap_getAttr(res->entry, "automountInformation"); 2913 if (value != NULL) 2914 (void) fprintf(stdout, " %s\n", value[0]); 2915 else 2916 (void) fprintf(stdout, "\n"); 2917 } 2918 } 2919 2920 2921 /* 2922 * /etc/passwd 2923 * 2924 */ 2925 2926 static int 2927 genent_passwd(char *line, int (*cback)()) 2928 { 2929 char buf[BUFSIZ+1]; 2930 char *s, *t; 2931 entry_col ecol[8]; 2932 int retval = 1; 2933 char pname[BUFSIZ]; 2934 2935 struct passwd data; 2936 int rc = GENENT_OK; 2937 2938 2939 /* 2940 * don't clobber our argument 2941 */ 2942 if (strlen(line) >= sizeof (buf)) { 2943 (void) strlcpy(parse_err_msg, gettext("line too long"), 2944 PARSE_ERR_MSG_LEN); 2945 return (GENENT_PARSEERR); 2946 } 2947 (void) strcpy(buf, line); 2948 t = buf; 2949 2950 /* ignore empty entries */ 2951 if (*t == '\0') 2952 return (GENENT_OK); 2953 2954 /* 2955 * clear column data 2956 */ 2957 (void) memset((char *)ecol, 0, sizeof (ecol)); 2958 2959 /* 2960 * name (col 0) 2961 */ 2962 if ((s = strchr(t, ':')) == 0) { 2963 (void) strlcpy(parse_err_msg, gettext("no password"), 2964 PARSE_ERR_MSG_LEN); 2965 return (GENENT_PARSEERR); 2966 } 2967 *s++ = 0; 2968 ecol[0].ec_value.ec_value_val = t; 2969 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2970 t = s; 2971 2972 /* 2973 * passwd (col 1) 2974 */ 2975 if ((s = strchr(t, ':')) == 0) { 2976 (void) strlcpy(parse_err_msg, gettext("no uid"), 2977 PARSE_ERR_MSG_LEN); 2978 return (GENENT_PARSEERR); 2979 } 2980 *s++ = 0; 2981 2982 ecol[1].ec_value.ec_value_val = t; 2983 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2984 2985 t = s; 2986 2987 /* 2988 * uid (col 2) 2989 */ 2990 if ((s = strchr(t, ':')) == 0 || s == t) { 2991 (void) strlcpy(parse_err_msg, gettext("no gid"), 2992 PARSE_ERR_MSG_LEN); 2993 return (GENENT_PARSEERR); 2994 } 2995 *s++ = 0; 2996 ecol[2].ec_value.ec_value_val = t; 2997 ecol[2].ec_value.ec_value_len = strlen(t)+1; 2998 t = s; 2999 3000 /* 3001 * gid (col 3) 3002 */ 3003 if ((s = strchr(t, ':')) == 0 || s == t) { 3004 (void) strlcpy(parse_err_msg, gettext("no gcos"), 3005 PARSE_ERR_MSG_LEN); 3006 return (GENENT_PARSEERR); 3007 } 3008 *s++ = 0; 3009 ecol[3].ec_value.ec_value_val = t; 3010 ecol[3].ec_value.ec_value_len = strlen(t)+1; 3011 t = s; 3012 3013 /* 3014 * gcos (col 4) 3015 */ 3016 if ((s = strchr(t, ':')) == 0) { 3017 (void) strlcpy(parse_err_msg, gettext("no home"), 3018 PARSE_ERR_MSG_LEN); 3019 return (GENENT_PARSEERR); 3020 } 3021 *s++ = 0; 3022 ecol[4].ec_value.ec_value_val = t; 3023 ecol[4].ec_value.ec_value_len = strlen(t)+1; 3024 t = s; 3025 3026 /* 3027 * home (col 5) 3028 */ 3029 if ((s = strchr(t, ':')) == 0) { 3030 (void) strlcpy(parse_err_msg, gettext("no shell"), 3031 PARSE_ERR_MSG_LEN); 3032 return (GENENT_PARSEERR); 3033 } 3034 *s++ = 0; 3035 ecol[5].ec_value.ec_value_val = t; 3036 ecol[5].ec_value.ec_value_len = strlen(t)+1; 3037 t = s; 3038 3039 /* 3040 * shell (col 6) 3041 */ 3042 ecol[6].ec_value.ec_value_val = t; 3043 ecol[6].ec_value.ec_value_len = strlen(t)+1; 3044 3045 /* 3046 * build entry 3047 */ 3048 data.pw_name = strdup(ecol[0].ec_value.ec_value_val); 3049 3050 if (flags & F_PASSWD) { 3051 /* Add {crypt} before passwd entry */ 3052 (void) snprintf(pname, sizeof (pname), "{crypt}%s", 3053 ecol[1].ec_value.ec_value_val); 3054 data.pw_passwd = strdup(pname); 3055 } 3056 else 3057 data.pw_passwd = NULL; 3058 3059 if (ecol[2].ec_value.ec_value_val != NULL && 3060 ecol[2].ec_value.ec_value_val[0] != '\0') { 3061 data.pw_uid = ascii_to_int(ecol[2].ec_value.ec_value_val); 3062 if (data.pw_uid == (uid_t)-1) { 3063 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3064 gettext("invalid uid : %s"), 3065 ecol[2].ec_value.ec_value_val); 3066 return (GENENT_PARSEERR); 3067 } 3068 } else 3069 data.pw_uid = (uid_t)-1; 3070 3071 if (ecol[3].ec_value.ec_value_val != NULL && 3072 ecol[3].ec_value.ec_value_val[0] != '\0') { 3073 3074 data.pw_gid = ascii_to_int(ecol[3].ec_value.ec_value_val); 3075 if (data.pw_gid == (uid_t)-1) { 3076 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3077 gettext("invalid gid : %s"), 3078 ecol[3].ec_value.ec_value_val); 3079 return (GENENT_PARSEERR); 3080 } 3081 } else 3082 data.pw_gid = (uid_t)-1; 3083 3084 data.pw_age = NULL; 3085 data.pw_comment = NULL; 3086 data.pw_gecos = strdup(ecol[4].ec_value.ec_value_val); 3087 data.pw_dir = strdup(ecol[5].ec_value.ec_value_val); 3088 data.pw_shell = strdup(ecol[6].ec_value.ec_value_val); 3089 3090 if (flags & F_VERBOSE) 3091 (void) fprintf(stdout, 3092 gettext("Adding entry : %s\n"), data.pw_name); 3093 3094 retval = (*cback)(&data, 0); 3095 3096 if (retval == LDAP_ALREADY_EXISTS) { 3097 if (continue_onerror) 3098 (void) fprintf(stderr, 3099 gettext("Entry: %s - already Exists," 3100 " skipping it.\n"), data.pw_name); 3101 else { 3102 rc = GENENT_CBERR; 3103 (void) fprintf(stderr, 3104 gettext("Entry: %s - already Exists\n"), 3105 data.pw_name); 3106 } 3107 } else if (retval) 3108 rc = GENENT_CBERR; 3109 3110 free(data.pw_name); 3111 free(data.pw_gecos); 3112 free(data.pw_dir); 3113 free(data.pw_shell); 3114 return (rc); 3115 } 3116 3117 3118 static void 3119 dump_passwd(ns_ldap_result_t *res) 3120 { 3121 char **value = NULL; 3122 3123 value = __ns_ldap_getAttr(res->entry, "uid"); 3124 if (value == NULL) 3125 return; 3126 else 3127 (void) fprintf(stdout, "%s:", value[0]); 3128 value = __ns_ldap_getAttr(res->entry, "userPassword"); 3129 3130 /* 3131 * Don't print the encrypted password, Use x to 3132 * indicate it is in the shadow database. 3133 */ 3134 (void) fprintf(stdout, "x:"); 3135 3136 value = __ns_ldap_getAttr(res->entry, "uidNumber"); 3137 if (value && value[0]) 3138 (void) fprintf(stdout, "%s:", value[0]); 3139 value = __ns_ldap_getAttr(res->entry, "gidNumber"); 3140 if (value && value[0]) 3141 (void) fprintf(stdout, "%s:", value[0]); 3142 value = __ns_ldap_getAttr(res->entry, "gecos"); 3143 if (value == NULL) 3144 (void) fprintf(stdout, ":"); 3145 else 3146 (void) fprintf(stdout, "%s:", value[0]); 3147 value = __ns_ldap_getAttr(res->entry, "homeDirectory"); 3148 if (value == NULL) 3149 (void) fprintf(stdout, ":"); 3150 else 3151 (void) fprintf(stdout, "%s:", value[0]); 3152 value = __ns_ldap_getAttr(res->entry, "loginShell"); 3153 if (value == NULL) 3154 (void) fprintf(stdout, "\n"); 3155 else 3156 (void) fprintf(stdout, "%s\n", value[0]); 3157 3158 } 3159 3160 /* 3161 * /etc/shadow 3162 */ 3163 3164 static int 3165 genent_shadow(char *line, int (*cback)()) 3166 { 3167 char buf[BUFSIZ+1]; 3168 char *s, *t; 3169 entry_col ecol[9]; 3170 char pname[BUFSIZ]; 3171 3172 struct spwd data; 3173 int spflag; 3174 int retval; 3175 3176 3177 /* 3178 * don't clobber our argument 3179 */ 3180 if (strlen(line) >= sizeof (buf)) { 3181 (void) strlcpy(parse_err_msg, gettext("line too long"), 3182 PARSE_ERR_MSG_LEN); 3183 return (GENENT_PARSEERR); 3184 } 3185 (void) strcpy(buf, line); 3186 t = buf; 3187 3188 /* ignore empty entries */ 3189 if (*t == '\0') 3190 return (GENENT_OK); 3191 3192 /* 3193 * clear column data 3194 */ 3195 (void) memset((char *)ecol, 0, sizeof (ecol)); 3196 3197 /* 3198 * name (col 0) 3199 */ 3200 if ((s = strchr(t, ':')) == 0) { 3201 (void) strlcpy(parse_err_msg, gettext("no uid"), 3202 PARSE_ERR_MSG_LEN); 3203 return (GENENT_PARSEERR); 3204 } 3205 *s++ = 0; 3206 ecol[0].ec_value.ec_value_val = t; 3207 ecol[0].ec_value.ec_value_len = strlen(t)+1; 3208 t = s; 3209 3210 /* 3211 * passwd (col 1) 3212 */ 3213 if ((s = strchr(t, ':')) == 0) { 3214 (void) strlcpy(parse_err_msg, gettext("Improper format"), 3215 PARSE_ERR_MSG_LEN); 3216 return (GENENT_PARSEERR); 3217 } 3218 *s++ = 0; 3219 3220 ecol[1].ec_value.ec_value_val = t; 3221 ecol[1].ec_value.ec_value_len = strlen(t)+1; 3222 3223 t = s; 3224 3225 /* 3226 * shadow last change (col 2) 3227 */ 3228 if ((s = strchr(t, ':')) == 0) { 3229 (void) strlcpy(parse_err_msg, gettext("Improper format"), 3230 PARSE_ERR_MSG_LEN); 3231 return (GENENT_PARSEERR); 3232 } 3233 *s++ = 0; 3234 ecol[2].ec_value.ec_value_val = t; 3235 ecol[2].ec_value.ec_value_len = strlen(t)+1; 3236 t = s; 3237 3238 /* 3239 * shadow min (col 3) 3240 */ 3241 if ((s = strchr(t, ':')) == 0) { 3242 (void) strlcpy(parse_err_msg, gettext("Improper format"), 3243 PARSE_ERR_MSG_LEN); 3244 return (GENENT_PARSEERR); 3245 } 3246 *s++ = 0; 3247 ecol[3].ec_value.ec_value_val = t; 3248 ecol[3].ec_value.ec_value_len = strlen(t)+1; 3249 t = s; 3250 3251 /* 3252 * shadow max (col 4) 3253 */ 3254 if ((s = strchr(t, ':')) == 0) { 3255 (void) strlcpy(parse_err_msg, gettext("Improper format"), 3256 PARSE_ERR_MSG_LEN); 3257 return (GENENT_PARSEERR); 3258 } 3259 *s++ = 0; 3260 ecol[4].ec_value.ec_value_val = t; 3261 ecol[4].ec_value.ec_value_len = strlen(t)+1; 3262 t = s; 3263 3264 /* 3265 * shadow warn (col 5) 3266 */ 3267 if ((s = strchr(t, ':')) == 0) { 3268 (void) strlcpy(parse_err_msg, gettext("Improper format"), 3269 PARSE_ERR_MSG_LEN); 3270 return (GENENT_PARSEERR); 3271 } 3272 *s++ = 0; 3273 ecol[5].ec_value.ec_value_val = t; 3274 ecol[5].ec_value.ec_value_len = strlen(t)+1; 3275 t = s; 3276 3277 /* 3278 * shadow inactive (col 6) 3279 */ 3280 if ((s = strchr(t, ':')) != 0) { 3281 *s++ = 0; 3282 ecol[6].ec_value.ec_value_val = t; 3283 ecol[6].ec_value.ec_value_len = strlen(t)+1; 3284 t = s; 3285 } 3286 3287 /* 3288 * shadow expire (col 7) 3289 */ 3290 if ((s = strchr(t, ':')) != 0) { 3291 *s++ = 0; 3292 ecol[7].ec_value.ec_value_val = t; 3293 ecol[7].ec_value.ec_value_len = strlen(t)+1; 3294 t = s; 3295 3296 /* 3297 * flag (col 8) 3298 */ 3299 ecol[8].ec_value.ec_value_val = t; 3300 ecol[8].ec_value.ec_value_len = strlen(t)+1; 3301 } 3302 3303 /* 3304 * build entry 3305 */ 3306 3307 data.sp_namp = strdup(ecol[0].ec_value.ec_value_val); 3308 3309 if (ecol[1].ec_value.ec_value_val != NULL && 3310 ecol[1].ec_value.ec_value_val[0] != '\0') { 3311 /* Add {crypt} before passwd entry */ 3312 (void) snprintf(pname, sizeof (pname), "{crypt}%s", 3313 ecol[1].ec_value.ec_value_val); 3314 data.sp_pwdp = strdup(pname); 3315 } else { 3316 /* 3317 * no password (e.g., deleted by "passwd -d"): 3318 * use the special value NS_LDAP_NO_UNIX_PASSWORD 3319 * instead. 3320 */ 3321 (void) snprintf(pname, sizeof (pname), "{crypt}%s", 3322 NS_LDAP_NO_UNIX_PASSWORD); 3323 data.sp_pwdp = strdup(pname); 3324 } 3325 3326 if (ecol[2].ec_value.ec_value_val != NULL && 3327 ecol[2].ec_value.ec_value_val[0] != '\0') { 3328 3329 data.sp_lstchg = ascii_to_int(ecol[2].ec_value.ec_value_val); 3330 if (data.sp_lstchg < -1) { 3331 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3332 gettext("invalid last changed date: %s"), 3333 ecol[2].ec_value.ec_value_val); 3334 return (GENENT_PARSEERR); 3335 } 3336 } else 3337 data.sp_lstchg = -1; 3338 3339 if (ecol[3].ec_value.ec_value_val != NULL && 3340 ecol[3].ec_value.ec_value_val[0] != '\0') { 3341 3342 data.sp_min = ascii_to_int(ecol[3].ec_value.ec_value_val); 3343 if (data.sp_min < -1) { 3344 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3345 gettext("invalid sp_min : %s"), 3346 ecol[3].ec_value.ec_value_val); 3347 return (GENENT_PARSEERR); 3348 } 3349 } else 3350 data.sp_min = -1; 3351 3352 if (ecol[4].ec_value.ec_value_val != NULL && 3353 ecol[4].ec_value.ec_value_val[0] != '\0') { 3354 3355 data.sp_max = ascii_to_int(ecol[4].ec_value.ec_value_val); 3356 if (data.sp_max < -1) { 3357 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3358 gettext("invalid sp_max : %s"), 3359 ecol[4].ec_value.ec_value_val); 3360 return (GENENT_PARSEERR); 3361 } 3362 } else 3363 data.sp_max = -1; 3364 3365 if (ecol[5].ec_value.ec_value_val != NULL && 3366 ecol[5].ec_value.ec_value_val[0] != '\0') { 3367 3368 data.sp_warn = ascii_to_int(ecol[5].ec_value.ec_value_val); 3369 if (data.sp_warn < -1) { 3370 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3371 gettext("invalid sp_warn : %s"), 3372 ecol[5].ec_value.ec_value_val); 3373 return (GENENT_PARSEERR); 3374 } 3375 } else 3376 data.sp_warn = -1; 3377 3378 if (ecol[6].ec_value.ec_value_val != NULL && 3379 ecol[6].ec_value.ec_value_val[0] != '\0') { 3380 3381 data.sp_inact = ascii_to_int(ecol[6].ec_value.ec_value_val); 3382 if (data.sp_inact < -1) { 3383 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3384 gettext("invalid sp_inact : %s"), 3385 ecol[6].ec_value.ec_value_val); 3386 return (GENENT_PARSEERR); 3387 } 3388 } else 3389 data.sp_inact = -1; 3390 3391 if (ecol[7].ec_value.ec_value_val != NULL && 3392 ecol[7].ec_value.ec_value_val[0] != '\0') { 3393 3394 data.sp_expire = ascii_to_int(ecol[7].ec_value.ec_value_val); 3395 if (data.sp_expire < -1) { 3396 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3397 gettext("invalid login expiry date : %s"), 3398 ecol[7].ec_value.ec_value_val); 3399 return (GENENT_PARSEERR); 3400 } 3401 } else 3402 data.sp_expire = -1; 3403 3404 if (ecol[8].ec_value.ec_value_val != NULL && 3405 ecol[8].ec_value.ec_value_val[0] != '\0') { 3406 3407 /* 3408 * data.sp_flag is an unsigned int, 3409 * assign -1 to it, make no sense. 3410 * Use spflag here to avoid lint warning. 3411 */ 3412 spflag = ascii_to_int(ecol[8].ec_value.ec_value_val); 3413 if (spflag < 0) { 3414 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3415 gettext("invalid flag value: %s"), 3416 ecol[8].ec_value.ec_value_val); 3417 return (GENENT_PARSEERR); 3418 } else 3419 data.sp_flag = spflag; 3420 } else 3421 data.sp_flag = 0; 3422 3423 if (flags & F_VERBOSE) 3424 (void) fprintf(stdout, 3425 gettext("Adding entry : %s\n"), data.sp_namp); 3426 3427 retval = (*cback)(&data, 1); 3428 if (retval != NS_LDAP_SUCCESS) { 3429 if (retval == LDAP_NO_SUCH_OBJECT) 3430 (void) fprintf(stdout, 3431 gettext("Cannot add shadow entry (%s), " 3432 "add passwd entry first\n"), data.sp_namp); 3433 if (continue_onerror == 0) 3434 return (GENENT_CBERR); 3435 } 3436 3437 free(data.sp_namp); 3438 free(data.sp_pwdp); 3439 return (GENENT_OK); 3440 } 3441 3442 static void 3443 dump_shadow(ns_ldap_result_t *res) 3444 { 3445 char **value = NULL; 3446 char pnam[256]; 3447 3448 value = __ns_ldap_getAttr(res->entry, "uid"); 3449 if (value == NULL) 3450 return; 3451 else 3452 (void) fprintf(stdout, "%s:", value[0]); 3453 value = __ns_ldap_getAttr(res->entry, "userPassword"); 3454 if (value == NULL) 3455 (void) fprintf(stdout, "*:"); 3456 else { 3457 (void) strcpy(pnam, value[0]); 3458 if (strncasecmp(value[0], "{crypt}", 7) == 0) { 3459 if (strcmp(pnam + 7, NS_LDAP_NO_UNIX_PASSWORD) == 0) 3460 (void) fprintf(stdout, ":"); 3461 else 3462 (void) fprintf(stdout, "%s:", (pnam+7)); 3463 } else 3464 (void) fprintf(stdout, "*:"); 3465 } 3466 value = __ns_ldap_getAttr(res->entry, "shadowLastChange"); 3467 if (value == NULL) 3468 (void) fprintf(stdout, ":"); 3469 else 3470 (void) fprintf(stdout, "%s:", value[0]); 3471 value = __ns_ldap_getAttr(res->entry, "shadowMin"); 3472 if (value == NULL) 3473 (void) fprintf(stdout, ":"); 3474 else 3475 (void) fprintf(stdout, "%s:", value[0]); 3476 value = __ns_ldap_getAttr(res->entry, "shadowMax"); 3477 if (value == NULL) 3478 (void) fprintf(stdout, ":"); 3479 else 3480 (void) fprintf(stdout, "%s:", value[0]); 3481 3482 value = __ns_ldap_getAttr(res->entry, "shadowWarning"); 3483 if (value == NULL) 3484 (void) fprintf(stdout, ":"); 3485 else 3486 (void) fprintf(stdout, "%s:", value[0]); 3487 3488 value = __ns_ldap_getAttr(res->entry, "shadowInactive"); 3489 if (value == NULL) 3490 (void) fprintf(stdout, ":"); 3491 else 3492 (void) fprintf(stdout, "%s:", value[0]); 3493 3494 value = __ns_ldap_getAttr(res->entry, "shadowExpire"); 3495 if (value == NULL) 3496 (void) fprintf(stdout, ":"); 3497 else 3498 (void) fprintf(stdout, "%s:", value[0]); 3499 3500 value = __ns_ldap_getAttr(res->entry, "shadowFlag"); 3501 if (value == NULL || value[0] == NULL || strcmp(value[0], "0") == 0) 3502 (void) fprintf(stdout, "\n"); 3503 else 3504 (void) fprintf(stdout, "%s\n", value[0]); 3505 } 3506 3507 static int 3508 genent_bootparams(char *line, int (*cback)()) 3509 { 3510 char buf[BUFSIZ+1]; 3511 char *t; 3512 entry_col ecol[2]; 3513 int ctr = 0, retval = 1; 3514 3515 struct _ns_bootp data; 3516 char *parameter; 3517 int rc = GENENT_OK; 3518 3519 /* 3520 * don't clobber our argument 3521 */ 3522 if (strlen(line) >= sizeof (buf)) { 3523 (void) strlcpy(parse_err_msg, gettext("line too long"), 3524 PARSE_ERR_MSG_LEN); 3525 return (GENENT_PARSEERR); 3526 } 3527 (void) strcpy(buf, line); 3528 3529 /* 3530 * clear column data 3531 */ 3532 (void) memset((char *)ecol, 0, sizeof (ecol)); 3533 3534 3535 /* 3536 * cname (col 0) 3537 */ 3538 if ((t = strtok(buf, " \t")) == 0) { 3539 (void) strlcpy(parse_err_msg, gettext("no cname"), 3540 PARSE_ERR_MSG_LEN); 3541 return (GENENT_PARSEERR); 3542 } 3543 ecol[0].ec_value.ec_value_val = t; 3544 ecol[0].ec_value.ec_value_len = strlen(t)+1; 3545 3546 3547 3548 /* build entry */ 3549 data.name = strdup(ecol[0].ec_value.ec_value_val); 3550 3551 /* 3552 * name (col 1) 3553 */ 3554 3555 data.param = NULL; 3556 3557 while (t = strtok(NULL, " \t")) { 3558 3559 /* 3560 * don't clobber comment in canonical entry 3561 */ 3562 3563 3564 ecol[1].ec_value.ec_value_val = t; 3565 ecol[1].ec_value.ec_value_len = strlen(t)+1; 3566 3567 ctr++; 3568 parameter = strdup(ecol[1].ec_value.ec_value_val); 3569 if ((data.param = (char **)realloc(data.param, 3570 (ctr + 1) * sizeof (char **))) == NULL) { 3571 (void) fprintf(stderr, gettext("out of memory\n")); 3572 exit(1); 3573 } 3574 data.param[ctr-1] = parameter; 3575 3576 } 3577 3578 3579 /* End the list of all the aliases by NULL */ 3580 if ((data.param = (char **)realloc(data.param, 3581 (ctr + 1) * sizeof (char **))) == NULL) { 3582 (void) fprintf(stderr, gettext("out of memory\n")); 3583 exit(1); 3584 } 3585 data.param[ctr] = NULL; 3586 3587 if (flags & F_VERBOSE) 3588 (void) fprintf(stdout, 3589 gettext("Adding entry : %s\n"), data.name); 3590 3591 retval = (*cback)(&data, 0); 3592 3593 if (retval == LDAP_ALREADY_EXISTS) { 3594 if (continue_onerror) 3595 (void) fprintf(stderr, 3596 gettext("Entry: %s - already Exists," 3597 " skipping it.\n"), data.name); 3598 else { 3599 rc = GENENT_CBERR; 3600 (void) fprintf(stderr, 3601 gettext("Entry: %s - already Exists\n"), 3602 data.name); 3603 } 3604 } else if (retval) 3605 rc = GENENT_CBERR; 3606 3607 free(data.name); 3608 free(data.param); 3609 3610 return (rc); 3611 3612 } 3613 3614 /* 3615 * Count number of tokens in string which has tokens separated by colons. 3616 * 3617 * NULL or "" - 0 tokens 3618 * "foo" - 1 token 3619 * "foo:bar" - 2 tokens 3620 * ":bar" - 2 tokens, first empty 3621 * "::" - 3 tokens, all empty 3622 */ 3623 static int 3624 count_tokens(char *string, char delim) 3625 { 3626 int i = 0; 3627 char *s = string; 3628 3629 if (string == NULL || *string == '\0') 3630 return (0); 3631 3632 /* Count delimiters */ 3633 while ((s = strchr(s, delim)) != NULL && *s != '\0') { 3634 i++; 3635 s++; 3636 } 3637 3638 return (i + 1); 3639 } 3640 3641 static int 3642 genent_project(char *line, int (*cback)()) 3643 { 3644 char buf[BUFSIZ+1]; 3645 char *b = buf; 3646 char *s; 3647 int rc = GENENT_OK, retval; 3648 int index = 0; 3649 struct project data; 3650 3651 (void) memset(&data, 0, sizeof (struct project)); 3652 3653 /* 3654 * don't clobber our argument 3655 */ 3656 if (strlen(line) >= sizeof (buf)) { 3657 (void) strlcpy(parse_err_msg, gettext("line too long"), 3658 PARSE_ERR_MSG_LEN); 3659 return (GENENT_PARSEERR); 3660 } 3661 3662 if (count_tokens(line, ':') != 6) { 3663 (void) strlcpy(parse_err_msg, gettext("Improper format"), 3664 PARSE_ERR_MSG_LEN); 3665 return (GENENT_PARSEERR); 3666 } 3667 3668 (void) strcpy(buf, line); 3669 3670 s = strsep(&b, ":"); 3671 while (s != NULL) { 3672 switch (index) { 3673 /* Project name */ 3674 case 0: 3675 if (check_projname(s) != 0) { 3676 (void) strlcpy(parse_err_msg, 3677 gettext("invalid project name"), 3678 PARSE_ERR_MSG_LEN); 3679 return (GENENT_PARSEERR); 3680 } else { 3681 data.pj_name = strdup(s); 3682 } 3683 break; 3684 3685 /* Project ID */ 3686 case 1: 3687 { 3688 char *endptr = NULL; 3689 int projid = strtoul(s, &endptr, 10); 3690 3691 if (*s == '\0' || strlen(endptr) != 0 || projid < 0 || 3692 projid > MAXPROJID) { 3693 (void) strlcpy(parse_err_msg, 3694 gettext("invalid project id"), 3695 PARSE_ERR_MSG_LEN); 3696 return (GENENT_PARSEERR); 3697 } else { 3698 data.pj_projid = projid; 3699 } 3700 break; 3701 } 3702 3703 /* Project description */ 3704 case 2: 3705 if (*s != '\0') 3706 data.pj_comment = strdup(s); 3707 break; 3708 3709 /* Project users */ 3710 case 3: 3711 { 3712 if (*s == '\0') 3713 break; 3714 3715 char *usrlist = strdup(s); 3716 int i = 0; 3717 int usr_count = count_tokens(usrlist, ','); 3718 char *u = strsep(&usrlist, ","); 3719 3720 if (usr_count == 0) { 3721 free(usrlist); 3722 break; 3723 } 3724 3725 /* +1 to NULL-terminate the array */ 3726 data.pj_users = (char **)calloc(usr_count + 1, 3727 sizeof (char *)); 3728 3729 while (u != NULL) { 3730 data.pj_users[i++] = strdup(u); 3731 u = strsep(&usrlist, ","); 3732 } 3733 3734 free(usrlist); 3735 break; 3736 } 3737 3738 /* Project groups */ 3739 case 4: 3740 { 3741 if (*s == '\0') 3742 break; 3743 3744 char *grouplist = strdup(s); 3745 int i = 0; 3746 int grp_count = count_tokens(grouplist, ','); 3747 char *g = strsep(&grouplist, ","); 3748 3749 if (grp_count == 0) { 3750 free(grouplist); 3751 break; 3752 } 3753 3754 /* +1 to NULL-terminate the array */ 3755 data.pj_groups = (char **)calloc(grp_count + 1, 3756 sizeof (char *)); 3757 3758 while (g != NULL) { 3759 data.pj_groups[i++] = strdup(g); 3760 g = strsep(&grouplist, ","); 3761 } 3762 3763 free(grouplist); 3764 break; 3765 } 3766 3767 /* Attributes */ 3768 case 5: 3769 if (*s != '\0') 3770 data.pj_attr = strdup(s); 3771 3772 break; 3773 } 3774 3775 /* Next token */ 3776 s = strsep(&b, ":"); 3777 index++; 3778 } 3779 3780 if (flags & F_VERBOSE) 3781 (void) fprintf(stdout, 3782 gettext("Adding entry : %s\n"), data.pj_name); 3783 3784 retval = (*cback)(&data, 0); 3785 3786 if (retval == LDAP_ALREADY_EXISTS) { 3787 if (continue_onerror) 3788 (void) fprintf(stderr, 3789 gettext("Entry: %s - already Exists," 3790 " skipping it.\n"), data.pj_name); 3791 else { 3792 rc = GENENT_CBERR; 3793 (void) fprintf(stderr, 3794 gettext("Entry: %s - already Exists\n"), 3795 data.pj_name); 3796 } 3797 } else if (retval) 3798 rc = GENENT_CBERR; 3799 3800 /* Clean up */ 3801 free(data.pj_name); 3802 free(data.pj_attr); 3803 if (data.pj_users != NULL) { 3804 for (index = 0; data.pj_users[index] != NULL; index++) 3805 free(data.pj_users[index]); 3806 free(data.pj_users); 3807 } 3808 if (data.pj_groups != NULL) { 3809 for (index = 0; data.pj_groups[index] != NULL; index++) 3810 free(data.pj_groups[index]); 3811 free(data.pj_groups); 3812 } 3813 3814 return (rc); 3815 } 3816 3817 static void 3818 dump_project(ns_ldap_result_t *res) 3819 { 3820 char **value = NULL; 3821 char *endptr = NULL; 3822 int projid; 3823 3824 if (res == NULL || res->entry == NULL) 3825 return; 3826 3827 /* Sanity checking */ 3828 value = __ns_ldap_getAttr(res->entry, "SolarisProjectID"); 3829 3830 if (value[0] == NULL) 3831 return; 3832 3833 projid = strtoul(value[0], &endptr, 10); 3834 if (*value[0] == '\0' || strlen(endptr) != 0 || projid < 0 || 3835 projid > MAXPROJID) 3836 return; 3837 3838 value = __ns_ldap_getAttr(res->entry, "SolarisProjectName"); 3839 if (value && value[0] && check_projname(value[0]) == 0) 3840 (void) fprintf(stdout, "%s:", value[0]); 3841 else 3842 return; 3843 3844 (void) fprintf(stdout, "%d:", projid); 3845 3846 value = __ns_ldap_getAttr(res->entry, "description"); 3847 if (value && value[0]) 3848 (void) fprintf(stdout, "%s:", value[0]); 3849 else 3850 (void) fprintf(stdout, ":"); 3851 3852 value = __ns_ldap_getAttr(res->entry, "memberUid"); 3853 if (value) { 3854 int i; 3855 for (i = 0; value[i] != NULL; i++) 3856 if (value[i+1] != NULL) 3857 (void) fprintf(stdout, "%s,", value[i]); 3858 else 3859 (void) fprintf(stdout, "%s:", value[i]); 3860 } else { 3861 (void) fprintf(stdout, ":"); 3862 } 3863 3864 value = __ns_ldap_getAttr(res->entry, "memberGid"); 3865 if (value) { 3866 int i; 3867 for (i = 0; value[i] != NULL; i++) 3868 if (value[i+1] != NULL) 3869 (void) fprintf(stdout, "%s,", value[i]); 3870 else 3871 (void) fprintf(stdout, "%s:", value[i]); 3872 } else { 3873 (void) fprintf(stdout, ":"); 3874 } 3875 3876 value = __ns_ldap_getAttr(res->entry, "SolarisProjectAttr"); 3877 if (value && value[0]) 3878 (void) fprintf(stdout, "%s\n", value[0]); 3879 else 3880 (void) fprintf(stdout, "\n"); 3881 3882 } 3883 3884 static void 3885 dump_bootparams(ns_ldap_result_t *res) 3886 { 3887 char **value = NULL; 3888 int attr_count = 0; 3889 3890 value = __ns_ldap_getAttr(res->entry, "cn"); 3891 if (value[0] != NULL) 3892 (void) fprintf(stdout, "%s", value[0]); 3893 value = __ns_ldap_getAttr(res->entry, "bootParameter"); 3894 if (value != NULL) 3895 while (value[attr_count] != NULL) { 3896 (void) fprintf(stdout, "\t%s", value[attr_count]); 3897 attr_count++; 3898 } 3899 (void) fprintf(stdout, "\n"); 3900 3901 3902 } 3903 3904 static char * 3905 fget_line_at(struct line_buf *line, int n, FILE *fp) 3906 { 3907 int c; 3908 3909 line->len = n; 3910 3911 for (;;) { 3912 c = fgetc(fp); 3913 if (c == -1) 3914 break; 3915 if (line->len >= line->alloc) 3916 line_buf_expand(line); 3917 line->str[line->len++] = c; 3918 3919 if (c == '\n') 3920 break; 3921 } 3922 3923 /* Null Terminate */ 3924 if (line->len >= line->alloc) 3925 line_buf_expand(line); 3926 line->str[line->len++] = 0; 3927 3928 /* if no characters are read, return NULL to indicate EOF */ 3929 if (line->str[0] == '\0') 3930 return (0); 3931 3932 return (line->str); 3933 } 3934 3935 /* 3936 * return a line from the file, discarding comments and blank lines 3937 */ 3938 static int 3939 filedbmline_comment(struct line_buf *line, FILE *etcf, int *lineno, 3940 struct file_loc *loc) 3941 { 3942 int i, len = 0; 3943 3944 loc->offset = ftell(etcf); 3945 for (;;) { 3946 if (fget_line_at(line, len, etcf) == 0) 3947 return (0); 3948 3949 if (lineno) 3950 (*lineno)++; 3951 3952 len = strlen(line->str); 3953 if (len >= 2 && 3954 line->str[0] != '#' && 3955 line->str[len-2] == '\\' && line->str[len-1] == '\n') { 3956 line->str[len-2] = 0; 3957 len -= 2; 3958 continue; /* append next line at end */ 3959 } 3960 3961 if (line->str[len-1] == '\n') { 3962 line->str[len-1] = 0; 3963 len -= 1; 3964 } 3965 3966 /* 3967 * Skip lines where '#' is the first non-blank character. 3968 */ 3969 for (i = 0; i < len; i++) { 3970 if (line->str[i] == '#') { 3971 line->str[i] = '\0'; 3972 len = i; 3973 break; 3974 } 3975 if (line->str[i] != ' ' && line->str[i] != '\t') 3976 break; 3977 } 3978 3979 /* 3980 * A line with one or more white space characters followed 3981 * by a comment will now be blank. The special case of a 3982 * line with '#' in the first byte will have len == 0. 3983 */ 3984 if (len > 0 && !blankline(line->str)) 3985 break; 3986 3987 len = 0; 3988 loc->offset = ftell(etcf); 3989 } 3990 3991 loc->size = len; 3992 return (1); 3993 } 3994 3995 /* 3996 * return a line from the file, discarding comments, blanks, and '+' lines 3997 */ 3998 static int 3999 filedbmline_plus(struct line_buf *line, FILE *etcf, int *lineno, 4000 struct file_loc *loc) 4001 { 4002 int len = 0; 4003 4004 loc->offset = ftell(etcf); 4005 for (;;) { 4006 if (fget_line_at(line, len, etcf) == 0) 4007 return (0); 4008 4009 if (lineno) 4010 (*lineno)++; 4011 4012 len = strlen(line->str); 4013 if (line->str[len-1] == '\n') { 4014 line->str[len-1] = 0; 4015 len -= 1; 4016 } 4017 4018 if (!blankline(line->str) && 4019 line->str[0] != '+' && line->str[0] != '-' && 4020 line->str[0] != '#') 4021 break; 4022 4023 len = 0; 4024 loc->offset = ftell(etcf); 4025 } 4026 4027 loc->size = len; 4028 return (1); 4029 } 4030 4031 4032 /* Populating the ttypelist structure */ 4033 4034 static struct ttypelist_t ttypelist[] = { 4035 { NS_LDAP_TYPE_HOSTS, genent_hosts, dump_hosts, 4036 filedbmline_comment, "iphost", "cn" }, 4037 { NS_LDAP_TYPE_IPNODES, genent_hosts, dump_hosts, 4038 filedbmline_comment, "iphost", "cn" }, 4039 { NS_LDAP_TYPE_RPC, genent_rpc, dump_rpc, 4040 filedbmline_comment, "oncrpc", "cn" }, 4041 { NS_LDAP_TYPE_PROTOCOLS, genent_protocols, dump_protocols, 4042 filedbmline_comment, "ipprotocol", "cn" }, 4043 { NS_LDAP_TYPE_NETWORKS, genent_networks, dump_networks, 4044 filedbmline_comment, "ipnetwork", "ipnetworknumber" }, 4045 { NS_LDAP_TYPE_SERVICES, genent_services, dump_services, 4046 filedbmline_comment, "ipservice", "cn" }, 4047 { NS_LDAP_TYPE_GROUP, genent_group, dump_group, 4048 filedbmline_plus, "posixgroup", "gidnumber" }, 4049 { NS_LDAP_TYPE_NETMASKS, genent_netmasks, dump_netmasks, 4050 filedbmline_comment, "ipnetwork", "ipnetworknumber"}, 4051 { NS_LDAP_TYPE_ETHERS, genent_ethers, dump_ethers, 4052 filedbmline_comment, "ieee802Device", "cn" }, 4053 { NS_LDAP_TYPE_NETGROUP, genent_netgroup, dump_netgroup, 4054 filedbmline_comment, "nisnetgroup", "cn" }, 4055 { NS_LDAP_TYPE_BOOTPARAMS, genent_bootparams, dump_bootparams, 4056 filedbmline_comment, "bootableDevice", "cn" }, 4057 { NS_LDAP_TYPE_PUBLICKEY, genent_publickey, NULL /* dump_publickey */, 4058 filedbmline_comment, "niskeyobject", "cn" }, 4059 { NS_LDAP_TYPE_PASSWD, genent_passwd, dump_passwd, 4060 filedbmline_plus, "posixaccount", "uid" }, 4061 { NS_LDAP_TYPE_SHADOW, genent_shadow, dump_shadow, 4062 filedbmline_plus, "shadowaccount", "uid" }, 4063 { NS_LDAP_TYPE_ALIASES, genent_aliases, dump_aliases, 4064 filedbmline_plus, "mailGroup", "cn" }, 4065 { NS_LDAP_TYPE_AUTOMOUNT, genent_automount, dump_automount, 4066 filedbmline_comment, "automount", "automountKey" }, 4067 { NS_LDAP_TYPE_USERATTR, genent_user_attr, dump_user_attr, 4068 filedbmline_comment, "SolarisUserAttr", "uid" }, 4069 { NS_LDAP_TYPE_PROFILE, genent_prof_attr, dump_prof_attr, 4070 filedbmline_comment, "SolarisProfAttr", "cn" }, 4071 { NS_LDAP_TYPE_EXECATTR, genent_exec_attr, dump_exec_attr, 4072 filedbmline_comment, "SolarisExecAttr", "cn" }, 4073 { NS_LDAP_TYPE_AUTHATTR, genent_auth_attr, dump_auth_attr, 4074 filedbmline_comment, "SolarisAuthAttr", "cn" }, 4075 { NS_LDAP_TYPE_TNRHDB, genent_tnrhdb, dump_tnrhdb, 4076 filedbmline_comment, "ipTnetHost", "ipTnetNumber" }, 4077 { NS_LDAP_TYPE_TNRHTP, genent_tnrhtp, dump_tnrhtp, 4078 filedbmline_comment, "ipTnetTemplate", "ipTnetTemplateName" }, 4079 { NS_LDAP_TYPE_PROJECT, genent_project, dump_project, 4080 filedbmline_comment, "SolarisProject", "SolarisProjectName" }, 4081 { 0, 0, 0, 0, 0, 0 } 4082 }; 4083 4084 4085 4086 4087 static int lineno = 0; 4088 4089 static void 4090 addfile() 4091 { 4092 struct line_buf line; 4093 struct file_loc loc; 4094 4095 /* Initializing the Line Buffer */ 4096 line_buf_init(&line); 4097 4098 /* Loop through all the lines in the file */ 4099 while (tt->filedbmline(&line, etcf, &lineno, &loc)) { 4100 switch ((*(tt->genent))(line.str, addentry)) { 4101 case GENENT_OK: 4102 break; 4103 case GENENT_PARSEERR: 4104 (void) fprintf(stderr, 4105 gettext("parse error: %s (line %d)\n"), 4106 parse_err_msg, lineno); 4107 exit_val = 1; 4108 break; 4109 case GENENT_CBERR: 4110 (void) fprintf(stderr, 4111 gettext("Error while adding line: %s\n"), 4112 line.str); 4113 exit_val = 2; 4114 free(line.str); 4115 return; 4116 break; 4117 case GENENT_ERR: 4118 (void) fprintf(stderr, 4119 gettext("Internal Error while adding line: %s\n"), 4120 line.str); 4121 exit_val = 3; 4122 free(line.str); 4123 return; 4124 break; 4125 } 4126 } 4127 free(line.str); 4128 } 4129 4130 static void 4131 dumptable(char *service) 4132 { 4133 4134 ns_ldap_result_t *eres = NULL; 4135 ns_ldap_error_t *err = NULL; 4136 int rc = 0, success = 0; 4137 char filter[BUFSIZ]; 4138 int done = 0; 4139 void *cookie = NULL; 4140 4141 /* set the appropriate filter */ 4142 if (strcmp(tt->ttype, NS_LDAP_TYPE_PROFILE) == 0) { 4143 /* 4144 * prof_attr entries are SolarisProfAttr 4145 * without AUXILIARY SolarisExecAttr 4146 */ 4147 (void) snprintf(filter, sizeof (filter), 4148 "(&(objectclass=%s)(!(objectclass=SolarisExecAttr)))", 4149 tt->objclass); 4150 } else if (strcmp(tt->ttype, NS_LDAP_TYPE_TNRHDB) == 0) { 4151 /* 4152 * tnrhtp entries are ipTnet entries with SolarisAttrKeyValue 4153 */ 4154 (void) snprintf(filter, sizeof (filter), 4155 "(&(objectclass=%s)(SolarisAttrKeyValue=*)))", 4156 tt->objclass); 4157 } else { 4158 (void) snprintf(filter, sizeof (filter), 4159 "(objectclass=%s)", tt->objclass); 4160 } 4161 4162 if (flags & F_VERBOSE) 4163 (void) fprintf(stdout, gettext("FILTER = %s\n"), filter); 4164 4165 /* Pass cred only if supplied. Cred is not always needed for dump */ 4166 if (authority.cred.unix_cred.userID == NULL || 4167 authority.cred.unix_cred.passwd == NULL) 4168 rc = __ns_ldap_firstEntry(service, filter, tt->sortattr, NULL, 4169 NULL, NULL, NS_LDAP_HARD, &cookie, &eres, &err, NULL); 4170 else 4171 rc = __ns_ldap_firstEntry(service, filter, tt->sortattr, NULL, 4172 NULL, &authority, NS_LDAP_HARD, &cookie, &eres, &err, NULL); 4173 4174 switch (rc) { 4175 case NS_LDAP_SUCCESS: 4176 nent_add++; 4177 success = 1; 4178 if (eres != NULL) { 4179 if (strcmp(databasetype, "publickey") == 0) 4180 dump_publickey(eres, service); 4181 else 4182 (*(tt->dump))(eres); 4183 } 4184 else 4185 (void) fprintf(stderr, gettext("No entries found.\n")); 4186 break; 4187 4188 case NS_LDAP_OP_FAILED: 4189 exit_val = 2; 4190 (void) fprintf(stderr, gettext("operation failed.\n")); 4191 break; 4192 4193 case NS_LDAP_INVALID_PARAM: 4194 exit_val = 2; 4195 (void) fprintf(stderr, 4196 gettext("invalid parameter(s) passed.\n")); 4197 break; 4198 4199 case NS_LDAP_NOTFOUND: 4200 exit_val = 2; 4201 (void) fprintf(stderr, gettext("entry not found.\n")); 4202 break; 4203 4204 case NS_LDAP_MEMORY: 4205 exit_val = 2; 4206 (void) fprintf(stderr, 4207 gettext("internal memory allocation error.\n")); 4208 break; 4209 4210 case NS_LDAP_CONFIG: 4211 exit_val = 2; 4212 (void) fprintf(stderr, 4213 gettext("LDAP Configuration problem.\n")); 4214 perr(err); 4215 break; 4216 4217 case NS_LDAP_PARTIAL: 4218 exit_val = 2; 4219 (void) fprintf(stderr, 4220 gettext("partial result returned\n")); 4221 perr(err); 4222 break; 4223 4224 case NS_LDAP_INTERNAL: 4225 exit_val = 2; 4226 (void) fprintf(stderr, 4227 gettext("internal LDAP error occured.\n")); 4228 perr(err); 4229 break; 4230 } 4231 4232 if (eres != NULL) { 4233 (void) __ns_ldap_freeResult(&eres); 4234 eres = NULL; 4235 } 4236 4237 if (success) { 4238 while (!done) { 4239 rc = __ns_ldap_nextEntry(cookie, &eres, &err); 4240 if (rc != NS_LDAP_SUCCESS || eres == NULL) { 4241 done = 1; 4242 continue; 4243 } 4244 4245 /* Print the result */ 4246 if (eres != NULL) { 4247 if (strcmp(databasetype, "publickey") == 0) 4248 dump_publickey(eres, service); 4249 else 4250 (*(tt->dump))(eres); 4251 (void) __ns_ldap_freeResult(&eres); 4252 eres = NULL; 4253 } 4254 } 4255 } 4256 } 4257 4258 int 4259 main(int argc, char **argv) 4260 { 4261 char *password; 4262 ns_standalone_conf_t standalone_cfg = standaloneDefaults; 4263 int c; 4264 int rc; 4265 int ldaprc; 4266 int authstried = 0; 4267 int op = OP_ADD; 4268 char *ttype, *authmech = 0, *etcfile = 0; 4269 /* Temporary password variable */ 4270 char ps[LDAP_MAXNAMELEN]; 4271 char filter[BUFSIZ]; 4272 void **paramVal = NULL; 4273 ns_auth_t **app; 4274 ns_auth_t **authpp = NULL; 4275 ns_auth_t *authp = NULL; 4276 ns_ldap_error_t *errorp = NULL; 4277 ns_ldap_result_t *resultp; 4278 ns_ldap_entry_t *e; 4279 int flag = 0; 4280 int version1 = 0; 4281 4282 (void) setlocale(LC_ALL, ""); 4283 (void) textdomain(TEXT_DOMAIN); 4284 4285 openlog("ldapaddent", LOG_PID, LOG_USER); 4286 4287 inputbasedn = NULL; 4288 authority.cred.unix_cred.passwd = NULL; 4289 authority.cred.unix_cred.userID = NULL; 4290 authority.auth.type = NS_LDAP_AUTH_SIMPLE; 4291 4292 while ((c = getopt(argc, argv, "cdh:N:M:vpf:D:w:j:b:a:P:r:")) != EOF) { 4293 switch (c) { 4294 case 'd': 4295 if (op) 4296 usage(gettext( 4297 "no other option should be specified")); 4298 op = OP_DUMP; 4299 break; 4300 case 'c': 4301 continue_onerror = 1; 4302 break; 4303 case 'v': 4304 flags |= F_VERBOSE; 4305 break; 4306 case 'p': 4307 flags |= F_PASSWD; 4308 break; 4309 case 'M': 4310 standalone_cfg.type = NS_LDAP_SERVER; 4311 standalone_cfg.SA_DOMAIN = optarg; 4312 break; 4313 case 'h': 4314 standalone_cfg.type = NS_LDAP_SERVER; 4315 if (separatePort(optarg, 4316 &standalone_cfg.SA_SERVER, 4317 &standalone_cfg.SA_PORT) > 0) { 4318 exit(1); 4319 } 4320 break; 4321 case 'P': 4322 standalone_cfg.type = NS_LDAP_SERVER; 4323 authority.hostcertpath = optarg; 4324 break; 4325 case 'N': 4326 standalone_cfg.type = NS_LDAP_SERVER; 4327 standalone_cfg.SA_PROFILE_NAME = optarg; 4328 break; 4329 case 'f': 4330 etcfile = optarg; 4331 break; 4332 case 'D': 4333 authority.cred.unix_cred.userID = strdup(optarg); 4334 break; 4335 case 'w': 4336 if (authority.cred.unix_cred.passwd) { 4337 (void) fprintf(stderr, 4338 gettext("Warning: The -w option is mutually" 4339 " exclusive of -j. -w is ignored.\n")); 4340 break; 4341 } 4342 4343 if (optarg != NULL && 4344 optarg[0] == '-' && optarg[1] == '\0') { 4345 /* Ask for a password later */ 4346 break; 4347 } 4348 4349 authority.cred.unix_cred.passwd = strdup(optarg); 4350 break; 4351 case 'j': 4352 if (authority.cred.unix_cred.passwd != NULL) { 4353 (void) fprintf(stderr, 4354 gettext("The -w option is mutually " 4355 "exclusive of -j. -w is ignored.\n")); 4356 free(authority.cred.unix_cred.passwd); 4357 } 4358 authority.cred.unix_cred.passwd = readPwd(optarg); 4359 if (authority.cred.unix_cred.passwd == NULL) { 4360 exit(1); 4361 } 4362 break; 4363 case 'b': 4364 inputbasedn = strdup(optarg); 4365 break; 4366 case 'a': 4367 authmech = strdup(optarg); 4368 break; 4369 default: 4370 usage(gettext("Invalid option")); 4371 } 4372 } 4373 4374 if (standalone_cfg.type == NS_LDAP_SERVER && 4375 standalone_cfg.SA_SERVER == NULL) { 4376 (void) fprintf(stderr, 4377 gettext("Please specify an LDAP server you want " 4378 "to connect to. \n")); 4379 exit(1); 4380 } 4381 4382 if (authmech != NULL) { 4383 if (__ns_ldap_initAuth(authmech, &authority.auth, &errorp) != 4384 NS_LDAP_SUCCESS) { 4385 if (errorp) { 4386 (void) fprintf(stderr, "%s", errorp->message); 4387 (void) __ns_ldap_freeError(&errorp); 4388 } 4389 exit(1); 4390 } 4391 } 4392 4393 if (authority.auth.saslmech != NS_LDAP_SASL_GSSAPI && 4394 authority.cred.unix_cred.userID == NULL && 4395 op != OP_DUMP) { 4396 /* This is not an optional parameter. Exit */ 4397 (void) fprintf(stderr, 4398 gettext("DN must be specified unless SASL/GSSAPI is used." 4399 " Use option -D.\n")); 4400 exit(1); 4401 } 4402 4403 if (authority.auth.saslmech != NS_LDAP_SASL_GSSAPI && 4404 authority.cred.unix_cred.passwd == NULL && 4405 (op != OP_DUMP || 4406 standalone_cfg.type != NS_CACHEMGR && 4407 authority.cred.unix_cred.userID != NULL)) { 4408 /* If password is not specified, then prompt user for it. */ 4409 password = getpassphrase("Enter password:"); 4410 (void) strcpy(ps, password); 4411 authority.cred.unix_cred.passwd = strdup(ps); 4412 } 4413 4414 standalone_cfg.SA_AUTH = authmech == NULL ? NULL : &authority.auth; 4415 standalone_cfg.SA_CERT_PATH = authority.hostcertpath; 4416 standalone_cfg.SA_BIND_DN = authority.cred.unix_cred.userID; 4417 standalone_cfg.SA_BIND_PWD = authority.cred.unix_cred.passwd; 4418 4419 if (__ns_ldap_initStandalone(&standalone_cfg, 4420 &errorp) != NS_LDAP_SUCCESS) { 4421 if (errorp) { 4422 (void) fprintf(stderr, "%s", errorp->message); 4423 } 4424 exit(1); 4425 } 4426 4427 if (authmech == NULL) { 4428 ldaprc = __ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp, 4429 &errorp); 4430 if (ldaprc != NS_LDAP_SUCCESS || 4431 (authpp == NULL && op != OP_DUMP)) { 4432 (void) fprintf(stderr, 4433 gettext("No legal authentication method " 4434 "configured.\n")); 4435 (void) fprintf(stderr, 4436 gettext("Provide a legal authentication method " 4437 "using -a option\n")); 4438 exit(1); 4439 } 4440 4441 /* Use the first authentication method which is not none */ 4442 for (app = authpp; *app; app++) { 4443 authp = *app; 4444 if (authp->type != NS_LDAP_AUTH_NONE) { 4445 authstried++; 4446 authority.auth.type = authp->type; 4447 authority.auth.tlstype = authp->tlstype; 4448 authority.auth.saslmech = authp->saslmech; 4449 authority.auth.saslopt = authp->saslopt; 4450 break; 4451 } 4452 } 4453 if (authstried == 0 && op != OP_DUMP) { 4454 (void) fprintf(stderr, 4455 gettext("No legal authentication method configured." 4456 "\nProvide a legal authentication method using " 4457 "-a option")); 4458 exit(1); 4459 } 4460 if (authority.auth.saslmech == NS_LDAP_SASL_GSSAPI && 4461 authority.cred.unix_cred.passwd != NULL && 4462 authority.cred.unix_cred.userID != NULL) { 4463 /* 4464 * -a is not specified and the auth method sasl/GSSAPI 4465 * is defined in the configuration of the ldap profile. 4466 * Even -D and -w is provided it's not valid usage. 4467 * Drop them on the floor. 4468 */ 4469 4470 (void) fprintf(stderr, 4471 gettext("The default authentication is " 4472 "sasl/GSSAPI.\n" 4473 "The bind DN and password will be ignored.\n")); 4474 authority.cred.unix_cred.passwd = NULL; 4475 authority.cred.unix_cred.userID = NULL; 4476 } 4477 } 4478 4479 ttype = argv[optind++]; 4480 4481 if (ttype == NULL) { 4482 usage(gettext("No database type specified")); 4483 exit(1); 4484 } 4485 4486 if (strncasecmp(ttype, "automount", 9) == 0) { 4487 (void) fprintf(stderr, 4488 gettext("automount is not a valid service for ldapaddent.\n" 4489 "Please use auto_*.\n" 4490 "e.g. auto_home, auto_ws etc.\n ")); 4491 exit(1); 4492 } 4493 4494 for (tt = ttypelist; tt->ttype; tt++) { 4495 if (strcmp(tt->ttype, ttype) == 0) 4496 break; 4497 if (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0 && 4498 strncmp(ttype, NS_LDAP_TYPE_AUTOMOUNT, 4499 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) 4500 break; 4501 } 4502 4503 if (tt->ttype == 0) { 4504 (void) fprintf(stderr, 4505 gettext("database %s not supported;" 4506 " supported databases are:\n"), ttype); 4507 for (tt = ttypelist; tt->ttype; tt++) 4508 (void) fprintf(stderr, gettext("\t%s\n"), tt->ttype); 4509 exit(1); 4510 } 4511 4512 if (flags & F_VERBOSE) 4513 (void) fprintf(stdout, gettext("SERVICE = %s\n"), tt->ttype); 4514 4515 databasetype = ttype; 4516 4517 if (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0) { 4518 paramVal = NULL; 4519 errorp = NULL; 4520 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, 4521 &errorp); 4522 if (paramVal && *paramVal && 4523 strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0) 4524 version1 = 1; 4525 if (paramVal) 4526 (void) __ns_ldap_freeParam(¶mVal); 4527 if (errorp) 4528 (void) __ns_ldap_freeError(&errorp); 4529 } 4530 4531 /* Check if the container exists in first place */ 4532 (void) strcpy(&filter[0], "(objectclass=*)"); 4533 4534 rc = __ns_ldap_list(databasetype, filter, NULL, (const char **)NULL, 4535 NULL, NS_LDAP_SCOPE_BASE, &resultp, &errorp, NULL, NULL); 4536 4537 /* create a container for auto_* if it does not exist already */ 4538 if ((rc == NS_LDAP_NOTFOUND) && (op == OP_ADD) && 4539 (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0)) { 4540 static char *oclist[] = {NULL, "top", NULL}; 4541 if (version1) 4542 oclist[0] = "nisMap"; 4543 else 4544 oclist[0] = "automountMap"; 4545 e = __s_mk_entry(oclist, 3); 4546 if (e == NULL) { 4547 (void) fprintf(stderr, 4548 gettext("internal memory allocation error.\n")); 4549 exit(1); 4550 } 4551 if (__s_add_attr(e, 4552 version1 ? "nisMapName" : "automountMapName", 4553 databasetype) != NS_LDAP_SUCCESS) { 4554 (void) fprintf(stderr, 4555 gettext("internal memory allocation error.\n")); 4556 ldap_freeEntry(e); 4557 exit(1); 4558 } 4559 4560 if (inputbasedn == NULL) { 4561 if (get_basedn(databasetype, &inputbasedn) != 4562 NS_LDAP_SUCCESS) { 4563 (void) fprintf(stderr, 4564 gettext("Could not obtain basedn\n")); 4565 ldap_freeEntry(e); 4566 exit(1); 4567 } 4568 } 4569 if (__ns_ldap_addEntry(databasetype, inputbasedn, e, 4570 &authority, flag, &errorp) != NS_LDAP_SUCCESS) { 4571 (void) fprintf(stderr, 4572 gettext("Could not create container for %s\n"), 4573 databasetype); 4574 ldap_freeEntry(e); 4575 } 4576 } else if (strcmp(databasetype, "publickey") != 0) { 4577 if (rc == NS_LDAP_NOTFOUND) { 4578 (void) fprintf(stderr, 4579 gettext("Container %s does not exist\n"), 4580 databasetype); 4581 exit(1); 4582 } 4583 } 4584 4585 if (op == OP_DUMP) { 4586 if (strcmp(databasetype, "publickey") == 0) { 4587 dumptable("hosts"); 4588 dumptable("passwd"); 4589 } else { 4590 dumptable(databasetype); 4591 } 4592 exit(exit_val); 4593 } 4594 4595 if (etcfile) { 4596 if ((etcf = fopen(etcfile, "r")) == 0) { 4597 (void) fprintf(stderr, 4598 gettext("can't open file %s\n"), etcfile); 4599 exit(1); 4600 } 4601 } else { 4602 etcfile = "stdin"; 4603 etcf = stdin; 4604 } 4605 4606 if (op == OP_ADD) { 4607 (void) addfile(); 4608 (void) fprintf(stdout, gettext("%d entries added\n"), nent_add); 4609 } 4610 4611 __ns_ldap_cancelStandalone(); 4612 /* exit() -> return for make lint */ 4613 return (exit_val); 4614 } 4615 4616 4617 /* 4618 * This is called when service == auto_*. 4619 * It calls __ns_ldap_getSearchDescriptors 4620 * to generate the dn from SSD's base dn. 4621 * If there is no SSD available, 4622 * default base dn will be used 4623 * Only the first baseDN in the SSD is used 4624 */ 4625 4626 static int get_basedn(char *service, char **basedn) { 4627 int rc = NS_LDAP_SUCCESS; 4628 char *dn = NULL; 4629 ns_ldap_search_desc_t **desc = NULL; 4630 ns_ldap_error_t *errp = NULL; 4631 void **paramVal = NULL; 4632 int prepend_automountmapname = FALSE; 4633 4634 /* 4635 * Get auto_* SSD first 4636 */ 4637 4638 if ((rc = __ns_ldap_getSearchDescriptors( 4639 (const char *) service, 4640 &desc, &errp)) == NS_LDAP_SUCCESS && 4641 desc != NULL) { 4642 4643 if (desc[0] != NULL && desc[0]->basedn != NULL) { 4644 dn = strdup(desc[0]->basedn); 4645 if (dn == NULL) { 4646 (void) __ns_ldap_freeSearchDescriptors 4647 (&desc); 4648 return (NS_LDAP_MEMORY); 4649 } 4650 } 4651 } 4652 4653 /* clean up */ 4654 if (desc) (void) __ns_ldap_freeSearchDescriptors(&desc); 4655 if (errp) (void) __ns_ldap_freeError(&errp); 4656 4657 /* 4658 * If no dn is duplicated from auto_* SSD, try automount SSD 4659 */ 4660 if (dn == NULL) { 4661 if ((rc = __ns_ldap_getSearchDescriptors( 4662 "automount", &desc, &errp)) 4663 == NS_LDAP_SUCCESS && desc != NULL) { 4664 4665 if (desc[0] != NULL && desc[0]->basedn != NULL) { 4666 dn = strdup(desc[0]->basedn); 4667 if (dn == NULL) { 4668 (void) __ns_ldap_freeSearchDescriptors 4669 (&desc); 4670 return (NS_LDAP_MEMORY); 4671 } 4672 prepend_automountmapname = TRUE; 4673 } 4674 } 4675 /* clean up */ 4676 if (desc) (void) __ns_ldap_freeSearchDescriptors(&desc); 4677 if (errp) (void) __ns_ldap_freeError(&errp); 4678 } 4679 4680 /* 4681 * If no dn is duplicated from auto_* or automount SSD, 4682 * use default DN 4683 */ 4684 4685 if (dn == NULL) { 4686 if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 4687 ¶mVal, &errp)) == NS_LDAP_SUCCESS) { 4688 dn = strdup((char *)paramVal[0]); 4689 if (dn == NULL) { 4690 (void) __ns_ldap_freeParam(¶mVal); 4691 return (NS_LDAP_MEMORY); 4692 } 4693 prepend_automountmapname = TRUE; 4694 } 4695 if (paramVal) (void) __ns_ldap_freeParam(¶mVal); 4696 if (errp) (void) __ns_ldap_freeError(&errp); 4697 } 4698 4699 4700 if (dn == NULL) { 4701 return (NS_LDAP_OP_FAILED); 4702 } else { 4703 /* 4704 * If dn is duplicated from 4705 * automount SSD basedn or 4706 * default base dn 4707 * then prepend automountMapName=auto_xxx 4708 */ 4709 if (prepend_automountmapname) 4710 rc = __s_api_prepend_automountmapname_to_dn( 4711 service, &dn, &errp); 4712 4713 if (rc != NS_LDAP_SUCCESS) { 4714 (void) __ns_ldap_freeError(&errp); 4715 free(dn); 4716 return (rc); 4717 } 4718 4719 *basedn = dn; 4720 4721 return (NS_LDAP_SUCCESS); 4722 } 4723 } 4724 static char * 4725 h_errno2str(int h_errno) { 4726 switch (h_errno) { 4727 case HOST_NOT_FOUND: 4728 return ("HOST_NOT_FOUND"); 4729 break; 4730 case TRY_AGAIN: 4731 return ("TRY_AGAIN"); 4732 break; 4733 case NO_RECOVERY: 4734 return ("NO_RECOVERY"); 4735 break; 4736 case NO_DATA: 4737 return ("NO_DATA"); 4738 break; 4739 default: 4740 break; 4741 } 4742 return ("UNKNOWN_ERROR"); 4743 } 4744