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