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