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