1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 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 int ctr = 0; 1653 int retval = 1; 1654 int rc = GENENT_OK; 1655 1656 /* 1657 * don't clobber our argument 1658 */ 1659 if (strlen(line) >= sizeof (buf)) { 1660 (void) strcpy(parse_err_msg, "line too long"); 1661 return (GENENT_PARSEERR); 1662 } 1663 (void) strcpy(buf, line); 1664 t = buf; 1665 1666 /* ignore empty entries */ 1667 if (*t == '\0') 1668 return (GENENT_OK); 1669 1670 /* 1671 * clear column data 1672 */ 1673 (void) memset((char *)ecol, 0, sizeof (ecol)); 1674 1675 /* 1676 * name (col 0) 1677 */ 1678 if ((s = strchr(t, ':')) == 0) { 1679 (void) strcpy(parse_err_msg, "no passwd"); 1680 return (GENENT_PARSEERR); 1681 } 1682 *s++ = 0; 1683 ecol[0].ec_value.ec_value_val = t; 1684 ecol[0].ec_value.ec_value_len = strlen(t)+1; 1685 t = s; 1686 1687 /* 1688 * passwd (col 1) 1689 */ 1690 if ((s = strchr(t, ':')) == 0) { 1691 (void) strcpy(parse_err_msg, "no gid"); 1692 return (GENENT_PARSEERR); 1693 } 1694 *s++ = 0; 1695 ecol[1].ec_value.ec_value_val = t; 1696 ecol[1].ec_value.ec_value_len = strlen(t)+1; 1697 t = s; 1698 1699 1700 /* 1701 * gid (col 2) 1702 */ 1703 if ((s = strchr(t, ':')) == 0 || s == t) { 1704 (void) strcpy(parse_err_msg, "no members"); 1705 return (GENENT_PARSEERR); 1706 } 1707 *s++ = 0; 1708 ecol[2].ec_value.ec_value_val = t; 1709 ecol[2].ec_value.ec_value_len = strlen(t)+1; 1710 t = s; 1711 1712 /* 1713 * members (col 3) 1714 */ 1715 ecol[3].ec_value.ec_value_val = t; 1716 ecol[3].ec_value.ec_value_len = strlen(t)+1; 1717 1718 1719 /* 1720 * build entry 1721 */ 1722 data.gr_name = strdup(ecol[0].ec_value.ec_value_val); 1723 data.gr_passwd = strdup(ecol[1].ec_value.ec_value_val); 1724 if (ecol[2].ec_value.ec_value_val != NULL && 1725 ecol[2].ec_value.ec_value_val[0] != '\0') { 1726 1727 data.gr_gid = ascii_to_int(ecol[2].ec_value.ec_value_val); 1728 if (data.gr_gid == -1) { 1729 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 1730 "invalid group id: %s", 1731 ecol[2].ec_value.ec_value_val); 1732 return (GENENT_PARSEERR); 1733 } 1734 } else 1735 data.gr_gid = -1; 1736 1737 data.gr_mem = NULL; 1738 1739 /* Compute maximum amount of members */ 1740 s = t; 1741 while (s = strchr(s, ',')) { 1742 s++; 1743 ctr++; 1744 } 1745 1746 /* Allocate memory for all members */ 1747 data.gr_mem = calloc(ctr + 2, sizeof (char **)); 1748 if (data.gr_mem == NULL) { 1749 (void) fprintf(stderr, gettext("out of memory\n")); 1750 exit(1); 1751 } 1752 1753 ctr = 0; 1754 while (s = strchr(t, ',')) { 1755 1756 *s++ = 0; 1757 ecol[3].ec_value.ec_value_val = t; 1758 t = s; 1759 /* Send to server only non empty member names */ 1760 if (strlen(ecol[3].ec_value.ec_value_val) != 0) 1761 data.gr_mem[ctr++] = ecol[3].ec_value.ec_value_val; 1762 } 1763 1764 /* Send to server only non empty member names */ 1765 if (strlen(t) != 0) 1766 data.gr_mem[ctr++] = t; 1767 1768 /* Array of members completed, finished by NULL, see calloc() */ 1769 1770 if (flags & F_VERBOSE) 1771 (void) fprintf(stdout, 1772 gettext("Adding entry : %s\n"), data.gr_name); 1773 1774 retval = (*cback)(&data, 0); 1775 1776 if (retval == LDAP_ALREADY_EXISTS) { 1777 if (continue_onerror) 1778 (void) fprintf(stderr, 1779 gettext("Entry: %s - already Exists, skipping it.\n"), 1780 data.gr_name); 1781 else { 1782 rc = GENENT_CBERR; 1783 (void) fprintf(stderr, 1784 gettext("Entry: %s - already Exists\n"), 1785 data.gr_name); 1786 } 1787 } else if (retval) 1788 rc = GENENT_CBERR; 1789 1790 free(data.gr_name); 1791 free(data.gr_passwd); 1792 free(data.gr_mem); 1793 1794 return (rc); 1795 } 1796 1797 static void 1798 dump_group(ns_ldap_result_t *res) 1799 { 1800 char **value = NULL; 1801 char pnam[256]; 1802 int attr_count = 0; 1803 1804 value = __ns_ldap_getAttr(res->entry, "cn"); 1805 if (value && value[0]) 1806 (void) fprintf(stdout, "%s:", value[0]); 1807 value = __ns_ldap_getAttr(res->entry, "userPassword"); 1808 if (value == NULL || value[0] == NULL) 1809 (void) fprintf(stdout, "*:"); 1810 else { 1811 (void) strcpy(pnam, value[0]); 1812 if (strncasecmp(value[0], "{crypt}", 7) == 0) 1813 (void) fprintf(stdout, "%s:", (pnam+7)); 1814 else 1815 (void) fprintf(stdout, "*:"); 1816 } 1817 value = __ns_ldap_getAttr(res->entry, "gidNumber"); 1818 if (value && value[0]) 1819 (void) fprintf(stdout, "%s:", value[0]); 1820 1821 value = __ns_ldap_getAttr(res->entry, "memberUid"); 1822 if (value != NULL && value[0] != NULL) { 1823 while (value[attr_count] != NULL) { 1824 if (value[attr_count+1] == NULL) 1825 (void) fprintf(stdout, "%s", value[attr_count]); 1826 else 1827 (void) fprintf(stdout, "%s,", 1828 value[attr_count]); 1829 attr_count++; 1830 } 1831 (void) fprintf(stdout, "\n"); 1832 } 1833 else 1834 (void) fprintf(stdout, "\n"); 1835 } 1836 1837 1838 1839 1840 1841 /* 1842 * /etc/ethers 1843 */ 1844 1845 static int 1846 genent_ethers(char *line, int (*cback)()) 1847 { 1848 char buf[BUFSIZ+1]; 1849 char *t; 1850 entry_col ecol[3]; 1851 int retval = 1; 1852 struct _ns_ethers data; 1853 int rc = GENENT_OK; 1854 1855 /* 1856 * don't clobber our argument 1857 */ 1858 if (strlen(line) >= sizeof (buf)) { 1859 (void) strcpy(parse_err_msg, "line too long"); 1860 return (GENENT_PARSEERR); 1861 } 1862 (void) strcpy(buf, line); 1863 1864 /* 1865 * clear column data 1866 */ 1867 (void) memset((char *)ecol, 0, sizeof (ecol)); 1868 1869 /* 1870 * comment (col 2) 1871 */ 1872 t = strchr(buf, '#'); 1873 if (t) { 1874 *t++ = 0; 1875 ecol[2].ec_value.ec_value_val = t; 1876 ecol[2].ec_value.ec_value_len = strlen(t)+1; 1877 } else { 1878 ecol[2].ec_value.ec_value_val = 0; 1879 ecol[2].ec_value.ec_value_len = 0; 1880 } 1881 1882 /* 1883 * addr(col 0) 1884 */ 1885 if ((t = strtok(buf, " \t")) == 0) { 1886 (void) strcpy(parse_err_msg, "no name"); 1887 return (GENENT_PARSEERR); 1888 } 1889 ecol[0].ec_value.ec_value_val = t; 1890 ecol[0].ec_value.ec_value_len = strlen(t)+1; 1891 1892 /* 1893 * name(col 1) 1894 */ 1895 if ((t = strtok(NULL, " \t")) == 0) { 1896 (void) strcpy(parse_err_msg, "no white space allowed in name"); 1897 return (GENENT_PARSEERR); 1898 } 1899 ecol[1].ec_value.ec_value_val = t; 1900 ecol[1].ec_value.ec_value_len = strlen(t)+1; 1901 1902 1903 /* 1904 * build entry 1905 */ 1906 1907 data.ether = strdup(ecol[0].ec_value.ec_value_val); 1908 data.name = strdup(ecol[1].ec_value.ec_value_val); 1909 1910 1911 if (flags & F_VERBOSE) 1912 (void) fprintf(stdout, 1913 gettext("Adding entry : %s\n"), data.name); 1914 1915 retval = (*cback)(&data, 0); 1916 1917 if (retval == LDAP_ALREADY_EXISTS) { 1918 if (continue_onerror) 1919 (void) fprintf(stderr, 1920 gettext("Entry: %s - already Exists, skipping it.\n"), 1921 data.name); 1922 else { 1923 rc = GENENT_CBERR; 1924 (void) fprintf(stderr, 1925 gettext("Entry: %s - already Exists\n"), 1926 data.name); 1927 } 1928 } else if (retval) 1929 rc = GENENT_CBERR; 1930 1931 free(data.ether); 1932 free(data.name); 1933 1934 return (rc); 1935 } 1936 1937 1938 static void 1939 dump_ethers(ns_ldap_result_t *res) 1940 { 1941 char **value = NULL; 1942 1943 value = __ns_ldap_getAttr(res->entry, "macAddress"); 1944 if (value && value[0]) 1945 (void) fprintf(stdout, "%s", value[0]); 1946 else 1947 return; 1948 value = __ns_ldap_getAttr(res->entry, "cn"); 1949 if (value && value[0]) 1950 (void) fprintf(stdout, " %s\n", value[0]); 1951 } 1952 1953 static int 1954 genent_aliases(char *line, int (*cback)()) 1955 { 1956 char buf[BUFSIZ+1]; 1957 char *t, *aliases; 1958 char *cname; 1959 int ctr = 0; 1960 int retval = 1; 1961 int i; 1962 1963 struct _ns_alias data; 1964 char *alias; 1965 int rc = GENENT_OK; 1966 1967 /* 1968 * don't clobber our argument 1969 */ 1970 if (strlen(line) >= sizeof (buf)) { 1971 (void) strcpy(parse_err_msg, "line too long"); 1972 return (GENENT_PARSEERR); 1973 } 1974 1975 (void) strcpy(buf, line); 1976 1977 if ((t = strchr(buf, ':')) == 0) { 1978 (void) strcpy(parse_err_msg, "no alias name"); 1979 return (GENENT_PARSEERR); 1980 } 1981 1982 t[0] = '\0'; 1983 if (++t == '\0') { 1984 (void) strcpy(parse_err_msg, "no alias value"); 1985 return (GENENT_PARSEERR); 1986 } 1987 1988 cname = buf; 1989 aliases = t; 1990 1991 /* build entry */ 1992 data.alias = strdup(cname); 1993 if (!data.alias) { 1994 (void) fprintf(stderr, gettext("out of memory\n")); 1995 exit(1); 1996 } 1997 1998 data.member = NULL; 1999 t = strtok(aliases, ","); 2000 do { 2001 ctr++; 2002 while (t[0] == ' ') 2003 t++; 2004 alias = strdup(t); 2005 if ((alias == NULL) || 2006 ((data.member = (char **)realloc(data.member, 2007 (ctr + 1) * sizeof (char **))) == NULL)) { 2008 (void) fprintf(stderr, gettext("out of memory\n")); 2009 exit(1); 2010 } 2011 data.member[ctr-1] = alias; 2012 2013 } while (t = strtok(NULL, ",")); 2014 2015 data.member[ctr] = NULL; 2016 2017 if (flags & F_VERBOSE) 2018 (void) fprintf(stdout, 2019 gettext("Adding entry : %s\n"), data.alias); 2020 2021 retval = (*cback)(&data, 0); 2022 2023 if (retval == LDAP_ALREADY_EXISTS) { 2024 if (continue_onerror) 2025 (void) fprintf(stderr, 2026 gettext("Entry: %s - already Exists, skipping it.\n"), 2027 data.alias); 2028 else { 2029 rc = GENENT_CBERR; 2030 (void) fprintf(stderr, 2031 gettext("Entry: %s - already Exists\n"), 2032 data.alias); 2033 } 2034 } else if (retval) 2035 rc = GENENT_CBERR; 2036 2037 free(data.alias); 2038 i = 0; 2039 while (data.member[i]) 2040 free(data.member[i++]); 2041 free(data.member); 2042 2043 return (rc); 2044 } 2045 2046 2047 static void 2048 dump_aliases(ns_ldap_result_t *res) 2049 { 2050 2051 char **value = NULL; 2052 int attr_count = 0; 2053 2054 value = __ns_ldap_getAttr(res->entry, "mail"); 2055 if (value && value[0]) 2056 (void) fprintf(stdout, "%s:", value[0]); 2057 value = __ns_ldap_getAttr(res->entry, "mgrpRFC822MailMember"); 2058 if (value != NULL) 2059 while (value[attr_count] != NULL) { 2060 (void) fprintf(stdout, "%s,", value[attr_count]); 2061 attr_count++; 2062 } 2063 (void) fprintf(stdout, "\n"); 2064 2065 } 2066 2067 /* 2068 * /etc/publickey 2069 */ 2070 2071 static int 2072 genent_publickey(char *line, int (*cback)()) 2073 { 2074 char buf[BUFSIZ+1], tmpbuf[BUFSIZ+1], cname[BUFSIZ+1]; 2075 char *t, *p, *tmppubkey, *tmpprivkey; 2076 entry_col ecol[3]; 2077 int buflen, uid, retval = 1; 2078 struct passwd *pwd; 2079 char auth_type[BUFSIZ+1]; 2080 keylen_t keylen; 2081 algtype_t algtype; 2082 struct _ns_pubkey data; 2083 struct hostent *hp; 2084 struct in_addr in; 2085 2086 /* 2087 * don't clobber our argument 2088 */ 2089 if (strlen(line) >= sizeof (buf)) { 2090 (void) strcpy(parse_err_msg, "line too long"); 2091 return (GENENT_PARSEERR); 2092 } 2093 (void) strcpy(buf, line); 2094 2095 /* 2096 * clear column data 2097 */ 2098 (void) memset((char *)ecol, 0, sizeof (ecol)); 2099 2100 if ((t = strtok(buf, " \t")) == 0) { 2101 (void) strcpy(parse_err_msg, "no cname"); 2102 return (GENENT_PARSEERR); 2103 } 2104 2105 /* 2106 * Special case: /etc/publickey usually has an entry 2107 * for principal "nobody". We skip it. 2108 */ 2109 if (strcmp(t, "nobody") == 0) 2110 return (GENENT_OK); 2111 2112 /* 2113 * cname (col 0) 2114 */ 2115 if (strncmp(t, "unix.", 5)) { 2116 (void) strcpy(parse_err_msg, "bad cname"); 2117 return (GENENT_PARSEERR); 2118 } 2119 (void) strcpy(tmpbuf, &(t[5])); 2120 if ((p = strchr(tmpbuf, '@')) == 0) { 2121 (void) strcpy(parse_err_msg, "bad cname"); 2122 return (GENENT_PARSEERR); 2123 } 2124 *(p++) = 0; 2125 if (isdigit(*tmpbuf)) { 2126 2127 uid = atoi(tmpbuf); 2128 /* 2129 * don't generate entries for uids without passwd entries 2130 */ 2131 if ((pwd = getpwuid(uid)) == 0) { 2132 (void) fprintf(stderr, 2133 gettext("can't map uid %d to username, skipping\n"), 2134 uid); 2135 return (GENENT_OK); 2136 } 2137 (void) strcpy(cname, pwd->pw_name); 2138 data.hostcred = NS_HOSTCRED_FALSE; 2139 } else { 2140 if ((hp = gethostbyname(tmpbuf)) == 0) { 2141 (void) fprintf(stderr, 2142 gettext("can't map hostname %s to hostaddress, skipping\n"), 2143 tmpbuf); 2144 return (GENENT_OK); 2145 } 2146 (void) memcpy((char *)&in.s_addr, hp->h_addr_list[0], 2147 sizeof (in)); 2148 data.hostcred = NS_HOSTCRED_TRUE; 2149 (void) snprintf(cname, sizeof (cname), 2150 "%s+ipHostNumber=%s", tmpbuf, inet_ntoa(in)); 2151 } 2152 2153 ecol[0].ec_value.ec_value_val = cname; 2154 ecol[0].ec_value.ec_value_len = strlen(cname)+1; 2155 2156 /* 2157 * public_data (col 1) 2158 */ 2159 if ((t = strtok(NULL, " \t")) == 0) { 2160 (void) strcpy(parse_err_msg, "no private_data"); 2161 return (GENENT_PARSEERR); 2162 } 2163 if ((p = strchr(t, ':')) == 0) { 2164 (void) strcpy(parse_err_msg, "bad public_data"); 2165 return (GENENT_PARSEERR); 2166 } 2167 *(p++) = 0; 2168 ecol[1].ec_value.ec_value_val = t; 2169 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2170 keylen = (strlen(t) / 2) * 8; 2171 2172 /* 2173 * private_data (col 2) and algtype extraction 2174 */ 2175 if (*p == ':') 2176 p++; 2177 t = p; 2178 if (!(t = strchr(t, ':'))) { 2179 (void) fprintf(stderr, 2180 gettext("WARNING: No algorithm type data found " 2181 "in publickey file, assuming 0\n")); 2182 algtype = 0; 2183 } else { 2184 *t = '\0'; 2185 t++; 2186 algtype = atoi(t); 2187 } 2188 ecol[2].ec_value.ec_value_val = p; 2189 ecol[2].ec_value.ec_value_len = strlen(p)+1; 2190 2191 /* 2192 * auth_type (col 1) 2193 */ 2194 if (!(__nis_keyalg2authtype(keylen, algtype, auth_type, 2195 MECH_MAXATNAME))) { 2196 (void) fprintf(stderr, 2197 gettext("Could not convert algorithm type to " 2198 "corresponding auth type string\n")); 2199 return (GENENT_ERR); 2200 } 2201 2202 /* 2203 * build entry 2204 */ 2205 data.name = strdup(ecol[0].ec_value.ec_value_val); 2206 if (data.name == NULL) { 2207 (void) fprintf(stderr, gettext("out of memory\n")); 2208 exit(1); 2209 } 2210 2211 buflen = sizeof (auth_type) + strlen(ecol[1].ec_value.ec_value_val) + 3; 2212 if ((tmppubkey = (char *)malloc(buflen)) == NULL) { 2213 (void) fprintf(stderr, gettext("out of memory\n")); 2214 exit(1); 2215 } 2216 (void) snprintf(tmppubkey, buflen, "{%s}%s", auth_type, 2217 ecol[1].ec_value.ec_value_val); 2218 data.pubkey = tmppubkey; 2219 2220 buflen = sizeof (auth_type) + strlen(ecol[2].ec_value.ec_value_val) + 3; 2221 if ((tmpprivkey = (char *)malloc(buflen)) == NULL) { 2222 (void) fprintf(stderr, gettext("out of memory\n")); 2223 exit(1); 2224 } 2225 2226 (void) snprintf(tmpprivkey, buflen, "{%s}%s", auth_type, 2227 ecol[2].ec_value.ec_value_val); 2228 data.privkey = tmpprivkey; 2229 2230 retval = (*cback)(&data, 1); 2231 2232 if ((retval != NS_LDAP_SUCCESS) && (continue_onerror == 0)) 2233 return (GENENT_CBERR); 2234 else { 2235 free(data.name); 2236 free(data.pubkey); 2237 free(data.privkey); 2238 return (GENENT_OK); 2239 } 2240 } 2241 2242 static void 2243 dump_publickey(ns_ldap_result_t *res, char *container) 2244 { 2245 char **value = NULL; 2246 char buf[BUFSIZ]; 2247 char domainname[BUFSIZ]; 2248 char *pubptr, *prvptr; 2249 2250 if (res == NULL) 2251 return; 2252 2253 if (sysinfo(SI_SRPC_DOMAIN, domainname, BUFSIZ) < 0) { 2254 (void) fprintf(stderr, 2255 gettext("could not obtain domainname\n")); 2256 exit(1); 2257 } 2258 2259 /* 2260 * Retrieve all the attributes, but don't print 2261 * until we have all the required ones. 2262 */ 2263 2264 if (strcmp(container, "passwd") == 0) 2265 value = __ns_ldap_getAttr(res->entry, "uidNumber"); 2266 else 2267 value = __ns_ldap_getAttr(res->entry, "cn"); 2268 2269 if (value && value[0]) 2270 (void) snprintf(buf, sizeof (buf), "unix.%s@%s", 2271 value[0], domainname); 2272 else 2273 return; 2274 2275 value = __ns_ldap_getAttr(res->entry, "nisPublickey"); 2276 if (value != NULL && value[0] != NULL) { 2277 if ((pubptr = strchr(value[0], '}')) == NULL) 2278 return; 2279 } 2280 2281 value = __ns_ldap_getAttr(res->entry, "nisSecretkey"); 2282 if (value != NULL && value[0] != NULL) 2283 if ((prvptr = strchr(value[0], '}')) == NULL) 2284 return; 2285 2286 /* print the attributes, algorithm type is always 0 */ 2287 (void) fprintf(stdout, "%s %s:%s:0\n", buf, ++pubptr, ++prvptr); 2288 } 2289 2290 2291 2292 /* 2293 * /etc/netmasks 2294 */ 2295 2296 static int 2297 genent_netmasks(char *line, int (*cback)()) 2298 { 2299 char buf[BUFSIZ+1]; 2300 char *t; 2301 entry_col ecol[3]; 2302 2303 struct _ns_netmasks data; 2304 2305 2306 /* 2307 * don't clobber our argument 2308 */ 2309 if (strlen(line) >= sizeof (buf)) { 2310 (void) strcpy(parse_err_msg, "line too long"); 2311 return (GENENT_PARSEERR); 2312 } 2313 (void) strcpy(buf, line); 2314 2315 /* 2316 * clear column data 2317 */ 2318 (void) memset((char *)ecol, 0, sizeof (ecol)); 2319 2320 /* 2321 * comment (col 2) 2322 */ 2323 t = strchr(buf, '#'); 2324 if (t) { 2325 *t++ = 0; 2326 ecol[2].ec_value.ec_value_val = t; 2327 ecol[2].ec_value.ec_value_len = strlen(t)+1; 2328 } else { 2329 ecol[2].ec_value.ec_value_val = 0; 2330 ecol[2].ec_value.ec_value_len = 0; 2331 } 2332 2333 /* 2334 * addr(col 0) 2335 */ 2336 if ((t = strtok(buf, " \t")) == 0) { 2337 (void) strcpy(parse_err_msg, "no mask"); 2338 return (GENENT_PARSEERR); 2339 } 2340 ecol[0].ec_value.ec_value_val = t; 2341 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2342 2343 /* 2344 * mask (col 1) 2345 */ 2346 if ((t = strtok(NULL, " \t")) == 0) { 2347 (void) strcpy(parse_err_msg, "no mask"); 2348 return (GENENT_PARSEERR); 2349 } 2350 ecol[1].ec_value.ec_value_val = t; 2351 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2352 2353 /* build entry */ 2354 data.netnumber = ecol[0].ec_value.ec_value_val; 2355 data.netmask = ecol[1].ec_value.ec_value_val; 2356 2357 if (flags & F_VERBOSE) 2358 (void) fprintf(stdout, 2359 gettext("Adding entry : %s\n"), data.netnumber); 2360 2361 if ((*cback)(&data, 1) && continue_onerror == 0) 2362 return (GENENT_CBERR); 2363 2364 return (GENENT_OK); 2365 } 2366 2367 static void 2368 dump_netmasks(ns_ldap_result_t *res) 2369 { 2370 char **value = NULL; 2371 2372 value = __ns_ldap_getAttr(res->entry, "ipNetworkNumber"); 2373 if (value && value[0]) 2374 (void) fprintf(stdout, "%s", value[0]); 2375 value = __ns_ldap_getAttr(res->entry, "ipNetmaskNumber"); 2376 if (value && value[0]) 2377 (void) fprintf(stdout, " %s\n", value[0]); 2378 } 2379 2380 2381 /* 2382 * /etc/netgroup 2383 * column data format is: 2384 * col 0: netgroup name (or cname) 2385 * col 1: netgroup member, if this is a triplet 2386 * col 2: netgroup member, if not a triplet 2387 * col 3: comment 2388 */ 2389 2390 static int 2391 genent_netgroup(char *line, int (*cback)()) 2392 { 2393 char buf[BIGBUF+1]; /* netgroup entries tend to be big */ 2394 char *t; 2395 char *cname = NULL; 2396 entry_col ecol[4]; 2397 char *netg_tmp = NULL, *triplet_tmp = NULL; 2398 int netgcount = 0, tripletcount = 0, retval = 1; 2399 struct _ns_netgroups data; 2400 int rc = GENENT_OK; 2401 2402 /* don't clobber our argument */ 2403 if (strlen(line) >= sizeof (buf)) { 2404 (void) strcpy(parse_err_msg, "line too long"); 2405 return (GENENT_PARSEERR); 2406 } 2407 (void) strcpy(buf, line); 2408 2409 /* clear column data */ 2410 (void) memset((char *)ecol, 0, sizeof (ecol)); 2411 2412 /* 2413 * process 1st minimal entry, to validate that there is no 2414 * parsing error. 2415 * start with comment(col 3) 2416 */ 2417 t = strchr(buf, '#'); 2418 if (t) { 2419 *t++ = 0; 2420 ecol[3].ec_value.ec_value_val = t; 2421 ecol[3].ec_value.ec_value_len = strlen(t)+1; 2422 } else { 2423 ecol[3].ec_value.ec_value_val = ""; 2424 ecol[3].ec_value.ec_value_len = 0; 2425 } 2426 2427 ecol[1].ec_value.ec_value_val = NULL; 2428 ecol[2].ec_value.ec_value_val = NULL; 2429 2430 /* cname (col 0) */ 2431 if ((t = strtok(buf, " \t")) == 0) { 2432 (void) strcpy(parse_err_msg, "no cname"); 2433 return (GENENT_PARSEERR); 2434 } 2435 ecol[0].ec_value.ec_value_val = t; 2436 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2437 cname = t; 2438 2439 /* addr(col 1 and 2) */ 2440 if ((t = strtok(NULL, " \t")) == 0) { 2441 (void) strcpy(parse_err_msg, "no members for netgroup"); 2442 return (GENENT_PARSEERR); 2443 } 2444 2445 if (*t == '(') { 2446 ecol[1].ec_value.ec_value_val = t; 2447 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2448 } else { 2449 ecol[2].ec_value.ec_value_val = t; 2450 ecol[2].ec_value.ec_value_len = strlen(t)+1; 2451 } 2452 2453 2454 /* 2455 * now build entry. 2456 * start by clearing entry data 2457 */ 2458 (void) memset((struct _ns_netgroups *)&data, 0, sizeof (data)); 2459 2460 data.name = strdup(ecol[0].ec_value.ec_value_val); 2461 2462 if (ecol[1].ec_value.ec_value_val != NULL) { 2463 if ((data.triplet = calloc(1, sizeof (char **))) == NULL) { 2464 (void) fprintf(stderr, 2465 gettext("out of memory\n")); 2466 exit(1); 2467 } 2468 data.triplet[tripletcount++] = 2469 strdup(ecol[1].ec_value.ec_value_val); 2470 } else if (ecol[2].ec_value.ec_value_val != NULL) { 2471 if ((data.netgroup = calloc(1, sizeof (char **))) 2472 == NULL) { 2473 (void) fprintf(stderr, 2474 gettext("out of memory\n")); 2475 exit(1); 2476 } 2477 data.netgroup[netgcount++] = 2478 strdup(ecol[2].ec_value.ec_value_val); 2479 } 2480 2481 /* 2482 * we now have a valid entry (at least 1 netgroup name and 2483 * 1 netgroup member), proceed with the rest of the line 2484 */ 2485 while (t = strtok(NULL, " \t")) { 2486 2487 /* if next token is equal to netgroup name, ignore */ 2488 if (t != cname && strcasecmp(t, cname) == 0) 2489 continue; 2490 if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) 2491 continue; 2492 2493 if (*t == '(') { 2494 tripletcount++; 2495 triplet_tmp = strdup(t); 2496 if ((data.triplet = (char **)realloc(data.triplet, 2497 tripletcount * sizeof (char **))) == NULL) { 2498 (void) fprintf(stderr, 2499 gettext("out of memory\n")); 2500 exit(1); 2501 } 2502 data.triplet[tripletcount-1] = triplet_tmp; 2503 } else { 2504 netgcount++; 2505 netg_tmp = strdup(t); 2506 if ((data.netgroup = (char **)realloc(data.netgroup, 2507 netgcount * sizeof (char **))) == NULL) { 2508 (void) fprintf(stderr, 2509 gettext("out of memory\n")); 2510 exit(1); 2511 } 2512 data.netgroup[netgcount-1] = netg_tmp; 2513 } 2514 } 2515 2516 2517 /* End the list with NULL */ 2518 if ((data.triplet = (char **)realloc(data.triplet, 2519 (tripletcount + 1) * sizeof (char **))) == NULL) { 2520 (void) fprintf(stderr, gettext("out of memory\n")); 2521 exit(1); 2522 } 2523 data.triplet[tripletcount] = NULL; 2524 if ((data.netgroup = (char **)realloc(data.netgroup, 2525 (netgcount + 1) * sizeof (char **))) == NULL) { 2526 (void) fprintf(stderr, gettext("out of memory\n")); 2527 exit(1); 2528 } 2529 data.netgroup[netgcount] = NULL; 2530 2531 if (flags & F_VERBOSE) 2532 (void) fprintf(stdout, 2533 gettext("Adding entry : %s\n"), data.name); 2534 2535 retval = (*cback)(&data, 0); 2536 2537 if (retval == LDAP_ALREADY_EXISTS) { 2538 if (continue_onerror) 2539 (void) fprintf(stderr, 2540 gettext("Entry: %s - already Exists, skipping it.\n"), 2541 data.name); 2542 else { 2543 rc = GENENT_CBERR; 2544 (void) fprintf(stderr, 2545 gettext("Entry: %s - already Exists\n"), 2546 data.name); 2547 } 2548 } else if (retval) 2549 rc = GENENT_CBERR; 2550 2551 free(data.name); 2552 free(data.triplet); 2553 free(data.netgroup); 2554 2555 return (rc); 2556 } 2557 2558 static void 2559 dump_netgroup(ns_ldap_result_t *res) 2560 { 2561 char **value = NULL; 2562 int attr_count = 0; 2563 2564 value = __ns_ldap_getAttr(res->entry, "cn"); 2565 if ((value != NULL) && (value[0] != NULL)) 2566 (void) fprintf(stdout, "%s", value[0]); 2567 else 2568 return; 2569 value = __ns_ldap_getAttr(res->entry, "nisNetgroupTriple"); 2570 if (value != NULL) 2571 while (value[attr_count] != NULL) { 2572 (void) fprintf(stdout, " %s", value[attr_count]); 2573 attr_count++; 2574 } 2575 value = __ns_ldap_getAttr(res->entry, "memberNisNetgroup"); 2576 if (value != NULL) 2577 while (value[attr_count] != NULL) { 2578 (void) fprintf(stdout, " %s", value[attr_count]); 2579 attr_count++; 2580 } 2581 (void) fprintf(stdout, "\n"); 2582 2583 } 2584 2585 static int 2586 genent_automount(char *line, int (*cback)()) 2587 { 2588 char buf[BUFSIZ+1]; 2589 char *t, *s; 2590 entry_col ecol[2]; 2591 struct _ns_automount data; 2592 int retval = 1; 2593 int rc = GENENT_OK; 2594 2595 /* 2596 * don't clobber our argument 2597 */ 2598 if (strlen(line) >= sizeof (buf)) { 2599 (void) strcpy(parse_err_msg, "line too long"); 2600 return (GENENT_PARSEERR); 2601 } 2602 2603 /* replace every tabspace with single space */ 2604 replace_tab2space(line); 2605 (void) strcpy(buf, line); 2606 2607 /* 2608 * clear column data 2609 */ 2610 (void) memset((char *)ecol, 0, sizeof (ecol)); 2611 2612 /* 2613 * key (col 0) 2614 */ 2615 t = buf; 2616 while (t[0] == ' ') 2617 t++; 2618 2619 if ((s = strchr(t, ' ')) == 0) { 2620 return (GENENT_PARSEERR); 2621 } 2622 *s++ = 0; 2623 2624 ecol[0].ec_value.ec_value_val = t; 2625 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2626 t = s; 2627 2628 while (t[0] == ' ') 2629 t++; 2630 2631 /* 2632 * mapentry (col 1) 2633 */ 2634 2635 ecol[1].ec_value.ec_value_val = t; 2636 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2637 2638 data.mapname = strdup(databasetype); 2639 data.key = strdup(ecol[0].ec_value.ec_value_val); 2640 data.value = strdup(ecol[1].ec_value.ec_value_val); 2641 2642 if (flags & F_VERBOSE) 2643 (void) fprintf(stdout, 2644 gettext("Adding entry : %s\n"), data.key); 2645 2646 retval = (*cback)(&data, 0); 2647 2648 if (retval == LDAP_ALREADY_EXISTS) { 2649 if (continue_onerror) 2650 (void) fprintf(stderr, 2651 gettext("Entry: %s - already Exists, skipping it.\n"), 2652 data.key); 2653 else { 2654 rc = GENENT_CBERR; 2655 (void) fprintf(stderr, 2656 gettext("Entry: %s - already Exists\n"), 2657 data.key); 2658 } 2659 } else if (retval) 2660 rc = GENENT_CBERR; 2661 2662 free(data.mapname); 2663 free(data.key); 2664 free(data.value); 2665 return (rc); 2666 } 2667 2668 static void 2669 dump_automount(ns_ldap_result_t *res) 2670 { 2671 char **value = NULL; 2672 2673 if (res == NULL) 2674 return; 2675 2676 value = __ns_ldap_getAttr(res->entry, "automountKey"); 2677 if (value != NULL) { 2678 (void) fprintf(stdout, "%s", value[0]); 2679 value = __ns_ldap_getAttr(res->entry, "automountInformation"); 2680 if (value != NULL) 2681 (void) fprintf(stdout, " %s\n", value[0]); 2682 else 2683 (void) fprintf(stdout, "\n"); 2684 } 2685 } 2686 2687 2688 /* 2689 * /etc/passwd 2690 * 2691 */ 2692 2693 static int 2694 genent_passwd(char *line, int (*cback)()) 2695 { 2696 char buf[BUFSIZ+1]; 2697 char *s, *t; 2698 entry_col ecol[8]; 2699 int retval = 1; 2700 char pname[BUFSIZ]; 2701 2702 struct passwd data; 2703 int rc = GENENT_OK; 2704 2705 2706 /* 2707 * don't clobber our argument 2708 */ 2709 if (strlen(line) >= sizeof (buf)) { 2710 (void) strcpy(parse_err_msg, "line too long"); 2711 return (GENENT_PARSEERR); 2712 } 2713 (void) strcpy(buf, line); 2714 t = buf; 2715 2716 /* ignore empty entries */ 2717 if (*t == '\0') 2718 return (GENENT_OK); 2719 2720 /* 2721 * clear column data 2722 */ 2723 (void) memset((char *)ecol, 0, sizeof (ecol)); 2724 2725 /* 2726 * name (col 0) 2727 */ 2728 if ((s = strchr(t, ':')) == 0) { 2729 (void) strcpy(parse_err_msg, "no password"); 2730 return (GENENT_PARSEERR); 2731 } 2732 *s++ = 0; 2733 ecol[0].ec_value.ec_value_val = t; 2734 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2735 t = s; 2736 2737 /* 2738 * passwd (col 1) 2739 */ 2740 if ((s = strchr(t, ':')) == 0) { 2741 (void) strcpy(parse_err_msg, "no uid"); 2742 return (GENENT_PARSEERR); 2743 } 2744 *s++ = 0; 2745 2746 ecol[1].ec_value.ec_value_val = t; 2747 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2748 2749 t = s; 2750 2751 /* 2752 * uid (col 2) 2753 */ 2754 if ((s = strchr(t, ':')) == 0 || s == t) { 2755 (void) strcpy(parse_err_msg, "no gid"); 2756 return (GENENT_PARSEERR); 2757 } 2758 *s++ = 0; 2759 ecol[2].ec_value.ec_value_val = t; 2760 ecol[2].ec_value.ec_value_len = strlen(t)+1; 2761 t = s; 2762 2763 /* 2764 * gid (col 3) 2765 */ 2766 if ((s = strchr(t, ':')) == 0 || s == t) { 2767 (void) strcpy(parse_err_msg, "no gcos"); 2768 return (GENENT_PARSEERR); 2769 } 2770 *s++ = 0; 2771 ecol[3].ec_value.ec_value_val = t; 2772 ecol[3].ec_value.ec_value_len = strlen(t)+1; 2773 t = s; 2774 2775 /* 2776 * gcos (col 4) 2777 */ 2778 if ((s = strchr(t, ':')) == 0) { 2779 (void) strcpy(parse_err_msg, "no home"); 2780 return (GENENT_PARSEERR); 2781 } 2782 *s++ = 0; 2783 ecol[4].ec_value.ec_value_val = t; 2784 ecol[4].ec_value.ec_value_len = strlen(t)+1; 2785 t = s; 2786 2787 /* 2788 * home (col 5) 2789 */ 2790 if ((s = strchr(t, ':')) == 0) { 2791 (void) strcpy(parse_err_msg, "no shell"); 2792 return (GENENT_PARSEERR); 2793 } 2794 *s++ = 0; 2795 ecol[5].ec_value.ec_value_val = t; 2796 ecol[5].ec_value.ec_value_len = strlen(t)+1; 2797 t = s; 2798 2799 /* 2800 * shell (col 6) 2801 */ 2802 ecol[6].ec_value.ec_value_val = t; 2803 ecol[6].ec_value.ec_value_len = strlen(t)+1; 2804 2805 /* 2806 * build entry 2807 */ 2808 data.pw_name = strdup(ecol[0].ec_value.ec_value_val); 2809 2810 if (flags & F_PASSWD) { 2811 /* Add {crypt} before passwd entry */ 2812 (void) snprintf(pname, sizeof (pname), "{crypt}%s", 2813 ecol[1].ec_value.ec_value_val); 2814 data.pw_passwd = strdup(pname); 2815 } 2816 else 2817 data.pw_passwd = NULL; 2818 2819 if (ecol[2].ec_value.ec_value_val != NULL && 2820 ecol[2].ec_value.ec_value_val[0] != '\0') { 2821 data.pw_uid = ascii_to_int(ecol[2].ec_value.ec_value_val); 2822 if (data.pw_uid == -1) { 2823 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 2824 "invalid uid : %s", ecol[2].ec_value.ec_value_val); 2825 return (GENENT_PARSEERR); 2826 } 2827 } else 2828 data.pw_uid = -1; 2829 2830 if (ecol[3].ec_value.ec_value_val != NULL && 2831 ecol[3].ec_value.ec_value_val[0] != '\0') { 2832 2833 data.pw_gid = ascii_to_int(ecol[3].ec_value.ec_value_val); 2834 if (data.pw_gid == -1) { 2835 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 2836 "invalid gid : %s", ecol[3].ec_value.ec_value_val); 2837 return (GENENT_PARSEERR); 2838 } 2839 } else 2840 data.pw_gid = -1; 2841 2842 data.pw_age = NULL; 2843 data.pw_comment = NULL; 2844 data.pw_gecos = strdup(ecol[4].ec_value.ec_value_val); 2845 data.pw_dir = strdup(ecol[5].ec_value.ec_value_val); 2846 data.pw_shell = strdup(ecol[6].ec_value.ec_value_val); 2847 2848 if (flags & F_VERBOSE) 2849 (void) fprintf(stdout, 2850 gettext("Adding entry : %s\n"), data.pw_name); 2851 2852 retval = (*cback)(&data, 0); 2853 2854 if (retval == LDAP_ALREADY_EXISTS) { 2855 if (continue_onerror) 2856 (void) fprintf(stderr, 2857 gettext("Entry: %s - already Exists, skipping it.\n"), 2858 data.pw_name); 2859 else { 2860 rc = GENENT_CBERR; 2861 (void) fprintf(stderr, 2862 gettext("Entry: %s - already Exists\n"), 2863 data.pw_name); 2864 } 2865 } else if (retval) 2866 rc = GENENT_CBERR; 2867 2868 free(data.pw_name); 2869 free(data.pw_gecos); 2870 free(data.pw_dir); 2871 free(data.pw_shell); 2872 return (rc); 2873 } 2874 2875 2876 static void 2877 dump_passwd(ns_ldap_result_t *res) 2878 { 2879 char **value = NULL; 2880 char pnam[256]; 2881 2882 value = __ns_ldap_getAttr(res->entry, "uid"); 2883 if (value == NULL) 2884 return; 2885 else 2886 (void) fprintf(stdout, "%s:", value[0]); 2887 value = __ns_ldap_getAttr(res->entry, "userPassword"); 2888 if (value == NULL) 2889 (void) fprintf(stdout, "*:"); 2890 else { 2891 (void) strcpy(pnam, value[0]); 2892 if (strncasecmp(value[0], "{crypt}", 7) == 0) 2893 (void) fprintf(stdout, "%s:", (pnam+7)); 2894 else 2895 (void) fprintf(stdout, "*:"); 2896 } 2897 value = __ns_ldap_getAttr(res->entry, "uidNumber"); 2898 if (value && value[0]) 2899 (void) fprintf(stdout, "%s:", value[0]); 2900 value = __ns_ldap_getAttr(res->entry, "gidNumber"); 2901 if (value && value[0]) 2902 (void) fprintf(stdout, "%s:", value[0]); 2903 value = __ns_ldap_getAttr(res->entry, "gecos"); 2904 if (value == NULL) 2905 (void) fprintf(stdout, ":"); 2906 else 2907 (void) fprintf(stdout, "%s:", value[0]); 2908 value = __ns_ldap_getAttr(res->entry, "homeDirectory"); 2909 if (value == NULL) 2910 (void) fprintf(stdout, ":"); 2911 else 2912 (void) fprintf(stdout, "%s:", value[0]); 2913 value = __ns_ldap_getAttr(res->entry, "loginShell"); 2914 if (value == NULL) 2915 (void) fprintf(stdout, "\n"); 2916 else 2917 (void) fprintf(stdout, "%s\n", value[0]); 2918 2919 } 2920 2921 /* 2922 * /etc/shadow 2923 */ 2924 2925 static int 2926 genent_shadow(char *line, int (*cback)()) 2927 { 2928 char buf[BUFSIZ+1]; 2929 char *s, *t; 2930 entry_col ecol[9]; 2931 char pname[BUFSIZ]; 2932 2933 struct spwd data; 2934 int spflag; 2935 2936 2937 /* 2938 * don't clobber our argument 2939 */ 2940 if (strlen(line) >= sizeof (buf)) { 2941 (void) strcpy(parse_err_msg, "line too long"); 2942 return (GENENT_PARSEERR); 2943 } 2944 (void) strcpy(buf, line); 2945 t = buf; 2946 2947 /* ignore empty entries */ 2948 if (*t == '\0') 2949 return (GENENT_OK); 2950 2951 /* 2952 * clear column data 2953 */ 2954 (void) memset((char *)ecol, 0, sizeof (ecol)); 2955 2956 /* 2957 * name (col 0) 2958 */ 2959 if ((s = strchr(t, ':')) == 0) { 2960 (void) strcpy(parse_err_msg, "no uid"); 2961 return (GENENT_PARSEERR); 2962 } 2963 *s++ = 0; 2964 ecol[0].ec_value.ec_value_val = t; 2965 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2966 t = s; 2967 2968 /* 2969 * passwd (col 1) 2970 */ 2971 if ((s = strchr(t, ':')) == 0) { 2972 (void) strcpy(parse_err_msg, "Improper format"); 2973 return (GENENT_PARSEERR); 2974 } 2975 *s++ = 0; 2976 2977 ecol[1].ec_value.ec_value_val = t; 2978 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2979 2980 t = s; 2981 2982 /* 2983 * shadow last change (col 2) 2984 */ 2985 if ((s = strchr(t, ':')) == 0) { 2986 (void) strcpy(parse_err_msg, "Improper format"); 2987 return (GENENT_PARSEERR); 2988 } 2989 *s++ = 0; 2990 ecol[2].ec_value.ec_value_val = t; 2991 ecol[2].ec_value.ec_value_len = strlen(t)+1; 2992 t = s; 2993 2994 /* 2995 * shadow min (col 3) 2996 */ 2997 if ((s = strchr(t, ':')) == 0) { 2998 (void) strcpy(parse_err_msg, "Improper format"); 2999 return (GENENT_PARSEERR); 3000 } 3001 *s++ = 0; 3002 ecol[3].ec_value.ec_value_val = t; 3003 ecol[3].ec_value.ec_value_len = strlen(t)+1; 3004 t = s; 3005 3006 /* 3007 * shadow max (col 4) 3008 */ 3009 if ((s = strchr(t, ':')) == 0) { 3010 (void) strcpy(parse_err_msg, "Improper format"); 3011 return (GENENT_PARSEERR); 3012 } 3013 *s++ = 0; 3014 ecol[4].ec_value.ec_value_val = t; 3015 ecol[4].ec_value.ec_value_len = strlen(t)+1; 3016 t = s; 3017 3018 /* 3019 * shadow warn (col 5) 3020 */ 3021 if ((s = strchr(t, ':')) == 0) { 3022 (void) strcpy(parse_err_msg, "Improper format"); 3023 return (GENENT_PARSEERR); 3024 } 3025 *s++ = 0; 3026 ecol[5].ec_value.ec_value_val = t; 3027 ecol[5].ec_value.ec_value_len = strlen(t)+1; 3028 t = s; 3029 3030 /* 3031 * shadow inactive (col 6) 3032 */ 3033 if ((s = strchr(t, ':')) != 0) { 3034 *s++ = 0; 3035 ecol[6].ec_value.ec_value_val = t; 3036 ecol[6].ec_value.ec_value_len = strlen(t)+1; 3037 t = s; 3038 } 3039 3040 /* 3041 * shadow expire (col 7) 3042 */ 3043 if ((s = strchr(t, ':')) != 0) { 3044 *s++ = 0; 3045 ecol[7].ec_value.ec_value_val = t; 3046 ecol[7].ec_value.ec_value_len = strlen(t)+1; 3047 t = s; 3048 3049 /* 3050 * flag (col 8) 3051 */ 3052 ecol[8].ec_value.ec_value_val = t; 3053 ecol[8].ec_value.ec_value_len = strlen(t)+1; 3054 } 3055 3056 /* 3057 * build entry 3058 */ 3059 3060 data.sp_namp = strdup(ecol[0].ec_value.ec_value_val); 3061 3062 if (ecol[1].ec_value.ec_value_val != NULL && 3063 ecol[1].ec_value.ec_value_val[0] != '\0') { 3064 /* Add {crypt} before passwd entry */ 3065 (void) snprintf(pname, sizeof (pname), "{crypt}%s", 3066 ecol[1].ec_value.ec_value_val); 3067 data.sp_pwdp = strdup(pname); 3068 } else 3069 data.sp_pwdp = NULL; 3070 3071 if (ecol[2].ec_value.ec_value_val != NULL && 3072 ecol[2].ec_value.ec_value_val[0] != '\0') { 3073 3074 data.sp_lstchg = ascii_to_int(ecol[2].ec_value.ec_value_val); 3075 if (data.sp_lstchg < -1) { 3076 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3077 "invalid last changed date: %s", 3078 ecol[2].ec_value.ec_value_val); 3079 return (GENENT_PARSEERR); 3080 } 3081 } else 3082 data.sp_lstchg = -1; 3083 3084 if (ecol[3].ec_value.ec_value_val != NULL && 3085 ecol[3].ec_value.ec_value_val[0] != '\0') { 3086 3087 data.sp_min = ascii_to_int(ecol[3].ec_value.ec_value_val); 3088 if (data.sp_min < -1) { 3089 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3090 "invalid sp_min : %s", 3091 ecol[3].ec_value.ec_value_val); 3092 return (GENENT_PARSEERR); 3093 } 3094 } else 3095 data.sp_min = -1; 3096 3097 if (ecol[4].ec_value.ec_value_val != NULL && 3098 ecol[4].ec_value.ec_value_val[0] != '\0') { 3099 3100 data.sp_max = ascii_to_int(ecol[4].ec_value.ec_value_val); 3101 if (data.sp_max < -1) { 3102 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3103 "invalid sp_max : %s", 3104 ecol[4].ec_value.ec_value_val); 3105 return (GENENT_PARSEERR); 3106 } 3107 } else 3108 data.sp_max = -1; 3109 3110 if (ecol[5].ec_value.ec_value_val != NULL && 3111 ecol[5].ec_value.ec_value_val[0] != '\0') { 3112 3113 data.sp_warn = ascii_to_int(ecol[5].ec_value.ec_value_val); 3114 if (data.sp_warn < -1) { 3115 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3116 "invalid sp_warn : %s", 3117 ecol[5].ec_value.ec_value_val); 3118 return (GENENT_PARSEERR); 3119 } 3120 } else 3121 data.sp_warn = -1; 3122 3123 if (ecol[6].ec_value.ec_value_val != NULL && 3124 ecol[6].ec_value.ec_value_val[0] != '\0') { 3125 3126 data.sp_inact = ascii_to_int(ecol[6].ec_value.ec_value_val); 3127 if (data.sp_inact < -1) { 3128 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3129 "invalid sp_inact : %s", 3130 ecol[6].ec_value.ec_value_val); 3131 return (GENENT_PARSEERR); 3132 } 3133 } else 3134 data.sp_inact = -1; 3135 3136 if (ecol[7].ec_value.ec_value_val != NULL && 3137 ecol[7].ec_value.ec_value_val[0] != '\0') { 3138 3139 data.sp_expire = ascii_to_int(ecol[7].ec_value.ec_value_val); 3140 if (data.sp_expire < -1) { 3141 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3142 "invalid login expiry date : %s", 3143 ecol[7].ec_value.ec_value_val); 3144 return (GENENT_PARSEERR); 3145 } 3146 } else 3147 data.sp_expire = -1; 3148 3149 if (ecol[8].ec_value.ec_value_val != NULL && 3150 ecol[8].ec_value.ec_value_val[0] != '\0') { 3151 3152 /* 3153 * data.sp_flag is an unsigned int, 3154 * assign -1 to it, make no sense. 3155 * Use spflag here to avoid lint warning. 3156 */ 3157 spflag = ascii_to_int(ecol[8].ec_value.ec_value_val); 3158 if (spflag < 0) { 3159 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3160 "invalid flag value: %s", 3161 ecol[8].ec_value.ec_value_val); 3162 return (GENENT_PARSEERR); 3163 } else 3164 data.sp_flag = spflag; 3165 } else 3166 data.sp_flag = 0; 3167 3168 if (flags & F_VERBOSE) 3169 (void) fprintf(stdout, 3170 gettext("Adding entry : %s\n"), data.sp_namp); 3171 3172 if ((*cback)(&data, 1) && (continue_onerror == 0)) 3173 return (GENENT_CBERR); 3174 3175 free(data.sp_namp); 3176 free(data.sp_pwdp); 3177 return (GENENT_OK); 3178 } 3179 3180 static void 3181 dump_shadow(ns_ldap_result_t *res) 3182 { 3183 char **value = NULL; 3184 char pnam[256]; 3185 3186 value = __ns_ldap_getAttr(res->entry, "uid"); 3187 if (value == NULL) 3188 return; 3189 else 3190 (void) fprintf(stdout, "%s:", value[0]); 3191 value = __ns_ldap_getAttr(res->entry, "userPassword"); 3192 if (value == NULL) 3193 (void) fprintf(stdout, "*:"); 3194 else { 3195 (void) strcpy(pnam, value[0]); 3196 if (strncasecmp(value[0], "{crypt}", 7) == 0) 3197 (void) fprintf(stdout, "%s:", (pnam+7)); 3198 else 3199 (void) fprintf(stdout, "*:"); 3200 } 3201 value = __ns_ldap_getAttr(res->entry, "shadowLastChange"); 3202 if (value == NULL) 3203 (void) fprintf(stdout, ":"); 3204 else 3205 (void) fprintf(stdout, "%s:", value[0]); 3206 value = __ns_ldap_getAttr(res->entry, "shadowMin"); 3207 if (value == NULL) 3208 (void) fprintf(stdout, ":"); 3209 else 3210 (void) fprintf(stdout, "%s:", value[0]); 3211 value = __ns_ldap_getAttr(res->entry, "shadowMax"); 3212 if (value == NULL) 3213 (void) fprintf(stdout, ":"); 3214 else 3215 (void) fprintf(stdout, "%s:", value[0]); 3216 3217 /* ignore shadowWarning, shadowInactive, shadowExpire, shadowFlag */ 3218 (void) fprintf(stdout, ":::\n"); 3219 3220 } 3221 3222 3223 static int 3224 genent_bootparams(char *line, int (*cback)()) 3225 { 3226 char buf[BUFSIZ+1]; 3227 char *t; 3228 entry_col ecol[2]; 3229 int ctr = 0, retval = 1; 3230 3231 struct _ns_bootp data; 3232 char *parameter; 3233 int rc = GENENT_OK; 3234 3235 /* 3236 * don't clobber our argument 3237 */ 3238 if (strlen(line) >= sizeof (buf)) { 3239 (void) strcpy(parse_err_msg, "line too long"); 3240 return (GENENT_PARSEERR); 3241 } 3242 (void) strcpy(buf, line); 3243 3244 /* 3245 * clear column data 3246 */ 3247 (void) memset((char *)ecol, 0, sizeof (ecol)); 3248 3249 3250 /* 3251 * cname (col 0) 3252 */ 3253 if ((t = strtok(buf, " \t")) == 0) { 3254 (void) strcpy(parse_err_msg, "no cname"); 3255 return (GENENT_PARSEERR); 3256 } 3257 ecol[0].ec_value.ec_value_val = t; 3258 ecol[0].ec_value.ec_value_len = strlen(t)+1; 3259 3260 3261 3262 /* build entry */ 3263 data.name = strdup(ecol[0].ec_value.ec_value_val); 3264 3265 /* 3266 * name (col 1) 3267 */ 3268 3269 data.param = NULL; 3270 3271 do { 3272 3273 /* 3274 * don't clobber comment in canonical entry 3275 */ 3276 3277 3278 ecol[1].ec_value.ec_value_val = t; 3279 ecol[1].ec_value.ec_value_len = strlen(t)+1; 3280 3281 ctr++; 3282 parameter = strdup(ecol[1].ec_value.ec_value_val); 3283 if ((data.param = (char **)realloc(data.param, 3284 (ctr + 1) * sizeof (char **))) == NULL) { 3285 (void) fprintf(stderr, gettext("out of memory\n")); 3286 exit(1); 3287 } 3288 data.param[ctr-1] = parameter; 3289 3290 } while (t = strtok(NULL, " \t")); 3291 3292 3293 /* End the list of all the aliases by NULL */ 3294 if ((data.param = (char **)realloc(data.param, 3295 (ctr + 1) * sizeof (char **))) == NULL) { 3296 (void) fprintf(stderr, gettext("out of memory\n")); 3297 exit(1); 3298 } 3299 data.param[ctr] = NULL; 3300 3301 if (flags & F_VERBOSE) 3302 (void) fprintf(stdout, 3303 gettext("Adding entry : %s\n"), data.name); 3304 3305 retval = (*cback)(&data, 0); 3306 3307 if (retval == LDAP_ALREADY_EXISTS) { 3308 if (continue_onerror) 3309 (void) fprintf(stderr, 3310 gettext("Entry: %s - already Exists, skipping it.\n"), 3311 data.name); 3312 else { 3313 rc = GENENT_CBERR; 3314 (void) fprintf(stderr, 3315 gettext("Entry: %s - already Exists\n"), 3316 data.name); 3317 } 3318 } else if (retval) 3319 rc = GENENT_CBERR; 3320 3321 free(data.name); 3322 free(data.param); 3323 3324 return (rc); 3325 3326 } 3327 3328 3329 static void 3330 dump_bootparams(ns_ldap_result_t *res) 3331 { 3332 char **value = NULL; 3333 int attr_count = 0; 3334 3335 value = __ns_ldap_getAttr(res->entry, "cn"); 3336 if (value[0] != NULL) 3337 (void) fprintf(stdout, "%s", value[0]); 3338 value = __ns_ldap_getAttr(res->entry, "bootParameter"); 3339 if (value != NULL) 3340 while (value[attr_count] != NULL) { 3341 (void) fprintf(stdout, "\t%s", value[attr_count]); 3342 attr_count++; 3343 } 3344 (void) fprintf(stdout, "\n"); 3345 3346 3347 } 3348 3349 static char * 3350 fget_line_at(struct line_buf *line, int n, FILE *fp) 3351 { 3352 int c; 3353 3354 line->len = n; 3355 3356 for (;;) { 3357 c = fgetc(fp); 3358 if (c == -1) 3359 break; 3360 if (line->len >= line->alloc) 3361 line_buf_expand(line); 3362 line->str[line->len++] = c; 3363 3364 if (c == '\n') 3365 break; 3366 } 3367 3368 /* Null Terminate */ 3369 if (line->len >= line->alloc) 3370 line_buf_expand(line); 3371 line->str[line->len++] = 0; 3372 3373 /* if no characters are read, return NULL to indicate EOF */ 3374 if (line->str[0] == '\0') 3375 return (0); 3376 3377 return (line->str); 3378 } 3379 3380 /* 3381 * return a line from the file, discarding comments and blank lines 3382 */ 3383 static int 3384 filedbmline_comment(struct line_buf *line, FILE *etcf, int *lineno, 3385 struct file_loc *loc) 3386 { 3387 int i, len = 0; 3388 3389 loc->offset = ftell(etcf); 3390 for (;;) { 3391 if (fget_line_at(line, len, etcf) == 0) 3392 return (0); 3393 3394 if (lineno) 3395 (*lineno)++; 3396 3397 len = strlen(line->str); 3398 if (len >= 2 && 3399 line->str[0] != '#' && 3400 line->str[len-2] == '\\' && line->str[len-1] == '\n') { 3401 line->str[len-2] = 0; 3402 len -= 2; 3403 continue; /* append next line at end */ 3404 } 3405 3406 if (line->str[len-1] == '\n') { 3407 line->str[len-1] = 0; 3408 len -= 1; 3409 } 3410 3411 /* 3412 * Skip lines where '#' is the first non-blank character. 3413 */ 3414 for (i = 0; i < len; i++) { 3415 if (line->str[i] == '#') { 3416 line->str[i] = '\0'; 3417 len = i; 3418 break; 3419 } 3420 if (line->str[i] != ' ' && line->str[i] != '\t') 3421 break; 3422 } 3423 3424 /* 3425 * A line with one or more white space characters followed 3426 * by a comment will now be blank. The special case of a 3427 * line with '#' in the first byte will have len == 0. 3428 */ 3429 if (len > 0 && !blankline(line->str)) 3430 break; 3431 3432 len = 0; 3433 loc->offset = ftell(etcf); 3434 } 3435 3436 loc->size = len; 3437 return (1); 3438 } 3439 3440 /* 3441 * return a line from the file, discarding comments, blanks, and '+' lines 3442 */ 3443 static int 3444 filedbmline_plus(struct line_buf *line, FILE *etcf, int *lineno, 3445 struct file_loc *loc) 3446 { 3447 int len = 0; 3448 3449 loc->offset = ftell(etcf); 3450 for (;;) { 3451 if (fget_line_at(line, len, etcf) == 0) 3452 return (0); 3453 3454 if (lineno) 3455 (*lineno)++; 3456 3457 len = strlen(line->str); 3458 if (line->str[len-1] == '\n') { 3459 line->str[len-1] = 0; 3460 len -= 1; 3461 } 3462 3463 if (!blankline(line->str) && 3464 line->str[0] != '+' && line->str[0] != '-' && 3465 line->str[0] != '#') 3466 break; 3467 3468 len = 0; 3469 loc->offset = ftell(etcf); 3470 } 3471 3472 loc->size = len; 3473 return (1); 3474 } 3475 3476 3477 /* Populating the ttypelist structure */ 3478 3479 static struct ttypelist_t ttypelist[] = { 3480 { NS_LDAP_TYPE_HOSTS, genent_hosts, dump_hosts, 3481 filedbmline_comment, "iphost" }, 3482 { NS_LDAP_TYPE_IPNODES, genent_hosts, dump_hosts, 3483 filedbmline_comment, "iphost" }, 3484 { NS_LDAP_TYPE_RPC, genent_rpc, dump_rpc, 3485 filedbmline_comment, "oncrpc" }, 3486 { NS_LDAP_TYPE_PROTOCOLS, genent_protocols, dump_protocols, 3487 filedbmline_comment, "ipprotocol" }, 3488 { NS_LDAP_TYPE_NETWORKS, genent_networks, dump_networks, 3489 filedbmline_comment, "ipnetwork" }, 3490 { NS_LDAP_TYPE_SERVICES, genent_services, dump_services, 3491 filedbmline_comment, "ipservice" }, 3492 { NS_LDAP_TYPE_GROUP, genent_group, dump_group, 3493 filedbmline_plus, "posixgroup" }, 3494 { NS_LDAP_TYPE_NETMASKS, genent_netmasks, dump_netmasks, 3495 filedbmline_comment, "ipnetwork" }, 3496 { NS_LDAP_TYPE_ETHERS, genent_ethers, dump_ethers, 3497 filedbmline_comment, "ieee802Device" }, 3498 { NS_LDAP_TYPE_NETGROUP, genent_netgroup, dump_netgroup, 3499 filedbmline_comment, "nisnetgroup" }, 3500 { NS_LDAP_TYPE_BOOTPARAMS, genent_bootparams, dump_bootparams, 3501 filedbmline_comment, "bootableDevice" }, 3502 { NS_LDAP_TYPE_PUBLICKEY, genent_publickey, NULL /* dump_publickey */, 3503 filedbmline_comment, "niskeyobject" }, 3504 { NS_LDAP_TYPE_PASSWD, genent_passwd, dump_passwd, 3505 filedbmline_plus, "posixaccount" }, 3506 { NS_LDAP_TYPE_SHADOW, genent_shadow, dump_shadow, 3507 filedbmline_plus, "shadowaccount" }, 3508 { NS_LDAP_TYPE_ALIASES, genent_aliases, dump_aliases, 3509 filedbmline_plus, "mailGroup" }, 3510 { NS_LDAP_TYPE_AUTOMOUNT, genent_automount, dump_automount, 3511 filedbmline_comment, "automount" }, 3512 { NS_LDAP_TYPE_USERATTR, genent_user_attr, dump_user_attr, 3513 filedbmline_comment, "SolarisUserAttr" }, 3514 { NS_LDAP_TYPE_PROFILE, genent_prof_attr, dump_prof_attr, 3515 filedbmline_comment, "SolarisProfAttr" }, 3516 { NS_LDAP_TYPE_EXECATTR, genent_exec_attr, dump_exec_attr, 3517 filedbmline_comment, "SolarisExecAttr" }, 3518 { NS_LDAP_TYPE_AUTHATTR, genent_auth_attr, dump_auth_attr, 3519 filedbmline_comment, "SolarisAuthAttr" }, 3520 { NS_LDAP_TYPE_AUUSER, genent_audit_user, dump_audit_user, 3521 filedbmline_comment, "SolarisAuditUser" }, 3522 { 0, 0, 0, 0, 0 } 3523 }; 3524 3525 3526 3527 3528 static int lineno = 0; 3529 3530 static void 3531 addfile() 3532 { 3533 struct line_buf line; 3534 struct file_loc loc; 3535 3536 /* Initializing the Line Buffer */ 3537 line_buf_init(&line); 3538 3539 /* Loop through all the lines in the file */ 3540 while (tt->filedbmline(&line, etcf, &lineno, &loc)) { 3541 switch ((*(tt->genent))(line.str, addentry)) { 3542 case GENENT_OK: 3543 break; 3544 case GENENT_PARSEERR: 3545 (void) fprintf(stderr, 3546 gettext("parse error: %s (line %d)\n"), 3547 parse_err_msg, lineno); 3548 exit_val = 1; 3549 break; 3550 case GENENT_CBERR: 3551 (void) fprintf(stderr, 3552 gettext("Error while adding line: %s\n"), 3553 line.str); 3554 exit_val = 2; 3555 free(line.str); 3556 return; 3557 break; 3558 case GENENT_ERR: 3559 (void) fprintf(stderr, 3560 gettext("Internal Error while adding line: %s\n"), 3561 line.str); 3562 exit_val = 3; 3563 free(line.str); 3564 return; 3565 break; 3566 } 3567 } 3568 free(line.str); 3569 } 3570 3571 static void 3572 dumptable(char *service) 3573 { 3574 3575 ns_ldap_result_t *eres = NULL; 3576 ns_ldap_error_t *err = NULL; 3577 int rc = 0, success = 0; 3578 char filter[BUFSIZ]; 3579 int done = 0; 3580 void *cookie = NULL; 3581 3582 /* set the appropriate filter */ 3583 if (strcmp(tt->ttype, NS_LDAP_TYPE_PROFILE) == 0) { 3584 /* 3585 * prof_attr entries are SolarisProfAttr 3586 * without AUXILIARY SolarisExecAttr 3587 */ 3588 (void) snprintf(filter, sizeof (filter), 3589 "(&(objectclass=%s)(!(objectclass=SolarisExecAttr)))", 3590 tt->objclass); 3591 } else 3592 (void) snprintf(filter, sizeof (filter), 3593 "(objectclass=%s)", tt->objclass); 3594 3595 if (flags & F_VERBOSE) 3596 (void) fprintf(stdout, gettext("FILTER = %s\n"), filter); 3597 3598 /* Pass cred only if supplied. Cred is not always needed for dump */ 3599 if (authority.cred.unix_cred.userID == NULL || 3600 authority.cred.unix_cred.passwd == NULL) 3601 rc = __ns_ldap_firstEntry(service, filter, NULL, NULL, 3602 NULL, NS_LDAP_HARD, &cookie, &eres, &err, NULL); 3603 else 3604 rc = __ns_ldap_firstEntry(service, filter, NULL, NULL, 3605 &authority, NS_LDAP_HARD, &cookie, &eres, &err, NULL); 3606 3607 switch (rc) { 3608 case NS_LDAP_SUCCESS: 3609 nent_add++; 3610 success = 1; 3611 if (eres != NULL) { 3612 if (strcmp(databasetype, "publickey") == 0) 3613 dump_publickey(eres, service); 3614 else 3615 (*(tt->dump))(eres); 3616 } 3617 else 3618 (void) fprintf(stderr, gettext("No entries found.\n")); 3619 break; 3620 3621 case NS_LDAP_OP_FAILED: 3622 exit_val = 2; 3623 (void) fprintf(stderr, gettext("operation failed.\n")); 3624 break; 3625 3626 case NS_LDAP_INVALID_PARAM: 3627 exit_val = 2; 3628 (void) fprintf(stderr, 3629 gettext("invalid parameter(s) passed.\n")); 3630 break; 3631 3632 case NS_LDAP_NOTFOUND: 3633 exit_val = 2; 3634 (void) fprintf(stderr, gettext("entry not found.\n")); 3635 break; 3636 3637 case NS_LDAP_MEMORY: 3638 exit_val = 2; 3639 (void) fprintf(stderr, 3640 gettext("internal memory allocation error.\n")); 3641 break; 3642 3643 case NS_LDAP_CONFIG: 3644 exit_val = 2; 3645 (void) fprintf(stderr, 3646 gettext("LDAP Configuration problem.\n")); 3647 perr(err); 3648 break; 3649 3650 case NS_LDAP_PARTIAL: 3651 exit_val = 2; 3652 (void) fprintf(stderr, 3653 gettext("partial result returned\n")); 3654 perr(err); 3655 break; 3656 3657 case NS_LDAP_INTERNAL: 3658 exit_val = 2; 3659 (void) fprintf(stderr, 3660 gettext("internal LDAP error occured.\n")); 3661 perr(err); 3662 break; 3663 } 3664 3665 if (eres != NULL) { 3666 (void) __ns_ldap_freeResult(&eres); 3667 eres = NULL; 3668 } 3669 3670 if (success) { 3671 while (!done) { 3672 rc = __ns_ldap_nextEntry(cookie, &eres, &err); 3673 if (rc != NS_LDAP_SUCCESS || eres == NULL) { 3674 done = 1; 3675 continue; 3676 } 3677 3678 /* Print the result */ 3679 if (eres != NULL) { 3680 if (strcmp(databasetype, "publickey") == 0) 3681 dump_publickey(eres, service); 3682 else 3683 (*(tt->dump))(eres); 3684 (void) __ns_ldap_freeResult(&eres); 3685 eres = NULL; 3686 } 3687 } 3688 } 3689 } 3690 3691 int 3692 main(int argc, char **argv) 3693 { 3694 char *password; 3695 int c; 3696 int rc; 3697 int ldaprc; 3698 int authstried = 0; 3699 int supportedauth = 0; 3700 int op = OP_ADD; 3701 char *ttype, *authmech = 0, *etcfile = 0; 3702 char ps[LDAP_MAXNAMELEN]; /* Temporary password variable */ 3703 char filter[BUFSIZ]; 3704 void **paramVal = NULL; 3705 ns_auth_t **app; 3706 ns_auth_t **authpp = NULL; 3707 ns_auth_t *authp = NULL; 3708 ns_ldap_error_t *errorp = NULL; 3709 ns_ldap_result_t *resultp; 3710 ns_ldap_entry_t *e; 3711 int flag = 0; 3712 int version1 = 0; 3713 3714 (void) setlocale(LC_ALL, ""); 3715 (void) textdomain(TEXT_DOMAIN); 3716 3717 openlog("ldapaddent", LOG_PID, LOG_USER); 3718 3719 inputbasedn = NULL; 3720 authority.cred.unix_cred.passwd = NULL; 3721 authority.cred.unix_cred.userID = NULL; 3722 authority.auth.type = NS_LDAP_AUTH_SIMPLE; 3723 3724 while ((c = getopt(argc, argv, "cdhvpf:D:w:b:a:")) != EOF) { 3725 switch (c) { 3726 case 'd': 3727 if (op) 3728 usage("no other option should be specified"); 3729 op = OP_DUMP; 3730 break; 3731 case 'c': 3732 continue_onerror = 1; 3733 break; 3734 case 'v': 3735 flags |= F_VERBOSE; 3736 break; 3737 case 'p': 3738 flags |= F_PASSWD; 3739 break; 3740 case 'f': 3741 etcfile = optarg; 3742 break; 3743 case 'D': 3744 authority.cred.unix_cred.userID = strdup(optarg); 3745 break; 3746 case 'w': 3747 authority.cred.unix_cred.passwd = strdup(optarg); 3748 break; 3749 case 'b': 3750 inputbasedn = strdup(optarg); 3751 break; 3752 case 'a': 3753 authmech = strdup(optarg); 3754 break; 3755 3756 default: 3757 usage(gettext("Invalid option")); 3758 } 3759 } 3760 3761 3762 if (authority.cred.unix_cred.userID == NULL && op != OP_DUMP) { 3763 /* This is not an optional parameter. Exit */ 3764 (void) fprintf(stderr, 3765 gettext("Distinguished Name to bind to directory" 3766 " must be specified. use option -D.\n")); 3767 exit(1); 3768 } 3769 3770 if (authority.cred.unix_cred.passwd == NULL && op != OP_DUMP) { 3771 /* If password is not specified, then prompt user for it. */ 3772 password = getpassphrase("Enter password:"); 3773 (void) strcpy(ps, password); 3774 authority.cred.unix_cred.passwd = strdup(ps); 3775 } 3776 3777 if (authmech != NULL) { 3778 if (strcasecmp(authmech, "simple") == 0) { 3779 authority.auth.type = NS_LDAP_AUTH_SIMPLE; 3780 authority.auth.tlstype = NS_LDAP_TLS_NONE; 3781 authority.auth.saslmech = NS_LDAP_SASL_NONE; 3782 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3783 supportedauth = 1; 3784 } 3785 if (strcasecmp(authmech, "sasl/CRAM-MD5") == 0) { 3786 authority.auth.type = NS_LDAP_AUTH_SASL; 3787 authority.auth.tlstype = NS_LDAP_TLS_SASL; 3788 authority.auth.saslmech = NS_LDAP_SASL_CRAM_MD5; 3789 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3790 supportedauth = 1; 3791 } 3792 if (strcasecmp(authmech, "sasl/DIGEST-MD5") == 0) { 3793 authority.auth.type = NS_LDAP_AUTH_SASL; 3794 authority.auth.tlstype = NS_LDAP_TLS_SASL; 3795 authority.auth.saslmech = NS_LDAP_SASL_DIGEST_MD5; 3796 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3797 supportedauth = 1; 3798 } 3799 if (strcasecmp(authmech, "tls:simple") == 0) { 3800 authority.auth.type = NS_LDAP_AUTH_TLS; 3801 authority.auth.tlstype = NS_LDAP_TLS_SIMPLE; 3802 authority.auth.saslmech = NS_LDAP_SASL_NONE; 3803 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3804 supportedauth = 1; 3805 } 3806 if (strcasecmp(authmech, "tls:sasl/CRAM-MD5") == 0) { 3807 authority.auth.type = NS_LDAP_AUTH_TLS; 3808 authority.auth.tlstype = NS_LDAP_TLS_SASL; 3809 authority.auth.saslmech = NS_LDAP_SASL_CRAM_MD5; 3810 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3811 supportedauth = 1; 3812 } 3813 if (strcasecmp(authmech, "tls:sasl/DIGEST-MD5") == 0) { 3814 authority.auth.type = NS_LDAP_AUTH_TLS; 3815 authority.auth.tlstype = NS_LDAP_TLS_SASL; 3816 authority.auth.saslmech = NS_LDAP_SASL_DIGEST_MD5; 3817 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3818 supportedauth = 1; 3819 } 3820 if (!supportedauth) { 3821 (void) fprintf(stderr, 3822 gettext("Invalid authentication method specified")); 3823 exit(1); 3824 } 3825 } 3826 3827 if (authmech == NULL) { 3828 ldaprc = __ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp, 3829 &errorp); 3830 if (ldaprc != NS_LDAP_SUCCESS || 3831 (authpp == NULL && op != OP_DUMP)) { 3832 (void) fprintf(stderr, 3833 gettext("No legal authentication method " 3834 "configured.\n")); 3835 (void) fprintf(stderr, 3836 gettext("Provide a legal authentication method " 3837 "using -a option\n")); 3838 exit(1); 3839 } 3840 3841 /* Use the first authentication method which is not none */ 3842 for (app = authpp; *app; app++) { 3843 authp = *app; 3844 if (authp->type != NS_LDAP_AUTH_NONE) { 3845 authstried++; 3846 authority.auth.type = authp->type; 3847 authority.auth.tlstype = authp->tlstype; 3848 authority.auth.saslmech = authp->saslmech; 3849 authority.auth.saslopt = authp->saslopt; 3850 break; 3851 } 3852 } 3853 if (authstried == 0 && op != OP_DUMP) { 3854 (void) fprintf(stderr, 3855 gettext("No legal authentication method configured.\n" 3856 "Provide a legal authentication method using " 3857 "-a option")); 3858 exit(1); 3859 } 3860 } 3861 3862 ttype = argv[optind++]; 3863 3864 if (ttype == NULL) { 3865 usage(gettext("No database type specified")); 3866 exit(1); 3867 } 3868 3869 if (strncasecmp(ttype, "automount", 9) == 0) { 3870 (void) fprintf(stderr, 3871 gettext("automount is not a valid service for ldapaddent.\n" 3872 "Please use auto_*.\n" 3873 "e.g. auto_home, auto_ws etc.\n ")); 3874 exit(1); 3875 } 3876 3877 for (tt = ttypelist; tt->ttype; tt++) { 3878 if (strcmp(tt->ttype, ttype) == 0) 3879 break; 3880 if (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0 && 3881 strncmp(ttype, NS_LDAP_TYPE_AUTOMOUNT, 3882 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) 3883 break; 3884 } 3885 3886 if (tt->ttype == 0) { 3887 (void) fprintf(stderr, 3888 gettext("database %s not supported;" 3889 " supported databases are:\n"), ttype); 3890 for (tt = ttypelist; tt->ttype; tt++) 3891 (void) fprintf(stderr, gettext("\t%s\n"), tt->ttype); 3892 exit(1); 3893 } 3894 3895 if (flags & F_VERBOSE) 3896 (void) fprintf(stdout, gettext("SERVICE = %s\n"), tt->ttype); 3897 3898 databasetype = ttype; 3899 3900 if (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0) { 3901 paramVal = NULL; 3902 errorp = NULL; 3903 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, 3904 &errorp); 3905 if (paramVal && *paramVal && 3906 strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0) 3907 version1 = 1; 3908 if (paramVal) 3909 (void) __ns_ldap_freeParam(¶mVal); 3910 if (errorp) 3911 (void) __ns_ldap_freeError(&errorp); 3912 } 3913 3914 /* Check if the container exists in first place */ 3915 (void) strcpy(&filter[0], "(objectclass=*)"); 3916 3917 rc = __ns_ldap_list(databasetype, filter, NULL, (const char **)NULL, 3918 NULL, NS_LDAP_SCOPE_BASE, &resultp, &errorp, NULL, NULL); 3919 3920 /* create a container for auto_* if it does not exist already */ 3921 if ((rc == NS_LDAP_NOTFOUND) && (op == OP_ADD) && 3922 (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0)) { 3923 static char *oclist[] = {NULL, "top", NULL}; 3924 if (version1) 3925 oclist[0] = "nisMap"; 3926 else 3927 oclist[0] = "automountMap"; 3928 e = __s_mk_entry(oclist, 3); 3929 if (e == NULL) { 3930 (void) fprintf(stderr, 3931 gettext("internal memory allocation error.\n")); 3932 exit(1); 3933 } 3934 if (__s_add_attr(e, 3935 version1 ? "nisMapName" : "automountMapName", 3936 databasetype) != NS_LDAP_SUCCESS) { 3937 (void) fprintf(stderr, 3938 gettext("internal memory allocation error.\n")); 3939 ldap_freeEntry(e); 3940 exit(1); 3941 } 3942 3943 if (inputbasedn == NULL) { 3944 if (get_basedn(databasetype, &inputbasedn) != 3945 NS_LDAP_SUCCESS) { 3946 (void) fprintf(stderr, 3947 gettext("Could not obtain basedn\n")); 3948 ldap_freeEntry(e); 3949 exit(1); 3950 } 3951 } 3952 if (__ns_ldap_addEntry(databasetype, inputbasedn, e, 3953 &authority, flag, &errorp) != NS_LDAP_SUCCESS) { 3954 (void) fprintf(stderr, 3955 gettext("Could not create container for %s\n"), 3956 databasetype); 3957 ldap_freeEntry(e); 3958 } 3959 } else if (strcmp(databasetype, "publickey") != 0) { 3960 if (rc == NS_LDAP_NOTFOUND) { 3961 (void) fprintf(stderr, 3962 gettext("Container %s does not exist\n"), 3963 databasetype); 3964 exit(1); 3965 } 3966 } 3967 3968 if (op == OP_DUMP) { 3969 if (strcmp(databasetype, "publickey") == 0) { 3970 dumptable("hosts"); 3971 dumptable("passwd"); 3972 } else { 3973 dumptable(databasetype); 3974 } 3975 exit(exit_val); 3976 } 3977 3978 if (etcfile) { 3979 if ((etcf = fopen(etcfile, "r")) == 0) { 3980 (void) fprintf(stderr, 3981 gettext("can't open file %s\n"), etcfile); 3982 exit(1); 3983 } 3984 } else { 3985 etcfile = "stdin"; 3986 etcf = stdin; 3987 } 3988 3989 if (op == OP_ADD) { 3990 (void) addfile(); 3991 (void) fprintf(stdout, gettext("%d entries added\n"), nent_add); 3992 } 3993 3994 /* exit() -> return for make lint */ 3995 return (exit_val); 3996 } 3997 3998 3999 /* 4000 * This is called when service == auto_*. 4001 * It calls __ns_ldap_getSearchDescriptors 4002 * to generate the dn from SSD's base dn. 4003 * If there is no SSD available, 4004 * default base dn will be used 4005 * Only the first baseDN in the SSD is used 4006 */ 4007 4008 static int get_basedn(char *service, char **basedn) { 4009 int rc = NS_LDAP_SUCCESS; 4010 char *dn = NULL; 4011 ns_ldap_search_desc_t **desc = NULL; 4012 ns_ldap_error_t *errp = NULL; 4013 void **paramVal = NULL; 4014 int prepend_automountmapname = FALSE; 4015 4016 /* 4017 * Get auto_* SSD first 4018 */ 4019 4020 if ((rc = __ns_ldap_getSearchDescriptors( 4021 (const char *) service, 4022 &desc, &errp)) == NS_LDAP_SUCCESS && 4023 desc != NULL) { 4024 4025 if (desc[0] != NULL && desc[0]->basedn != NULL) { 4026 dn = strdup(desc[0]->basedn); 4027 if (dn == NULL) { 4028 (void) __ns_ldap_freeSearchDescriptors 4029 (&desc); 4030 return (NS_LDAP_MEMORY); 4031 } 4032 } 4033 } 4034 4035 /* clean up */ 4036 if (desc) (void) __ns_ldap_freeSearchDescriptors(&desc); 4037 if (errp) (void) __ns_ldap_freeError(&errp); 4038 4039 /* 4040 * If no dn is duplicated from auto_* SSD, try automount SSD 4041 */ 4042 if (dn == NULL) { 4043 if ((rc = __ns_ldap_getSearchDescriptors( 4044 "automount", &desc, &errp)) 4045 == NS_LDAP_SUCCESS && desc != NULL) { 4046 4047 if (desc[0] != NULL && desc[0]->basedn != NULL) { 4048 dn = strdup(desc[0]->basedn); 4049 if (dn == NULL) { 4050 (void) __ns_ldap_freeSearchDescriptors 4051 (&desc); 4052 return (NS_LDAP_MEMORY); 4053 } 4054 prepend_automountmapname = TRUE; 4055 } 4056 } 4057 /* clean up */ 4058 if (desc) (void) __ns_ldap_freeSearchDescriptors(&desc); 4059 if (errp) (void) __ns_ldap_freeError(&errp); 4060 } 4061 4062 /* 4063 * If no dn is duplicated from auto_* or automount SSD, 4064 * use default DN 4065 */ 4066 4067 if (dn == NULL) { 4068 if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 4069 ¶mVal, &errp)) == NS_LDAP_SUCCESS) { 4070 dn = strdup((char *)paramVal[0]); 4071 if (dn == NULL) { 4072 (void) __ns_ldap_freeParam(¶mVal); 4073 return (NS_LDAP_MEMORY); 4074 } 4075 prepend_automountmapname = TRUE; 4076 } 4077 if (paramVal) (void) __ns_ldap_freeParam(¶mVal); 4078 if (errp) (void) __ns_ldap_freeError(&errp); 4079 } 4080 4081 4082 if (dn == NULL) { 4083 return (NS_LDAP_OP_FAILED); 4084 } else { 4085 /* 4086 * If dn is duplicated from 4087 * automount SSD basedn or 4088 * default base dn 4089 * then prepend automountMapName=auto_xxx 4090 */ 4091 if (prepend_automountmapname) 4092 rc = __s_api_prepend_automountmapname_to_dn( 4093 service, &dn, &errp); 4094 4095 if (rc != NS_LDAP_SUCCESS) { 4096 (void) __ns_ldap_freeError(&errp); 4097 free(dn); 4098 return (rc); 4099 } 4100 4101 *basedn = dn; 4102 4103 return (NS_LDAP_SUCCESS); 4104 } 4105 } 4106