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