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