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