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