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