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 attr_count = 0; 2650 value = __ns_ldap_getAttr(res->entry, "memberNisNetgroup"); 2651 if (value != NULL) 2652 while (value[attr_count] != NULL) { 2653 (void) fprintf(stdout, " %s", value[attr_count]); 2654 attr_count++; 2655 } 2656 (void) fprintf(stdout, "\n"); 2657 2658 } 2659 2660 static int 2661 genent_automount(char *line, int (*cback)()) 2662 { 2663 char buf[BUFSIZ+1]; 2664 char *t, *s; 2665 entry_col ecol[2]; 2666 struct _ns_automount data; 2667 int retval = 1; 2668 int rc = GENENT_OK; 2669 2670 /* 2671 * don't clobber our argument 2672 */ 2673 if (strlen(line) >= sizeof (buf)) { 2674 (void) strcpy(parse_err_msg, "line too long"); 2675 return (GENENT_PARSEERR); 2676 } 2677 2678 /* replace every tabspace with single space */ 2679 replace_tab2space(line); 2680 (void) strcpy(buf, line); 2681 2682 /* 2683 * clear column data 2684 */ 2685 (void) memset((char *)ecol, 0, sizeof (ecol)); 2686 2687 /* 2688 * key (col 0) 2689 */ 2690 t = buf; 2691 while (t[0] == ' ') 2692 t++; 2693 2694 if ((s = strchr(t, ' ')) == 0) { 2695 return (GENENT_PARSEERR); 2696 } 2697 *s++ = 0; 2698 2699 ecol[0].ec_value.ec_value_val = t; 2700 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2701 t = s; 2702 2703 while (t[0] == ' ') 2704 t++; 2705 2706 /* 2707 * mapentry (col 1) 2708 */ 2709 2710 ecol[1].ec_value.ec_value_val = t; 2711 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2712 2713 data.mapname = strdup(databasetype); 2714 data.key = strdup(ecol[0].ec_value.ec_value_val); 2715 data.value = strdup(ecol[1].ec_value.ec_value_val); 2716 2717 if (flags & F_VERBOSE) 2718 (void) fprintf(stdout, 2719 gettext("Adding entry : %s\n"), data.key); 2720 2721 retval = (*cback)(&data, 0); 2722 2723 if (retval == LDAP_ALREADY_EXISTS) { 2724 if (continue_onerror) 2725 (void) fprintf(stderr, 2726 gettext("Entry: %s - already Exists, skipping it.\n"), 2727 data.key); 2728 else { 2729 rc = GENENT_CBERR; 2730 (void) fprintf(stderr, 2731 gettext("Entry: %s - already Exists\n"), 2732 data.key); 2733 } 2734 } else if (retval) 2735 rc = GENENT_CBERR; 2736 2737 free(data.mapname); 2738 free(data.key); 2739 free(data.value); 2740 return (rc); 2741 } 2742 2743 static void 2744 dump_automount(ns_ldap_result_t *res) 2745 { 2746 char **value = NULL; 2747 2748 if (res == NULL) 2749 return; 2750 2751 value = __ns_ldap_getAttr(res->entry, "automountKey"); 2752 if (value != NULL) { 2753 (void) fprintf(stdout, "%s", value[0]); 2754 value = __ns_ldap_getAttr(res->entry, "automountInformation"); 2755 if (value != NULL) 2756 (void) fprintf(stdout, " %s\n", value[0]); 2757 else 2758 (void) fprintf(stdout, "\n"); 2759 } 2760 } 2761 2762 2763 /* 2764 * /etc/passwd 2765 * 2766 */ 2767 2768 static int 2769 genent_passwd(char *line, int (*cback)()) 2770 { 2771 char buf[BUFSIZ+1]; 2772 char *s, *t; 2773 entry_col ecol[8]; 2774 int retval = 1; 2775 char pname[BUFSIZ]; 2776 2777 struct passwd data; 2778 int rc = GENENT_OK; 2779 2780 2781 /* 2782 * don't clobber our argument 2783 */ 2784 if (strlen(line) >= sizeof (buf)) { 2785 (void) strcpy(parse_err_msg, "line too long"); 2786 return (GENENT_PARSEERR); 2787 } 2788 (void) strcpy(buf, line); 2789 t = buf; 2790 2791 /* ignore empty entries */ 2792 if (*t == '\0') 2793 return (GENENT_OK); 2794 2795 /* 2796 * clear column data 2797 */ 2798 (void) memset((char *)ecol, 0, sizeof (ecol)); 2799 2800 /* 2801 * name (col 0) 2802 */ 2803 if ((s = strchr(t, ':')) == 0) { 2804 (void) strcpy(parse_err_msg, "no password"); 2805 return (GENENT_PARSEERR); 2806 } 2807 *s++ = 0; 2808 ecol[0].ec_value.ec_value_val = t; 2809 ecol[0].ec_value.ec_value_len = strlen(t)+1; 2810 t = s; 2811 2812 /* 2813 * passwd (col 1) 2814 */ 2815 if ((s = strchr(t, ':')) == 0) { 2816 (void) strcpy(parse_err_msg, "no uid"); 2817 return (GENENT_PARSEERR); 2818 } 2819 *s++ = 0; 2820 2821 ecol[1].ec_value.ec_value_val = t; 2822 ecol[1].ec_value.ec_value_len = strlen(t)+1; 2823 2824 t = s; 2825 2826 /* 2827 * uid (col 2) 2828 */ 2829 if ((s = strchr(t, ':')) == 0 || s == t) { 2830 (void) strcpy(parse_err_msg, "no gid"); 2831 return (GENENT_PARSEERR); 2832 } 2833 *s++ = 0; 2834 ecol[2].ec_value.ec_value_val = t; 2835 ecol[2].ec_value.ec_value_len = strlen(t)+1; 2836 t = s; 2837 2838 /* 2839 * gid (col 3) 2840 */ 2841 if ((s = strchr(t, ':')) == 0 || s == t) { 2842 (void) strcpy(parse_err_msg, "no gcos"); 2843 return (GENENT_PARSEERR); 2844 } 2845 *s++ = 0; 2846 ecol[3].ec_value.ec_value_val = t; 2847 ecol[3].ec_value.ec_value_len = strlen(t)+1; 2848 t = s; 2849 2850 /* 2851 * gcos (col 4) 2852 */ 2853 if ((s = strchr(t, ':')) == 0) { 2854 (void) strcpy(parse_err_msg, "no home"); 2855 return (GENENT_PARSEERR); 2856 } 2857 *s++ = 0; 2858 ecol[4].ec_value.ec_value_val = t; 2859 ecol[4].ec_value.ec_value_len = strlen(t)+1; 2860 t = s; 2861 2862 /* 2863 * home (col 5) 2864 */ 2865 if ((s = strchr(t, ':')) == 0) { 2866 (void) strcpy(parse_err_msg, "no shell"); 2867 return (GENENT_PARSEERR); 2868 } 2869 *s++ = 0; 2870 ecol[5].ec_value.ec_value_val = t; 2871 ecol[5].ec_value.ec_value_len = strlen(t)+1; 2872 t = s; 2873 2874 /* 2875 * shell (col 6) 2876 */ 2877 ecol[6].ec_value.ec_value_val = t; 2878 ecol[6].ec_value.ec_value_len = strlen(t)+1; 2879 2880 /* 2881 * build entry 2882 */ 2883 data.pw_name = strdup(ecol[0].ec_value.ec_value_val); 2884 2885 if (flags & F_PASSWD) { 2886 /* Add {crypt} before passwd entry */ 2887 (void) snprintf(pname, sizeof (pname), "{crypt}%s", 2888 ecol[1].ec_value.ec_value_val); 2889 data.pw_passwd = strdup(pname); 2890 } 2891 else 2892 data.pw_passwd = NULL; 2893 2894 if (ecol[2].ec_value.ec_value_val != NULL && 2895 ecol[2].ec_value.ec_value_val[0] != '\0') { 2896 data.pw_uid = ascii_to_int(ecol[2].ec_value.ec_value_val); 2897 if (data.pw_uid == -1) { 2898 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 2899 "invalid uid : %s", ecol[2].ec_value.ec_value_val); 2900 return (GENENT_PARSEERR); 2901 } 2902 } else 2903 data.pw_uid = -1; 2904 2905 if (ecol[3].ec_value.ec_value_val != NULL && 2906 ecol[3].ec_value.ec_value_val[0] != '\0') { 2907 2908 data.pw_gid = ascii_to_int(ecol[3].ec_value.ec_value_val); 2909 if (data.pw_gid == -1) { 2910 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 2911 "invalid gid : %s", ecol[3].ec_value.ec_value_val); 2912 return (GENENT_PARSEERR); 2913 } 2914 } else 2915 data.pw_gid = -1; 2916 2917 data.pw_age = NULL; 2918 data.pw_comment = NULL; 2919 data.pw_gecos = strdup(ecol[4].ec_value.ec_value_val); 2920 data.pw_dir = strdup(ecol[5].ec_value.ec_value_val); 2921 data.pw_shell = strdup(ecol[6].ec_value.ec_value_val); 2922 2923 if (flags & F_VERBOSE) 2924 (void) fprintf(stdout, 2925 gettext("Adding entry : %s\n"), data.pw_name); 2926 2927 retval = (*cback)(&data, 0); 2928 2929 if (retval == LDAP_ALREADY_EXISTS) { 2930 if (continue_onerror) 2931 (void) fprintf(stderr, 2932 gettext("Entry: %s - already Exists, skipping it.\n"), 2933 data.pw_name); 2934 else { 2935 rc = GENENT_CBERR; 2936 (void) fprintf(stderr, 2937 gettext("Entry: %s - already Exists\n"), 2938 data.pw_name); 2939 } 2940 } else if (retval) 2941 rc = GENENT_CBERR; 2942 2943 free(data.pw_name); 2944 free(data.pw_gecos); 2945 free(data.pw_dir); 2946 free(data.pw_shell); 2947 return (rc); 2948 } 2949 2950 2951 static void 2952 dump_passwd(ns_ldap_result_t *res) 2953 { 2954 char **value = NULL; 2955 char pnam[256]; 2956 2957 value = __ns_ldap_getAttr(res->entry, "uid"); 2958 if (value == NULL) 2959 return; 2960 else 2961 (void) fprintf(stdout, "%s:", value[0]); 2962 value = __ns_ldap_getAttr(res->entry, "userPassword"); 2963 if (value == NULL) 2964 (void) fprintf(stdout, "*:"); 2965 else { 2966 (void) strcpy(pnam, value[0]); 2967 if (strncasecmp(value[0], "{crypt}", 7) == 0) 2968 (void) fprintf(stdout, "%s:", (pnam+7)); 2969 else 2970 (void) fprintf(stdout, "*:"); 2971 } 2972 value = __ns_ldap_getAttr(res->entry, "uidNumber"); 2973 if (value && value[0]) 2974 (void) fprintf(stdout, "%s:", value[0]); 2975 value = __ns_ldap_getAttr(res->entry, "gidNumber"); 2976 if (value && value[0]) 2977 (void) fprintf(stdout, "%s:", value[0]); 2978 value = __ns_ldap_getAttr(res->entry, "gecos"); 2979 if (value == NULL) 2980 (void) fprintf(stdout, ":"); 2981 else 2982 (void) fprintf(stdout, "%s:", value[0]); 2983 value = __ns_ldap_getAttr(res->entry, "homeDirectory"); 2984 if (value == NULL) 2985 (void) fprintf(stdout, ":"); 2986 else 2987 (void) fprintf(stdout, "%s:", value[0]); 2988 value = __ns_ldap_getAttr(res->entry, "loginShell"); 2989 if (value == NULL) 2990 (void) fprintf(stdout, "\n"); 2991 else 2992 (void) fprintf(stdout, "%s\n", value[0]); 2993 2994 } 2995 2996 /* 2997 * /etc/shadow 2998 */ 2999 3000 static int 3001 genent_shadow(char *line, int (*cback)()) 3002 { 3003 char buf[BUFSIZ+1]; 3004 char *s, *t; 3005 entry_col ecol[9]; 3006 char pname[BUFSIZ]; 3007 3008 struct spwd data; 3009 int spflag; 3010 int retval; 3011 3012 3013 /* 3014 * don't clobber our argument 3015 */ 3016 if (strlen(line) >= sizeof (buf)) { 3017 (void) strcpy(parse_err_msg, "line too long"); 3018 return (GENENT_PARSEERR); 3019 } 3020 (void) strcpy(buf, line); 3021 t = buf; 3022 3023 /* ignore empty entries */ 3024 if (*t == '\0') 3025 return (GENENT_OK); 3026 3027 /* 3028 * clear column data 3029 */ 3030 (void) memset((char *)ecol, 0, sizeof (ecol)); 3031 3032 /* 3033 * name (col 0) 3034 */ 3035 if ((s = strchr(t, ':')) == 0) { 3036 (void) strcpy(parse_err_msg, "no uid"); 3037 return (GENENT_PARSEERR); 3038 } 3039 *s++ = 0; 3040 ecol[0].ec_value.ec_value_val = t; 3041 ecol[0].ec_value.ec_value_len = strlen(t)+1; 3042 t = s; 3043 3044 /* 3045 * passwd (col 1) 3046 */ 3047 if ((s = strchr(t, ':')) == 0) { 3048 (void) strcpy(parse_err_msg, "Improper format"); 3049 return (GENENT_PARSEERR); 3050 } 3051 *s++ = 0; 3052 3053 ecol[1].ec_value.ec_value_val = t; 3054 ecol[1].ec_value.ec_value_len = strlen(t)+1; 3055 3056 t = s; 3057 3058 /* 3059 * shadow last change (col 2) 3060 */ 3061 if ((s = strchr(t, ':')) == 0) { 3062 (void) strcpy(parse_err_msg, "Improper format"); 3063 return (GENENT_PARSEERR); 3064 } 3065 *s++ = 0; 3066 ecol[2].ec_value.ec_value_val = t; 3067 ecol[2].ec_value.ec_value_len = strlen(t)+1; 3068 t = s; 3069 3070 /* 3071 * shadow min (col 3) 3072 */ 3073 if ((s = strchr(t, ':')) == 0) { 3074 (void) strcpy(parse_err_msg, "Improper format"); 3075 return (GENENT_PARSEERR); 3076 } 3077 *s++ = 0; 3078 ecol[3].ec_value.ec_value_val = t; 3079 ecol[3].ec_value.ec_value_len = strlen(t)+1; 3080 t = s; 3081 3082 /* 3083 * shadow max (col 4) 3084 */ 3085 if ((s = strchr(t, ':')) == 0) { 3086 (void) strcpy(parse_err_msg, "Improper format"); 3087 return (GENENT_PARSEERR); 3088 } 3089 *s++ = 0; 3090 ecol[4].ec_value.ec_value_val = t; 3091 ecol[4].ec_value.ec_value_len = strlen(t)+1; 3092 t = s; 3093 3094 /* 3095 * shadow warn (col 5) 3096 */ 3097 if ((s = strchr(t, ':')) == 0) { 3098 (void) strcpy(parse_err_msg, "Improper format"); 3099 return (GENENT_PARSEERR); 3100 } 3101 *s++ = 0; 3102 ecol[5].ec_value.ec_value_val = t; 3103 ecol[5].ec_value.ec_value_len = strlen(t)+1; 3104 t = s; 3105 3106 /* 3107 * shadow inactive (col 6) 3108 */ 3109 if ((s = strchr(t, ':')) != 0) { 3110 *s++ = 0; 3111 ecol[6].ec_value.ec_value_val = t; 3112 ecol[6].ec_value.ec_value_len = strlen(t)+1; 3113 t = s; 3114 } 3115 3116 /* 3117 * shadow expire (col 7) 3118 */ 3119 if ((s = strchr(t, ':')) != 0) { 3120 *s++ = 0; 3121 ecol[7].ec_value.ec_value_val = t; 3122 ecol[7].ec_value.ec_value_len = strlen(t)+1; 3123 t = s; 3124 3125 /* 3126 * flag (col 8) 3127 */ 3128 ecol[8].ec_value.ec_value_val = t; 3129 ecol[8].ec_value.ec_value_len = strlen(t)+1; 3130 } 3131 3132 /* 3133 * build entry 3134 */ 3135 3136 data.sp_namp = strdup(ecol[0].ec_value.ec_value_val); 3137 3138 if (ecol[1].ec_value.ec_value_val != NULL && 3139 ecol[1].ec_value.ec_value_val[0] != '\0') { 3140 /* Add {crypt} before passwd entry */ 3141 (void) snprintf(pname, sizeof (pname), "{crypt}%s", 3142 ecol[1].ec_value.ec_value_val); 3143 data.sp_pwdp = strdup(pname); 3144 } else 3145 data.sp_pwdp = NULL; 3146 3147 if (ecol[2].ec_value.ec_value_val != NULL && 3148 ecol[2].ec_value.ec_value_val[0] != '\0') { 3149 3150 data.sp_lstchg = ascii_to_int(ecol[2].ec_value.ec_value_val); 3151 if (data.sp_lstchg < -1) { 3152 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3153 "invalid last changed date: %s", 3154 ecol[2].ec_value.ec_value_val); 3155 return (GENENT_PARSEERR); 3156 } 3157 } else 3158 data.sp_lstchg = -1; 3159 3160 if (ecol[3].ec_value.ec_value_val != NULL && 3161 ecol[3].ec_value.ec_value_val[0] != '\0') { 3162 3163 data.sp_min = ascii_to_int(ecol[3].ec_value.ec_value_val); 3164 if (data.sp_min < -1) { 3165 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3166 "invalid sp_min : %s", 3167 ecol[3].ec_value.ec_value_val); 3168 return (GENENT_PARSEERR); 3169 } 3170 } else 3171 data.sp_min = -1; 3172 3173 if (ecol[4].ec_value.ec_value_val != NULL && 3174 ecol[4].ec_value.ec_value_val[0] != '\0') { 3175 3176 data.sp_max = ascii_to_int(ecol[4].ec_value.ec_value_val); 3177 if (data.sp_max < -1) { 3178 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3179 "invalid sp_max : %s", 3180 ecol[4].ec_value.ec_value_val); 3181 return (GENENT_PARSEERR); 3182 } 3183 } else 3184 data.sp_max = -1; 3185 3186 if (ecol[5].ec_value.ec_value_val != NULL && 3187 ecol[5].ec_value.ec_value_val[0] != '\0') { 3188 3189 data.sp_warn = ascii_to_int(ecol[5].ec_value.ec_value_val); 3190 if (data.sp_warn < -1) { 3191 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3192 "invalid sp_warn : %s", 3193 ecol[5].ec_value.ec_value_val); 3194 return (GENENT_PARSEERR); 3195 } 3196 } else 3197 data.sp_warn = -1; 3198 3199 if (ecol[6].ec_value.ec_value_val != NULL && 3200 ecol[6].ec_value.ec_value_val[0] != '\0') { 3201 3202 data.sp_inact = ascii_to_int(ecol[6].ec_value.ec_value_val); 3203 if (data.sp_inact < -1) { 3204 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3205 "invalid sp_inact : %s", 3206 ecol[6].ec_value.ec_value_val); 3207 return (GENENT_PARSEERR); 3208 } 3209 } else 3210 data.sp_inact = -1; 3211 3212 if (ecol[7].ec_value.ec_value_val != NULL && 3213 ecol[7].ec_value.ec_value_val[0] != '\0') { 3214 3215 data.sp_expire = ascii_to_int(ecol[7].ec_value.ec_value_val); 3216 if (data.sp_expire < -1) { 3217 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3218 "invalid login expiry date : %s", 3219 ecol[7].ec_value.ec_value_val); 3220 return (GENENT_PARSEERR); 3221 } 3222 } else 3223 data.sp_expire = -1; 3224 3225 if (ecol[8].ec_value.ec_value_val != NULL && 3226 ecol[8].ec_value.ec_value_val[0] != '\0') { 3227 3228 /* 3229 * data.sp_flag is an unsigned int, 3230 * assign -1 to it, make no sense. 3231 * Use spflag here to avoid lint warning. 3232 */ 3233 spflag = ascii_to_int(ecol[8].ec_value.ec_value_val); 3234 if (spflag < 0) { 3235 (void) snprintf(parse_err_msg, sizeof (parse_err_msg), 3236 "invalid flag value: %s", 3237 ecol[8].ec_value.ec_value_val); 3238 return (GENENT_PARSEERR); 3239 } else 3240 data.sp_flag = spflag; 3241 } else 3242 data.sp_flag = 0; 3243 3244 if (flags & F_VERBOSE) 3245 (void) fprintf(stdout, 3246 gettext("Adding entry : %s\n"), data.sp_namp); 3247 3248 retval = (*cback)(&data, 1); 3249 if (retval != NS_LDAP_SUCCESS) { 3250 if (retval == LDAP_NO_SUCH_OBJECT) 3251 (void) fprintf(stdout, 3252 gettext("Cannot add shadow entry (%s), " 3253 "add passwd entry first\n"), data.sp_namp); 3254 if (continue_onerror == 0) 3255 return (GENENT_CBERR); 3256 } 3257 3258 free(data.sp_namp); 3259 free(data.sp_pwdp); 3260 return (GENENT_OK); 3261 } 3262 3263 static void 3264 dump_shadow(ns_ldap_result_t *res) 3265 { 3266 char **value = NULL; 3267 char pnam[256]; 3268 3269 value = __ns_ldap_getAttr(res->entry, "uid"); 3270 if (value == NULL) 3271 return; 3272 else 3273 (void) fprintf(stdout, "%s:", value[0]); 3274 value = __ns_ldap_getAttr(res->entry, "userPassword"); 3275 if (value == NULL) 3276 (void) fprintf(stdout, "*:"); 3277 else { 3278 (void) strcpy(pnam, value[0]); 3279 if (strncasecmp(value[0], "{crypt}", 7) == 0) 3280 (void) fprintf(stdout, "%s:", (pnam+7)); 3281 else 3282 (void) fprintf(stdout, "*:"); 3283 } 3284 value = __ns_ldap_getAttr(res->entry, "shadowLastChange"); 3285 if (value == NULL) 3286 (void) fprintf(stdout, ":"); 3287 else 3288 (void) fprintf(stdout, "%s:", value[0]); 3289 value = __ns_ldap_getAttr(res->entry, "shadowMin"); 3290 if (value == NULL) 3291 (void) fprintf(stdout, ":"); 3292 else 3293 (void) fprintf(stdout, "%s:", value[0]); 3294 value = __ns_ldap_getAttr(res->entry, "shadowMax"); 3295 if (value == NULL) 3296 (void) fprintf(stdout, ":"); 3297 else 3298 (void) fprintf(stdout, "%s:", value[0]); 3299 3300 /* ignore shadowWarning, shadowInactive, shadowExpire, shadowFlag */ 3301 (void) fprintf(stdout, ":::\n"); 3302 3303 } 3304 3305 3306 static int 3307 genent_bootparams(char *line, int (*cback)()) 3308 { 3309 char buf[BUFSIZ+1]; 3310 char *t; 3311 entry_col ecol[2]; 3312 int ctr = 0, retval = 1; 3313 3314 struct _ns_bootp data; 3315 char *parameter; 3316 int rc = GENENT_OK; 3317 3318 /* 3319 * don't clobber our argument 3320 */ 3321 if (strlen(line) >= sizeof (buf)) { 3322 (void) strcpy(parse_err_msg, "line too long"); 3323 return (GENENT_PARSEERR); 3324 } 3325 (void) strcpy(buf, line); 3326 3327 /* 3328 * clear column data 3329 */ 3330 (void) memset((char *)ecol, 0, sizeof (ecol)); 3331 3332 3333 /* 3334 * cname (col 0) 3335 */ 3336 if ((t = strtok(buf, " \t")) == 0) { 3337 (void) strcpy(parse_err_msg, "no cname"); 3338 return (GENENT_PARSEERR); 3339 } 3340 ecol[0].ec_value.ec_value_val = t; 3341 ecol[0].ec_value.ec_value_len = strlen(t)+1; 3342 3343 3344 3345 /* build entry */ 3346 data.name = strdup(ecol[0].ec_value.ec_value_val); 3347 3348 /* 3349 * name (col 1) 3350 */ 3351 3352 data.param = NULL; 3353 3354 while (t = strtok(NULL, " \t")) { 3355 3356 /* 3357 * don't clobber comment in canonical entry 3358 */ 3359 3360 3361 ecol[1].ec_value.ec_value_val = t; 3362 ecol[1].ec_value.ec_value_len = strlen(t)+1; 3363 3364 ctr++; 3365 parameter = strdup(ecol[1].ec_value.ec_value_val); 3366 if ((data.param = (char **)realloc(data.param, 3367 (ctr + 1) * sizeof (char **))) == NULL) { 3368 (void) fprintf(stderr, gettext("out of memory\n")); 3369 exit(1); 3370 } 3371 data.param[ctr-1] = parameter; 3372 3373 } 3374 3375 3376 /* End the list of all the aliases by NULL */ 3377 if ((data.param = (char **)realloc(data.param, 3378 (ctr + 1) * sizeof (char **))) == NULL) { 3379 (void) fprintf(stderr, gettext("out of memory\n")); 3380 exit(1); 3381 } 3382 data.param[ctr] = NULL; 3383 3384 if (flags & F_VERBOSE) 3385 (void) fprintf(stdout, 3386 gettext("Adding entry : %s\n"), data.name); 3387 3388 retval = (*cback)(&data, 0); 3389 3390 if (retval == LDAP_ALREADY_EXISTS) { 3391 if (continue_onerror) 3392 (void) fprintf(stderr, 3393 gettext("Entry: %s - already Exists, skipping it.\n"), 3394 data.name); 3395 else { 3396 rc = GENENT_CBERR; 3397 (void) fprintf(stderr, 3398 gettext("Entry: %s - already Exists\n"), 3399 data.name); 3400 } 3401 } else if (retval) 3402 rc = GENENT_CBERR; 3403 3404 free(data.name); 3405 free(data.param); 3406 3407 return (rc); 3408 3409 } 3410 3411 3412 static void 3413 dump_bootparams(ns_ldap_result_t *res) 3414 { 3415 char **value = NULL; 3416 int attr_count = 0; 3417 3418 value = __ns_ldap_getAttr(res->entry, "cn"); 3419 if (value[0] != NULL) 3420 (void) fprintf(stdout, "%s", value[0]); 3421 value = __ns_ldap_getAttr(res->entry, "bootParameter"); 3422 if (value != NULL) 3423 while (value[attr_count] != NULL) { 3424 (void) fprintf(stdout, "\t%s", value[attr_count]); 3425 attr_count++; 3426 } 3427 (void) fprintf(stdout, "\n"); 3428 3429 3430 } 3431 3432 static char * 3433 fget_line_at(struct line_buf *line, int n, FILE *fp) 3434 { 3435 int c; 3436 3437 line->len = n; 3438 3439 for (;;) { 3440 c = fgetc(fp); 3441 if (c == -1) 3442 break; 3443 if (line->len >= line->alloc) 3444 line_buf_expand(line); 3445 line->str[line->len++] = c; 3446 3447 if (c == '\n') 3448 break; 3449 } 3450 3451 /* Null Terminate */ 3452 if (line->len >= line->alloc) 3453 line_buf_expand(line); 3454 line->str[line->len++] = 0; 3455 3456 /* if no characters are read, return NULL to indicate EOF */ 3457 if (line->str[0] == '\0') 3458 return (0); 3459 3460 return (line->str); 3461 } 3462 3463 /* 3464 * return a line from the file, discarding comments and blank lines 3465 */ 3466 static int 3467 filedbmline_comment(struct line_buf *line, FILE *etcf, int *lineno, 3468 struct file_loc *loc) 3469 { 3470 int i, len = 0; 3471 3472 loc->offset = ftell(etcf); 3473 for (;;) { 3474 if (fget_line_at(line, len, etcf) == 0) 3475 return (0); 3476 3477 if (lineno) 3478 (*lineno)++; 3479 3480 len = strlen(line->str); 3481 if (len >= 2 && 3482 line->str[0] != '#' && 3483 line->str[len-2] == '\\' && line->str[len-1] == '\n') { 3484 line->str[len-2] = 0; 3485 len -= 2; 3486 continue; /* append next line at end */ 3487 } 3488 3489 if (line->str[len-1] == '\n') { 3490 line->str[len-1] = 0; 3491 len -= 1; 3492 } 3493 3494 /* 3495 * Skip lines where '#' is the first non-blank character. 3496 */ 3497 for (i = 0; i < len; i++) { 3498 if (line->str[i] == '#') { 3499 line->str[i] = '\0'; 3500 len = i; 3501 break; 3502 } 3503 if (line->str[i] != ' ' && line->str[i] != '\t') 3504 break; 3505 } 3506 3507 /* 3508 * A line with one or more white space characters followed 3509 * by a comment will now be blank. The special case of a 3510 * line with '#' in the first byte will have len == 0. 3511 */ 3512 if (len > 0 && !blankline(line->str)) 3513 break; 3514 3515 len = 0; 3516 loc->offset = ftell(etcf); 3517 } 3518 3519 loc->size = len; 3520 return (1); 3521 } 3522 3523 /* 3524 * return a line from the file, discarding comments, blanks, and '+' lines 3525 */ 3526 static int 3527 filedbmline_plus(struct line_buf *line, FILE *etcf, int *lineno, 3528 struct file_loc *loc) 3529 { 3530 int len = 0; 3531 3532 loc->offset = ftell(etcf); 3533 for (;;) { 3534 if (fget_line_at(line, len, etcf) == 0) 3535 return (0); 3536 3537 if (lineno) 3538 (*lineno)++; 3539 3540 len = strlen(line->str); 3541 if (line->str[len-1] == '\n') { 3542 line->str[len-1] = 0; 3543 len -= 1; 3544 } 3545 3546 if (!blankline(line->str) && 3547 line->str[0] != '+' && line->str[0] != '-' && 3548 line->str[0] != '#') 3549 break; 3550 3551 len = 0; 3552 loc->offset = ftell(etcf); 3553 } 3554 3555 loc->size = len; 3556 return (1); 3557 } 3558 3559 3560 /* Populating the ttypelist structure */ 3561 3562 static struct ttypelist_t ttypelist[] = { 3563 { NS_LDAP_TYPE_HOSTS, genent_hosts, dump_hosts, 3564 filedbmline_comment, "iphost" }, 3565 { NS_LDAP_TYPE_IPNODES, genent_hosts, dump_hosts, 3566 filedbmline_comment, "iphost" }, 3567 { NS_LDAP_TYPE_RPC, genent_rpc, dump_rpc, 3568 filedbmline_comment, "oncrpc" }, 3569 { NS_LDAP_TYPE_PROTOCOLS, genent_protocols, dump_protocols, 3570 filedbmline_comment, "ipprotocol" }, 3571 { NS_LDAP_TYPE_NETWORKS, genent_networks, dump_networks, 3572 filedbmline_comment, "ipnetwork" }, 3573 { NS_LDAP_TYPE_SERVICES, genent_services, dump_services, 3574 filedbmline_comment, "ipservice" }, 3575 { NS_LDAP_TYPE_GROUP, genent_group, dump_group, 3576 filedbmline_plus, "posixgroup" }, 3577 { NS_LDAP_TYPE_NETMASKS, genent_netmasks, dump_netmasks, 3578 filedbmline_comment, "ipnetwork" }, 3579 { NS_LDAP_TYPE_ETHERS, genent_ethers, dump_ethers, 3580 filedbmline_comment, "ieee802Device" }, 3581 { NS_LDAP_TYPE_NETGROUP, genent_netgroup, dump_netgroup, 3582 filedbmline_comment, "nisnetgroup" }, 3583 { NS_LDAP_TYPE_BOOTPARAMS, genent_bootparams, dump_bootparams, 3584 filedbmline_comment, "bootableDevice" }, 3585 { NS_LDAP_TYPE_PUBLICKEY, genent_publickey, NULL /* dump_publickey */, 3586 filedbmline_comment, "niskeyobject" }, 3587 { NS_LDAP_TYPE_PASSWD, genent_passwd, dump_passwd, 3588 filedbmline_plus, "posixaccount" }, 3589 { NS_LDAP_TYPE_SHADOW, genent_shadow, dump_shadow, 3590 filedbmline_plus, "shadowaccount" }, 3591 { NS_LDAP_TYPE_ALIASES, genent_aliases, dump_aliases, 3592 filedbmline_plus, "mailGroup" }, 3593 { NS_LDAP_TYPE_AUTOMOUNT, genent_automount, dump_automount, 3594 filedbmline_comment, "automount" }, 3595 { NS_LDAP_TYPE_USERATTR, genent_user_attr, dump_user_attr, 3596 filedbmline_comment, "SolarisUserAttr" }, 3597 { NS_LDAP_TYPE_PROFILE, genent_prof_attr, dump_prof_attr, 3598 filedbmline_comment, "SolarisProfAttr" }, 3599 { NS_LDAP_TYPE_EXECATTR, genent_exec_attr, dump_exec_attr, 3600 filedbmline_comment, "SolarisExecAttr" }, 3601 { NS_LDAP_TYPE_AUTHATTR, genent_auth_attr, dump_auth_attr, 3602 filedbmline_comment, "SolarisAuthAttr" }, 3603 { NS_LDAP_TYPE_AUUSER, genent_audit_user, dump_audit_user, 3604 filedbmline_comment, "SolarisAuditUser" }, 3605 { NS_LDAP_TYPE_TNRHDB, genent_tnrhdb, dump_tnrhdb, 3606 filedbmline_comment, "ipTnetHost" }, 3607 { NS_LDAP_TYPE_TNRHTP, genent_tnrhtp, dump_tnrhtp, 3608 filedbmline_comment, "ipTnetTemplate" }, 3609 { 0, 0, 0, 0, 0 } 3610 }; 3611 3612 3613 3614 3615 static int lineno = 0; 3616 3617 static void 3618 addfile() 3619 { 3620 struct line_buf line; 3621 struct file_loc loc; 3622 3623 /* Initializing the Line Buffer */ 3624 line_buf_init(&line); 3625 3626 /* Loop through all the lines in the file */ 3627 while (tt->filedbmline(&line, etcf, &lineno, &loc)) { 3628 switch ((*(tt->genent))(line.str, addentry)) { 3629 case GENENT_OK: 3630 break; 3631 case GENENT_PARSEERR: 3632 (void) fprintf(stderr, 3633 gettext("parse error: %s (line %d)\n"), 3634 parse_err_msg, lineno); 3635 exit_val = 1; 3636 break; 3637 case GENENT_CBERR: 3638 (void) fprintf(stderr, 3639 gettext("Error while adding line: %s\n"), 3640 line.str); 3641 exit_val = 2; 3642 free(line.str); 3643 return; 3644 break; 3645 case GENENT_ERR: 3646 (void) fprintf(stderr, 3647 gettext("Internal Error while adding line: %s\n"), 3648 line.str); 3649 exit_val = 3; 3650 free(line.str); 3651 return; 3652 break; 3653 } 3654 } 3655 free(line.str); 3656 } 3657 3658 static void 3659 dumptable(char *service) 3660 { 3661 3662 ns_ldap_result_t *eres = NULL; 3663 ns_ldap_error_t *err = NULL; 3664 int rc = 0, success = 0; 3665 char filter[BUFSIZ]; 3666 int done = 0; 3667 void *cookie = NULL; 3668 3669 /* set the appropriate filter */ 3670 if (strcmp(tt->ttype, NS_LDAP_TYPE_PROFILE) == 0) { 3671 /* 3672 * prof_attr entries are SolarisProfAttr 3673 * without AUXILIARY SolarisExecAttr 3674 */ 3675 (void) snprintf(filter, sizeof (filter), 3676 "(&(objectclass=%s)(!(objectclass=SolarisExecAttr)))", 3677 tt->objclass); 3678 } else if (strcmp(tt->ttype, NS_LDAP_TYPE_TNRHDB) == 0) { 3679 /* 3680 * tnrhtp entries are ipTnet entries with SolarisAttrKeyValue 3681 */ 3682 (void) snprintf(filter, sizeof (filter), 3683 "(&(objectclass=%s)(SolarisAttrKeyValue=*)))", 3684 tt->objclass); 3685 } else { 3686 (void) snprintf(filter, sizeof (filter), 3687 "(objectclass=%s)", tt->objclass); 3688 } 3689 3690 if (flags & F_VERBOSE) 3691 (void) fprintf(stdout, gettext("FILTER = %s\n"), filter); 3692 3693 /* Pass cred only if supplied. Cred is not always needed for dump */ 3694 if (authority.cred.unix_cred.userID == NULL || 3695 authority.cred.unix_cred.passwd == NULL) 3696 rc = __ns_ldap_firstEntry(service, filter, NULL, NULL, 3697 NULL, NS_LDAP_HARD, &cookie, &eres, &err, NULL); 3698 else 3699 rc = __ns_ldap_firstEntry(service, filter, NULL, NULL, 3700 &authority, NS_LDAP_HARD, &cookie, &eres, &err, NULL); 3701 3702 switch (rc) { 3703 case NS_LDAP_SUCCESS: 3704 nent_add++; 3705 success = 1; 3706 if (eres != NULL) { 3707 if (strcmp(databasetype, "publickey") == 0) 3708 dump_publickey(eres, service); 3709 else 3710 (*(tt->dump))(eres); 3711 } 3712 else 3713 (void) fprintf(stderr, gettext("No entries found.\n")); 3714 break; 3715 3716 case NS_LDAP_OP_FAILED: 3717 exit_val = 2; 3718 (void) fprintf(stderr, gettext("operation failed.\n")); 3719 break; 3720 3721 case NS_LDAP_INVALID_PARAM: 3722 exit_val = 2; 3723 (void) fprintf(stderr, 3724 gettext("invalid parameter(s) passed.\n")); 3725 break; 3726 3727 case NS_LDAP_NOTFOUND: 3728 exit_val = 2; 3729 (void) fprintf(stderr, gettext("entry not found.\n")); 3730 break; 3731 3732 case NS_LDAP_MEMORY: 3733 exit_val = 2; 3734 (void) fprintf(stderr, 3735 gettext("internal memory allocation error.\n")); 3736 break; 3737 3738 case NS_LDAP_CONFIG: 3739 exit_val = 2; 3740 (void) fprintf(stderr, 3741 gettext("LDAP Configuration problem.\n")); 3742 perr(err); 3743 break; 3744 3745 case NS_LDAP_PARTIAL: 3746 exit_val = 2; 3747 (void) fprintf(stderr, 3748 gettext("partial result returned\n")); 3749 perr(err); 3750 break; 3751 3752 case NS_LDAP_INTERNAL: 3753 exit_val = 2; 3754 (void) fprintf(stderr, 3755 gettext("internal LDAP error occured.\n")); 3756 perr(err); 3757 break; 3758 } 3759 3760 if (eres != NULL) { 3761 (void) __ns_ldap_freeResult(&eres); 3762 eres = NULL; 3763 } 3764 3765 if (success) { 3766 while (!done) { 3767 rc = __ns_ldap_nextEntry(cookie, &eres, &err); 3768 if (rc != NS_LDAP_SUCCESS || eres == NULL) { 3769 done = 1; 3770 continue; 3771 } 3772 3773 /* Print the result */ 3774 if (eres != NULL) { 3775 if (strcmp(databasetype, "publickey") == 0) 3776 dump_publickey(eres, service); 3777 else 3778 (*(tt->dump))(eres); 3779 (void) __ns_ldap_freeResult(&eres); 3780 eres = NULL; 3781 } 3782 } 3783 } 3784 } 3785 3786 int 3787 main(int argc, char **argv) 3788 { 3789 char *password; 3790 int c; 3791 int rc; 3792 int ldaprc; 3793 int authstried = 0; 3794 int supportedauth = 0; 3795 int op = OP_ADD; 3796 char *ttype, *authmech = 0, *etcfile = 0; 3797 char ps[LDAP_MAXNAMELEN]; /* Temporary password variable */ 3798 char filter[BUFSIZ]; 3799 void **paramVal = NULL; 3800 ns_auth_t **app; 3801 ns_auth_t **authpp = NULL; 3802 ns_auth_t *authp = NULL; 3803 ns_ldap_error_t *errorp = NULL; 3804 ns_ldap_result_t *resultp; 3805 ns_ldap_entry_t *e; 3806 int flag = 0; 3807 int version1 = 0; 3808 3809 (void) setlocale(LC_ALL, ""); 3810 (void) textdomain(TEXT_DOMAIN); 3811 3812 openlog("ldapaddent", LOG_PID, LOG_USER); 3813 3814 inputbasedn = NULL; 3815 authority.cred.unix_cred.passwd = NULL; 3816 authority.cred.unix_cred.userID = NULL; 3817 authority.auth.type = NS_LDAP_AUTH_SIMPLE; 3818 3819 while ((c = getopt(argc, argv, "cdhvpf:D:w:b:a:")) != EOF) { 3820 switch (c) { 3821 case 'd': 3822 if (op) 3823 usage("no other option should be specified"); 3824 op = OP_DUMP; 3825 break; 3826 case 'c': 3827 continue_onerror = 1; 3828 break; 3829 case 'v': 3830 flags |= F_VERBOSE; 3831 break; 3832 case 'p': 3833 flags |= F_PASSWD; 3834 break; 3835 case 'f': 3836 etcfile = optarg; 3837 break; 3838 case 'D': 3839 authority.cred.unix_cred.userID = strdup(optarg); 3840 break; 3841 case 'w': 3842 authority.cred.unix_cred.passwd = strdup(optarg); 3843 break; 3844 case 'b': 3845 inputbasedn = strdup(optarg); 3846 break; 3847 case 'a': 3848 authmech = strdup(optarg); 3849 break; 3850 3851 default: 3852 usage(gettext("Invalid option")); 3853 } 3854 } 3855 3856 3857 if (authority.cred.unix_cred.userID == NULL && op != OP_DUMP) { 3858 /* This is not an optional parameter. Exit */ 3859 (void) fprintf(stderr, 3860 gettext("Distinguished Name to bind to directory" 3861 " must be specified. use option -D.\n")); 3862 exit(1); 3863 } 3864 3865 if (authority.cred.unix_cred.passwd == NULL && op != OP_DUMP) { 3866 /* If password is not specified, then prompt user for it. */ 3867 password = getpassphrase("Enter password:"); 3868 (void) strcpy(ps, password); 3869 authority.cred.unix_cred.passwd = strdup(ps); 3870 } 3871 3872 if (authmech != NULL) { 3873 if (strcasecmp(authmech, "simple") == 0) { 3874 authority.auth.type = NS_LDAP_AUTH_SIMPLE; 3875 authority.auth.tlstype = NS_LDAP_TLS_NONE; 3876 authority.auth.saslmech = NS_LDAP_SASL_NONE; 3877 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3878 supportedauth = 1; 3879 } 3880 if (strcasecmp(authmech, "sasl/CRAM-MD5") == 0) { 3881 authority.auth.type = NS_LDAP_AUTH_SASL; 3882 authority.auth.tlstype = NS_LDAP_TLS_SASL; 3883 authority.auth.saslmech = NS_LDAP_SASL_CRAM_MD5; 3884 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3885 supportedauth = 1; 3886 } 3887 if (strcasecmp(authmech, "sasl/DIGEST-MD5") == 0) { 3888 authority.auth.type = NS_LDAP_AUTH_SASL; 3889 authority.auth.tlstype = NS_LDAP_TLS_SASL; 3890 authority.auth.saslmech = NS_LDAP_SASL_DIGEST_MD5; 3891 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3892 supportedauth = 1; 3893 } 3894 if (strcasecmp(authmech, "tls:simple") == 0) { 3895 authority.auth.type = NS_LDAP_AUTH_TLS; 3896 authority.auth.tlstype = NS_LDAP_TLS_SIMPLE; 3897 authority.auth.saslmech = NS_LDAP_SASL_NONE; 3898 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3899 supportedauth = 1; 3900 } 3901 if (strcasecmp(authmech, "tls:sasl/CRAM-MD5") == 0) { 3902 authority.auth.type = NS_LDAP_AUTH_TLS; 3903 authority.auth.tlstype = NS_LDAP_TLS_SASL; 3904 authority.auth.saslmech = NS_LDAP_SASL_CRAM_MD5; 3905 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3906 supportedauth = 1; 3907 } 3908 if (strcasecmp(authmech, "tls:sasl/DIGEST-MD5") == 0) { 3909 authority.auth.type = NS_LDAP_AUTH_TLS; 3910 authority.auth.tlstype = NS_LDAP_TLS_SASL; 3911 authority.auth.saslmech = NS_LDAP_SASL_DIGEST_MD5; 3912 authority.auth.saslopt = NS_LDAP_SASLOPT_NONE; 3913 supportedauth = 1; 3914 } 3915 if (!supportedauth) { 3916 (void) fprintf(stderr, 3917 gettext("Invalid authentication method specified")); 3918 exit(1); 3919 } 3920 } 3921 3922 if (authmech == NULL) { 3923 ldaprc = __ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp, 3924 &errorp); 3925 if (ldaprc != NS_LDAP_SUCCESS || 3926 (authpp == NULL && op != OP_DUMP)) { 3927 (void) fprintf(stderr, 3928 gettext("No legal authentication method " 3929 "configured.\n")); 3930 (void) fprintf(stderr, 3931 gettext("Provide a legal authentication method " 3932 "using -a option\n")); 3933 exit(1); 3934 } 3935 3936 /* Use the first authentication method which is not none */ 3937 for (app = authpp; *app; app++) { 3938 authp = *app; 3939 if (authp->type != NS_LDAP_AUTH_NONE) { 3940 authstried++; 3941 authority.auth.type = authp->type; 3942 authority.auth.tlstype = authp->tlstype; 3943 authority.auth.saslmech = authp->saslmech; 3944 authority.auth.saslopt = authp->saslopt; 3945 break; 3946 } 3947 } 3948 if (authstried == 0 && op != OP_DUMP) { 3949 (void) fprintf(stderr, 3950 gettext("No legal authentication method configured.\n" 3951 "Provide a legal authentication method using " 3952 "-a option")); 3953 exit(1); 3954 } 3955 } 3956 3957 ttype = argv[optind++]; 3958 3959 if (ttype == NULL) { 3960 usage(gettext("No database type specified")); 3961 exit(1); 3962 } 3963 3964 if (strncasecmp(ttype, "automount", 9) == 0) { 3965 (void) fprintf(stderr, 3966 gettext("automount is not a valid service for ldapaddent.\n" 3967 "Please use auto_*.\n" 3968 "e.g. auto_home, auto_ws etc.\n ")); 3969 exit(1); 3970 } 3971 3972 for (tt = ttypelist; tt->ttype; tt++) { 3973 if (strcmp(tt->ttype, ttype) == 0) 3974 break; 3975 if (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0 && 3976 strncmp(ttype, NS_LDAP_TYPE_AUTOMOUNT, 3977 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) 3978 break; 3979 } 3980 3981 if (tt->ttype == 0) { 3982 (void) fprintf(stderr, 3983 gettext("database %s not supported;" 3984 " supported databases are:\n"), ttype); 3985 for (tt = ttypelist; tt->ttype; tt++) 3986 (void) fprintf(stderr, gettext("\t%s\n"), tt->ttype); 3987 exit(1); 3988 } 3989 3990 if (flags & F_VERBOSE) 3991 (void) fprintf(stdout, gettext("SERVICE = %s\n"), tt->ttype); 3992 3993 databasetype = ttype; 3994 3995 if (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0) { 3996 paramVal = NULL; 3997 errorp = NULL; 3998 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, 3999 &errorp); 4000 if (paramVal && *paramVal && 4001 strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0) 4002 version1 = 1; 4003 if (paramVal) 4004 (void) __ns_ldap_freeParam(¶mVal); 4005 if (errorp) 4006 (void) __ns_ldap_freeError(&errorp); 4007 } 4008 4009 /* Check if the container exists in first place */ 4010 (void) strcpy(&filter[0], "(objectclass=*)"); 4011 4012 rc = __ns_ldap_list(databasetype, filter, NULL, (const char **)NULL, 4013 NULL, NS_LDAP_SCOPE_BASE, &resultp, &errorp, NULL, NULL); 4014 4015 /* create a container for auto_* if it does not exist already */ 4016 if ((rc == NS_LDAP_NOTFOUND) && (op == OP_ADD) && 4017 (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0)) { 4018 static char *oclist[] = {NULL, "top", NULL}; 4019 if (version1) 4020 oclist[0] = "nisMap"; 4021 else 4022 oclist[0] = "automountMap"; 4023 e = __s_mk_entry(oclist, 3); 4024 if (e == NULL) { 4025 (void) fprintf(stderr, 4026 gettext("internal memory allocation error.\n")); 4027 exit(1); 4028 } 4029 if (__s_add_attr(e, 4030 version1 ? "nisMapName" : "automountMapName", 4031 databasetype) != NS_LDAP_SUCCESS) { 4032 (void) fprintf(stderr, 4033 gettext("internal memory allocation error.\n")); 4034 ldap_freeEntry(e); 4035 exit(1); 4036 } 4037 4038 if (inputbasedn == NULL) { 4039 if (get_basedn(databasetype, &inputbasedn) != 4040 NS_LDAP_SUCCESS) { 4041 (void) fprintf(stderr, 4042 gettext("Could not obtain basedn\n")); 4043 ldap_freeEntry(e); 4044 exit(1); 4045 } 4046 } 4047 if (__ns_ldap_addEntry(databasetype, inputbasedn, e, 4048 &authority, flag, &errorp) != NS_LDAP_SUCCESS) { 4049 (void) fprintf(stderr, 4050 gettext("Could not create container for %s\n"), 4051 databasetype); 4052 ldap_freeEntry(e); 4053 } 4054 } else if (strcmp(databasetype, "publickey") != 0) { 4055 if (rc == NS_LDAP_NOTFOUND) { 4056 (void) fprintf(stderr, 4057 gettext("Container %s does not exist\n"), 4058 databasetype); 4059 exit(1); 4060 } 4061 } 4062 4063 if (op == OP_DUMP) { 4064 if (strcmp(databasetype, "publickey") == 0) { 4065 dumptable("hosts"); 4066 dumptable("passwd"); 4067 } else { 4068 dumptable(databasetype); 4069 } 4070 exit(exit_val); 4071 } 4072 4073 if (etcfile) { 4074 if ((etcf = fopen(etcfile, "r")) == 0) { 4075 (void) fprintf(stderr, 4076 gettext("can't open file %s\n"), etcfile); 4077 exit(1); 4078 } 4079 } else { 4080 etcfile = "stdin"; 4081 etcf = stdin; 4082 } 4083 4084 if (op == OP_ADD) { 4085 (void) addfile(); 4086 (void) fprintf(stdout, gettext("%d entries added\n"), nent_add); 4087 } 4088 4089 /* exit() -> return for make lint */ 4090 return (exit_val); 4091 } 4092 4093 4094 /* 4095 * This is called when service == auto_*. 4096 * It calls __ns_ldap_getSearchDescriptors 4097 * to generate the dn from SSD's base dn. 4098 * If there is no SSD available, 4099 * default base dn will be used 4100 * Only the first baseDN in the SSD is used 4101 */ 4102 4103 static int get_basedn(char *service, char **basedn) { 4104 int rc = NS_LDAP_SUCCESS; 4105 char *dn = NULL; 4106 ns_ldap_search_desc_t **desc = NULL; 4107 ns_ldap_error_t *errp = NULL; 4108 void **paramVal = NULL; 4109 int prepend_automountmapname = FALSE; 4110 4111 /* 4112 * Get auto_* SSD first 4113 */ 4114 4115 if ((rc = __ns_ldap_getSearchDescriptors( 4116 (const char *) service, 4117 &desc, &errp)) == NS_LDAP_SUCCESS && 4118 desc != NULL) { 4119 4120 if (desc[0] != NULL && desc[0]->basedn != NULL) { 4121 dn = strdup(desc[0]->basedn); 4122 if (dn == NULL) { 4123 (void) __ns_ldap_freeSearchDescriptors 4124 (&desc); 4125 return (NS_LDAP_MEMORY); 4126 } 4127 } 4128 } 4129 4130 /* clean up */ 4131 if (desc) (void) __ns_ldap_freeSearchDescriptors(&desc); 4132 if (errp) (void) __ns_ldap_freeError(&errp); 4133 4134 /* 4135 * If no dn is duplicated from auto_* SSD, try automount SSD 4136 */ 4137 if (dn == NULL) { 4138 if ((rc = __ns_ldap_getSearchDescriptors( 4139 "automount", &desc, &errp)) 4140 == NS_LDAP_SUCCESS && desc != NULL) { 4141 4142 if (desc[0] != NULL && desc[0]->basedn != NULL) { 4143 dn = strdup(desc[0]->basedn); 4144 if (dn == NULL) { 4145 (void) __ns_ldap_freeSearchDescriptors 4146 (&desc); 4147 return (NS_LDAP_MEMORY); 4148 } 4149 prepend_automountmapname = TRUE; 4150 } 4151 } 4152 /* clean up */ 4153 if (desc) (void) __ns_ldap_freeSearchDescriptors(&desc); 4154 if (errp) (void) __ns_ldap_freeError(&errp); 4155 } 4156 4157 /* 4158 * If no dn is duplicated from auto_* or automount SSD, 4159 * use default DN 4160 */ 4161 4162 if (dn == NULL) { 4163 if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 4164 ¶mVal, &errp)) == NS_LDAP_SUCCESS) { 4165 dn = strdup((char *)paramVal[0]); 4166 if (dn == NULL) { 4167 (void) __ns_ldap_freeParam(¶mVal); 4168 return (NS_LDAP_MEMORY); 4169 } 4170 prepend_automountmapname = TRUE; 4171 } 4172 if (paramVal) (void) __ns_ldap_freeParam(¶mVal); 4173 if (errp) (void) __ns_ldap_freeError(&errp); 4174 } 4175 4176 4177 if (dn == NULL) { 4178 return (NS_LDAP_OP_FAILED); 4179 } else { 4180 /* 4181 * If dn is duplicated from 4182 * automount SSD basedn or 4183 * default base dn 4184 * then prepend automountMapName=auto_xxx 4185 */ 4186 if (prepend_automountmapname) 4187 rc = __s_api_prepend_automountmapname_to_dn( 4188 service, &dn, &errp); 4189 4190 if (rc != NS_LDAP_SUCCESS) { 4191 (void) __ns_ldap_freeError(&errp); 4192 free(dn); 4193 return (rc); 4194 } 4195 4196 *basedn = dn; 4197 4198 return (NS_LDAP_SUCCESS); 4199 } 4200 } 4201