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