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