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